feat: Add encoderhero and heroscript_dumps/loads

- Add encoderhero import to multiple modules
- Implement heroscript_dumps and heroscript_loads functions
- Update several methods to use `if mut` for cleaner optionals
- Rename rclone globals for clarity
This commit is contained in:
Mahmoud-Emad
2025-10-13 21:49:19 +03:00
parent 25fbc61f49
commit f789564f51
21 changed files with 268 additions and 99 deletions

View File

@@ -2,7 +2,6 @@ module ipapi
import incubaid.herolib.core.base
import incubaid.herolib.core.playbook { PlayBook }
import incubaid.herolib.ui.console
import json
__global (

View File

@@ -1,8 +1,8 @@
module ipapi
import incubaid.herolib.data.paramsparser
import incubaid.herolib.data.encoderhero
import incubaid.herolib.core.httpconnection
import os
pub const version = '1.14.3'
const singleton = false
@@ -11,7 +11,7 @@ const default = true
// TODO: THIS IS EXAMPLE CODE AND NEEDS TO BE CHANGED IN LINE TO STRUCT BELOW, IS STRUCTURED AS HEROSCRIPT
pub fn heroscript_default() !string {
heroscript := "
!!ipapi.configure
!!ipapi.configure
name:'default'
"
@@ -24,7 +24,6 @@ pub fn heroscript_default() !string {
pub struct IPApi {
pub mut:
name string = 'default'
conn ?&httpconnection.HTTPConnection @[str: skip]
}
@@ -42,6 +41,17 @@ fn obj_init(obj_ IPApi) !IPApi {
return obj
}
/////////////NORMALLY NO NEED TO TOUCH
pub fn heroscript_dumps(obj IPApi) !string {
return encoderhero.encode[IPApi](obj)!
}
pub fn heroscript_loads(heroscript string) !IPApi {
mut obj := encoderhero.decode[IPApi](heroscript)!
return obj
}
pub fn (mut client IPApi) connection() !&httpconnection.HTTPConnection {
mut c := client.conn or {
mut c2 := httpconnection.new(

View File

@@ -1,12 +1,18 @@
module mailclient
import incubaid.herolib.data.paramsparser
import incubaid.herolib.data.encoderhero
import os
pub const version = '0.0.0'
const singleton = false
const default = true
@[params]
pub struct DefaultConfigArgs {
instance string = 'default'
}
pub fn heroscript_default(args DefaultConfigArgs) !string {
mail_from := os.getenv_opt('MAIL_FROM') or { 'info@example.com' }
mail_password := os.getenv_opt('MAIL_PASSWORD') or { 'secretpassword' }
@@ -20,7 +26,7 @@ pub fn heroscript_default(args DefaultConfigArgs) !string {
mail_password: '${mail_password}'
mail_port: ${mail_port}
mail_server: '${mail_server}'
mail_username: '${mail_username}'
mail_username: '${mail_username}'
"
return heroscript
@@ -55,3 +61,14 @@ fn obj_init(obj_ MailClient) !MailClient {
mut obj := obj_
return obj
}
/////////////NORMALLY NO NEED TO TOUCH
pub fn heroscript_dumps(obj MailClient) !string {
return encoderhero.encode[MailClient](obj)!
}
pub fn heroscript_loads(heroscript string) !MailClient {
mut obj := encoderhero.decode[MailClient](heroscript)!
return obj
}

View File

@@ -1,8 +1,8 @@
module meilisearch
import incubaid.herolib.data.paramsparser
import incubaid.herolib.data.encoderhero
import incubaid.herolib.core.httpconnection
import os
pub const version = '1.0.0'
const singleton = false
@@ -53,3 +53,14 @@ fn (mut self MeilisearchClient) httpclient() !&httpconnection.HTTPConnection {
}
return http_conn
}
/////////////NORMALLY NO NEED TO TOUCH
pub fn heroscript_dumps(obj MeilisearchClient) !string {
return encoderhero.encode[MeilisearchClient](obj)!
}
pub fn heroscript_loads(heroscript string) !MeilisearchClient {
mut obj := encoderhero.decode[MeilisearchClient](heroscript)!
return obj
}

View File

@@ -44,6 +44,11 @@ fn (mut t HTTPTransport) send(request string, params jsonrpc.SendParams) !string
return response
}
// url implements the IRPCTransportClient interface
fn (t HTTPTransport) url() string {
return t.http_conn.base_url
}
// Admin methods
// get_info gets general info about the node

View File

@@ -15,9 +15,9 @@ pub const default_url = 'http://localhost:8990'
@[heap]
pub struct MyceliumRPC {
pub mut:
name string = 'default'
url string = default_url // RPC server URL
// rpc_client ?&jsonrpc.Client @[skip]
name string = 'default'
url string = default_url // RPC server URL
rpc_client ?&jsonrpc.Client @[skip]
}
// your checking & initialization code if needed

View File

@@ -8,13 +8,6 @@ import os
// name string // name of the remote
// }
// new creates a new RCloneClient instance
pub fn new(name string) !RCloneClient {
return RCloneClient{
name: name
}
}
// mount mounts a remote at the specified path
pub fn (mut r RCloneClient) mount(remote_path string, local_path string) ! {
if !os.exists(local_path) {

View File

@@ -1,6 +1,7 @@
module runpod
import incubaid.herolib.data.paramsparser
import incubaid.herolib.data.encoderhero
import os
pub const version = '1.14.3'
@@ -41,3 +42,14 @@ fn obj_init(obj_ RunPod) !RunPod {
mut obj := obj_
return obj
}
/////////////NORMALLY NO NEED TO TOUCH
pub fn heroscript_dumps(obj RunPod) !string {
return encoderhero.encode[RunPod](obj)!
}
pub fn heroscript_loads(heroscript string) !RunPod {
mut obj := encoderhero.decode[RunPod](heroscript)!
return obj
}

View File

@@ -116,13 +116,12 @@ pub fn (mut e Email) add_content(content []Content) {
}
pub fn (mut e Email) add_headers(headers map[string]string) {
e.headers or {
if mut email_headers := e.headers {
for k, v in headers {
email_headers[k] = v
}
} else {
e.headers = headers.clone()
return
}
for k, v in headers {
e.headers[k] = v
}
}

View File

@@ -1,6 +1,5 @@
module sendgrid
@[params]
pub struct Personalizations {
pub mut:
to []Recipient @[required]
@@ -27,13 +26,12 @@ fn (mut p Personalizations) set_from(r Recipient) {
// add_cc adds an array of recipients who will receive a copy of your email.
fn (mut p Personalizations) add_cc(r []Recipient) {
p.cc or {
if mut cc := p.cc {
for item in r {
cc << item
}
} else {
p.cc = r
return
}
for item in r {
p.cc << item
}
}
@@ -45,26 +43,24 @@ fn (mut p Personalizations) set_subject(s string) {
// add_headers adds a plbook of key/value pairs to specify handling instructions for your email.
// if some of the new headers already existed, their values are overwritten.
fn (mut p Personalizations) add_headers(new_headers map[string]string) {
p.headers or {
if mut headers := p.headers {
for k, v in new_headers {
headers[k] = v
}
} else {
p.headers = new_headers.clone()
return
}
for k, v in new_headers {
p.headers[k] = v
}
}
// add_substitution adds a plbook of key/value pairs to allow you to insert data without using Dynamic Transactional Templates.
// if some of the keys already existed, their values are overwritten.
fn (mut p Personalizations) add_substitution(new_subs map[string]string) {
p.substitutions or {
if mut substitutions := p.substitutions {
for k, v in new_subs {
substitutions[k] = v
}
} else {
p.substitutions = new_subs.clone()
return
}
for k, v in new_subs {
p.substitutions[k] = v
}
}
@@ -72,13 +68,12 @@ fn (mut p Personalizations) add_substitution(new_subs map[string]string) {
// Dynamic template data is available using Handlebars syntax in Dynamic Transactional Templates.
// if some of the keys already existed, their values are overwritten.
fn (mut p Personalizations) add_dynamic_template_data(new_dynamic_template_data map[string]string) {
p.dynamic_template_data or {
if mut dynamic_template_data := p.dynamic_template_data {
for k, v in new_dynamic_template_data {
dynamic_template_data[k] = v
}
} else {
p.dynamic_template_data = new_dynamic_template_data.clone()
return
}
for k, v in new_dynamic_template_data {
p.dynamic_template_data[k] = v
}
}
@@ -86,13 +81,12 @@ fn (mut p Personalizations) add_dynamic_template_data(new_dynamic_template_data
// custom args are values that are specific to this personalization that will be carried along with the email and its activity data.
// if some of the keys already existed, their values are overwritten.
fn (mut p Personalizations) add_custom_args(new_custom_args map[string]string) {
p.custom_args or {
if mut custom_args := p.custom_args {
for k, v in new_custom_args {
custom_args[k] = v
}
} else {
p.custom_args = new_custom_args.clone()
return
}
for k, v in new_custom_args {
p.custom_args[k] = v
}
}

View File

@@ -1,7 +1,6 @@
module sendgrid
import incubaid.herolib.data.paramsparser
import os
import incubaid.herolib.data.encoderhero
pub const version = '0.0.0'
const singleton = true
@@ -26,3 +25,14 @@ fn obj_init(obj_ SendGrid) !SendGrid {
panic('implement')
return obj
}
/////////////NORMALLY NO NEED TO TOUCH
pub fn heroscript_dumps(obj SendGrid) !string {
return encoderhero.encode[SendGrid](obj)!
}
pub fn heroscript_loads(heroscript string) !SendGrid {
mut obj := encoderhero.decode[SendGrid](heroscript)!
return obj
}

View File

@@ -1,6 +1,7 @@
module vastai
import incubaid.herolib.data.paramsparser
import incubaid.herolib.data.encoderhero
import incubaid.herolib.core.httpconnection
import os
@@ -57,3 +58,14 @@ fn (mut v VastAI) httpclient() !&httpconnection.HTTPConnection {
return http_conn
}
/////////////NORMALLY NO NEED TO TOUCH
pub fn heroscript_dumps(obj VastAI) !string {
return encoderhero.encode[VastAI](obj)!
}
pub fn heroscript_loads(heroscript string) !VastAI {
mut obj := encoderhero.decode[VastAI](heroscript)!
return obj
}

View File

@@ -1,6 +1,7 @@
module wireguard
import incubaid.herolib.data.paramsparser
import incubaid.herolib.data.encoderhero
pub const version = '1.14.3'
const singleton = false
@@ -36,3 +37,14 @@ fn obj_init(obj_ WireGuard) !WireGuard {
mut obj := obj_
return obj
}
/////////////NORMALLY NO NEED TO TOUCH
pub fn heroscript_dumps(obj WireGuard) !string {
return encoderhero.encode[WireGuard](obj)!
}
pub fn heroscript_loads(heroscript string) !WireGuard {
mut obj := encoderhero.decode[WireGuard](heroscript)!
return obj
}

View File

@@ -12,7 +12,7 @@ pub mut:
// examples:
// localhost:6379
// /tmp/redis-default.sock
pub fn get(addr string, auth string, namespace string) !ZDB {
pub fn get_zdb(addr string, auth string, namespace string) !ZDB {
console.print_header(' ZDB get: addr:${addr} namespace:${namespace}')
mut redis := redisclient.new(addr)!
mut zdb := ZDB{

View File

@@ -1,6 +1,7 @@
module zerodb_client
import incubaid.herolib.data.paramsparser
import incubaid.herolib.data.encoderhero
import os
pub const version = '0.0.0'
@@ -26,3 +27,14 @@ fn obj_init(obj_ ZeroDBClient) !ZeroDBClient {
panic('implement')
return obj
}
/////////////NORMALLY NO NEED TO TOUCH
pub fn heroscript_dumps(obj ZeroDBClient) !string {
return encoderhero.encode[ZeroDBClient](obj)!
}
pub fn heroscript_loads(heroscript string) !ZeroDBClient {
mut obj := encoderhero.decode[ZeroDBClient](heroscript)!
return obj
}

View File

@@ -0,0 +1,102 @@
module playcmds
import incubaid.herolib.core.playbook
import incubaid.herolib.clients.giteaclient
import incubaid.herolib.clients.ipapi
import incubaid.herolib.clients.jina
import incubaid.herolib.clients.mailclient
import incubaid.herolib.clients.meilisearch
import incubaid.herolib.clients.mycelium
import incubaid.herolib.clients.mycelium_rpc
import incubaid.herolib.clients.openai
import incubaid.herolib.clients.postgresql_client
import incubaid.herolib.clients.qdrant
import incubaid.herolib.clients.rclone
import incubaid.herolib.clients.runpod
import incubaid.herolib.clients.sendgrid
import incubaid.herolib.clients.vastai
import incubaid.herolib.clients.wireguard
import incubaid.herolib.clients.zerodb_client
import incubaid.herolib.clients.zinit
import incubaid.herolib.develop.heroprompt
import incubaid.herolib.installers.db.meilisearch_installer
import incubaid.herolib.installers.infra.coredns
import incubaid.herolib.installers.infra.gitea
import incubaid.herolib.installers.infra.livekit
import incubaid.herolib.installers.infra.zinit_installer
import incubaid.herolib.installers.lang.golang
import incubaid.herolib.installers.lang.nodejs
import incubaid.herolib.installers.lang.python
import incubaid.herolib.installers.lang.rust
import incubaid.herolib.installers.net.mycelium_installer
import incubaid.herolib.installers.net.wireguard_installer
import incubaid.herolib.installers.sysadmintools.b2
import incubaid.herolib.installers.sysadmintools.garage_s3
import incubaid.herolib.installers.threefold.griddriver
import incubaid.herolib.installers.virt.cloudhypervisor
import incubaid.herolib.installers.virt.docker
import incubaid.herolib.installers.virt.herorunner
import incubaid.herolib.installers.virt.lima
import incubaid.herolib.installers.virt.pacman
import incubaid.herolib.installers.virt.podman
import incubaid.herolib.installers.virt.youki
import incubaid.herolib.installers.web.bun
import incubaid.herolib.installers.web.tailwind
import incubaid.herolib.installers.web.tailwind4
import incubaid.herolib.installers.web.traefik
import incubaid.herolib.installers.web.zola
import incubaid.herolib.virt.hetznermanager
pub fn run_all(args_ PlayArgs) ! {
mut args := args_
// println('DEBUG: the args is: @{args}')
mut plbook := args.plbook or {
playbook.new(text: args.heroscript, path: args.heroscript_path)!
}
giteaclient.play(mut plbook)!
ipapi.play(mut plbook)!
jina.play(mut plbook)!
mailclient.play(mut plbook)!
meilisearch.play(mut plbook)!
mycelium.play(mut plbook)!
mycelium_rpc.play(mut plbook)!
openai.play(mut plbook)!
postgresql_client.play(mut plbook)!
qdrant.play(mut plbook)!
rclone.play(mut plbook)!
runpod.play(mut plbook)!
sendgrid.play(mut plbook)!
vastai.play(mut plbook)!
wireguard.play(mut plbook)!
zerodb_client.play(mut plbook)!
zinit.play(mut plbook)!
heroprompt.play(mut plbook)!
meilisearch_installer.play(mut plbook)!
coredns.play(mut plbook)!
gitea.play(mut plbook)!
livekit.play(mut plbook)!
zinit_installer.play(mut plbook)!
golang.play(mut plbook)!
nodejs.play(mut plbook)!
python.play(mut plbook)!
rust.play(mut plbook)!
mycelium_installer.play(mut plbook)!
wireguard_installer.play(mut plbook)!
b2.play(mut plbook)!
garage_s3.play(mut plbook)!
griddriver.play(mut plbook)!
cloudhypervisor.play(mut plbook)!
docker.play(mut plbook)!
herorunner.play(mut plbook)!
lima.play(mut plbook)!
pacman.play(mut plbook)!
podman.play(mut plbook)!
youki.play(mut plbook)!
bun.play(mut plbook)!
tailwind.play(mut plbook)!
tailwind4.play(mut plbook)!
traefik.play(mut plbook)!
zola.play(mut plbook)!
hetznermanager.play(mut plbook)!
}

View File

@@ -3,7 +3,6 @@ module rust
import incubaid.herolib.osal.core as osal
import incubaid.herolib.ui.console
import incubaid.herolib.core.texttools
import incubaid.herolib.core.pathlib
import incubaid.herolib.core
import incubaid.herolib.installers.base
import incubaid.herolib.installers.ulist

View File

@@ -4,11 +4,10 @@ import incubaid.herolib.core.base
import incubaid.herolib.core.playbook { PlayBook }
import incubaid.herolib.ui.console
import json
import incubaid.herolib.osal.startupmanager
__global (
rclone_global map[string]&RClone
rclone_default string
rclone_installer_global map[string]&RClone
rclone_installer_default string
)
/////////FACTORY
@@ -31,8 +30,8 @@ pub fn new(args ArgsGet) !&RClone {
pub fn get(args ArgsGet) !&RClone {
mut context := base.context()!
rclone_default = args.name
if args.fromdb || args.name !in rclone_global {
rclone_installer_default = args.name
if args.fromdb || args.name !in rclone_installer_global {
mut r := context.redis()!
if r.hexists('context:rclone', args.name)! {
data := r.hget('context:rclone', args.name)!
@@ -52,7 +51,7 @@ pub fn get(args ArgsGet) !&RClone {
}
return get(name: args.name)! // no longer from db nor create
}
return rclone_global[args.name] or {
return rclone_installer_global[args.name] or {
print_backtrace()
return error('could not get config for rclone with name:rclone')
}
@@ -61,7 +60,7 @@ pub fn get(args ArgsGet) !&RClone {
// register the config for the future
pub fn set(o RClone) ! {
mut o2 := set_in_mem(o)!
rclone_default = o2.name
rclone_installer_default = o2.name
mut context := base.context()!
mut r := context.redis()!
r.hset('context:rclone', o2.name, json.encode(o2))!
@@ -92,8 +91,8 @@ pub fn list(args ArgsList) ![]&RClone {
mut context := base.context()!
if args.fromdb {
// reset what is in mem
rclone_global = map[string]&RClone{}
rclone_default = ''
rclone_installer_global = map[string]&RClone{}
rclone_installer_default = ''
}
if args.fromdb {
mut r := context.redis()!
@@ -105,7 +104,7 @@ pub fn list(args ArgsList) ![]&RClone {
return res
} else {
// load from memory
for _, client in rclone_global {
for _, client in rclone_installer_global {
res << client
}
}
@@ -115,8 +114,8 @@ pub fn list(args ArgsList) ![]&RClone {
// only sets in mem, does not set as config
fn set_in_mem(o RClone) !RClone {
mut o2 := obj_init(o)!
rclone_global[o2.name] = &o2
rclone_default = o2.name
rclone_installer_global[o2.name] = &o2
rclone_installer_default = o2.name
return o2
}
@@ -181,5 +180,5 @@ pub fn (mut self RClone) destroy() ! {
// switch instance to be used for rclone
pub fn switch(name string) {
rclone_default = name
rclone_installer_default = name
}

View File

@@ -1,8 +1,6 @@
module rclone
import incubaid.herolib.data.paramsparser
import incubaid.herolib.data.encoderhero
import os
pub const version = '1.67.0'
const singleton = false

View File

@@ -34,6 +34,12 @@ fn ulist_get() !ulist.UList {
// uploads to S3 server if configured
fn upload() ! {}
fn build() ! {
// griddriver is distributed as a binary, no build needed
// just call install
install()!
}
fn install() ! {
console.print_header('installing griddriver')
mut url := ''

View File

@@ -2,29 +2,15 @@ module youki
import incubaid.herolib.osal.core as osal
import incubaid.herolib.ui.console
import incubaid.herolib.core.texttools
import incubaid.herolib.core.pathlib
import incubaid.herolib.develop.gittools
import incubaid.herolib.installers.ulist
import incubaid.herolib.installers.lang.golang
import incubaid.herolib.installers.lang.rust
import incubaid.herolib.installers.lang.python
import os
import incubaid.herolib.installers.lang.rust as rust_installer
// checks if a certain version or above is installed
fn installed() !bool {
// THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED
// res := os.execute('${osal.profile_path_source_and()!} youki version')
// if res.exit_code != 0 {
// return false
// }
// r := res.output.split_into_lines().filter(it.trim_space().len > 0)
// if r.len != 1 {
// return error("couldn't parse youki version.\n${res.output}")
// }
// if texttools.version(version) > texttools.version(r[0]) {
// return false
// }
if osal.cmd_exists('youki') {
return true
}
return false
}
@@ -38,6 +24,7 @@ fn build() ! {
// mut installer := get()!
url := 'https://github.com/containers/youki'
mut rust := rust_installer.get()!
rust.install()!
console.print_header('build youki')
@@ -67,19 +54,11 @@ fn build() ! {
// get the Upload List of the files
fn ulist_get() !ulist.UList {
// mut installer := get()!
// optionally build a UList which is all paths which are result of building, is then used e.g. in upload
return ulist.UList{}
}
// uploads to S3 server if configured
fn upload() ! {
// mut installer := get()!
// installers.upload(
// cmdname: 'youki'
// source: '${gitpath}/target/x86_64-unknown-linux-musl/release/youki'
// )!
}
fn upload() ! {}
fn destroy() ! {
osal.package_remove('