This commit is contained in:
2025-08-12 10:36:26 +02:00
parent 4cd5b51085
commit 6b46b3dbaa
30 changed files with 472 additions and 747 deletions

View File

@@ -13,12 +13,12 @@ prod_mode := fp.bool('prod', `p`, false, 'Build production version (optimized)')
help_requested := fp.bool('help', `h`, false, 'Show help message') help_requested := fp.bool('help', `h`, false, 'Show help message')
if help_requested { if help_requested {
println(fp.usage()) println(fp.usage())
exit(0) exit(0)
} }
additional_args := fp.finalize() or { additional_args := fp.finalize() or {
eprintln(err) eprintln(err)
println(fp.usage()) println(fp.usage())
exit(1) exit(1)
} }

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env -S v -n -cg -w -parallel-cc -enable-globals run #!/usr/bin/env -S v -n -cg -w -parallel-cc -enable-globals run
// #!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
// #!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
import os import os
import flag import flag
@@ -14,20 +14,20 @@ prod_mode := fp.bool('prod', `p`, false, 'Build production version (optimized)')
help_requested := fp.bool('help', `h`, false, 'Show help message') help_requested := fp.bool('help', `h`, false, 'Show help message')
if help_requested { if help_requested {
println(fp.usage()) println(fp.usage())
exit(0) exit(0)
} }
additional_args := fp.finalize() or { additional_args := fp.finalize() or {
eprintln(err) eprintln(err)
println(fp.usage()) println(fp.usage())
exit(1) exit(1)
} }
if additional_args.len > 0 { if additional_args.len > 0 {
eprintln('Unexpected arguments: ${additional_args.join(' ')}') eprintln('Unexpected arguments: ${additional_args.join(' ')}')
println(fp.usage()) println(fp.usage())
exit(1) exit(1)
} }
// Change to the hero directory // Change to the hero directory
@@ -37,35 +37,37 @@ os.chdir(hero_dir) or { panic('Failed to change directory to ${hero_dir}: ${err}
// Set HEROPATH based on OS // Set HEROPATH based on OS
mut heropath := '/usr/local/bin/hero' mut heropath := '/usr/local/bin/hero'
if os.user_os() == 'macos' { if os.user_os() == 'macos' {
heropath = os.join_path(os.home_dir(), 'hero/bin/hero') heropath = os.join_path(os.home_dir(), 'hero/bin/hero')
} }
// Set compilation command based on OS and mode // Set compilation command based on OS and mode
compile_cmd := if os.user_os() == 'macos' { compile_cmd := if os.user_os() == 'macos' {
if prod_mode { if prod_mode {
'v -enable-globals -w -n -prod hero.v' 'v -enable-globals -w -n -prod hero.v'
} else { } else {
'v -w -cg -gc none -cc tcc -d use_openssl -enable-globals hero.v' 'v -w -cg -gc none -cc tcc -d use_openssl -enable-globals hero.v'
} }
} else { } else {
if prod_mode { if prod_mode {
'v -cg -enable-globals -parallel-cc -w -n hero.v' 'v -cg -enable-globals -parallel-cc -w -n hero.v'
} else { } else {
'v -cg -enable-globals -w -n hero.v' 'v -cg -enable-globals -w -n hero.v'
} }
} }
println('Building in ${if prod_mode { 'production' } else { 'debug' }} mode...') println('Building in ${if prod_mode { 'production' } else { 'debug' }} mode...')
if os.system(compile_cmd) != 0 { if os.system(compile_cmd) != 0 {
panic('Failed to compile hero.v with command: ${compile_cmd}') panic('Failed to compile hero.v with command: ${compile_cmd}')
} }
// Make executable // Make executable
os.chmod('hero', 0o755) or { panic('Failed to make hero binary executable: ${err}') } os.chmod('hero', 0o755) or { panic('Failed to make hero binary executable: ${err}') }
// Ensure destination directory exists // Ensure destination directory exists
os.mkdir_all(os.dir(heropath)) or { panic('Failed to create directory ${os.dir(heropath)}: ${err}') } os.mkdir_all(os.dir(heropath)) or {
panic('Failed to create directory ${os.dir(heropath)}: ${err}')
}
println(heropath) println(heropath)
// Copy to destination paths // Copy to destination paths
os.cp('hero', heropath) or { panic('Failed to copy hero binary to ${heropath}: ${err}') } os.cp('hero', heropath) or { panic('Failed to copy hero binary to ${heropath}: ${err}') }

View File

@@ -64,7 +64,9 @@ account = ${s3keyid}
key = ${s3appid} key = ${s3appid}
hard_delete = true' hard_delete = true'
os.write_file(rclone_conf, config_content) or { return error('Failed to write rclone config: ${err}') } os.write_file(rclone_conf, config_content) or {
return error('Failed to write rclone config: ${err}')
}
println('made S3 config on: ${rclone_conf}') println('made S3 config on: ${rclone_conf}')
content := os.read_file(rclone_conf) or { return error('Failed to read rclone config: ${err}') } content := os.read_file(rclone_conf) or { return error('Failed to read rclone config: ${err}') }
@@ -72,8 +74,10 @@ hard_delete = true'
} }
fn hero_upload() ! { fn hero_upload() ! {
hero_path := os.find_abs_path_of_executable('hero') or { return error("Error: 'hero' command not found in PATH") } hero_path := os.find_abs_path_of_executable('hero') or {
return error("Error: 'hero' command not found in PATH")
}
s3_configure()! s3_configure()!
platform_id := get_platform_id() platform_id := get_platform_id()
@@ -83,15 +87,18 @@ fn hero_upload() ! {
// List contents // List contents
os.execute_or_panic('rclone --config="${rclone_conf}" lsl b2:threefold/${platform_id}/') os.execute_or_panic('rclone --config="${rclone_conf}" lsl b2:threefold/${platform_id}/')
// Copy hero binary // Copy hero binary
os.execute_or_panic('rclone --config="${rclone_conf}" copy "${hero_path}" b2:threefold/${platform_id}/') os.execute_or_panic('rclone --config="${rclone_conf}" copy "${hero_path}" b2:threefold/${platform_id}/')
} }
fn main() { fn main() {
//os.execute_or_panic('${os.home_dir()}/code/github/freeflowuniverse/herolib/cli/compile.vsh -p') // os.execute_or_panic('${os.home_dir()}/code/github/freeflowuniverse/herolib/cli/compile.vsh -p')
println("compile hero can take 60 sec+ on osx.") println('compile hero can take 60 sec+ on osx.')
os.execute_or_panic('${os.home_dir()}/code/github/freeflowuniverse/herolib/cli/compile.vsh -p') os.execute_or_panic('${os.home_dir()}/code/github/freeflowuniverse/herolib/cli/compile.vsh -p')
println( "upload:") println('upload:')
hero_upload() or { eprintln(err) exit(1) } hero_upload() or {
eprintln(err)
exit(1)
}
} }

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env -S v -n -cg -w -parallel-cc -enable-globals run #!/usr/bin/env -S v -n -cg -w -parallel-cc -enable-globals run
// #!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
// #!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
import os import os
import flag import flag
@@ -14,20 +14,20 @@ prod_mode := fp.bool('prod', `p`, false, 'Build production version (optimized)')
help_requested := fp.bool('help', `h`, false, 'Show help message') help_requested := fp.bool('help', `h`, false, 'Show help message')
if help_requested { if help_requested {
println(fp.usage()) println(fp.usage())
exit(0) exit(0)
} }
additional_args := fp.finalize() or { additional_args := fp.finalize() or {
eprintln(err) eprintln(err)
println(fp.usage()) println(fp.usage())
exit(1) exit(1)
} }
if additional_args.len > 0 { if additional_args.len > 0 {
eprintln('Unexpected arguments: ${additional_args.join(' ')}') eprintln('Unexpected arguments: ${additional_args.join(' ')}')
println(fp.usage()) println(fp.usage())
exit(1) exit(1)
} }
// Change to the vdo directory // Change to the vdo directory
@@ -37,35 +37,37 @@ os.chdir(hero_dir) or { panic('Failed to change directory to ${hero_dir}: ${err}
// Set HEROPATH based on OS // Set HEROPATH based on OS
mut heropath := '/usr/local/bin/vdo' mut heropath := '/usr/local/bin/vdo'
if os.user_os() == 'macos' { if os.user_os() == 'macos' {
heropath = os.join_path(os.home_dir(), 'hero/bin/vdo') heropath = os.join_path(os.home_dir(), 'hero/bin/vdo')
} }
// Set compilation command based on OS and mode // Set compilation command based on OS and mode
compile_cmd := if os.user_os() == 'macos' { compile_cmd := if os.user_os() == 'macos' {
if prod_mode { if prod_mode {
'v -enable-globals -w -n -prod vdo.v' 'v -enable-globals -w -n -prod vdo.v'
} else { } else {
'v -w -cg -gc none -cc tcc -d use_openssl -enable-globals vdo.v' 'v -w -cg -gc none -cc tcc -d use_openssl -enable-globals vdo.v'
} }
} else { } else {
if prod_mode { if prod_mode {
'v -cg -enable-globals -parallel-cc -w -n vdo.v' 'v -cg -enable-globals -parallel-cc -w -n vdo.v'
} else { } else {
'v -cg -enable-globals -w -n vdo.v' 'v -cg -enable-globals -w -n vdo.v'
} }
} }
println('Building in ${if prod_mode { 'production' } else { 'debug' }} mode...') println('Building in ${if prod_mode { 'production' } else { 'debug' }} mode...')
if os.system(compile_cmd) != 0 { if os.system(compile_cmd) != 0 {
panic('Failed to compile vdo.v with command: ${compile_cmd}') panic('Failed to compile vdo.v with command: ${compile_cmd}')
} }
// Make executable // Make executable
os.chmod('vdo', 0o755) or { panic('Failed to make vdo binary executable: ${err}') } os.chmod('vdo', 0o755) or { panic('Failed to make vdo binary executable: ${err}') }
// Ensure destination directory exists // Ensure destination directory exists
os.mkdir_all(os.dir(heropath)) or { panic('Failed to create directory ${os.dir(heropath)}: ${err}') } os.mkdir_all(os.dir(heropath)) or {
panic('Failed to create directory ${os.dir(heropath)}: ${err}')
}
println(heropath) println(heropath)
// Copy to destination paths // Copy to destination paths
os.cp('vdo', heropath) or { panic('Failed to copy vdo binary to ${heropath}: ${err}') } os.cp('vdo', heropath) or { panic('Failed to copy vdo binary to ${heropath}: ${err}') }

View File

@@ -15,7 +15,7 @@ import freeflowuniverse.herolib.core.playcmds
fn playcmds_do(path string) ! { fn playcmds_do(path string) ! {
mut plbook := playbook.new(path: path)! mut plbook := playbook.new(path: path)!
playcmds.run(plbook:plbook)! playcmds.run(plbook: plbook)!
} }
fn do() ! { fn do() ! {
@@ -114,4 +114,4 @@ fn main() {
fn pre_func(cmd Command) ! { fn pre_func(cmd Command) ! {
herocmds.plbook_run(cmd)! herocmds.plbook_run(cmd)!
} }

View File

@@ -6,7 +6,7 @@ fn main() {
// Create and start the MCP server // Create and start the MCP server
mut server := v_do.new_server() mut server := v_do.new_server()
server.start() or { server.start() or {
eprintln('Error starting server: $err') eprintln('Error starting server: ${err}')
exit(1) exit(1)
} }
} }

35
doc.vsh
View File

@@ -7,13 +7,13 @@ abs_dir_of_script := dir(@FILE)
// Format code // Format code
println('Formatting code...') println('Formatting code...')
if os.system('v fmt -w ${abs_dir_of_script}/examples') != 0 { if os.system('v fmt -w ${abs_dir_of_script}/examples') != 0 {
eprintln('Warning: Failed to format examples') eprintln('Warning: Failed to format examples')
exit(1) exit(1)
} }
if os.system('v fmt -w ${abs_dir_of_script}/lib') != 0 { if os.system('v fmt -w ${abs_dir_of_script}/lib') != 0 {
eprintln('Warning: Failed to format herolib') eprintln('Warning: Failed to format herolib')
exit(1) exit(1)
} }
// Clean existing docs // Clean existing docs
@@ -24,9 +24,7 @@ os.rmdir_all('docs') or {}
os.rmdir_all('vdocs') or {} os.rmdir_all('vdocs') or {}
herolib_path := os.join_path(abs_dir_of_script, 'lib') herolib_path := os.join_path(abs_dir_of_script, 'lib')
os.chdir(herolib_path) or { os.chdir(herolib_path) or { panic('Failed to change directory to herolib: ${err}') }
panic('Failed to change directory to herolib: ${err}')
}
os.mkdir_all('_docs') or {} os.mkdir_all('_docs') or {}
os.mkdir_all('docs') or {} os.mkdir_all('docs') or {}
@@ -35,17 +33,14 @@ os.mkdir_all('vdocs') or {}
// Generate HTML documentation // Generate HTML documentation
println('Generating HTML documentation...') println('Generating HTML documentation...')
if os.system('v doc -m -f html . -readme -comments -no-timestamp -o ../docs') != 0 { if os.system('v doc -m -f html . -readme -comments -no-timestamp -o ../docs') != 0 {
panic('Failed to generate HTML documentation') panic('Failed to generate HTML documentation')
} }
if os.system('v doc -m -f md . -no-color -o ../vdocs/') != 0 { if os.system('v doc -m -f md . -no-color -o ../vdocs/') != 0 {
panic('Failed to generate Hero markdown documentation') panic('Failed to generate Hero markdown documentation')
} }
os.chdir(abs_dir_of_script) or { panic('Failed to change directory to abs_dir_of_script: ${err}') }
os.chdir(abs_dir_of_script) or {
panic('Failed to change directory to abs_dir_of_script: ${err}')
}
// Generate Markdown documentation // Generate Markdown documentation
println('Generating Markdown documentation...') println('Generating Markdown documentation...')
@@ -60,12 +55,10 @@ println('Generating Markdown documentation...')
// Open documentation in browser on non-Linux systems // Open documentation in browser on non-Linux systems
$if !linux { $if !linux {
os.chdir(abs_dir_of_script) or { os.chdir(abs_dir_of_script) or { panic('Failed to change directory: ${err}') }
panic('Failed to change directory: ${err}') if os.system('open docs/index.html') != 0 {
} eprintln('Warning: Failed to open documentation in browser')
if os.system('open docs/index.html') != 0 { }
eprintln('Warning: Failed to open documentation in browser')
}
} }
// Create Jekyll required files // Create Jekyll required files
@@ -75,7 +68,7 @@ os.mkdir_all('docs/assets/css') or {}
// Create style.scss // Create style.scss
style_content := '---\n---\n\n@import "{{ site.theme }}";' style_content := '---\n---\n\n@import "{{ site.theme }}";'
os.write_file('docs/assets/css/style.scss', style_content) or { os.write_file('docs/assets/css/style.scss', style_content) or {
panic('Failed to create style.scss: ${err}') panic('Failed to create style.scss: ${err}')
} }
// Create _config.yml // Create _config.yml
@@ -94,7 +87,7 @@ exclude:
- vendor/ruby/' - vendor/ruby/'
os.write_file('docs/_config.yml', config_content) or { os.write_file('docs/_config.yml', config_content) or {
panic('Failed to create _config.yml: ${err}') panic('Failed to create _config.yml: ${err}')
} }
println('Documentation generation completed successfully!') println('Documentation generation completed successfully!')

View File

@@ -4,46 +4,45 @@ import os
import flag import flag
fn addtoscript(tofind string, toadd string) ! { fn addtoscript(tofind string, toadd string) ! {
home_dir := os.home_dir() home_dir := os.home_dir()
mut rc_file := '${home_dir}/.zshrc' mut rc_file := '${home_dir}/.zshrc'
if !os.exists(rc_file) { if !os.exists(rc_file) {
rc_file = '${home_dir}/.bashrc' rc_file = '${home_dir}/.bashrc'
if !os.exists(rc_file) { if !os.exists(rc_file) {
return error('No .zshrc or .bashrc found in home directory') return error('No .zshrc or .bashrc found in home directory')
} }
} }
// Read current content // Read current content
mut content := os.read_file(rc_file)! mut content := os.read_file(rc_file)!
// Remove existing alias if present
lines := content.split('\n')
mut new_lines := []string{}
mut prev_is_emtpy := false
for line in lines {
if prev_is_emtpy {
if line.trim_space() == ""{
continue
}else{
prev_is_emtpy = false
}
}
if line.trim_space() == ""{
prev_is_emtpy = true
}
if !line.contains(tofind) { // Remove existing alias if present
new_lines << line lines := content.split('\n')
} mut new_lines := []string{}
} mut prev_is_emtpy := false
new_lines << toadd for line in lines {
new_lines << "" if prev_is_emtpy {
// Write back to file if line.trim_space() == '' {
new_content := new_lines.join('\n') continue
os.write_file(rc_file, new_content)! } else {
prev_is_emtpy = false
}
}
if line.trim_space() == '' {
prev_is_emtpy = true
}
if !line.contains(tofind) {
new_lines << line
}
}
new_lines << toadd
new_lines << ''
// Write back to file
new_content := new_lines.join('\n')
os.write_file(rc_file, new_content)!
} }
vroot := @VROOT vroot := @VROOT
abs_dir_of_script := dir(@FILE) abs_dir_of_script := dir(@FILE)
@@ -52,20 +51,20 @@ println('Resetting all symlinks...')
os.rm('${os.home_dir()}/.vmodules/freeflowuniverse/herolib') or {} os.rm('${os.home_dir()}/.vmodules/freeflowuniverse/herolib') or {}
// Create necessary directories // Create necessary directories
os.mkdir_all('${os.home_dir()}/.vmodules/freeflowuniverse') or { os.mkdir_all('${os.home_dir()}/.vmodules/freeflowuniverse') or {
panic('Failed to create directory ~/.vmodules/freeflowuniverse: ${err}') panic('Failed to create directory ~/.vmodules/freeflowuniverse: ${err}')
} }
// Create new symlinks // Create new symlinks
os.symlink('${abs_dir_of_script}/lib', '${os.home_dir()}/.vmodules/freeflowuniverse/herolib') or { os.symlink('${abs_dir_of_script}/lib', '${os.home_dir()}/.vmodules/freeflowuniverse/herolib') or {
panic('Failed to create herolib symlink: ${err}') panic('Failed to create herolib symlink: ${err}')
} }
println('Herolib installation completed successfully!') println('Herolib installation completed successfully!')
// Add vtest alias // Add vtest alias
addtoscript('alias vtest=', 'alias vtest=\'v -stats -enable-globals -n -w -cg -gc none -cc tcc test\' ') or { addtoscript('alias vtest=', "alias vtest='v -stats -enable-globals -n -w -cg -gc none -cc tcc test' ") or {
eprintln('Failed to add vtest alias: ${err}') eprintln('Failed to add vtest alias: ${err}')
} }
println('Added vtest alias to shell configuration') println('Added vtest alias to shell configuration')

View File

@@ -5,9 +5,9 @@ import freeflowuniverse.herolib.web.ui
fn main() { fn main() {
println('Starting UI test server on port 8080...') println('Starting UI test server on port 8080...')
println('Visit http://localhost:8080 to see the admin interface') println('Visit http://localhost:8080 to see the admin interface')
ui.start( ui.start(
title: 'Test Admin Panel' title: 'Test Admin Panel'
port: 8080 port: 8080
)! )!
} }

View File

@@ -10,41 +10,39 @@ fp.version('v0.1.0')
fp.description('Generate code') fp.description('Generate code')
fp.skip_executable() fp.skip_executable()
mut path := fp.string('path', `p`, "", 'Path where to generate a module, if not mentioned will scan over all installers & clients.\nif . then will be path we are on.') mut path := fp.string('path', `p`, '', 'Path where to generate a module, if not mentioned will scan over all installers & clients.\nif . then will be path we are on.')
reset := fp.bool('reset', `r`, false, 'If we want to reset') reset := fp.bool('reset', `r`, false, 'If we want to reset')
interactive := fp.bool('interactive', `i`, false, 'If we want to work interactive') interactive := fp.bool('interactive', `i`, false, 'If we want to work interactive')
scan := fp.bool('scan', `s`, false, 'If we want to scan') scan := fp.bool('scan', `s`, false, 'If we want to scan')
help_requested := fp.bool('help', `h`, false, 'Show help message') help_requested := fp.bool('help', `h`, false, 'Show help message')
if help_requested { if help_requested {
println(fp.usage()) println(fp.usage())
exit(0) exit(0)
} }
additional_args := fp.finalize() or { additional_args := fp.finalize() or {
eprintln(err) eprintln(err)
println(fp.usage()) println(fp.usage())
exit(1) exit(1)
} }
if additional_args.len > 0 { if additional_args.len > 0 {
eprintln('Unexpected arguments: ${additional_args.join(' ')}') eprintln('Unexpected arguments: ${additional_args.join(' ')}')
println(fp.usage()) println(fp.usage())
exit(1) exit(1)
} }
// reset bool // regenerate all, dangerous !!! // reset bool // regenerate all, dangerous !!!
// interactive bool //if we want to ask // interactive bool //if we want to ask
// path string // path string
if path.trim_space() == '.' {
if path.trim_space() == "." {
path = os.getwd() path = os.getwd()
} }
if ! scan { if !scan {
generator.do(path:path, reset:reset, interactive:interactive)! generator.do(path: path, reset: reset, interactive: interactive)!
}else{ } else {
generator.scan(path:path, reset:reset, interactive:interactive)! generator.scan(path: path, reset: reset, interactive: interactive)!
} }

View File

@@ -4,46 +4,45 @@ import os
import flag import flag
fn addtoscript(tofind string, toadd string) ! { fn addtoscript(tofind string, toadd string) ! {
home_dir := os.home_dir() home_dir := os.home_dir()
mut rc_file := '${home_dir}/.zshrc' mut rc_file := '${home_dir}/.zshrc'
if !os.exists(rc_file) { if !os.exists(rc_file) {
rc_file = '${home_dir}/.bashrc' rc_file = '${home_dir}/.bashrc'
if !os.exists(rc_file) { if !os.exists(rc_file) {
return error('No .zshrc or .bashrc found in home directory') return error('No .zshrc or .bashrc found in home directory')
} }
} }
// Read current content // Read current content
mut content := os.read_file(rc_file)! mut content := os.read_file(rc_file)!
// Remove existing alias if present
lines := content.split('\n')
mut new_lines := []string{}
mut prev_is_emtpy := false
for line in lines {
if prev_is_emtpy {
if line.trim_space() == ""{
continue
}else{
prev_is_emtpy = false
}
}
if line.trim_space() == ""{
prev_is_emtpy = true
}
if !line.contains(tofind) { // Remove existing alias if present
new_lines << line lines := content.split('\n')
} mut new_lines := []string{}
} mut prev_is_emtpy := false
new_lines << toadd for line in lines {
new_lines << "" if prev_is_emtpy {
// Write back to file if line.trim_space() == '' {
new_content := new_lines.join('\n') continue
os.write_file(rc_file, new_content)! } else {
prev_is_emtpy = false
}
}
if line.trim_space() == '' {
prev_is_emtpy = true
}
if !line.contains(tofind) {
new_lines << line
}
}
new_lines << toadd
new_lines << ''
// Write back to file
new_content := new_lines.join('\n')
os.write_file(rc_file, new_content)!
} }
vroot := @VROOT vroot := @VROOT
abs_dir_of_script := dir(@FILE) abs_dir_of_script := dir(@FILE)
@@ -52,29 +51,29 @@ println('Resetting all symlinks...')
os.rm('${os.home_dir()}/.vmodules/freeflowuniverse/herolib') or {} os.rm('${os.home_dir()}/.vmodules/freeflowuniverse/herolib') or {}
// Create necessary directories // Create necessary directories
os.mkdir_all('${os.home_dir()}/.vmodules/freeflowuniverse') or { os.mkdir_all('${os.home_dir()}/.vmodules/freeflowuniverse') or {
panic('Failed to create directory ~/.vmodules/freeflowuniverse: ${err}') panic('Failed to create directory ~/.vmodules/freeflowuniverse: ${err}')
} }
// Create new symlinks // Create new symlinks
os.symlink('${abs_dir_of_script}/lib', '${os.home_dir()}/.vmodules/freeflowuniverse/herolib') or { os.symlink('${abs_dir_of_script}/lib', '${os.home_dir()}/.vmodules/freeflowuniverse/herolib') or {
panic('Failed to create herolib symlink: ${err}') panic('Failed to create herolib symlink: ${err}')
} }
println('Herolib installation completed successfully!') println('Herolib installation completed successfully!')
// Add vtest alias // Add vtest alias
addtoscript('alias vtest=', 'alias vtest=\'v -stats -enable-globals -show-c-output -n -w -cg -gc none -cc tcc test\' ') or { addtoscript('alias vtest=', "alias vtest='v -stats -enable-globals -show-c-output -n -w -cg -gc none -cc tcc test' ") or {
eprintln('Failed to add vtest alias: ${err}') eprintln('Failed to add vtest alias: ${err}')
} }
// Add vrun alias // Add vrun alias
addtoscript('alias vrun=', 'alias vrun=\'v -stats -enable-globals -show-c-output -n -w -cg -gc none -cc tcc run\' ') or { addtoscript('alias vrun=', "alias vrun='v -stats -enable-globals -show-c-output -n -w -cg -gc none -cc tcc run' ") or {
eprintln('Failed to add vrun alias: ${err}') eprintln('Failed to add vrun alias: ${err}')
} }
addtoscript('HOME/hero/bin', 'export PATH="\$PATH:\$HOME/hero/bin"') or { addtoscript('HOME/hero/bin', 'export PATH="\$PATH:\$HOME/hero/bin"') or {
eprintln('Failed to add path to hero, ${err}') eprintln('Failed to add path to hero, ${err}')
} }
// ulimit -n 32000 // ulimit -n 32000

View File

@@ -7,6 +7,6 @@ import os
// your checking & initialization code if needed // your checking & initialization code if needed
fn (mut ws RepromptWorkspace) reprompt() !string { fn (mut ws RepromptWorkspace) reprompt() !string {
//TODO: fill in template based on selection // TODO: fill in template based on selection
return "" return ''
} }

View File

@@ -24,7 +24,6 @@ pub mut:
selections []string // paths selected in the RepromptDir selections []string // paths selected in the RepromptDir
} }
// your checking & initialization code if needed // your checking & initialization code if needed
fn obj_init(mycfg_ RepromptWorkspace) !RepromptWorkspace { fn obj_init(mycfg_ RepromptWorkspace) !RepromptWorkspace {
mut mycfg := mycfg_ mut mycfg := mycfg_
@@ -37,13 +36,13 @@ fn obj_init(mycfg_ RepromptWorkspace) !RepromptWorkspace {
/////////////NORMALLY NO NEED TO TOUCH /////////////NORMALLY NO NEED TO TOUCH
pub fn heroscript_dumps(obj RepromptWorkspace) !string { pub fn heroscript_dumps(obj RepromptWorkspace) !string {
//create heroscript following template // create heroscript following template
//check for our homedir on our machine and replace in the heroscript to @HOME in path // check for our homedir on our machine and replace in the heroscript to @HOME in path
return encoderhero.encode[RepromptWorkspace](obj)! return encoderhero.encode[RepromptWorkspace](obj)!
} }
pub fn heroscript_loads(heroscript string) !RepromptWorkspace { pub fn heroscript_loads(heroscript string) !RepromptWorkspace {
//TODO: parse heroscript populate RepromptWorkspace // TODO: parse heroscript populate RepromptWorkspace
mut obj := encoderhero.decode[RepromptWorkspace](heroscript)! mut obj := encoderhero.decode[RepromptWorkspace](heroscript)!
return obj return obj
} }

View File

@@ -5,6 +5,7 @@ import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.web.docusaurus import freeflowuniverse.herolib.web.docusaurus
import os import os
import cli { Command, Flag } import cli { Command, Flag }
import freeflowuniverse.herolib.core.playbook
pub fn cmd_docusaurus(mut cmdroot Command) Command { pub fn cmd_docusaurus(mut cmdroot Command) Command {
mut cmd_run := Command{ mut cmd_run := Command{
@@ -113,94 +114,98 @@ pub fn cmd_docusaurus(mut cmdroot Command) Command {
// description: 'create a new docusaurus site.' // description: 'create a new docusaurus site.'
// }) // })
cmd_run.add_flag(Flag{
flag: .bool
required: false
name: 'reset'
abbrev: 'r'
description: 'reset the docusaurus building process, reinstall all.'
})
cmdroot.add_command(cmd_run) cmdroot.add_command(cmd_run)
return cmdroot return cmdroot
} }
fn cmd_docusaurus_execute(cmd Command) ! { fn cmd_docusaurus_execute(cmd Command) ! {
// ---------- FLAGS ----------
mut open := cmd.flags.get_bool('open') or { false } mut open := cmd.flags.get_bool('open') or { false }
mut buildpublish := cmd.flags.get_bool('buildpublish') or { false } mut buildpublish := cmd.flags.get_bool('buildpublish') or { false }
mut builddevpublish := cmd.flags.get_bool('builddevpublish') or { false } mut builddevpublish := cmd.flags.get_bool('builddevpublish') or { false }
mut dev := cmd.flags.get_bool('dev') or { false } mut dev := cmd.flags.get_bool('dev') or { false }
mut new := cmd.flags.get_bool('new') or { false }
mut reset := cmd.flags.get_bool('reset') or { false } mut reset := cmd.flags.get_bool('reset') or { false }
// (the earlier duplicate reset flag has been removed)
// --- Build Path Logic --- // ---------- PATH LOGIC ----------
mut build_path := cmd.flags.get_string('buildpath') or { '' } // Resolve the source directory that contains a cfg subdirectory.
if build_path == '' { mut path := cmd.flags.get_string('path') or { '' }
build_path = '${os.home_dir()}/hero/var/docusaurus'
}
// --- Path Logic ---
mut provided_path := cmd.flags.get_string('path') or { '' }
mut source_path := '' mut source_path := ''
if path != '' {
if provided_path != '' { // user supplied a path
if !os.exists(provided_path) || !os.is_dir(provided_path) { if !os.exists(path) || !os.is_dir(path) {
return error('Provided path "${provided_path}" does not exist or is not a directory.') return error('Provided path "${path}" does not exist or is not a directory.')
} }
cfg_subdir := os.join_path(path, 'cfg')
// Check if the provided path contains a cfg subdirectory (ebook directory structure) source_path = if os.exists(cfg_subdir) && os.is_dir(cfg_subdir) {
cfg_subdir := os.join_path(provided_path, 'cfg') path
if os.exists(cfg_subdir) && os.is_dir(cfg_subdir) { } else if path.ends_with('cfg') {
source_path = provided_path os.dir(path)
} else { } else {
if provided_path.ends_with('cfg') { return error('Provided path "${path}" does not contain a cfg subdirectory.')
// If path ends with cfg, use parent directory as source
source_path = os.dir(provided_path)
} else {
return error('Provided path "${provided_path}" does not contain a "cfg" subdirectory.')
}
} }
} else { } else {
mut cwd := os.getwd() // default to current working directory
cwd := os.getwd()
cfg_dir := os.join_path(cwd, 'cfg') cfg_dir := os.join_path(cwd, 'cfg')
if !os.exists(cfg_dir) || !os.is_dir(cfg_dir) { if !os.exists(cfg_dir) || !os.is_dir(cfg_dir) {
return error('Flag -path not provided and directory "./cfg" not found in the current working directory.') return error('No path supplied and "./cfg" not found in the current directory.')
} }
source_path = cwd source_path = cwd
} }
console.print_header('Running Docusaurus for: ${source_path}') console.print_header('Running Docusaurus for: ${source_path}')
// Use the centralized site processing function from docusaurus module // ---------- BUILD PLAYBOOK ----------
mysite := docusaurus.process_site_from_path(source_path, '')! // Build a PlayBook from the source directory (it contains the HeroScript actions)
site_name := mysite.siteconfig.name mut plbook := playbook.new(path: source_path)!
// Set up the docusaurus factory // If the user asked for a CLIlevel reset we inject a temporary define action
docusaurus.factory_set( // so that the underlying factory_set receives `reset:true`.
path_build: build_path if reset {
reset: reset // prepend a temporary docusaurus.define action (this is safe because the playbook
install: reset // already contains the real definitions, the extra one will just be ignored later)
template_update: reset mut reset_action := playbook.Action{
)! actor: 'docusaurus'
name: 'define'
params: {
'reset': 'true'
}
done: false
}
// Insert at the front of the action list
plbook.actions.prepend(reset_action)
}
// Add the docusaurus site // ---------- RUN DOCUSUROUS ----------
mut dsite := docusaurus.dsite_add( // This will:
sitename: site_name // * read the generic `site.*` definitions,
path: source_path // * create a Docusaurus factory (or reuse an existing one),
play: false // Site already processed // * add the site to the factory via `dsite_add`.
)! docusaurus.play(mut plbook)!
// Execute the requested action directly // After `play` we should have exactly one site in the global map.
// Retrieve it if more than one exists we pick the one whose source path matches.
mut dsite_opt := docusaurus.dsite_get(plbook.ensure_once(filter: 'site.define')!.params.get('name')!) or {
// fallback: take the first entry
if docusaurus_sites.len == 0 {
return error('No Docusaurus site was created by the playbook.')
}
docusaurus_sites.values()[0]!
}
// ---------- ACTIONS ----------
if buildpublish { if buildpublish {
dsite.build_publish()! dsite_opt.build_publish()!
} else if builddevpublish { } else if builddevpublish {
dsite.build()! dsite_opt.build()!
} else if dev { } else if dev {
dsite.dev( dsite_opt.dev(
open: open open: open
watch_changes: false watch_changes: false
)! )!
} else { } else {
dsite.build()! // default: just build the static site
dsite_opt.build()!
} }
} }

View File

@@ -1,121 +0,0 @@
module herocmds
// import freeflowuniverse.herolib.web.mdbook
import freeflowuniverse.herolib.core.pathlib
import cli { Command, Flag }
import os
import freeflowuniverse.herolib.ui.console
// path string //if location on filessytem, if exists, this has prio on git_url
// git_url string // location of where the hero scripts are
// git_pull bool // means when getting new repo will pull even when repo is already there
// git_pullreset bool // means we will force a pull and reset old content
// coderoot string //the location of coderoot if its another one
pub fn cmd_mdbook(mut cmdroot Command) {
mut cmd_mdbook := Command{
name: 'mdbook'
usage: '
## Manage your MDBooks
example:
hero mdbook -u https://git.threefold.info/tfgrid/info_tfgrid/src/branch/main/heroscript
If you do -gp it will pull newest book content from git and give error if there are local changes.
If you do -gr it will pull newest book content from git and overwrite local changes (careful).
'
description: 'create, edit, show mdbooks'
required_args: 0
execute: cmd_mdbook_execute
}
cmd_run_add_flags(mut cmd_mdbook)
cmd_mdbook.add_flag(Flag{
flag: .string
name: 'name'
abbrev: 'n'
description: 'name of the mdbook.'
})
// cmd_mdbook.add_flag(Flag{
// flag: .bool
// required: false
// name: 'edit'
// description: 'will open vscode for collections & summary.'
// })
cmd_mdbook.add_flag(Flag{
flag: .bool
required: false
name: 'open'
abbrev: 'o'
description: 'will open the generated book.'
})
mut cmd_list := Command{
sort_flags: true
name: 'list'
execute: cmd_mdbook_list
description: 'will list existing mdbooks'
}
cmd_mdbook.add_command(cmd_list)
cmdroot.add_command(cmd_mdbook)
}
fn cmd_mdbook_list(cmd Command) ! {
console.print_header('MDBooks:')
build_path := os.join_path(os.home_dir(), 'hero/var/mdbuild')
mut build_dir := pathlib.get_dir(path: build_path)!
list := build_dir.list(
recursive: false
dirs_only: true
)!
for path in list.paths {
console.print_stdout(path.name())
}
}
fn cmd_mdbook_execute(cmd Command) ! {
mut name := cmd.flags.get_string('name') or { '' }
mut url := cmd.flags.get_string('url') or { '' }
mut path := cmd.flags.get_string('path') or { '' }
if path.len > 0 || url.len > 0 {
// execute the attached plbook
mut plbook, _ := plbook_run(cmd)!
// get name from the book.generate action
if name == '' {
mut a := plbook.get(filter: 'book.define')!
name = a.params.get('name') or { '' }
}
} else {
mdbook_help(cmd)
}
if name == '' {
console.print_debug('did not find name of book to generate, check in heroscript or specify with --name')
mdbook_help(cmd)
exit(1)
}
edit := cmd.flags.get_bool('edit') or { false }
open := cmd.flags.get_bool('open') or { false }
if edit || open {
// mdbook.book_open(name)!
}
if edit {
// mdbook.book_edit(name)!
}
}
fn mdbook_help(cmd Command) {
console.clear()
console.print_header('Instructions for mdbook:')
console.print_lf(1)
console.print_stdout(cmd.help_message())
console.print_lf(5)
}

View File

@@ -1,143 +0,0 @@
module herocmds
// import freeflowuniverse.herolib.web.starlight
import os
import cli
// pub fn cmd_starlight(mut cmdroot Command) {
// mut cmd_run := Command{
// name: 'starlight'
// description: 'Generate, build, run starlight sites.'
// required_args: 0
// execute: cmd_starlight_execute
// }
// // cmd_run.add_flag(Flag{
// // flag: .bool
// // required: false
// // name: 'reset'
// // abbrev: 'r'
// // description: 'will reset.'
// // })
// cmd_run.add_flag(Flag{
// flag: .string
// required: false
// name: 'url'
// abbrev: 'u'
// // default: ''
// description: 'Url where starlight source is.'
// })
// cmd_run.add_flag(Flag{
// flag: .string
// required: false
// name: 'path'
// abbrev: 'p'
// // default: ''
// description: 'Path where starlight source is.'
// })
// cmd_run.add_flag(Flag{
// flag: .string
// required: false
// name: 'deploykey'
// abbrev: 'dk'
// // default: ''
// description: 'Path of SSH Key used to deploy.'
// })
// cmd_run.add_flag(Flag{
// flag: .string
// required: false
// name: 'publish'
// // default: ''
// description: 'Path where to publish.'
// })
// cmd_run.add_flag(Flag{
// flag: .bool
// required: false
// name: 'buildpublish'
// abbrev: 'bp'
// description: 'build and publish.'
// })
// cmd_run.add_flag(Flag{
// flag: .bool
// required: false
// name: 'builddevpublish'
// abbrev: 'bpd'
// description: 'build dev version and publish.'
// })
// cmd_run.add_flag(Flag{
// flag: .bool
// required: false
// name: 'update'
// description: 'update your environment the template and the repo you are working on (git pull).'
// })
// cmd_run.add_flag(Flag{
// flag: .bool
// required: false
// name: 'dev'
// abbrev: 'd'
// description: 'Run your dev environment on local browser.'
// })
// cmd_run.add_flag(Flag{
// flag: .bool
// required: false
// name: 'new'
// abbrev: 'n'
// description: 'create a new starlight site.'
// })
// cmdroot.add_command(cmd_run)
// }
// fn cmd_starlight_execute(cmd Command) ! {
// mut update := cmd.flags.get_bool('update') or { false }
// mut init := cmd.flags.get_bool('new') or { false }
// mut url := cmd.flags.get_string('url') or { '' }
// mut publish_path := cmd.flags.get_string('publish') or { '' }
// mut deploykey := cmd.flags.get_string('deploykey') or { '' }
// mut path := cmd.flags.get_string('path') or { '' }
// mut buildpublish := cmd.flags.get_bool('buildpublish') or { false }
// mut builddevpublish := cmd.flags.get_bool('builddevpublish') or { false }
// mut dev := cmd.flags.get_bool('dev') or { false }
// // if build== false && build== false && build== false {
// // eprintln("specify build, builddev or dev")
// // exit(1)
// // }
// mut docs := starlight.new(update: update)!
// mut site := docs.get(
// url: url
// path: path
// update: update
// publish_path: publish_path
// deploykey: deploykey
// init: init
// )!
// if publish_path.len > 0 {
// site.build()!
// }
// if buildpublish {
// site.build_publish()!
// }
// if builddevpublish {
// site.build_dev_publish()!
// }
// if dev {
// site.dev(host: 'localhost', port: 3000)!
// }
// }

View File

@@ -92,21 +92,21 @@ pub fn (mut plbook PlayBook) find(args FindArgs) ![]&Action {
return res return res
} }
//use this in play function to make sure we only have one of those actions, the one action is then returned // use this in play function to make sure we only have one of those actions, the one action is then returned
pub fn (mut plbook PlayBook) ensure_once(args FindArgs) !&Action { pub fn (mut plbook PlayBook) ensure_once(args FindArgs) !&Action {
mut res := plbook.find(args) or { [] } mut res := plbook.find(args) or { [] }
if res.len == 0 { if res.len == 0 {
return error('No actions found based on filter: ${args.filter}') return error('No actions found based on filter: ${args.filter}')
} }
if res.len > 1 { if res.len > 1 {
return error("More than 1 action found based on filter: ${args.filter}, this Playbook only supports 1.") return error('More than 1 action found based on filter: ${args.filter}, this Playbook only supports 1.')
} }
return res[0] or { panic('bug') } return res[0] or { panic('bug') }
} }
//check its once, if not say that playbook only can have one action // check its once, if not say that playbook only can have one action
pub fn (mut plbook PlayBook)exists_once (args FindArgs) bool { pub fn (mut plbook PlayBook) exists_once(args FindArgs) bool {
mut res := plbook.find(args) or { [] } mut res := plbook.find(args) or { [] }
return res.len == 1 return res.len == 1
} }

View File

@@ -21,27 +21,27 @@ pub mut:
} }
pub fn run(args_ PlayArgs) ! { pub fn run(args_ PlayArgs) ! {
mut args := args_ mut args := args_
mut plbook := args.plbook or { mut plbook := args.plbook or {
playbook.new(text: args.heroscript, path: args.heroscript_path)! playbook.new(text: args.heroscript, path: args.heroscript_path)!
} }
// Core actions // Core actions
play_core(mut plbook)! play_core(mut plbook)!
// Git actions // Git actions
play_git(mut plbook)! play_git(mut plbook)!
// Business model (e.g. currency, bizmodel) // Business model (e.g. currency, bizmodel)
bizmodel.play(mut plbook)! bizmodel.play(mut plbook)!
// OpenAI client // OpenAI client
openai.play(mut plbook)! openai.play(mut plbook)!
// Website / docs // Website / docs
site.play(mut plbook)! site.play(mut plbook)!
doctree.play(mut plbook)! doctree.play(mut plbook)!
docusaurus.play(mut plbook)! docusaurus.play(mut plbook)!
// Ensure we did not leave any actions unprocessed // Ensure we did not leave any actions unprocessed
plbook.empty_check()! plbook.empty_check()!
} }

View File

@@ -46,7 +46,7 @@ pub fn (mut site DocSite) generate() ! {
mut aa := site.path_src.dir_get('docs')! mut aa := site.path_src.dir_get('docs')!
aa.copy(dest: '${f.path_build.path}/docs', delete: true)! aa.copy(dest: '${f.path_build.path}/docs', delete: true)!
} }
mut main_file := pathlib.get_file(path: '${cfg_path}/main.json', create: true)! mut main_file := pathlib.get_file(path: '${cfg_path}/main.json', create: true)!
main_file.write(json.encode_pretty(site.config.main))! main_file.write(json.encode_pretty(site.config.main))!
@@ -56,11 +56,10 @@ pub fn (mut site DocSite) generate() ! {
mut footer_file := pathlib.get_file(path: '${cfg_path}/footer.json', create: true)! mut footer_file := pathlib.get_file(path: '${cfg_path}/footer.json', create: true)!
footer_file.write(json.encode_pretty(site.config.footer))! footer_file.write(json.encode_pretty(site.config.footer))!
// Generate the actual docs content from the processed site configuration // Generate the actual docs content from the processed site configuration
docs_path := '${f.path_build.path}/docs' docs_path := '${f.path_build.path}/docs'
//TODO: check site vs website // TODO: check site vs website
website := site.website website := site.website
generate_docs( generate_docs(
path: docs_path path: docs_path
@@ -72,11 +71,12 @@ pub fn (mut site DocSite) generate() ! {
pub fn (mut site DocSite) process_imports() ! { pub fn (mut site DocSite) process_imports() ! {
mut gs := gittools.new()! mut gs := gittools.new()!
mut f:=factory_get()! mut f := factory_get()!
for item in site.website.siteconfig.imports { for item in site.website.siteconfig.imports {
if true {
if true{panic("not implemented import")} panic('not implemented import')
}
mypath := gs.get_path( mypath := gs.get_path(
pull: false pull: false
@@ -88,7 +88,7 @@ pub fn (mut site DocSite) process_imports() ! {
mypatho.copy(dest: '${f.path_build.path}/docs/${item.dest}', delete: false)! mypatho.copy(dest: '${f.path_build.path}/docs/${item.dest}', delete: false)!
println(item) println(item)
//replace: {'NAME': 'MyName', 'URGENCY': 'red'} // replace: {'NAME': 'MyName', 'URGENCY': 'red'}
mut ri := regext.regex_instructions_new() mut ri := regext.regex_instructions_new()
for key, val in item.replace { for key, val in item.replace {
ri.add_item('\{${key}\}', val)! ri.add_item('\{${key}\}', val)!

View File

@@ -8,8 +8,6 @@ import freeflowuniverse.herolib.web.site
import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.ui.console
import freeflowuniverse.herolib.osal.core as osal import freeflowuniverse.herolib.osal.core as osal
@[params] @[params]
pub struct AddArgs { pub struct AddArgs {
pub mut: pub mut:
@@ -71,7 +69,7 @@ pub fn dsite_add(args_ AddArgs) !&DocSite {
// Get the site object after processing, this is the website which is a generic definition of a site // Get the site object after processing, this is the website which is a generic definition of a site
mut website := site.get(name: args.sitename)! mut website := site.get(name: args.sitename)!
// Create the DocSite instance // Create the DocSite instance
mut dsite := &DocSite{ mut dsite := &DocSite{
name: args.sitename name: args.sitename

View File

@@ -15,7 +15,7 @@ mut:
client &doctreeclient.DocTreeClient client &doctreeclient.DocTreeClient
flat bool // if flat then won't use sitenames as subdir's flat bool // if flat then won't use sitenames as subdir's
site Site site Site
errors []string // collect errors here errors []string // collect errors here
} }
@[params] @[params]
@@ -23,7 +23,7 @@ struct SiteGeneratorArgs {
mut: mut:
path string path string
flat bool // if flat then won't use sitenames as subdir's flat bool // if flat then won't use sitenames as subdir's
site Site //this is the generic website we are feeding site Site // this is the generic website we are feeding
} }
// Generate docs from site configuration // Generate docs from site configuration
@@ -51,16 +51,13 @@ pub fn generate_docs(args SiteGeneratorArgs) ! {
if gen.errors.len > 0 { if gen.errors.len > 0 {
return error('Errors occurred during site generation:\n${gen.errors.join('\n\n')}\nPlease fix the errors and try again.\nPage List: is header collection and page name per collection.\nAvailable pages:\n${gen.client.list_markdown()!}') return error('Errors occurred during site generation:\n${gen.errors.join('\n\n')}\nPlease fix the errors and try again.\nPage List: is header collection and page name per collection.\nAvailable pages:\n${gen.client.list_markdown()!}')
} }
} }
fn (mut mysite SiteGenerator) error( msg string) ! { fn (mut mysite SiteGenerator) error(msg string) ! {
console.print_stderr('Error: ${msg}') console.print_stderr('Error: ${msg}')
mysite.errors << msg mysite.errors << msg
} }
fn (mut mysite SiteGenerator) page_generate(args_ Page) ! { fn (mut mysite SiteGenerator) page_generate(args_ Page) ! {
mut args := args_ mut args := args_
@@ -69,7 +66,7 @@ fn (mut mysite SiteGenerator) page_generate(args_ Page) ! {
mut parts := args.src.split(':') mut parts := args.src.split(':')
if parts.len != 2 { if parts.len != 2 {
mysite.error("Invalid src format for page '${args.src}', expected format: collection:page_name, TODO: fix in ${args.path}, check the collection & page_name exists in the pagelist")! mysite.error("Invalid src format for page '${args.src}', expected format: collection:page_name, TODO: fix in ${args.path}, check the collection & page_name exists in the pagelist")!
return return
} }
collection_name := parts[0] collection_name := parts[0]
page_name := parts[1] page_name := parts[1]
@@ -129,7 +126,7 @@ fn (mut mysite SiteGenerator) page_generate(args_ Page) ! {
c += '\n${page_content}\n' c += '\n${page_content}\n'
if args.path.ends_with('/') || args.path.trim_space()=="" { if args.path.ends_with('/') || args.path.trim_space() == '' {
// means is dir // means is dir
args.path += page_name args.path += page_name
} }

View File

@@ -4,7 +4,6 @@ import freeflowuniverse.herolib.core.playbook { PlayBook }
import freeflowuniverse.herolib.web.site import freeflowuniverse.herolib.web.site
pub fn play(mut plbook PlayBook) ! { pub fn play(mut plbook PlayBook) ! {
if !plbook.exists(filter: 'docusaurus.') { if !plbook.exists(filter: 'docusaurus.') {
return return
} }
@@ -36,9 +35,9 @@ pub fn play(mut plbook PlayBook) ! {
dsite_add( dsite_add(
sitename: site_name sitename: site_name
path: p.get_default('path', '')! path: p.get_default('path', '')!
git_url: p.get_default('git_url','')! git_url: p.get_default('git_url', '')!
git_reset: p.get_default_false('git_reset') git_reset: p.get_default_false('git_reset')
git_root: p.get_default('git_root','')! git_root: p.get_default('git_root', '')!
git_pull: p.get_default_false('git_pull') git_pull: p.get_default_false('git_pull')
path_publish: p.get_default('path_publish', f.path_publish.path)! path_publish: p.get_default('path_publish', f.path_publish.path)!
)! )!

View File

@@ -1,11 +1,11 @@
module site module site
import freeflowuniverse.herolib.core.playbook { Action, PlayBook } import freeflowuniverse.herolib.core.playbook { PlayBook }
import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.core.texttools
import time import time
pub fn play(mut plbook PlayBook) ! { pub fn play(mut plbook PlayBook) ! {
if !plbook.exists(filter: 'site.'){ if !plbook.exists(filter: 'site.') {
return return
} }
@@ -14,7 +14,7 @@ pub fn play(mut plbook PlayBook) ! {
mut p := config_action.params mut p := config_action.params
name := p.get_default('name', 'default')! // Use 'default' as fallback name name := p.get_default('name', 'default')! // Use 'default' as fallback name
//configure the website // configure the website
mut website := new(name: name)! mut website := new(name: name)!
mut config := &website.siteconfig mut config := &website.siteconfig
@@ -30,7 +30,6 @@ pub fn play(mut plbook PlayBook) ! {
config.base_url = p.get_default('base_url', '/')! config.base_url = p.get_default('base_url', '/')!
config.url_home = p.get_default('url_home', '')! config.url_home = p.get_default('url_home', '')!
// Process !!site.config_meta for specific metadata overrides // Process !!site.config_meta for specific metadata overrides
mut meta_action := plbook.ensure_once(filter: 'site.config_meta')! mut meta_action := plbook.ensure_once(filter: 'site.config_meta')!
mut p_meta := meta_action.params mut p_meta := meta_action.params
@@ -53,10 +52,8 @@ pub fn play(mut plbook PlayBook) ! {
play_build_dest_dev(mut plbook, mut config)! play_build_dest_dev(mut plbook, mut config)!
play_pages(mut plbook, mut website)! play_pages(mut plbook, mut website)!
} }
fn play_import(mut plbook PlayBook, mut config SiteConfig) ! { fn play_import(mut plbook PlayBook, mut config SiteConfig) ! {
mut import_actions := plbook.find(filter: 'site.import')! mut import_actions := plbook.find(filter: 'site.import')!
// println('import_actions: ${import_actions}') // println('import_actions: ${import_actions}')

View File

@@ -81,103 +81,89 @@ pub fn start(args FactoryArgs) ! {
// Routes // Routes
// Redirect root to /admin // Redirect root to /admin
@[get; '/'] @['/'; get]
pub fn (app &App) root(mut ctx Context) veb.Result { pub fn (app &App) root(mut ctx Context) veb.Result {
return ctx.redirect('/admin') return ctx.redirect('/admin')
} }
// Admin home page // Admin home page
@[get; '/admin'] @['/admin'; get]
pub fn (app &App) admin_index(mut ctx Context) veb.Result { pub fn (app &App) admin_index(mut ctx Context) veb.Result {
return ctx.html(app.render_admin('/', 'Welcome')) return ctx.html(app.render_admin('/', 'Welcome'))
} }
// HeroScript editor page // HeroScript editor page
@[get; '/admin/heroscript'] @['/admin/heroscript'; get]
pub fn (app &App) admin_heroscript(mut ctx Context) veb.Result { pub fn (app &App) admin_heroscript(mut ctx Context) veb.Result {
return ctx.html(app.render_heroscript()) return ctx.html(app.render_heroscript())
} }
// Chat page // Chat page
@[get; '/admin/chat'] @['/admin/chat'; get]
pub fn (app &App) admin_chat(mut ctx Context) veb.Result { pub fn (app &App) admin_chat(mut ctx Context) veb.Result {
return ctx.html(app.render_chat()) return ctx.html(app.render_chat())
} }
// Static CSS files // Static CSS files
@[get; '/static/css/colors.css'] @['/static/css/colors.css'; get]
pub fn (app &App) serve_colors_css(mut ctx Context) veb.Result { pub fn (app &App) serve_colors_css(mut ctx Context) veb.Result {
css_path := os.join_path(os.dir(@FILE), 'templates', 'css', 'colors.css') css_path := os.join_path(os.dir(@FILE), 'templates', 'css', 'colors.css')
css_content := os.read_file(css_path) or { css_content := os.read_file(css_path) or { return ctx.text('/* CSS file not found */') }
return ctx.text('/* CSS file not found */')
}
ctx.set_content_type('text/css') ctx.set_content_type('text/css')
return ctx.text(css_content) return ctx.text(css_content)
} }
@[get; '/static/css/main.css'] @['/static/css/main.css'; get]
pub fn (app &App) serve_main_css(mut ctx Context) veb.Result { pub fn (app &App) serve_main_css(mut ctx Context) veb.Result {
css_path := os.join_path(os.dir(@FILE), 'templates', 'css', 'main.css') css_path := os.join_path(os.dir(@FILE), 'templates', 'css', 'main.css')
css_content := os.read_file(css_path) or { css_content := os.read_file(css_path) or { return ctx.text('/* CSS file not found */') }
return ctx.text('/* CSS file not found */')
}
ctx.set_content_type('text/css') ctx.set_content_type('text/css')
return ctx.text(css_content) return ctx.text(css_content)
} }
// Static JS files // Static JS files
@[get; '/static/js/theme.js'] @['/static/js/theme.js'; get]
pub fn (app &App) serve_theme_js(mut ctx Context) veb.Result { pub fn (app &App) serve_theme_js(mut ctx Context) veb.Result {
js_path := os.join_path(os.dir(@FILE), 'templates', 'js', 'theme.js') js_path := os.join_path(os.dir(@FILE), 'templates', 'js', 'theme.js')
js_content := os.read_file(js_path) or { js_content := os.read_file(js_path) or { return ctx.text('/* JS file not found */') }
return ctx.text('/* JS file not found */')
}
ctx.set_content_type('application/javascript') ctx.set_content_type('application/javascript')
return ctx.text(js_content) return ctx.text(js_content)
} }
@[get; '/static/js/heroscript.js'] @['/static/js/heroscript.js'; get]
pub fn (app &App) serve_heroscript_js(mut ctx Context) veb.Result { pub fn (app &App) serve_heroscript_js(mut ctx Context) veb.Result {
js_path := os.join_path(os.dir(@FILE), 'templates', 'js', 'heroscript.js') js_path := os.join_path(os.dir(@FILE), 'templates', 'js', 'heroscript.js')
js_content := os.read_file(js_path) or { js_content := os.read_file(js_path) or { return ctx.text('/* JS file not found */') }
return ctx.text('/* JS file not found */')
}
ctx.set_content_type('application/javascript') ctx.set_content_type('application/javascript')
return ctx.text(js_content) return ctx.text(js_content)
} }
@[get; '/static/js/chat.js'] @['/static/js/chat.js'; get]
pub fn (app &App) serve_chat_js(mut ctx Context) veb.Result { pub fn (app &App) serve_chat_js(mut ctx Context) veb.Result {
js_path := os.join_path(os.dir(@FILE), 'templates', 'js', 'chat.js') js_path := os.join_path(os.dir(@FILE), 'templates', 'js', 'chat.js')
js_content := os.read_file(js_path) or { js_content := os.read_file(js_path) or { return ctx.text('/* JS file not found */') }
return ctx.text('/* JS file not found */')
}
ctx.set_content_type('application/javascript') ctx.set_content_type('application/javascript')
return ctx.text(js_content) return ctx.text(js_content)
} }
@[get; '/static/css/heroscript.css'] @['/static/css/heroscript.css'; get]
pub fn (app &App) serve_heroscript_css(mut ctx Context) veb.Result { pub fn (app &App) serve_heroscript_css(mut ctx Context) veb.Result {
css_path := os.join_path(os.dir(@FILE), 'templates', 'css', 'heroscript.css') css_path := os.join_path(os.dir(@FILE), 'templates', 'css', 'heroscript.css')
css_content := os.read_file(css_path) or { css_content := os.read_file(css_path) or { return ctx.text('/* CSS file not found */') }
return ctx.text('/* CSS file not found */')
}
ctx.set_content_type('text/css') ctx.set_content_type('text/css')
return ctx.text(css_content) return ctx.text(css_content)
} }
@[get; '/static/css/chat.css'] @['/static/css/chat.css'; get]
pub fn (app &App) serve_chat_css(mut ctx Context) veb.Result { pub fn (app &App) serve_chat_css(mut ctx Context) veb.Result {
css_path := os.join_path(os.dir(@FILE), 'templates', 'css', 'chat.css') css_path := os.join_path(os.dir(@FILE), 'templates', 'css', 'chat.css')
css_content := os.read_file(css_path) or { css_content := os.read_file(css_path) or { return ctx.text('/* CSS file not found */') }
return ctx.text('/* CSS file not found */')
}
ctx.set_content_type('text/css') ctx.set_content_type('text/css')
return ctx.text(css_content) return ctx.text(css_content)
} }
// Catch-all content under /admin/* // Catch-all content under /admin/*
@[get; '/admin/:path...'] @['/admin/:path...'; get]
pub fn (app &App) admin_section(mut ctx Context, path string) veb.Result { pub fn (app &App) admin_section(mut ctx Context, path string) veb.Result {
// Render current path in the main content // Render current path in the main content
return ctx.html(app.render_admin(path, 'Content')) return ctx.html(app.render_admin(path, 'Content'))
@@ -188,16 +174,16 @@ pub fn (app &App) admin_section(mut ctx Context, path string) veb.Result {
fn (app &App) render_admin(path string, heading string) string { fn (app &App) render_admin(path string, heading string) string {
// Get the template file path relative to the module // Get the template file path relative to the module
template_path := os.join_path(os.dir(@FILE), 'templates', 'admin_layout.html') template_path := os.join_path(os.dir(@FILE), 'templates', 'admin_layout.html')
// Read the template file // Read the template file
template_content := os.read_file(template_path) or { template_content := os.read_file(template_path) or {
// Fallback to inline template if file not found // Fallback to inline template if file not found
return app.render_admin_fallback(path, heading) return app.render_admin_fallback(path, heading)
} }
// Generate menu HTML // Generate menu HTML
menu_content := menu_html(app.menu, 0, 'm') menu_content := menu_html(app.menu, 0, 'm')
// Simple template variable replacement // Simple template variable replacement
mut result := template_content mut result := template_content
result = result.replace('{{.title}}', app.title) result = result.replace('{{.title}}', app.title)
@@ -207,7 +193,7 @@ fn (app &App) render_admin(path string, heading string) string {
result = result.replace('{{.css_colors_url}}', '/static/css/colors.css') result = result.replace('{{.css_colors_url}}', '/static/css/colors.css')
result = result.replace('{{.css_main_url}}', '/static/css/main.css') result = result.replace('{{.css_main_url}}', '/static/css/main.css')
result = result.replace('{{.js_theme_url}}', '/static/js/theme.js') result = result.replace('{{.js_theme_url}}', '/static/js/theme.js')
return result return result
} }
@@ -215,16 +201,16 @@ fn (app &App) render_admin(path string, heading string) string {
fn (app &App) render_heroscript() string { fn (app &App) render_heroscript() string {
// Get the template file path relative to the module // Get the template file path relative to the module
template_path := os.join_path(os.dir(@FILE), 'templates', 'heroscript_editor.html') template_path := os.join_path(os.dir(@FILE), 'templates', 'heroscript_editor.html')
// Read the template file // Read the template file
template_content := os.read_file(template_path) or { template_content := os.read_file(template_path) or {
// Fallback to basic template if file not found // Fallback to basic template if file not found
return app.render_heroscript_fallback() return app.render_heroscript_fallback()
} }
// Generate menu HTML // Generate menu HTML
menu_content := menu_html(app.menu, 0, 'm') menu_content := menu_html(app.menu, 0, 'm')
// Simple template variable replacement // Simple template variable replacement
mut result := template_content mut result := template_content
result = result.replace('{{.title}}', app.title) result = result.replace('{{.title}}', app.title)
@@ -234,7 +220,7 @@ fn (app &App) render_heroscript() string {
result = result.replace('{{.css_heroscript_url}}', '/static/css/heroscript.css') result = result.replace('{{.css_heroscript_url}}', '/static/css/heroscript.css')
result = result.replace('{{.js_theme_url}}', '/static/js/theme.js') result = result.replace('{{.js_theme_url}}', '/static/js/theme.js')
result = result.replace('{{.js_heroscript_url}}', '/static/js/heroscript.js') result = result.replace('{{.js_heroscript_url}}', '/static/js/heroscript.js')
return result return result
} }
@@ -242,16 +228,16 @@ fn (app &App) render_heroscript() string {
fn (app &App) render_chat() string { fn (app &App) render_chat() string {
// Get the template file path relative to the module // Get the template file path relative to the module
template_path := os.join_path(os.dir(@FILE), 'templates', 'chat.html') template_path := os.join_path(os.dir(@FILE), 'templates', 'chat.html')
// Read the template file // Read the template file
template_content := os.read_file(template_path) or { template_content := os.read_file(template_path) or {
// Fallback to basic template if file not found // Fallback to basic template if file not found
return app.render_chat_fallback() return app.render_chat_fallback()
} }
// Generate menu HTML // Generate menu HTML
menu_content := menu_html(app.menu, 0, 'm') menu_content := menu_html(app.menu, 0, 'm')
// Simple template variable replacement // Simple template variable replacement
mut result := template_content mut result := template_content
result = result.replace('{{.title}}', app.title) result = result.replace('{{.title}}', app.title)
@@ -261,7 +247,7 @@ fn (app &App) render_chat() string {
result = result.replace('{{.css_chat_url}}', '/static/css/chat.css') result = result.replace('{{.css_chat_url}}', '/static/css/chat.css')
result = result.replace('{{.js_theme_url}}', '/static/js/theme.js') result = result.replace('{{.js_theme_url}}', '/static/js/theme.js')
result = result.replace('{{.js_chat_url}}', '/static/js/chat.js') result = result.replace('{{.js_chat_url}}', '/static/js/chat.js')
return result return result
} }
@@ -376,7 +362,8 @@ fn (app &App) render_admin_fallback(path string, heading string) string {
<div class="p-2"> <div class="p-2">
<div class="menu-section">Navigation</div> <div class="menu-section">Navigation</div>
<div class="list-group list-group-flush"> <div class="list-group list-group-flush">
${menu_html(app.menu, 0, 'm')} ${menu_html(app.menu,
0, 'm')}
</div> </div>
</div> </div>
</aside> </aside>
@@ -411,10 +398,14 @@ fn menu_html(items []MenuItem, depth int, prefix string) string {
if it.children.len > 0 { if it.children.len > 0 {
// expandable group // expandable group
out << '<div class="list-group-item">' out << '<div class="list-group-item">'
out << '<a class="menu-toggle d-flex align-items-center justify-content-between" data-bs-toggle="collapse" href="#${id}" role="button" aria-expanded="${if depth == 0 { "true" } else { "false" }}" aria-controls="${id}">' out << '<a class="menu-toggle d-flex align-items-center justify-content-between" data-bs-toggle="collapse" href="#${id}" role="button" aria-expanded="${if depth == 0 {
'true'
} else {
'false'
}}" aria-controls="${id}">'
out << '<span>${it.title}</span><span class="chev">&rsaquo;</span>' out << '<span>${it.title}</span><span class="chev">&rsaquo;</span>'
out << '</a>' out << '</a>'
out << '<div class="collapse ${if depth == 0 { "show" } else { "" }}" id="${id}">' out << '<div class="collapse ${if depth == 0 { 'show' } else { '' }}" id="${id}">'
out << '<div class="ms-2 mt-1">' out << '<div class="ms-2 mt-1">'
out << menu_html(it.children, depth + 1, id) out << menu_html(it.children, depth + 1, id)
out << '</div>' out << '</div>'
@@ -422,7 +413,11 @@ fn menu_html(items []MenuItem, depth int, prefix string) string {
out << '</div>' out << '</div>'
} else { } else {
// leaf // leaf
out << '<div class="list-group-item menu-leaf"><a href="${if it.href.len > 0 { it.href } else { "/admin" }}">${it.title}</a></div>' out << '<div class="list-group-item menu-leaf"><a href="${if it.href.len > 0 {
it.href
} else {
'/admin'
}}">${it.title}</a></div>'
} }
} }
return out.join('\n') return out.join('\n')
@@ -433,45 +428,75 @@ fn default_menu() []MenuItem {
return [ return [
MenuItem{ MenuItem{
title: 'Dashboard' title: 'Dashboard'
href: '/admin' href: '/admin'
}, },
MenuItem{ MenuItem{
title: 'HeroScript' title: 'HeroScript'
href: '/admin/heroscript' href: '/admin/heroscript'
}, },
MenuItem{ MenuItem{
title: 'Chat' title: 'Chat'
href: '/admin/chat' href: '/admin/chat'
}, },
MenuItem{ MenuItem{
title: 'Users' title: 'Users'
children: [ children: [
MenuItem{ title: 'Overview', href: '/admin/users/overview' }, MenuItem{
MenuItem{ title: 'Create', href: '/admin/users/create' }, title: 'Overview'
MenuItem{ title: 'Roles', href: '/admin/users/roles' }, href: '/admin/users/overview'
},
MenuItem{
title: 'Create'
href: '/admin/users/create'
},
MenuItem{
title: 'Roles'
href: '/admin/users/roles'
},
] ]
}, },
MenuItem{ MenuItem{
title: 'Content' title: 'Content'
children: [ children: [
MenuItem{ title: 'Pages', href: '/admin/content/pages' },
MenuItem{ title: 'Media', href: '/admin/content/media' },
MenuItem{ MenuItem{
title: 'Settings' title: 'Pages'
href: '/admin/content/pages'
},
MenuItem{
title: 'Media'
href: '/admin/content/media'
},
MenuItem{
title: 'Settings'
children: [ children: [
MenuItem{ title: 'SEO', href: '/admin/content/settings/seo' }, MenuItem{
MenuItem{ title: 'Themes', href: '/admin/content/settings/themes' }, title: 'SEO'
href: '/admin/content/settings/seo'
},
MenuItem{
title: 'Themes'
href: '/admin/content/settings/themes'
},
] ]
}, },
] ]
}, },
MenuItem{ MenuItem{
title: 'System' title: 'System'
children: [ children: [
MenuItem{ title: 'Status', href: '/admin/system/status' }, MenuItem{
MenuItem{ title: 'Logs', href: '/admin/system/logs' }, title: 'Status'
MenuItem{ title: 'Backups', href: '/admin/system/backups' }, href: '/admin/system/status'
},
MenuItem{
title: 'Logs'
href: '/admin/system/logs'
},
MenuItem{
title: 'Backups'
href: '/admin/system/backups'
},
] ]
}, },
] ]
} }

View File

@@ -18,7 +18,6 @@ fn startupcmd() ![]zinit.ZProcessNewArgs {
return res return res
} }
fn running() !bool { fn running() !bool {
res := os.execute('${osal.profile_path_source_and()!} caddy version') res := os.execute('${osal.profile_path_source_and()!} caddy version')
if res.exit_code == 0 { if res.exit_code == 0 {
@@ -82,7 +81,6 @@ fn upload() ! {
// )! // )!
} }
fn install() ! { fn install() ! {
console.print_header('install caddy') console.print_header('install caddy')
@@ -160,9 +158,6 @@ fn destroy() ! {
// ")! // ")!
} }
// configure caddy as default webserver & start // configure caddy as default webserver & start
// node, path, domain // node, path, domain
// path e.g. /var/www // path e.g. /var/www

View File

@@ -8,8 +8,6 @@ import freeflowuniverse.herolib.sysadmin.startupmanager
import freeflowuniverse.herolib.installers.lang.golang import freeflowuniverse.herolib.installers.lang.golang
import os import os
pub fn install_caddy_from_release() ! { pub fn install_caddy_from_release() ! {
version := '2.8.4' version := '2.8.4'
mut url := '' mut url := ''

View File

@@ -18,7 +18,6 @@ fn get_latest_release() !string {
return release.tag_name return release.tag_name
} }
// Show current version // Show current version
latest_release := get_latest_release() or { latest_release := get_latest_release() or {
eprintln('Error getting latest release: ${err}') eprintln('Error getting latest release: ${err}')
@@ -81,17 +80,12 @@ lines[version_line_idx] = ' version: \'${new_version}\''
os.write_file(hero_v_path, lines.join_lines()) or { os.write_file(hero_v_path, lines.join_lines()) or {
eprintln('Error writing to ${hero_v_path}: ${err}') eprintln('Error writing to ${hero_v_path}: ${err}')
// Restore backup // Restore backup
os.cp('${hero_v_path}.backup', hero_v_path) or { os.cp('${hero_v_path}.backup', hero_v_path) or { eprintln('Error restoring backup: ${err}') }
eprintln('Error restoring backup: ${err}')
}
exit(1) exit(1)
} }
// Clean up backup // Clean up backup
os.rm('${hero_v_path}.backup') or { os.rm('${hero_v_path}.backup') or { eprintln('Warning: Could not remove backup file: ${err}') }
eprintln('Warning: Could not remove backup file: ${err}')
}
// Update version in install_hero.sh // Update version in install_hero.sh
install_hero_path := '${ourdir}/install_hero.sh' install_hero_path := '${ourdir}/install_hero.sh'
@@ -130,8 +124,7 @@ os.rm('${install_hero_path}.backup') or {
eprintln('Warning: Could not remove backup file of install_hero.sh: ${err}') eprintln('Warning: Could not remove backup file of install_hero.sh: ${err}')
} }
cmd := '
cmd:='
git add . -A git add . -A
git commit -am "bump version to ${new_version}" git commit -am "bump version to ${new_version}"
git push git push

View File

@@ -25,63 +25,58 @@ pub mut:
pub fn biz_model_example(name string) BizModel { pub fn biz_model_example(name string) BizModel {
mut biz_model := BizModel{ mut biz_model := BizModel{
name: name name: name
intlist: []int{len: 10, init: rand.intn(100) or { 0 }} intlist: []int{len: 10, init: rand.intn(100) or { 0 }}
intstr: []string{len: 10, init: rand.string(5)} intstr: []string{len: 10, init: rand.string(5)}
mymap: map[string]SubItem{} mymap: map[string]SubItem{}
} }
for i in 0 .. 100 { for i in 0 .. 100 {
sub_item := SubItem{ sub_item := SubItem{
name: 'SubItem ${i}' name: 'SubItem ${i}'
intlist: []int{len: 5, init: rand.intn(50) or { 0 }} intlist: []int{len: 5, init: rand.intn(50) or { 0 }}
intstr: []string{len: 5, init: rand.string(3)} intstr: []string{len: 5, init: rand.string(3)}
} }
biz_model.mymap['item_${i}'] = sub_item biz_model.mymap['item_${i}'] = sub_item
} }
return biz_model return biz_model
} }
pub fn get(name string) !BizModel { pub fn get(name string) !BizModel {
rlock bizmodels { rlock bizmodels {
if ! (name in bizmodels) { if name !in bizmodels {
return error("can't find bizmodel: ${name}") return error("can't find bizmodel: ${name}")
} }
return bizmodels[name] or { panic("bug") } return bizmodels[name] or { panic('bug') }
} }
return error("bug") return error('bug')
} }
pub fn getset(name string) BizModel { pub fn getset(name string) BizModel {
lock bizmodels { lock bizmodels {
if ! (name in bizmodels) { if name !in bizmodels {
set(biz_model_example(name)) set(biz_model_example(name))
} }
return bizmodels[name] or { panic("bug") } return bizmodels[name] or { panic('bug') }
} }
return BizModel{} //weird we need to do this return BizModel{} // weird we need to do this
} }
pub fn set(bizmodel BizModel) { pub fn set(bizmodel BizModel) {
lock bizmodels { lock bizmodels {
bizmodels[bizmodel.name] = bizmodel bizmodels[bizmodel.name] = bizmodel
} }
} }
fn fill_biz_models(nr int) { fn fill_biz_models(nr int) {
for i in 0 .. nr { for i in 0 .. nr {
getset("bm${i}") getset('bm${i}')
} }
rlock bizmodels{ rlock bizmodels {
//check we have enough bizmodels in mem // check we have enough bizmodels in mem
assert bizmodels.len == nr assert bizmodels.len == nr
} }
} }
fn get_memory_usage() i64 { fn get_memory_usage() i64 {
@@ -93,41 +88,39 @@ fn get_memory_usage() i64 {
fn main() { fn main() {
sw := time.new_stopwatch() sw := time.new_stopwatch()
nr:=100 nr := 100
nr_new :=100000 //make small changes, the garbage collector should keep it clean nr_new := 100000 // make small changes, the garbage collector should keep it clean
fill_biz_models(nr) fill_biz_models(nr)
memory_usage_1 := get_memory_usage() memory_usage_1 := get_memory_usage()
println('Memory usage after creating ${nr} BizModels: ${memory_usage_1} KB') println('Memory usage after creating ${nr} BizModels: ${memory_usage_1} KB')
println('Time taken: ${sw.elapsed().milliseconds()} ms') println('Time taken: ${sw.elapsed().milliseconds()} ms')
for _ in 0 .. nr_new { for _ in 0 .. nr_new {
currentnr:=rand.intn(nr-1) or {panic(err)} currentnr := rand.intn(nr - 1) or { panic(err) }
mut new_model:= get("bm${currentnr}")! mut new_model := get('bm${currentnr}')!
//new_model.intlist = new_model.intlist.map(it + rand.intn(10) or { 0 }) // new_model.intlist = new_model.intlist.map(it + rand.intn(10) or { 0 })
new_model.intstr = new_model.intstr.map(it + rand.string(2)) new_model.intstr = new_model.intstr.map(it + rand.string(2))
mut new_model2:= get("bm${currentnr}")! mut new_model2 := get('bm${currentnr}')!
assert new_model2.intstr != new_model.intstr //should be different because was not a reference assert new_model2.intstr != new_model.intstr // should be different because was not a reference
set(new_model) set(new_model)
mut new_model3:= get("bm${currentnr}")! mut new_model3 := get('bm${currentnr}')!
assert new_model3.intstr == new_model.intstr //should be different because was not a reference assert new_model3.intstr == new_model.intstr // should be different because was not a reference
} }
rlock bizmodels{ rlock bizmodels {
//check we have enough bizmodels in mem // check we have enough bizmodels in mem
assert bizmodels.len == nr assert bizmodels.len == nr
} }
println("wait 1 sec") println('wait 1 sec')
//lets make sure garbage collector works // lets make sure garbage collector works
time.sleep(1 * time.second) time.sleep(1 * time.second)
memory_usage_2 := get_memory_usage() memory_usage_2 := get_memory_usage()
println('Memory usage after creating ${nr_new} random BizModels: ${memory_usage_2} KB') println('Memory usage after creating ${nr_new} random BizModels: ${memory_usage_2} KB')
println('Time taken: ${sw.elapsed().milliseconds()} ms') println('Time taken: ${sw.elapsed().milliseconds()} ms')
println("QUESTION: why does memory go up?, we didn't add to the memory should have been equal...") println("QUESTION: why does memory go up?, we didn't add to the memory should have been equal...")
} }

View File

@@ -26,62 +26,58 @@ pub mut:
pub fn biz_model_example(name string) BizModel { pub fn biz_model_example(name string) BizModel {
mut biz_model := BizModel{ mut biz_model := BizModel{
name: name name: name
intlist: []int{len: 10, init: rand.intn(100) or { 0 }} intlist: []int{len: 10, init: rand.intn(100) or { 0 }}
intstr: []string{len: 10, init: rand.string(5)} intstr: []string{len: 10, init: rand.string(5)}
mymap: map[string]SubItem{} mymap: map[string]SubItem{}
} }
for i in 0 .. 100 { for i in 0 .. 100 {
sub_item := SubItem{ sub_item := SubItem{
name: 'SubItem ${i}' name: 'SubItem ${i}'
intlist: []int{len: 5, init: rand.intn(50) or { 0 }} intlist: []int{len: 5, init: rand.intn(50) or { 0 }}
intstr: []string{len: 5, init: rand.string(3)} intstr: []string{len: 5, init: rand.string(3)}
} }
biz_model.mymap['item_${i}'] = sub_item biz_model.mymap['item_${i}'] = sub_item
} }
return biz_model return biz_model
} }
pub fn get(name string) !BizModel { pub fn get(name string) !BizModel {
rlock bizmodels { rlock bizmodels {
if ! (name in bizmodels) { if name !in bizmodels {
return error("can't find bizmodel: ${name}") return error("can't find bizmodel: ${name}")
} }
return bizmodels[name] or { panic("bug") } return bizmodels[name] or { panic('bug') }
} }
return error("bug") return error('bug')
} }
pub fn getset(name string) BizModel { pub fn getset(name string) BizModel {
lock bizmodels { lock bizmodels {
if ! (name in bizmodels) { if name !in bizmodels {
set(biz_model_example(name)) set(biz_model_example(name))
} }
return bizmodels[name] or { panic("bug") } return bizmodels[name] or { panic('bug') }
} }
return BizModel{} //weird we need to do this return BizModel{} // weird we need to do this
} }
pub fn set(bizmodel BizModel) { pub fn set(bizmodel BizModel) {
lock bizmodels { lock bizmodels {
bizmodels[bizmodel.name] = bizmodel bizmodels[bizmodel.name] = bizmodel
} }
} }
fn fill_biz_models(nr int) { fn fill_biz_models(nr int) {
for i in 0 .. nr { for i in 0 .. nr {
getset("bm${i}") getset('bm${i}')
} }
rlock bizmodels{ rlock bizmodels {
//check we have enough bizmodels in mem // check we have enough bizmodels in mem
assert bizmodels.len == nr assert bizmodels.len == nr
} }
} }
fn get_memory_usage() i64 { fn get_memory_usage() i64 {
@@ -93,33 +89,32 @@ fn get_memory_usage() i64 {
fn main() { fn main() {
sw := time.new_stopwatch() sw := time.new_stopwatch()
nr:=100 nr := 100
nr_new :=100000 //make small changes, the garbage collector should keep it clean nr_new := 100000 // make small changes, the garbage collector should keep it clean
fill_biz_models(nr) fill_biz_models(nr)
println("wait 0.5 sec") println('wait 0.5 sec')
//lets make sure garbage collector works // lets make sure garbage collector works
time.sleep(0.5 * time.second) time.sleep(0.5 * time.second)
memory_usage_1 := get_memory_usage() memory_usage_1 := get_memory_usage()
println('Memory usage after creating ${nr} BizModels: ${memory_usage_1} KB') println('Memory usage after creating ${nr} BizModels: ${memory_usage_1} KB')
println('Time taken: ${sw.elapsed().milliseconds()} ms') println('Time taken: ${sw.elapsed().milliseconds()} ms')
for _ in 0 .. nr_new { for _ in 0 .. nr_new {
currentnr:=rand.intn(nr-1) or {panic(err)} currentnr := rand.intn(nr - 1) or { panic(err) }
//println(currentnr) // println(currentnr)
set(biz_model_example("bm${currentnr}")) //will keep on overwriting set(biz_model_example('bm${currentnr}')) // will keep on overwriting
} }
println("wait 1 sec") println('wait 1 sec')
//lets make sure garbage collector works // lets make sure garbage collector works
time.sleep(1 * time.second) time.sleep(1 * time.second)
memory_usage_2 := get_memory_usage() memory_usage_2 := get_memory_usage()
println('Memory usage after creating ${nr_new} random BizModels: ${memory_usage_2} KB') println('Memory usage after creating ${nr_new} random BizModels: ${memory_usage_2} KB')
println('Time taken: ${sw.elapsed().milliseconds()} ms') println('Time taken: ${sw.elapsed().milliseconds()} ms')
println("QUESTION: this seems ok, memory doesn't go up much\nDon't understand why the globals_example does increase.") println("QUESTION: this seems ok, memory doesn't go up much\nDon't understand why the globals_example does increase.")
} }

View File

@@ -25,62 +25,58 @@ pub mut:
pub fn biz_model_example(name string) BizModel { pub fn biz_model_example(name string) BizModel {
mut biz_model := BizModel{ mut biz_model := BizModel{
name: name name: name
intlist: []int{len: 10, init: rand.intn(100) or { 0 }} intlist: []int{len: 10, init: rand.intn(100) or { 0 }}
intstr: []string{len: 10, init: rand.string(5)} intstr: []string{len: 10, init: rand.string(5)}
mymap: map[string]SubItem{} mymap: map[string]SubItem{}
} }
for i in 0 .. 100 { for i in 0 .. 100 {
sub_item := SubItem{ sub_item := SubItem{
name: 'SubItem ${i}' name: 'SubItem ${i}'
intlist: []int{len: 5, init: rand.intn(50) or { 0 }} intlist: []int{len: 5, init: rand.intn(50) or { 0 }}
intstr: []string{len: 5, init: rand.string(3)} intstr: []string{len: 5, init: rand.string(3)}
} }
biz_model.mymap['item_${i}'] = sub_item biz_model.mymap['item_${i}'] = sub_item
} }
return biz_model return biz_model
} }
pub fn get(name string) !&BizModel { pub fn get(name string) !&BizModel {
rlock bizmodels { rlock bizmodels {
if ! (name in bizmodels) { if name !in bizmodels {
return error("can't find bizmodel: ${name}") return error("can't find bizmodel: ${name}")
} }
return bizmodels[name] or { panic("bug") } return bizmodels[name] or { panic('bug') }
} }
return error("bug") return error('bug')
} }
pub fn getset(name string) &BizModel { pub fn getset(name string) &BizModel {
lock bizmodels { lock bizmodels {
if ! (name in bizmodels) { if name !in bizmodels {
//println("getset ${name}") // println("getset ${name}")
new(biz_model_example(name)) new(biz_model_example(name))
} }
return bizmodels[name] or { panic("bug") } return bizmodels[name] or { panic('bug') }
} }
return &BizModel{} //weird we need to do this return &BizModel{} // weird we need to do this
} }
pub fn new(bizmodel BizModel) { pub fn new(bizmodel BizModel) {
lock bizmodels { lock bizmodels {
bizmodels[bizmodel.name] = &bizmodel bizmodels[bizmodel.name] = &bizmodel
} }
} }
fn fill_biz_models(nr int) { fn fill_biz_models(nr int) {
for i in 0 .. nr { for i in 0 .. nr {
getset("bm${i}") getset('bm${i}')
} }
rlock bizmodels{ rlock bizmodels {
assert bizmodels.len == nr assert bizmodels.len == nr
} }
} }
fn get_memory_usage() i64 { fn get_memory_usage() i64 {
@@ -92,28 +88,27 @@ fn get_memory_usage() i64 {
fn main() { fn main() {
sw := time.new_stopwatch() sw := time.new_stopwatch()
nr:=100 nr := 100
nr_new :=100000 //make small changes, the garbage collector should keep it clean nr_new := 100000 // make small changes, the garbage collector should keep it clean
fill_biz_models(nr) fill_biz_models(nr)
memory_usage_1 := get_memory_usage() memory_usage_1 := get_memory_usage()
println('Memory usage after creating ${nr} BizModels: ${memory_usage_1} KB') println('Memory usage after creating ${nr} BizModels: ${memory_usage_1} KB')
println('Time taken: ${sw.elapsed().milliseconds()} ms') println('Time taken: ${sw.elapsed().milliseconds()} ms')
for _ in 0 .. nr_new { for _ in 0 .. nr_new {
currentnr:=rand.intn(nr-1) or {panic(err)} currentnr := rand.intn(nr - 1) or { panic(err) }
mut new_model:= get("bm${currentnr}")! mut new_model := get('bm${currentnr}')!
//new_model.intlist = new_model.intlist.map(it + rand.intn(10) or { 0 }) // new_model.intlist = new_model.intlist.map(it + rand.intn(10) or { 0 })
new_model.intstr = new_model.intstr.map(it + rand.string(2)) new_model.intstr = new_model.intstr.map(it + rand.string(2))
//set(new_model) //SHOULD NOT BE NEEDED TO SET BECAUSE IS REFERENCE // set(new_model) //SHOULD NOT BE NEEDED TO SET BECAUSE IS REFERENCE
mut new_model2:= get("bm${currentnr}")! mut new_model2 := get('bm${currentnr}')!
assert new_model2.intstr == new_model.intstr //should be same because was a reference assert new_model2.intstr == new_model.intstr // should be same because was a reference
} }
println("wait 1 sec") println('wait 1 sec')
//lets make sure garbage collector works, didn't make a difference though // lets make sure garbage collector works, didn't make a difference though
time.sleep(1 * time.second) time.sleep(1 * time.second)
memory_usage_2 := get_memory_usage() memory_usage_2 := get_memory_usage()
@@ -121,4 +116,4 @@ fn main() {
println('Time taken: ${sw.elapsed().milliseconds()} ms') println('Time taken: ${sw.elapsed().milliseconds()} ms')
println("QUESTION: why does memory go up?, we didn't add to the memory should have been equal... its also not lower compared to the references one") println("QUESTION: why does memory go up?, we didn't add to the memory should have been equal... its also not lower compared to the references one")
} }