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')
if help_requested {
println(fp.usage())
exit(0)
println(fp.usage())
exit(0)
}
additional_args := fp.finalize() or {
eprintln(err)
println(fp.usage())
exit(1)
}
eprintln(err)
println(fp.usage())
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 -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 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')
if help_requested {
println(fp.usage())
exit(0)
println(fp.usage())
exit(0)
}
additional_args := fp.finalize() or {
eprintln(err)
println(fp.usage())
exit(1)
eprintln(err)
println(fp.usage())
exit(1)
}
if additional_args.len > 0 {
eprintln('Unexpected arguments: ${additional_args.join(' ')}')
println(fp.usage())
exit(1)
eprintln('Unexpected arguments: ${additional_args.join(' ')}')
println(fp.usage())
exit(1)
}
// 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
mut heropath := '/usr/local/bin/hero'
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
compile_cmd := if os.user_os() == 'macos' {
if prod_mode {
'v -enable-globals -w -n -prod hero.v'
} else {
'v -w -cg -gc none -cc tcc -d use_openssl -enable-globals hero.v'
}
if prod_mode {
'v -enable-globals -w -n -prod hero.v'
} else {
'v -w -cg -gc none -cc tcc -d use_openssl -enable-globals hero.v'
}
} else {
if prod_mode {
'v -cg -enable-globals -parallel-cc -w -n hero.v'
} else {
'v -cg -enable-globals -w -n hero.v'
}
if prod_mode {
'v -cg -enable-globals -parallel-cc -w -n hero.v'
} else {
'v -cg -enable-globals -w -n hero.v'
}
}
println('Building in ${if prod_mode { 'production' } else { 'debug' }} mode...')
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
os.chmod('hero', 0o755) or { panic('Failed to make hero binary executable: ${err}') }
// 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)
// Copy to destination paths
os.cp('hero', heropath) or { panic('Failed to copy hero binary to ${heropath}: ${err}') }

View File

@@ -64,7 +64,9 @@ account = ${s3keyid}
key = ${s3appid}
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}')
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() ! {
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()!
platform_id := get_platform_id()
@@ -83,15 +87,18 @@ fn hero_upload() ! {
// List contents
os.execute_or_panic('rclone --config="${rclone_conf}" lsl b2:threefold/${platform_id}/')
// Copy hero binary
os.execute_or_panic('rclone --config="${rclone_conf}" copy "${hero_path}" b2:threefold/${platform_id}/')
}
fn main() {
//os.execute_or_panic('${os.home_dir()}/code/github/freeflowuniverse/herolib/cli/compile.vsh -p')
println("compile hero can take 60 sec+ on osx.")
// os.execute_or_panic('${os.home_dir()}/code/github/freeflowuniverse/herolib/cli/compile.vsh -p')
println('compile hero can take 60 sec+ on osx.')
os.execute_or_panic('${os.home_dir()}/code/github/freeflowuniverse/herolib/cli/compile.vsh -p')
println( "upload:")
hero_upload() or { eprintln(err) exit(1) }
println('upload:')
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 -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 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')
if help_requested {
println(fp.usage())
exit(0)
println(fp.usage())
exit(0)
}
additional_args := fp.finalize() or {
eprintln(err)
println(fp.usage())
exit(1)
eprintln(err)
println(fp.usage())
exit(1)
}
if additional_args.len > 0 {
eprintln('Unexpected arguments: ${additional_args.join(' ')}')
println(fp.usage())
exit(1)
eprintln('Unexpected arguments: ${additional_args.join(' ')}')
println(fp.usage())
exit(1)
}
// 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
mut heropath := '/usr/local/bin/vdo'
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
compile_cmd := if os.user_os() == 'macos' {
if prod_mode {
'v -enable-globals -w -n -prod vdo.v'
} else {
'v -w -cg -gc none -cc tcc -d use_openssl -enable-globals vdo.v'
}
if prod_mode {
'v -enable-globals -w -n -prod vdo.v'
} else {
'v -w -cg -gc none -cc tcc -d use_openssl -enable-globals vdo.v'
}
} else {
if prod_mode {
'v -cg -enable-globals -parallel-cc -w -n vdo.v'
} else {
'v -cg -enable-globals -w -n vdo.v'
}
if prod_mode {
'v -cg -enable-globals -parallel-cc -w -n vdo.v'
} else {
'v -cg -enable-globals -w -n vdo.v'
}
}
println('Building in ${if prod_mode { 'production' } else { 'debug' }} mode...')
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
os.chmod('vdo', 0o755) or { panic('Failed to make vdo binary executable: ${err}') }
// 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)
// Copy to destination paths
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) ! {
mut plbook := playbook.new(path: path)!
playcmds.run(plbook:plbook)!
playcmds.run(plbook: plbook)!
}
fn do() ! {
@@ -114,4 +114,4 @@ fn main() {
fn pre_func(cmd Command) ! {
herocmds.plbook_run(cmd)!
}
}

View File

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

35
doc.vsh
View File

@@ -7,13 +7,13 @@ abs_dir_of_script := dir(@FILE)
// Format code
println('Formatting code...')
if os.system('v fmt -w ${abs_dir_of_script}/examples') != 0 {
eprintln('Warning: Failed to format examples')
exit(1)
eprintln('Warning: Failed to format examples')
exit(1)
}
if os.system('v fmt -w ${abs_dir_of_script}/lib') != 0 {
eprintln('Warning: Failed to format herolib')
exit(1)
eprintln('Warning: Failed to format herolib')
exit(1)
}
// Clean existing docs
@@ -24,9 +24,7 @@ os.rmdir_all('docs') or {}
os.rmdir_all('vdocs') or {}
herolib_path := os.join_path(abs_dir_of_script, 'lib')
os.chdir(herolib_path) or {
panic('Failed to change directory to herolib: ${err}')
}
os.chdir(herolib_path) or { panic('Failed to change directory to herolib: ${err}') }
os.mkdir_all('_docs') or {}
os.mkdir_all('docs') or {}
@@ -35,17 +33,14 @@ os.mkdir_all('vdocs') or {}
// Generate HTML documentation
println('Generating HTML documentation...')
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 {
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
println('Generating Markdown documentation...')
@@ -60,12 +55,10 @@ println('Generating Markdown documentation...')
// Open documentation in browser on non-Linux systems
$if !linux {
os.chdir(abs_dir_of_script) or {
panic('Failed to change directory: ${err}')
}
if os.system('open docs/index.html') != 0 {
eprintln('Warning: Failed to open documentation in browser')
}
os.chdir(abs_dir_of_script) or { panic('Failed to change directory: ${err}') }
if os.system('open docs/index.html') != 0 {
eprintln('Warning: Failed to open documentation in browser')
}
}
// Create Jekyll required files
@@ -75,7 +68,7 @@ os.mkdir_all('docs/assets/css') or {}
// Create style.scss
style_content := '---\n---\n\n@import "{{ site.theme }}";'
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
@@ -94,7 +87,7 @@ exclude:
- vendor/ruby/'
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!')

View File

@@ -4,46 +4,45 @@ import os
import flag
fn addtoscript(tofind string, toadd string) ! {
home_dir := os.home_dir()
mut rc_file := '${home_dir}/.zshrc'
if !os.exists(rc_file) {
rc_file = '${home_dir}/.bashrc'
if !os.exists(rc_file) {
return error('No .zshrc or .bashrc found in home directory')
}
}
home_dir := os.home_dir()
mut rc_file := '${home_dir}/.zshrc'
if !os.exists(rc_file) {
rc_file = '${home_dir}/.bashrc'
if !os.exists(rc_file) {
return error('No .zshrc or .bashrc found in home directory')
}
}
// Read current content
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
}
// Read current content
mut content := os.read_file(rc_file)!
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)!
// 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) {
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
abs_dir_of_script := dir(@FILE)
@@ -52,20 +51,20 @@ println('Resetting all symlinks...')
os.rm('${os.home_dir()}/.vmodules/freeflowuniverse/herolib') or {}
// Create necessary directories
os.mkdir_all('${os.home_dir()}/.vmodules/freeflowuniverse') or {
panic('Failed to create directory ~/.vmodules/freeflowuniverse: ${err}')
os.mkdir_all('${os.home_dir()}/.vmodules/freeflowuniverse') or {
panic('Failed to create directory ~/.vmodules/freeflowuniverse: ${err}')
}
// Create new symlinks
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!')
// Add vtest alias
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}')
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}')
}
println('Added vtest alias to shell configuration')

View File

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

View File

@@ -10,41 +10,39 @@ fp.version('v0.1.0')
fp.description('Generate code')
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')
interactive := fp.bool('interactive', `i`, false, 'If we want to work interactive')
scan := fp.bool('scan', `s`, false, 'If we want to scan')
help_requested := fp.bool('help', `h`, false, 'Show help message')
if help_requested {
println(fp.usage())
exit(0)
println(fp.usage())
exit(0)
}
additional_args := fp.finalize() or {
eprintln(err)
println(fp.usage())
exit(1)
eprintln(err)
println(fp.usage())
exit(1)
}
if additional_args.len > 0 {
eprintln('Unexpected arguments: ${additional_args.join(' ')}')
println(fp.usage())
exit(1)
eprintln('Unexpected arguments: ${additional_args.join(' ')}')
println(fp.usage())
exit(1)
}
// reset bool // regenerate all, dangerous !!!
// interactive bool //if we want to ask
// path string
if path.trim_space() == "." {
if path.trim_space() == '.' {
path = os.getwd()
}
if ! scan {
generator.do(path:path, reset:reset, interactive:interactive)!
}else{
generator.scan(path:path, reset:reset, interactive:interactive)!
if !scan {
generator.do(path: path, reset: reset, interactive: interactive)!
} else {
generator.scan(path: path, reset: reset, interactive: interactive)!
}

View File

@@ -4,46 +4,45 @@ import os
import flag
fn addtoscript(tofind string, toadd string) ! {
home_dir := os.home_dir()
mut rc_file := '${home_dir}/.zshrc'
if !os.exists(rc_file) {
rc_file = '${home_dir}/.bashrc'
if !os.exists(rc_file) {
return error('No .zshrc or .bashrc found in home directory')
}
}
home_dir := os.home_dir()
mut rc_file := '${home_dir}/.zshrc'
if !os.exists(rc_file) {
rc_file = '${home_dir}/.bashrc'
if !os.exists(rc_file) {
return error('No .zshrc or .bashrc found in home directory')
}
}
// Read current content
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
}
// Read current content
mut content := os.read_file(rc_file)!
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)!
// 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) {
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
abs_dir_of_script := dir(@FILE)
@@ -52,29 +51,29 @@ println('Resetting all symlinks...')
os.rm('${os.home_dir()}/.vmodules/freeflowuniverse/herolib') or {}
// Create necessary directories
os.mkdir_all('${os.home_dir()}/.vmodules/freeflowuniverse') or {
panic('Failed to create directory ~/.vmodules/freeflowuniverse: ${err}')
os.mkdir_all('${os.home_dir()}/.vmodules/freeflowuniverse') or {
panic('Failed to create directory ~/.vmodules/freeflowuniverse: ${err}')
}
// Create new symlinks
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!')
// Add vtest alias
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}')
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}')
}
// Add vrun alias
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}')
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}')
}
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

View File

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

View File

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

View File

@@ -5,6 +5,7 @@ import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.web.docusaurus
import os
import cli { Command, Flag }
import freeflowuniverse.herolib.core.playbook
pub fn cmd_docusaurus(mut cmdroot Command) Command {
mut cmd_run := Command{
@@ -113,94 +114,98 @@ pub fn cmd_docusaurus(mut cmdroot Command) Command {
// 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)
return cmdroot
}
fn cmd_docusaurus_execute(cmd Command) ! {
// ---------- FLAGS ----------
mut open := cmd.flags.get_bool('open') or { false }
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 }
mut new := cmd.flags.get_bool('new') or { false }
mut reset := cmd.flags.get_bool('reset') or { false }
// (the earlier duplicate reset flag has been removed)
// --- Build Path Logic ---
mut build_path := cmd.flags.get_string('buildpath') or { '' }
if build_path == '' {
build_path = '${os.home_dir()}/hero/var/docusaurus'
}
// --- Path Logic ---
mut provided_path := cmd.flags.get_string('path') or { '' }
// ---------- PATH LOGIC ----------
// Resolve the source directory that contains a cfg subdirectory.
mut path := cmd.flags.get_string('path') or { '' }
mut source_path := ''
if provided_path != '' {
if !os.exists(provided_path) || !os.is_dir(provided_path) {
return error('Provided path "${provided_path}" does not exist or is not a directory.')
if path != '' {
// user supplied a path
if !os.exists(path) || !os.is_dir(path) {
return error('Provided path "${path}" does not exist or is not a directory.')
}
// Check if the provided path contains a cfg subdirectory (ebook directory structure)
cfg_subdir := os.join_path(provided_path, 'cfg')
if os.exists(cfg_subdir) && os.is_dir(cfg_subdir) {
source_path = provided_path
cfg_subdir := os.join_path(path, 'cfg')
source_path = if os.exists(cfg_subdir) && os.is_dir(cfg_subdir) {
path
} else if path.ends_with('cfg') {
os.dir(path)
} else {
if provided_path.ends_with('cfg') {
// 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.')
}
return error('Provided path "${path}" does not contain a cfg subdirectory.')
}
} else {
mut cwd := os.getwd()
// default to current working directory
cwd := os.getwd()
cfg_dir := os.join_path(cwd, 'cfg')
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
}
console.print_header('Running Docusaurus for: ${source_path}')
// Use the centralized site processing function from docusaurus module
mysite := docusaurus.process_site_from_path(source_path, '')!
site_name := mysite.siteconfig.name
// ---------- BUILD PLAYBOOK ----------
// Build a PlayBook from the source directory (it contains the HeroScript actions)
mut plbook := playbook.new(path: source_path)!
// Set up the docusaurus factory
docusaurus.factory_set(
path_build: build_path
reset: reset
install: reset
template_update: reset
)!
// If the user asked for a CLIlevel reset we inject a temporary define action
// so that the underlying factory_set receives `reset:true`.
if reset {
// prepend a temporary docusaurus.define action (this is safe because the playbook
// already contains the real definitions, the extra one will just be ignored later)
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
mut dsite := docusaurus.dsite_add(
sitename: site_name
path: source_path
play: false // Site already processed
)!
// ---------- RUN DOCUSUROUS ----------
// This will:
// * read the generic `site.*` definitions,
// * create a Docusaurus factory (or reuse an existing one),
// * 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 {
dsite.build_publish()!
dsite_opt.build_publish()!
} else if builddevpublish {
dsite.build()!
dsite_opt.build()!
} else if dev {
dsite.dev(
dsite_opt.dev(
open: open
watch_changes: false
)!
} 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
}
//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 {
// 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 {
mut res := plbook.find(args) or { [] }
if res.len == 0 {
return error('No actions found based on filter: ${args.filter}')
}
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') }
}
//check its once, if not say that playbook only can have one action
pub fn (mut plbook PlayBook)exists_once (args FindArgs) bool {
// check its once, if not say that playbook only can have one action
pub fn (mut plbook PlayBook) exists_once(args FindArgs) bool {
mut res := plbook.find(args) or { [] }
return res.len == 1
}

View File

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

View File

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

View File

@@ -8,8 +8,6 @@ import freeflowuniverse.herolib.web.site
import freeflowuniverse.herolib.ui.console
import freeflowuniverse.herolib.osal.core as osal
@[params]
pub struct AddArgs {
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
mut website := site.get(name: args.sitename)!
// Create the DocSite instance
mut dsite := &DocSite{
name: args.sitename

View File

@@ -15,7 +15,7 @@ mut:
client &doctreeclient.DocTreeClient
flat bool // if flat then won't use sitenames as subdir's
site Site
errors []string // collect errors here
errors []string // collect errors here
}
@[params]
@@ -23,7 +23,7 @@ struct SiteGeneratorArgs {
mut:
path string
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
@@ -51,16 +51,13 @@ pub fn generate_docs(args SiteGeneratorArgs) ! {
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()!}')
}
}
fn (mut mysite SiteGenerator) error( msg string) ! {
fn (mut mysite SiteGenerator) error(msg string) ! {
console.print_stderr('Error: ${msg}')
mysite.errors << msg
}
fn (mut mysite SiteGenerator) page_generate(args_ Page) ! {
mut args := args_
@@ -69,7 +66,7 @@ fn (mut mysite SiteGenerator) page_generate(args_ Page) ! {
mut parts := args.src.split(':')
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")!
return
return
}
collection_name := parts[0]
page_name := parts[1]
@@ -129,7 +126,7 @@ fn (mut mysite SiteGenerator) page_generate(args_ Page) ! {
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
args.path += page_name
}

View File

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

View File

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

View File

@@ -81,103 +81,89 @@ pub fn start(args FactoryArgs) ! {
// Routes
// Redirect root to /admin
@[get; '/']
@['/'; get]
pub fn (app &App) root(mut ctx Context) veb.Result {
return ctx.redirect('/admin')
}
// Admin home page
@[get; '/admin']
@['/admin'; get]
pub fn (app &App) admin_index(mut ctx Context) veb.Result {
return ctx.html(app.render_admin('/', 'Welcome'))
}
// HeroScript editor page
@[get; '/admin/heroscript']
@['/admin/heroscript'; get]
pub fn (app &App) admin_heroscript(mut ctx Context) veb.Result {
return ctx.html(app.render_heroscript())
}
// Chat page
@[get; '/admin/chat']
@['/admin/chat'; get]
pub fn (app &App) admin_chat(mut ctx Context) veb.Result {
return ctx.html(app.render_chat())
}
// 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 {
css_path := os.join_path(os.dir(@FILE), 'templates', 'css', 'colors.css')
css_content := os.read_file(css_path) or {
return ctx.text('/* CSS file not found */')
}
css_content := os.read_file(css_path) or { return ctx.text('/* CSS file not found */') }
ctx.set_content_type('text/css')
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 {
css_path := os.join_path(os.dir(@FILE), 'templates', 'css', 'main.css')
css_content := os.read_file(css_path) or {
return ctx.text('/* CSS file not found */')
}
css_content := os.read_file(css_path) or { return ctx.text('/* CSS file not found */') }
ctx.set_content_type('text/css')
return ctx.text(css_content)
}
// 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 {
js_path := os.join_path(os.dir(@FILE), 'templates', 'js', 'theme.js')
js_content := os.read_file(js_path) or {
return ctx.text('/* JS file not found */')
}
js_content := os.read_file(js_path) or { return ctx.text('/* JS file not found */') }
ctx.set_content_type('application/javascript')
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 {
js_path := os.join_path(os.dir(@FILE), 'templates', 'js', 'heroscript.js')
js_content := os.read_file(js_path) or {
return ctx.text('/* JS file not found */')
}
js_content := os.read_file(js_path) or { return ctx.text('/* JS file not found */') }
ctx.set_content_type('application/javascript')
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 {
js_path := os.join_path(os.dir(@FILE), 'templates', 'js', 'chat.js')
js_content := os.read_file(js_path) or {
return ctx.text('/* JS file not found */')
}
js_content := os.read_file(js_path) or { return ctx.text('/* JS file not found */') }
ctx.set_content_type('application/javascript')
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 {
css_path := os.join_path(os.dir(@FILE), 'templates', 'css', 'heroscript.css')
css_content := os.read_file(css_path) or {
return ctx.text('/* CSS file not found */')
}
css_content := os.read_file(css_path) or { return ctx.text('/* CSS file not found */') }
ctx.set_content_type('text/css')
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 {
css_path := os.join_path(os.dir(@FILE), 'templates', 'css', 'chat.css')
css_content := os.read_file(css_path) or {
return ctx.text('/* CSS file not found */')
}
css_content := os.read_file(css_path) or { return ctx.text('/* CSS file not found */') }
ctx.set_content_type('text/css')
return ctx.text(css_content)
}
// Catch-all content under /admin/*
@[get; '/admin/:path...']
@['/admin/:path...'; get]
pub fn (app &App) admin_section(mut ctx Context, path string) veb.Result {
// Render current path in the main 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 {
// Get the template file path relative to the module
template_path := os.join_path(os.dir(@FILE), 'templates', 'admin_layout.html')
// Read the template file
template_content := os.read_file(template_path) or {
// Fallback to inline template if file not found
return app.render_admin_fallback(path, heading)
}
// Generate menu HTML
menu_content := menu_html(app.menu, 0, 'm')
// Simple template variable replacement
mut result := template_content
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_main_url}}', '/static/css/main.css')
result = result.replace('{{.js_theme_url}}', '/static/js/theme.js')
return result
}
@@ -215,16 +201,16 @@ fn (app &App) render_admin(path string, heading string) string {
fn (app &App) render_heroscript() string {
// Get the template file path relative to the module
template_path := os.join_path(os.dir(@FILE), 'templates', 'heroscript_editor.html')
// Read the template file
template_content := os.read_file(template_path) or {
// Fallback to basic template if file not found
return app.render_heroscript_fallback()
}
// Generate menu HTML
menu_content := menu_html(app.menu, 0, 'm')
// Simple template variable replacement
mut result := template_content
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('{{.js_theme_url}}', '/static/js/theme.js')
result = result.replace('{{.js_heroscript_url}}', '/static/js/heroscript.js')
return result
}
@@ -242,16 +228,16 @@ fn (app &App) render_heroscript() string {
fn (app &App) render_chat() string {
// Get the template file path relative to the module
template_path := os.join_path(os.dir(@FILE), 'templates', 'chat.html')
// Read the template file
template_content := os.read_file(template_path) or {
// Fallback to basic template if file not found
return app.render_chat_fallback()
}
// Generate menu HTML
menu_content := menu_html(app.menu, 0, 'm')
// Simple template variable replacement
mut result := template_content
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('{{.js_theme_url}}', '/static/js/theme.js')
result = result.replace('{{.js_chat_url}}', '/static/js/chat.js')
return result
}
@@ -376,7 +362,8 @@ fn (app &App) render_admin_fallback(path string, heading string) string {
<div class="p-2">
<div class="menu-section">Navigation</div>
<div class="list-group list-group-flush">
${menu_html(app.menu, 0, 'm')}
${menu_html(app.menu,
0, 'm')}
</div>
</div>
</aside>
@@ -411,10 +398,14 @@ fn menu_html(items []MenuItem, depth int, prefix string) string {
if it.children.len > 0 {
// expandable group
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 << '</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 << menu_html(it.children, depth + 1, id)
out << '</div>'
@@ -422,7 +413,11 @@ fn menu_html(items []MenuItem, depth int, prefix string) string {
out << '</div>'
} else {
// 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')
@@ -433,45 +428,75 @@ fn default_menu() []MenuItem {
return [
MenuItem{
title: 'Dashboard'
href: '/admin'
href: '/admin'
},
MenuItem{
title: 'HeroScript'
href: '/admin/heroscript'
href: '/admin/heroscript'
},
MenuItem{
title: 'Chat'
href: '/admin/chat'
href: '/admin/chat'
},
MenuItem{
title: 'Users'
title: 'Users'
children: [
MenuItem{ title: 'Overview', href: '/admin/users/overview' },
MenuItem{ title: 'Create', href: '/admin/users/create' },
MenuItem{ title: 'Roles', href: '/admin/users/roles' },
MenuItem{
title: 'Overview'
href: '/admin/users/overview'
},
MenuItem{
title: 'Create'
href: '/admin/users/create'
},
MenuItem{
title: 'Roles'
href: '/admin/users/roles'
},
]
},
MenuItem{
title: 'Content'
title: 'Content'
children: [
MenuItem{ title: 'Pages', href: '/admin/content/pages' },
MenuItem{ title: 'Media', href: '/admin/content/media' },
MenuItem{
title: 'Settings'
title: 'Pages'
href: '/admin/content/pages'
},
MenuItem{
title: 'Media'
href: '/admin/content/media'
},
MenuItem{
title: 'Settings'
children: [
MenuItem{ title: 'SEO', href: '/admin/content/settings/seo' },
MenuItem{ title: 'Themes', href: '/admin/content/settings/themes' },
MenuItem{
title: 'SEO'
href: '/admin/content/settings/seo'
},
MenuItem{
title: 'Themes'
href: '/admin/content/settings/themes'
},
]
},
]
},
MenuItem{
title: 'System'
title: 'System'
children: [
MenuItem{ title: 'Status', href: '/admin/system/status' },
MenuItem{ title: 'Logs', href: '/admin/system/logs' },
MenuItem{ title: 'Backups', href: '/admin/system/backups' },
MenuItem{
title: 'Status'
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
}
fn running() !bool {
res := os.execute('${osal.profile_path_source_and()!} caddy version')
if res.exit_code == 0 {
@@ -82,7 +81,6 @@ fn upload() ! {
// )!
}
fn install() ! {
console.print_header('install caddy')
@@ -160,9 +158,6 @@ fn destroy() ! {
// ")!
}
// configure caddy as default webserver & start
// node, path, domain
// path e.g. /var/www

View File

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

View File

@@ -18,7 +18,6 @@ fn get_latest_release() !string {
return release.tag_name
}
// Show current version
latest_release := get_latest_release() or {
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 {
eprintln('Error writing to ${hero_v_path}: ${err}')
// Restore backup
os.cp('${hero_v_path}.backup', hero_v_path) or {
eprintln('Error restoring backup: ${err}')
}
os.cp('${hero_v_path}.backup', hero_v_path) or { eprintln('Error restoring backup: ${err}') }
exit(1)
}
// Clean up backup
os.rm('${hero_v_path}.backup') or {
eprintln('Warning: Could not remove backup file: ${err}')
}
os.rm('${hero_v_path}.backup') or { eprintln('Warning: Could not remove backup file: ${err}') }
// Update version in 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}')
}
cmd:='
cmd := '
git add . -A
git commit -am "bump version to ${new_version}"
git push

View File

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

View File

@@ -26,62 +26,58 @@ pub mut:
pub fn biz_model_example(name string) BizModel {
mut biz_model := BizModel{
name: name
name: name
intlist: []int{len: 10, init: rand.intn(100) or { 0 }}
intstr: []string{len: 10, init: rand.string(5)}
mymap: map[string]SubItem{}
intstr: []string{len: 10, init: rand.string(5)}
mymap: map[string]SubItem{}
}
for i in 0 .. 100 {
sub_item := SubItem{
name: 'SubItem ${i}'
name: 'SubItem ${i}'
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
}
return biz_model
}
pub fn get(name string) !BizModel {
rlock bizmodels {
if ! (name in bizmodels) {
if name !in bizmodels {
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 {
lock bizmodels {
if ! (name in bizmodels) {
set(biz_model_example(name))
if name !in bizmodels {
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) {
lock bizmodels {
bizmodels[bizmodel.name] = bizmodel
}
}
fn fill_biz_models(nr int) {
for i in 0 .. nr {
getset("bm${i}")
getset('bm${i}')
}
rlock bizmodels{
//check we have enough bizmodels in mem
rlock bizmodels {
// check we have enough bizmodels in mem
assert bizmodels.len == nr
}
}
fn get_memory_usage() i64 {
@@ -93,33 +89,32 @@ fn get_memory_usage() i64 {
fn main() {
sw := time.new_stopwatch()
nr:=100
nr_new :=100000 //make small changes, the garbage collector should keep it clean
nr := 100
nr_new := 100000 // make small changes, the garbage collector should keep it clean
fill_biz_models(nr)
println("wait 0.5 sec")
//lets make sure garbage collector works
time.sleep(0.5 * time.second)
println('wait 0.5 sec')
// lets make sure garbage collector works
time.sleep(0.5 * time.second)
memory_usage_1 := get_memory_usage()
println('Memory usage after creating ${nr} BizModels: ${memory_usage_1} KB')
println('Time taken: ${sw.elapsed().milliseconds()} ms')
for _ in 0 .. nr_new {
currentnr:=rand.intn(nr-1) or {panic(err)}
//println(currentnr)
set(biz_model_example("bm${currentnr}")) //will keep on overwriting
currentnr := rand.intn(nr - 1) or { panic(err) }
// println(currentnr)
set(biz_model_example('bm${currentnr}')) // will keep on overwriting
}
println("wait 1 sec")
//lets make sure garbage collector works
println('wait 1 sec')
// lets make sure garbage collector works
time.sleep(1 * time.second)
memory_usage_2 := get_memory_usage()
println('Memory usage after creating ${nr_new} random BizModels: ${memory_usage_2} KB')
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.")
}
}

View File

@@ -25,62 +25,58 @@ pub mut:
pub fn biz_model_example(name string) BizModel {
mut biz_model := BizModel{
name: name
name: name
intlist: []int{len: 10, init: rand.intn(100) or { 0 }}
intstr: []string{len: 10, init: rand.string(5)}
mymap: map[string]SubItem{}
intstr: []string{len: 10, init: rand.string(5)}
mymap: map[string]SubItem{}
}
for i in 0 .. 100 {
sub_item := SubItem{
name: 'SubItem ${i}'
name: 'SubItem ${i}'
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
}
return biz_model
}
pub fn get(name string) !&BizModel {
rlock bizmodels {
if ! (name in bizmodels) {
if name !in bizmodels {
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 {
lock bizmodels {
if ! (name in bizmodels) {
//println("getset ${name}")
new(biz_model_example(name))
if name !in bizmodels {
// println("getset ${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) {
lock bizmodels {
bizmodels[bizmodel.name] = &bizmodel
}
}
fn fill_biz_models(nr int) {
for i in 0 .. nr {
getset("bm${i}")
getset('bm${i}')
}
rlock bizmodels{
rlock bizmodels {
assert bizmodels.len == nr
}
}
fn get_memory_usage() i64 {
@@ -92,28 +88,27 @@ fn get_memory_usage() i64 {
fn main() {
sw := time.new_stopwatch()
nr:=100
nr_new :=100000 //make small changes, the garbage collector should keep it clean
nr := 100
nr_new := 100000 // make small changes, the garbage collector should keep it clean
fill_biz_models(nr)
memory_usage_1 := get_memory_usage()
println('Memory usage after creating ${nr} BizModels: ${memory_usage_1} KB')
println('Time taken: ${sw.elapsed().milliseconds()} ms')
for _ in 0 .. nr_new {
currentnr:=rand.intn(nr-1) or {panic(err)}
mut new_model:= get("bm${currentnr}")!
//new_model.intlist = new_model.intlist.map(it + rand.intn(10) or { 0 })
currentnr := rand.intn(nr - 1) or { panic(err) }
mut new_model := get('bm${currentnr}')!
// new_model.intlist = new_model.intlist.map(it + rand.intn(10) or { 0 })
new_model.intstr = new_model.intstr.map(it + rand.string(2))
//set(new_model) //SHOULD NOT BE NEEDED TO SET BECAUSE IS REFERENCE
mut new_model2:= get("bm${currentnr}")!
assert new_model2.intstr == new_model.intstr //should be same because was a reference
// set(new_model) //SHOULD NOT BE NEEDED TO SET BECAUSE IS REFERENCE
mut new_model2 := get('bm${currentnr}')!
assert new_model2.intstr == new_model.intstr // should be same because was a reference
}
println("wait 1 sec")
//lets make sure garbage collector works, didn't make a difference though
println('wait 1 sec')
// lets make sure garbage collector works, didn't make a difference though
time.sleep(1 * time.second)
memory_usage_2 := get_memory_usage()
@@ -121,4 +116,4 @@ fn main() {
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")
}
}