Files
herolib/aiprompts/instructions_archive/models_from_v/complete.md
2025-09-14 19:08:13 +02:00

73 KiB

<file_map> /Users/despiegk/code/github/incubaid/herolib └── aiprompts └── herolib_core ├── core_curdir_example.md ├── core_globals.md ├── core_heroscript_basics.md ├── core_heroscript_playbook.md ├── core_http_client.md ├── core_osal.md ├── core_ourtime.md ├── core_params.md ├── core_paths.md ├── core_text.md ├── core_ui_console.md └── core_vshell.md

/Users/despiegk/code/git.threefold.info/herocode/db ├── _archive │ ├── acldb │ │ ├── src │ │ │ ├── acl.rs │ │ │ ├── error.rs │ │ │ ├── lib.rs │ │ │ ├── main.rs │ │ │ ├── rpc.rs │ │ │ ├── server.rs │ │ │ ├── topic.rs │ │ │ └── utils.rs │ │ ├── static │ │ │ ├── openapi.json │ │ │ └── swagger-ui.html │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ └── README.md │ ├── adapter_macros │ │ ├── src │ │ │ └── lib.rs │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ └── README.md │ ├── herodb_old │ │ ├── aiprompts │ │ │ ├── builderparadigm.md │ │ │ ├── moduledocu.md │ │ │ ├── rhaiwrapping_advanced.md │ │ │ ├── rhaiwrapping_best_practices.md │ │ │ └── rhaiwrapping.md │ │ ├── examples │ │ │ ├── business_models_demo.rs │ │ │ ├── circle_basic_demo.rs │ │ │ ├── circle_models_demo.rs │ │ │ ├── circle_standalone.rs │ │ │ ├── ourdb_example.rs │ │ │ └── tst_index_example.rs │ │ ├── src │ │ │ ├── cmd │ │ │ │ ├── dbexample_biz │ │ │ │ │ ├── main.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── README.md │ │ │ │ ├── dbexample_gov │ │ │ │ │ └── main.rs │ │ │ │ ├── dbexample_mcc │ │ │ │ │ └── main.rs │ │ │ │ ├── dbexample_prod │ │ │ │ │ └── main.rs │ │ │ │ └── mod.rs │ │ │ ├── db │ │ │ │ ├── db.rs │ │ │ │ ├── error.rs │ │ │ │ ├── generic_store.rs │ │ │ │ ├── macros.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── model_methods.rs │ │ │ │ ├── model.rs │ │ │ │ ├── store.rs │ │ │ │ ├── tests.rs │ │ │ │ └── tst_index.rs │ │ │ ├── models │ │ │ │ ├── biz │ │ │ │ │ ├── rhai │ │ │ │ │ │ ├── examples │ │ │ │ │ │ │ ├── example.rhai │ │ │ │ │ │ │ └── example.rs │ │ │ │ │ │ ├── src │ │ │ │ │ │ │ ├── engine.rs │ │ │ │ │ │ │ ├── generic_wrapper.rs │ │ │ │ │ │ │ ├── lib.rs │ │ │ │ │ │ │ └── wrapper.rs │ │ │ │ │ │ ├── Cargo.lock │ │ │ │ │ │ └── Cargo.toml │ │ │ │ │ ├── contract.rs │ │ │ │ │ ├── currency.rs │ │ │ │ │ ├── customer.rs │ │ │ │ │ ├── exchange_rate.rs │ │ │ │ │ ├── invoice.rs │ │ │ │ │ ├── lib.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── product.rs │ │ │ │ │ ├── README.md │ │ │ │ │ ├── sale.rs │ │ │ │ │ └── service.rs │ │ │ │ ├── circle │ │ │ │ │ ├── circle.rs │ │ │ │ │ ├── lib.rs │ │ │ │ │ ├── member.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── name.rs │ │ │ │ │ ├── README.md │ │ │ │ │ └── wallet.rs │ │ │ │ ├── gov │ │ │ │ │ ├── committee.rs │ │ │ │ │ ├── company.rs │ │ │ │ │ ├── meeting.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── README.md │ │ │ │ │ ├── resolution.rs │ │ │ │ │ ├── shareholder.rs │ │ │ │ │ ├── user.rs │ │ │ │ │ └── vote.rs │ │ │ │ ├── mcc │ │ │ │ │ ├── calendar.rs │ │ │ │ │ ├── contacts.rs │ │ │ │ │ ├── event.rs │ │ │ │ │ ├── lib.rs │ │ │ │ │ ├── mail.rs │ │ │ │ │ ├── message.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── README.md │ │ │ │ ├── py │ │ │ │ │ ├── init.py │ │ │ │ │ ├── api.py │ │ │ │ │ ├── business.db │ │ │ │ │ ├── example.py │ │ │ │ │ ├── install_and_run.sh │ │ │ │ │ ├── models.py │ │ │ │ │ ├── README.md │ │ │ │ │ └── server.sh │ │ │ │ ├── instructions.md │ │ │ │ └── mod.rs │ │ │ ├── rhaiengine │ │ │ │ ├── engine.rs │ │ │ │ └── mod.rs │ │ │ ├── error.rs │ │ │ ├── instructions.md │ │ │ ├── lib.rs │ │ │ └── mod.rs │ │ ├── .gitignore │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ └── README.md │ ├── websocket │ │ └── architecture.md │ ├── instructions.md │ └── rhai.rs ├── herodb_old │ └── tmp │ └── circle_demo │ ├── circle │ │ └── circle │ │ └── lookup │ │ ├── .inc │ │ └── data │ ├── member │ │ └── member │ │ └── lookup │ │ ├── .inc │ │ └── data │ ├── name │ │ └── name │ │ └── lookup │ │ ├── .inc │ │ └── data │ └── wallet │ └── wallet │ └── lookup │ ├── .inc │ └── data ├── heromodels │ ├── docs │ │ ├── prompts │ │ │ ├── new_rhai_rs_gen.md │ │ │ └── rhai_rs_generation_prompt.md │ │ ├── herodb_ourdb_migration_plan.md │ │ ├── mcc_models_standalone_plan.md │ │ ├── model_trait_unification_plan.md │ │ ├── payment_usage.md │ │ ├── sigsocket_architecture.md │ │ ├── tst_implementation_plan.md │ │ └── tst_integration_plan.md │ ├── examples │ │ ├── biz_rhai │ │ │ ├── payment_flow_example.rs │ │ │ └── payment_flow.rhai │ │ ├── calendar_example │ │ │ └── main.rs │ │ ├── finance_example │ │ │ └── main.rs │ │ ├── governance_proposal_example │ │ │ └── main.rs │ │ ├── basic_user_example.rs │ │ ├── custom_model_example.rs │ │ ├── flow_example.rs │ │ ├── governance_activity_example.rs │ │ ├── legal_contract_example.rs │ │ ├── marketplace_example.rs │ │ ├── model_macro_example.rs │ │ ├── payment_flow_example.rs │ │ ├── simple_model_example.rs │ │ ├── test_reminder_functionality.rs │ │ └── test_signature_functionality.rs │ ├── src │ │ ├── db │ │ │ ├── fjall.rs │ │ │ └── hero.rs │ │ ├── herodb │ │ │ ├── db.rs │ │ │ ├── error.rs │ │ │ ├── generic_store.rs │ │ │ ├── macros.rs │ │ │ ├── mod.rs │ │ │ ├── model_methods.rs │ │ │ ├── model.rs │ │ │ ├── store.rs │ │ │ ├── tests.rs │ │ │ └── tst_index.rs │ │ ├── models │ │ │ ├── access │ │ │ │ ├── access.rs │ │ │ │ ├── mod.rs │ │ │ │ └── README.md │ │ │ ├── biz │ │ │ │ ├── company.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── payment.rs │ │ │ │ ├── product.rs │ │ │ │ ├── README.md │ │ │ │ ├── sale.rs │ │ │ │ └── shareholder.rs │ │ │ ├── calendar │ │ │ │ ├── calendar.rs │ │ │ │ ├── mod.rs │ │ │ │ └── README.md │ │ │ ├── circle │ │ │ │ ├── circle.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── README.md │ │ │ │ └── rhai.rs │ │ │ ├── contact │ │ │ │ ├── contact.rs │ │ │ │ ├── mod.rs │ │ │ │ └── README.md │ │ │ ├── core │ │ │ │ ├── comment.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── model.rs │ │ │ │ └── README.md │ │ │ ├── finance │ │ │ │ ├── account.rs │ │ │ │ ├── asset.rs │ │ │ │ ├── marketplace.rs │ │ │ │ ├── mod.rs │ │ │ │ └── README.md │ │ │ ├── flow │ │ │ │ ├── flow_step.rs │ │ │ │ ├── flow.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── README.md │ │ │ │ └── signature_requirement.rs │ │ │ ├── gov │ │ │ │ ├── committee.rs │ │ │ │ ├── company.rs │ │ │ │ ├── meeting.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── README.md │ │ │ │ ├── resolution.rs │ │ │ │ ├── shareholder.rs │ │ │ │ ├── user.rs │ │ │ │ └── vote.rs │ │ │ ├── governance │ │ │ │ ├── activity.rs │ │ │ │ ├── attached_file.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── proposal.rs │ │ │ │ └── README.md │ │ │ ├── legal │ │ │ │ ├── contract.rs │ │ │ │ ├── mod.rs │ │ │ │ └── README.md │ │ │ ├── library │ │ │ │ ├── collection.rs │ │ │ │ ├── items.rs │ │ │ │ ├── mod.rs │ │ │ │ └── README.md │ │ │ ├── log │ │ │ │ ├── log.rs │ │ │ │ ├── mod.rs │ │ │ │ └── README.md │ │ │ ├── object │ │ │ │ ├── mod.rs │ │ │ │ ├── object.rs │ │ │ │ └── README.md │ │ │ ├── projects │ │ │ │ ├── base.rs │ │ │ │ ├── epic.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── README.md │ │ │ │ ├── sprint_enums.rs │ │ │ │ ├── sprint.rs │ │ │ │ ├── task_enums.rs │ │ │ │ └── task.rs │ │ │ ├── userexample │ │ │ │ ├── mod.rs │ │ │ │ ├── README.md │ │ │ │ └── user.rs │ │ │ ├── lib.rs │ │ │ └── mod.rs │ │ ├── db.rs │ │ └── lib.rs │ ├── tests │ │ └── payment.rs │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ └── run_all_examples.sh ├── heromodels_core │ ├── src │ │ ├── base_data_builder.rs │ │ └── lib.rs │ ├── Cargo.lock │ └── Cargo.toml ├── heromodels-derive │ ├── src │ │ └── lib.rs │ ├── tests │ │ └── test_model_macro.rs │ ├── Cargo.lock │ └── Cargo.toml ├── ourdb │ ├── examples │ │ ├── advanced_usage.rs │ │ ├── basic_usage.rs │ │ ├── benchmark.rs │ │ ├── main.rs │ │ └── standalone_ourdb_example.rs │ ├── src │ │ ├── backend.rs │ │ ├── error.rs │ │ ├── lib.rs │ │ ├── location.rs │ │ └── lookup.rs │ ├── tests │ │ └── integration_tests.rs │ ├── API.md │ ├── architecture.md │ ├── Cargo.lock │ ├── Cargo.toml │ └── README.md ├── radixtree │ ├── benches │ │ └── radixtree_benchmarks.rs │ ├── examples │ │ ├── basic_usage.rs │ │ ├── large_scale_test.rs │ │ ├── performance_test.rs │ │ └── prefix_operations.rs │ ├── src │ │ ├── error.rs │ │ ├── lib.rs │ │ ├── node.rs │ │ ├── operations.rs │ │ └── serialize.rs │ ├── tests │ │ ├── basic_test.rs │ │ ├── getall_test.rs │ │ ├── prefix_test.rs │ │ └── serialize_test.rs │ ├── ARCHITECTURE.md │ ├── Cargo.lock │ ├── Cargo.toml │ ├── MIGRATION.md │ └── README.md ├── rhai_client_example │ ├── src │ │ └── main.rs │ ├── Cargo.lock │ └── Cargo.toml ├── rhai_client_macros │ ├── src │ │ └── lib.rs │ ├── Cargo.lock │ └── Cargo.toml ├── specs │ └── models │ ├── base │ │ └── base.v │ ├── biz │ │ ├── company.v │ │ ├── product.v │ │ ├── sale.v │ │ ├── shareholder.v │ │ └── user.v │ ├── circle │ │ ├── attachment.v │ │ ├── config.v │ │ ├── domainnames.v │ │ ├── group.v │ │ └── user.v │ ├── crm │ │ ├── account.v │ │ ├── call.v │ │ ├── campaign.v │ │ ├── case.v │ │ ├── contact.v │ │ ├── lead.v │ │ ├── opportunity.v │ │ └── task.v │ ├── finance │ │ ├── account.v │ │ ├── asset.v │ │ └── marketplace.v │ ├── flow │ │ └── flow.v │ ├── governance │ │ └── proposal.v │ ├── legal │ │ └── contract.v │ ├── mcc │ │ ├── calendar.v │ │ ├── contacts.v │ │ ├── message.v │ │ └── README.md │ ├── projects │ │ ├── base.v │ │ ├── epic.v │ │ ├── issue.v │ │ ├── kanban.v │ │ ├── sprint.v │ │ └── story.v │ ├── ticket │ │ ├── ticket_comment.v │ │ ├── ticket_enums.v │ │ └── ticket.v │ └── user.v ├── tst │ ├── examples │ │ ├── basic_usage.rs │ │ ├── performance.rs │ │ └── prefix_ops.rs │ ├── src │ │ ├── error.rs │ │ ├── lib.rs │ │ ├── node.rs │ │ ├── operations.rs │ │ └── serialize.rs │ ├── tests │ │ ├── basic_test.rs │ │ └── prefix_test.rs │ ├── Cargo.lock │ ├── Cargo.toml │ └── README.md ├── .gitignore └── rust-toolchain.toml

</file_map>

<file_contents> File: /Users/despiegk/code/github/incubaid/herolib/aiprompts/herolib_core/core_curdir_example.md

# Getting the Current Script's Path in Herolib/V Shell

can be used in any .v or .vsh script, easy to find content close to the script itself.

```v
#!/usr/bin/env vsh

const script_path = os.dir(@FILE) + '/scripts'
echo "Current scripts directory: ${script_directory}"


File: /Users/despiegk/code/github/incubaid/herolib/aiprompts/herolib_core/core_globals.md
```md
## how to remember clients, installers as a global

the following is a good pragmatic way to remember clients, installers as a global, use it as best practice.

```vmodule docsite

module docsite

import freeflowuniverse.herolib.core.texttools

__global (
	siteconfigs  map[string]&SiteConfig
)

@[params]
pub struct FactoryArgs {
pub mut:
	name string = "default"
}

pub fn new(args FactoryArgs) !&SiteConfig {
	name := texttools.name_fix(args.name)
	siteconfigs[name] = &SiteConfig{
		name: name
	}
	return get(name:name)!
}

pub fn get(args FactoryArgs) !&SiteConfig {
	name := texttools.name_fix(args.name)
	mut sc := siteconfigs[name] or {
		return error('siteconfig with name "${name}" does not exist')
	}
	return sc
}

pub fn default() !&SiteConfig {
	if siteconfigs.len == 0 {
		return new(name:'default')!
	}
	return get()!
}


File: /Users/despiegk/code/github/incubaid/herolib/aiprompts/herolib_core/core_heroscript_basics.md
```md
# HeroScript: Vlang Integration

## HeroScript Structure

HeroScript is a concise scripting language with the following structure:

```heroscript
!!actor.action_name
	param1: 'value1'
	param2: 'value with spaces'
	multiline_description: '
		This is a multiline description.
		It can span multiple lines.
		'
	arg1 arg2 // Arguments without keys

Key characteristics:

  • Actions: Start with !!, followed by actor.action_name (e.g., !!mailclient.configure).
  • Parameters: Defined as key:value. Values can be quoted for spaces.
  • Multiline Support: Parameters like description can span multiple lines.
  • Arguments: Values without keys (e.g., arg1).

Processing HeroScript in Vlang

HeroScript can be parsed into a playbook.PlayBook object, allowing structured access to actions and their parameters, this is used in most of the herolib modules, it allows configuration or actions in a structured way.

import freeflowuniverse.herolib.core.playbook { PlayBook }
import freeflowuniverse.herolib.ui.console

pub fn play(mut plbook PlayBook) ! {

	if plbook.exists_once(filter: 'docusaurus.define') {
		mut action := plbook.get(filter: 'docusaurus.define')!
		mut p := action.params
		//example how we get parameters from the action see core_params.md for more details
		ds = new(
			path: p.get_default('path_publish', '')!
			production:   p.get_default_false('production')
		)!
	}

	// Process 'docusaurus.add' actions to configure individual Docusaurus sites
	actions := plbook.find(filter: 'docusaurus.add')!
	for action in actions {
		mut p := action.params
		//do more processing here
	}
}

For detailed information on parameter retrieval methods (e.g., p.get(), p.get_int(), p.get_default_true()), refer to aiprompts/ai_core/core_params.md.


File: /Users/despiegk/code/github/incubaid/herolib/aiprompts/herolib_core/core_heroscript_playbook.md
```md
# PlayBook

## get & execute a playbook

HeroScript can be parsed into a `playbook.PlayBook` object, allowing structured access to actions and their parameters.

```v
import freeflowuniverse.herolib.core.playbook
import freeflowuniverse.herolib.core.playcmds

// path string
// text string
// git_url string
// git_pull bool
// git_branch string
// git_reset bool
// session  ?&base.Session      is optional
mut plbook := playbook.new(path: "....")!

//now we run all the commands as they are pre-defined in herolib, this will execute the playbook and do all actions.
playcmds.run(mut plbook)!


File: /Users/despiegk/code/github/incubaid/herolib/aiprompts/herolib_core/core_http_client.md
```md
# HTTPConnection Module

The `HTTPConnection` module provides a robust HTTP client for Vlang, supporting JSON, custom headers, retries, and caching.

## Key Features
- Type-safe JSON methods
- Custom headers
- Retry mechanism
- Caching
- URL encoding

## Basic Usage

```v
import freeflowuniverse.herolib.core.httpconnection

// Create a new HTTP connection
mut conn := httpconnection.new(
    name: 'my_api_client'
    url: 'https://api.example.com'
    retry: 3 // Number of retries for failed requests
    cache: true // Enable caching
)!

Integration with Management Classes

To integrate HTTPConnection into a management class (e.g., HetznerManager), use a method to lazily initialize and return the connection:

// Example: HetznerManager
pub fn (mut h HetznerManager) connection() !&httpconnection.HTTPConnection {
	mut c := h.conn or {
		mut c2 := httpconnection.new(
			name:  'hetzner_${h.name}'
			url:   h.baseurl
			cache: true
			retry: 3
		)!
		c2.basic_auth(h.user, h.password)
		c2
	}
	return c
}

Examples

GET Request with JSON Response

struct User {
    id    int
    name  string
    email string
}

user := conn.get_json_generic[User](
    prefix: 'users/1'
)!

POST Request with JSON Data

struct NewUserResponse {
    id int
    status string
}

new_user_resp := conn.post_json_generic[NewUserResponse](
    prefix: 'users'
    params: {
        'name': 'Jane Doe'
        'email': 'jane@example.com'
    }
)!

Custom Headers

Set default headers or add them per request:

import net.http { Header }

// Set default header
conn.default_header = http.new_header(key: .authorization, value: 'Bearer your-token')

// Add custom header for a specific request
response := conn.get_json(
    prefix: 'protected/resource'
    header: http.new_header(key: .content_type, value: 'application/json')
)!

Error Handling

Methods return a Result type for error handling:

user := conn.get_json_generic[User](
    prefix: 'users/1'
) or {
    println('Error fetching user: ${err}')
    return
}

File: /Users/despiegk/code/github/incubaid/herolib/aiprompts/herolib_core/core_osal.md

# OSAL Core Module - Key Capabilities (freeflowuniverse.herolib.osal.core)


```v
//example how to get started

import freeflowuniverse.herolib.osal.core as osal

osal.exec(cmd:"ls /")!

this document has info about the most core functions, more detailed info can be found in aiprompts/herolib_advanced/osal.md if needed.

Key Functions

1. Process Execution

  • osal.exec(cmd: Command) !Job: Execute a shell command.
    • Key Parameters: cmd (string), timeout (int), retry (int), work_folder (string), environment (map[string]string), stdout (bool), raise_error (bool).
    • Returns: Job (status, output, error, exit code).
  • osal.execute_silent(cmd string) !string: Execute silently, return output.
  • osal.cmd_exists(cmd string) bool: Check if a command exists.
  • osal.process_kill_recursive(args: ProcessKillArgs) !: Kill a process and its children.

2. Network Utilities

  • osal.ping(args: PingArgs) !bool: Check host reachability.
  • osal.tcp_port_test(args: TcpPortTestArgs) bool: Test if a TCP port is open.
    • Key Parameters: address (string), port (int).
  • osal.ipaddr_pub_get() !string: Get public IP address.

3. File System Operations

  • osal.file_write(path string, text string) !: Write text to a file.
  • osal.file_read(path string) !string: Read content from a file.
  • osal.dir_ensure(path string) !: Ensure a directory exists.
  • osal.rm(todelete string) !: Remove files/directories.

4. Environment Variables

  • osal.env_set(args: EnvSet): Set an environment variable.
    • Key Parameters: key (string), value (string).
  • osal.env_get(key string) !string: Get an environment variable's value.
  • osal.load_env_file(file_path string) !: Load variables from a file.

5. Command & Profile Management

  • osal.cmd_add(args: CmdAddArgs) !: Add a binary to system paths and update profiles.
    • Key Parameters: source (string, required), cmdname (string).
  • osal.profile_path_add_remove(args: ProfilePathAddRemoveArgs) !: Add/remove paths from profiles.
    • Key Parameters: paths2add (string), paths2delete (string).

6. System Information

  • osal.platform() !PlatformType: Identify the operating system.
  • osal.cputype() !CPUType: Identify the CPU architecture.
  • osal.hostname() !string: Get system hostname.


File: /Users/despiegk/code/github/incubaid/herolib/aiprompts/herolib_core/core_ourtime.md
```md
# OurTime Module

The `OurTime` module in V provides flexible time handling, supporting relative and absolute time formats, Unix timestamps, and formatting utilities.

## Key Features
- Create time objects from strings or current time
- Relative time expressions (e.g., `+1h`, `-2d`)
- Absolute time formats (e.g., `YYYY-MM-DD HH:mm:ss`)
- Unix timestamp conversion
- Time formatting and warping

## Basic Usage

```v
import freeflowuniverse.herolib.data.ourtime

// Current time
mut t := ourtime.now()

// From string
t2 := ourtime.new('2022-12-05 20:14:35')!

// Get formatted string
println(t2.str()) // e.g., 2022-12-05 20:14

// Get Unix timestamp
println(t2.unix()) // e.g., 1670271275

Time Formats

Relative Time

Use s (seconds), h (hours), d (days), w (weeks), M (months), Q (quarters), Y (years).

// Create with relative time
mut t := ourtime.new('+1w +2d -4h')!

// Warp existing time
mut t2 := ourtime.now()
t2.warp('+1h')!

Absolute Time

Supports YYYY-MM-DD HH:mm:ss, YYYY-MM-DD HH:mm, YYYY-MM-DD HH, YYYY-MM-DD, DD-MM-YYYY.

t1 := ourtime.new('2022-12-05 20:14:35')!
t2 := ourtime.new('2022-12-05')! // Time defaults to 00:00:00

Methods Overview

Creation

now_time := ourtime.now()
from_string := ourtime.new('2023-01-15')!
from_epoch := ourtime.new_from_epoch(1673788800)

Formatting

mut t := ourtime.now()
println(t.str()) // YYYY-MM-DD HH:mm
println(t.day()) // YYYY-MM-DD
println(t.key()) // YYYY_MM_DD_HH_mm_ss
println(t.md())  // Markdown format

Operations

mut t := ourtime.now()
t.warp('+1h')! // Move 1 hour forward
unix_ts := t.unix()
is_empty := t.empty()

Error Handling

Time parsing methods return a Result type and should be handled with ! or or blocks.

t_valid := ourtime.new('2023-01-01')!
t_invalid := ourtime.new('bad-date') or {
    println('Error: ${err}')
    ourtime.now() // Fallback
}

File: /Users/despiegk/code/github/incubaid/herolib/aiprompts/herolib_core/core_params.md

# Parameter Parsing in Vlang

This document details the `paramsparser` module, essential for handling parameters in HeroScript and other contexts.

## Obtaining a `paramsparser` Instance

```v
import freeflowuniverse.herolib.data.paramsparser

// Create new params from a string
params := paramsparser.new("color:red size:'large' priority:1 enable:true")!

// Or create an empty instance and add parameters programmatically
mut params := paramsparser.new_params()
params.set("color", "red")

Parameter Formats

The parser supports various input formats:

  1. Key-value pairs: key:value
  2. Quoted values: key:'value with spaces' (single or double quotes)
  3. Arguments without keys: arg1 arg2 (accessed by index)
  4. Comments: // this is a comment (ignored during parsing)

Example:

text := "name:'John Doe' age:30 active:true // user details"
params := paramsparser.new(text)!

Parameter Retrieval Methods

The paramsparser module provides a comprehensive set of methods for retrieving and converting parameter values.

Basic Retrieval

  • get(key string) !string: Retrieves a string value by key. Returns an error if the key does not exist.
  • get_default(key string, defval string) !string: Retrieves a string value by key, or returns defval if the key is not found.
  • exists(key string) bool: Checks if a keyword argument (key:value) exists.
  • exists_arg(key string) bool: Checks if an argument (value without a key) exists.

Argument Retrieval (Positional)

  • get_arg(nr int) !string: Retrieves an argument by its 0-based index. Returns an error if the index is out of bounds.
  • get_arg_default(nr int, defval string) !string: Retrieves an argument by index, or returns defval if the index is out of bounds.

Type-Specific Retrieval

  • get_int(key string) !int: Converts and retrieves an integer (int32).
  • get_int_default(key string, defval int) !int: Retrieves an integer with a default.
  • get_u32(key string) !u32: Converts and retrieves an unsigned 32-bit integer.
  • get_u32_default(key string, defval u32) !u32: Retrieves a u32 with a default.
  • get_u64(key string) !u64: Converts and retrieves an unsigned 64-bit integer.
  • get_u64_default(key string, defval u64) !u64: Retrieves a u64 with a default.
  • get_u8(key string) !u8: Converts and retrieves an unsigned 8-bit integer.
  • get_u8_default(key string, defval u8) !u8: Retrieves a u8 with a default.
  • get_float(key string) !f64: Converts and retrieves a 64-bit float.
  • get_float_default(key string, defval f64) !f64: Retrieves a float with a default.
  • get_percentage(key string) !f64: Converts a percentage string (e.g., "80%") to a float (0.8).
  • get_percentage_default(key string, defval string) !f64: Retrieves a percentage with a default.

Boolean Retrieval

  • get_default_true(key string) bool: Returns true if the value is empty, "1", "true", "y", or "yes". Otherwise false.
  • get_default_false(key string) bool: Returns false if the value is empty, "0", "false", "n", or "no". Otherwise true.

List Retrieval

Lists are typically comma-separated strings (e.g., users: "john,jane,bob").

  • get_list(key string) ![]string: Retrieves a list of strings.
  • get_list_default(key string, def []string) ![]string: Retrieves a list of strings with a default.
  • get_list_int(key string) ![]int: Retrieves a list of integers.
  • get_list_int_default(key string, def []int) []int: Retrieves a list of integers with a default.
  • get_list_f32(key string) ![]f32: Retrieves a list of 32-bit floats.
  • get_list_f32_default(key string, def []f32) []f32: Retrieves a list of f32 with a default.
  • get_list_f64(key string) ![]f64: Retrieves a list of 64-bit floats.
  • get_list_f64_default(key string, def []f64) []f64: Retrieves a list of f64 with a default.
  • get_list_i8(key string) ![]i8: Retrieves a list of 8-bit signed integers.
  • get_list_i8_default(key string, def []i8) []i8: Retrieves a list of i8 with a default.
  • get_list_i16(key string) ![]i16: Retrieves a list of 16-bit signed integers.
  • get_list_i16_default(key string, def []i16) []i16: Retrieves a list of i16 with a default.
  • get_list_i64(key string) ![]i64: Retrieves a list of 64-bit signed integers.
  • get_list_i64_default(key string, def []i64) []i64: Retrieves a list of i64 with a default.
  • get_list_u16(key string) ![]u16: Retrieves a list of 16-bit unsigned integers.
  • get_list_u16_default(key string, def []u16) []u16: Retrieves a list of u16 with a default.
  • get_list_u32(key string) ![]u32: Retrieves a list of 32-bit unsigned integers.
  • get_list_u32_default(key string, def []u32) []u32: Retrieves a list of u32 with a default.
  • get_list_u64(key string) ![]u64: Retrieves a list of 64-bit unsigned integers.
  • get_list_u64_default(key string, def []u64) []u64: Retrieves a list of u64 with a default.
  • get_list_namefix(key string) ![]string: Retrieves a list of strings, normalizing each item (e.g., "My Name" -> "my_name").
  • get_list_namefix_default(key string, def []string) ![]string: Retrieves a list of name-fixed strings with a default.

Specialized Retrieval

  • get_map() map[string]string: Returns all parameters as a map.
  • get_path(key string) !string: Retrieves a path string.
  • get_path_create(key string) !string: Retrieves a path string, creating the directory if it doesn't exist.
  • get_from_hashmap(key string, defval string, hashmap map[string]string) !string: Retrieves a value from a provided hashmap based on the parameter's value.
  • get_storagecapacity_in_bytes(key string) !u64: Converts storage capacity strings (e.g., "10 GB", "500 MB") to bytes (u64).
  • get_storagecapacity_in_bytes_default(key string, defval u64) !u64: Retrieves storage capacity in bytes with a default.
  • get_storagecapacity_in_gigabytes(key string) !u64: Converts storage capacity strings to gigabytes (u64).
  • get_time(key string) !ourtime.OurTime: Parses a time string (relative or absolute) into an ourtime.OurTime object.
  • get_time_default(key string, defval ourtime.OurTime) !ourtime.OurTime: Retrieves time with a default.
  • get_time_interval(key string) !Duration: Parses a time interval string into a Duration object.
  • get_timestamp(key string) !Duration: Parses a timestamp string into a Duration object.
  • get_timestamp_default(key string, defval Duration) !Duration: Retrieves a timestamp with a default.

File: /Users/despiegk/code/github/incubaid/herolib/aiprompts/herolib_core/core_paths.md
```md
# Pathlib Usage Guide

## Overview

The pathlib module provides a comprehensive interface for handling file system operations. Key features include:

- Robust path handling for files, directories, and symlinks
- Support for both absolute and relative paths
- Automatic home directory expansion (~)
- Recursive directory operations
- Path filtering and listing
- File and directory metadata access

## Basic Usage

### Importing pathlib
```v
import freeflowuniverse.herolib.core.pathlib

Creating Path Objects

// Create a Path object for a file
mut file_path := pathlib.get("path/to/file.txt")

// Create a Path object for a directory
mut dir_path := pathlib.get("path/to/directory")

Basic Path Operations

// Get absolute path
abs_path := file_path.absolute()

// Get real path (resolves symlinks)
real_path := file_path.realpath()

// Check if path exists
if file_path.exists() {
    // Path exists
}

Path Properties and Methods

Path Types

// Check if path is a file
if file_path.is_file() {
    // Handle as file
}

// Check if path is a directory
if dir_path.is_dir() {
    // Handle as directory
}

// Check if path is a symlink
if file_path.is_link() {
    // Handle as symlink
}

Path Normalization

// Normalize path (remove extra slashes, resolve . and ..)
normalized_path := file_path.path_normalize()

// Get path directory
dir_path := file_path.path_dir()

// Get path name without extension
name_no_ext := file_path.name_no_ext()

File and Directory Operations

File Operations

// Write to file
file_path.write("Content to write")!

// Read from file
content := file_path.read()!

// Delete file
file_path.delete()!

Directory Operations

// Create directory
mut dir := pathlib.get_dir(
    path: "path/to/new/dir"
    create: true
)!

// List directory contents
mut dir_list := dir.list()!

// Delete directory
dir.delete()!
// Create symlink
file_path.link("path/to/symlink", delete_exists: true)!

// Resolve symlink
real_path := file_path.realpath()

Advanced Operations

Path Copying

// Copy file to destination
file_path.copy(dest: "path/to/destination")!

Recursive Operations

// List directory recursively
mut recursive_list := dir.list(recursive: true)!

// Delete directory recursively
dir.delete()!

Path Filtering

// List files matching pattern
mut filtered_list := dir.list(
    regex: [r".*\.txt$"],
    recursive: true
)!

Best Practices

Error Handling

if file_path.exists() {
    // Safe to operate
} else {
    // Handle missing file
}

File: /Users/despiegk/code/github/incubaid/herolib/aiprompts/herolib_core/core_text.md
```md
# TextTools Module

The `texttools` module provides a comprehensive set of utilities for text manipulation and processing.

## Functions and Examples:

```v
import freeflowuniverse.herolib.core.texttools

assert hello_world == texttools.name_fix("Hello World!")

Name/Path Processing

  • name_fix(name string) string: Normalizes filenames and paths.
  • name_fix_keepspace(name string) !string: Like name_fix but preserves spaces.
  • name_fix_no_ext(name_ string) string: Removes file extension.
  • name_fix_snake_to_pascal(name string) string: Converts snake_case to PascalCase.
    name := texttools.name_fix_snake_to_pascal("hello_world") // Result: "HelloWorld"
    
  • snake_case(name string) string: Converts PascalCase to snake_case.
    name := texttools.snake_case("HelloWorld") // Result: "hello_world"
    
  • name_split(name string) !(string, string): Splits name into site and page components.

Text Cleaning

  • name_clean(r string) string: Normalizes names by removing special characters.
    name := texttools.name_clean("Hello@World!") // Result: "HelloWorld"
    
  • ascii_clean(r string) string: Removes all non-ASCII characters.
  • remove_empty_lines(text string) string: Removes empty lines from text.
    text := texttools.remove_empty_lines("line1\n\nline2\n\n\nline3") // Result: "line1\nline2\nline3"
    
  • remove_double_lines(text string) string: Removes consecutive empty lines.
  • remove_empty_js_blocks(text string) string: Removes empty code blocks (...).

Command Line Parsing

  • cmd_line_args_parser(text string) ![]string: Parses command line arguments with support for quotes and escaping.
    args := texttools.cmd_line_args_parser("'arg with spaces' --flag=value") // Result: ['arg with spaces', '--flag=value']
    
  • text_remove_quotes(text string) string: Removes quoted sections from text.
  • check_exists_outside_quotes(text string, items []string) bool: Checks if items exist in text outside of quotes.

Text Expansion

  • expand(txt_ string, l int, expand_with string) string: Expands text to a specified length with a given character.

Indentation

  • indent(text string, prefix string) string: Adds indentation prefix to each line.
    text := texttools.indent("line1\nline2", "  ") // Result: "  line1\n  line2\n"
    
  • dedent(text string) string: Removes common leading whitespace from every line.
    text := texttools.dedent("    line1\n    line2") // Result: "line1\nline2"
    

String Validation

  • is_int(text string) bool: Checks if text contains only digits.
  • is_upper_text(text string) bool: Checks if text contains only uppercase letters.

Multiline Processing

  • multiline_to_single(text string) !string: Converts multiline text to a single line with proper escaping.

Text Splitting

  • split_smart(t string, delimiter_ string) []string: Intelligent string splitting that respects quotes.

Tokenization

  • tokenize(text_ string) TokenizerResult: Tokenizes text into meaningful parts.
  • text_token_replace(text string, tofind string, replacewith string) !string: Replaces tokens in text.

Version Parsing

  • version(text_ string) int: Converts version strings to comparable integers.
    ver := texttools.version("v0.4.36") // Result: 4036
    ver = texttools.version("v1.4.36") // Result: 1004036
    

Formatting

  • format_rfc1123(t time.Time) string: Formats a time.Time object into RFC 1123 format.

Array Operations

  • to_array(r string) []string: Converts a comma or newline separated list to an array of strings.
    text := "item1,item2,item3"
    array := texttools.to_array(text) // Result: ['item1', 'item2', 'item3']
    
  • to_array_int(r string) []int: Converts a text list to an array of integers.
  • to_map(mapstring string, line string, delimiter_ string) map[string]string: Intelligent mapping of a line to a map based on a template.
    r := texttools.to_map("name,-,-,-,-,pid,-,-,-,-,path",
        "root   304   0.0  0.0 408185328   1360   ??  S    16Dec23   0:34.06 /usr/sbin/distnoted")
    // Result: {'name': 'root', 'pid': '1360', 'path': '/usr/sbin/distnoted'}
    

File: /Users/despiegk/code/github/incubaid/herolib/aiprompts/herolib_core/core_ui_console.md
```md
# module ui.console

has mechanisms to print better to console, see the methods below

import as

```v
import freeflowuniverse.herolib.ui.console

Methods


fn clear()
    //reset the console screen

fn color_bg(c BackgroundColor) string
    // will give ansi codes to change background color . dont forget to call reset to change back to normal

fn color_fg(c ForegroundColor) string
    // will give ansi codes to change foreground color . don't forget to call reset to change back to normal

struct PrintArgs {
pub mut:
	foreground   ForegroundColor
	background   BackgroundColor
	text         string
	style        Style
	reset_before bool = true
	reset_after  bool = true
}

fn cprint(args PrintArgs)
    // print with colors, reset...
    // ```
    //  	foreground ForegroundColor
    //  	background BackgroundColor
    //  	text string
    //  	style Style
    //  	reset_before bool = true
    //  	reset_after bool = true
    // ```

fn cprintln(args_ PrintArgs)

fn expand(txt_ string, l int, with string) string
    // expand text till length l, with string which is normally ' '

fn lf()
    line feed

fn new() UIConsole

fn print_array(arr [][]string, delimiter string, sort bool)
    // print 2 dimensional array, delimeter is between columns

fn print_debug(i IPrintable)

fn print_debug_title(title string, txt string)

fn print_green(txt string)

fn print_header(txt string)

fn print_item(txt string)

fn print_lf(nr int)

fn print_stderr(txt string)

fn print_stdout(txt string)

fn reset() string

fn silent_get() bool

fn silent_set()

fn silent_unset()

fn style(c Style) string
    // will give ansi codes to change style . don't forget to call reset to change back to normal

fn trim(c_ string) string

Console Object

Is used to ask feedback to users


struct UIConsole {
pub mut:
	x_max      int = 80
	y_max      int = 60
	prev_lf    bool
	prev_title bool
	prev_item  bool
}

//DropDownArgs:
// - description string
// - items []string
// - warning     string
// - clear       bool = true


fn (mut c UIConsole) ask_dropdown_int(args_ DropDownArgs) !int
    // return the dropdown as an int

fn (mut c UIConsole) ask_dropdown_multiple(args_ DropDownArgs) ![]string
    // result can be multiple, aloso can select all description string items       []string warning     string clear       bool = true

fn (mut c UIConsole) ask_dropdown(args DropDownArgs) !string
    // will return the string as given as response description

// QuestionArgs:
// - description string
// - question string
// - warning: string (if it goes wrong, which message to use)
// - reset bool = true
// - regex: to check what result need to be part of
// - minlen: min nr of chars

fn (mut c UIConsole) ask_question(args QuestionArgs) !string

fn (mut c UIConsole) ask_time(args QuestionArgs) !string

fn (mut c UIConsole) ask_date(args QuestionArgs) !string

fn (mut c UIConsole) ask_yesno(args YesNoArgs) !bool
    // yes is true, no is false
    // args:
    // - description string
    // - question string
    // - warning string
    // - clear bool = true

fn (mut c UIConsole) reset()

fn (mut c UIConsole) status() string

enums

enum BackgroundColor {
	default_color = 49 // 'default' is a reserved keyword in V
	black         = 40
	red           = 41
	green         = 42
	yellow        = 43
	blue          = 44
	magenta       = 45
	cyan          = 46
	light_gray    = 47
	dark_gray     = 100
	light_red     = 101
	light_green   = 102
	light_yellow  = 103
	light_blue    = 104
	light_magenta = 105
	light_cyan    = 106
	white         = 107
}
enum ForegroundColor {
	default_color = 39 // 'default' is a reserved keyword in V
	white         = 97
	black         = 30
	red           = 31
	green         = 32
	yellow        = 33
	blue          = 34
	magenta       = 35
	cyan          = 36
	light_gray    = 37
	dark_gray     = 90
	light_red     = 91
	light_green   = 92
	light_yellow  = 93
	light_blue    = 94
	light_magenta = 95
	light_cyan    = 96
}
enum Style {
	normal    = 99
	bold      = 1
	dim       = 2
	underline = 4
	blink     = 5
	reverse   = 7
	hidden    = 8
}


File: /Users/despiegk/code/github/incubaid/herolib/aiprompts/herolib_core/core_vshell.md
```md
# how to run the vshell example scripts

this is how we want example scripts to be, see the first line

```v
#!/usr/bin/env -S v -cg -gc none  -cc tcc -d use_openssl -enable-globals run

import freeflowuniverse.herolib...

the files are in ~/code/github/incubaid/herolib/examples for herolib

important instructions

  • never use fn main() in a .vsh script
  • always use the top line as in example above
  • these scripts can be executed as is but can also use vrun $pathOfFile

File: /Users/despiegk/code/git.threefold.info/herocode/db/heromodels/src/models/biz/company.rs
```rs
use heromodels_core::BaseModelDataOps;
use heromodels_core::{BaseModelData, Index};
use heromodels_derive::model;
use rhai::{CustomType, EvalAltResult, Position, TypeBuilder}; // For #[derive(CustomType)]
use serde::{Deserialize, Serialize};

// --- Enums ---

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum CompanyStatus {
    PendingPayment, // Company created but payment not completed
    Active,         // Payment completed, company is active
    Suspended,      // Company suspended (e.g., payment issues)
    Inactive,       // Company deactivated
}

impl Default for CompanyStatus {
    fn default() -> Self {
        CompanyStatus::PendingPayment
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum BusinessType {
    Coop,
    Single,
    Twin,
    Starter,
    Global,
}

impl Default for BusinessType {
    fn default() -> Self {
        BusinessType::Single
    }
}

impl BusinessType {
    pub fn to_string(&self) -> String {
        format!("{:?}", self)
    }

    pub fn from_string(s: &str) -> Result<Self, Box<EvalAltResult>> {
        match s.to_lowercase().as_str() {
            "coop" => Ok(BusinessType::Coop),
            "single" => Ok(BusinessType::Single),
            "twin" => Ok(BusinessType::Twin),
            "starter" => Ok(BusinessType::Starter),
            "global" => Ok(BusinessType::Global),
            _ => Err(Box::new(EvalAltResult::ErrorRuntime(
                format!("Invalid business type: {}", s).into(),
                Position::NONE,
            ))),
        }
    }
}

// --- Company Struct ---

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, CustomType, Default)] // Added CustomType
#[model]
pub struct Company {
    pub base_data: BaseModelData,
    pub name: String,
    pub registration_number: String,
    pub incorporation_date: i64, // Changed to i64 // Timestamp
    pub fiscal_year_end: String, // e.g., "MM-DD"
    pub email: String,
    pub phone: String,
    pub website: String,
    pub address: String,
    pub business_type: BusinessType,
    pub industry: String,
    pub description: String,
    pub status: CompanyStatus,
}

// --- Index Implementations (Example) ---

pub struct CompanyNameIndex;
impl Index for CompanyNameIndex {
    type Model = Company;
    type Key = str;
    fn key() -> &'static str {
        "name"
    }
}

pub struct CompanyRegistrationNumberIndex;
impl Index for CompanyRegistrationNumberIndex {
    type Model = Company;
    type Key = str;
    fn key() -> &'static str {
        "registration_number"
    }
}

// --- Builder Pattern ---

impl BaseModelDataOps for Company {
    fn get_base_data_mut(&mut self) -> &mut BaseModelData {
        &mut self.base_data
    }
}

impl Company {
    pub fn new() -> Self {
        Self {
            base_data: BaseModelData::new(),
            name: String::new(),
            registration_number: String::new(),
            incorporation_date: 0,
            fiscal_year_end: String::new(),
            email: String::new(),
            phone: String::new(),
            website: String::new(),
            address: String::new(),
            business_type: BusinessType::default(),
            industry: String::new(),
            description: String::new(),
            status: CompanyStatus::default(),
        }
    }

    pub fn name(mut self, name: impl ToString) -> Self {
        self.name = name.to_string();
        self
    }

    pub fn registration_number(mut self, registration_number: impl ToString) -> Self {
        self.registration_number = registration_number.to_string();
        self
    }

    pub fn incorporation_date(mut self, incorporation_date: i64) -> Self {
        self.incorporation_date = incorporation_date;
        self
    }

    pub fn fiscal_year_end(mut self, fiscal_year_end: impl ToString) -> Self {
        self.fiscal_year_end = fiscal_year_end.to_string();
        self
    }

    pub fn email(mut self, email: impl ToString) -> Self {
        self.email = email.to_string();
        self
    }

    pub fn phone(mut self, phone: impl ToString) -> Self {
        self.phone = phone.to_string();
        self
    }

    pub fn website(mut self, website: impl ToString) -> Self {
        self.website = website.to_string();
        self
    }

    pub fn address(mut self, address: impl ToString) -> Self {
        self.address = address.to_string();
        self
    }

    pub fn business_type(mut self, business_type: BusinessType) -> Self {
        self.business_type = business_type;
        self
    }

    pub fn industry(mut self, industry: impl ToString) -> Self {
        self.industry = industry.to_string();
        self
    }

    pub fn description(mut self, description: impl ToString) -> Self {
        self.description = description.to_string();
        self
    }

    pub fn status(mut self, status: CompanyStatus) -> Self {
        self.status = status;
        self
    }

    // Base data operations are now handled by BaseModelDataOps trait
}

File: /Users/despiegk/code/git.threefold.info/herocode/db/heromodels/src/models/biz/mod.rs

// Business models module
// Sub-modules will be declared here

pub mod company;
pub mod payment;
pub mod product;
// pub mod sale;
// pub mod shareholder;
// pub mod user;

// Re-export main types from sub-modules
pub use company::{BusinessType, Company, CompanyStatus};
pub use payment::{Payment, PaymentStatus};
pub mod shareholder;
pub use product::{Product, ProductComponent, ProductStatus, ProductType};
pub use shareholder::{Shareholder, ShareholderType};

pub mod sale;
pub use sale::{Sale, SaleItem, SaleStatus};

File: /Users/despiegk/code/git.threefold.info/herocode/db/heromodels/src/models/biz/payment.rs

use heromodels_core::BaseModelData;
use heromodels_derive::model;
use rhai::{CustomType, TypeBuilder};
use serde::{Deserialize, Serialize}; // For #[derive(CustomType)]

// --- Enums ---

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum PaymentStatus {
    Pending,
    Processing,
    Completed,
    Failed,
    Refunded,
}

impl std::fmt::Display for PaymentStatus {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            PaymentStatus::Pending => write!(f, "Pending"),
            PaymentStatus::Processing => write!(f, "Processing"),
            PaymentStatus::Completed => write!(f, "Completed"),
            PaymentStatus::Failed => write!(f, "Failed"),
            PaymentStatus::Refunded => write!(f, "Refunded"),
        }
    }
}

impl Default for PaymentStatus {
    fn default() -> Self {
        PaymentStatus::Pending
    }
}

// --- Payment Struct ---
#[model]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, CustomType)]
pub struct Payment {
    pub base_data: BaseModelData,

    // Stripe payment intent ID for tracking
    #[index]
    pub payment_intent_id: String,

    // Reference to the company this payment is for
    #[index]
    pub company_id: u32,

    // Payment plan details
    pub payment_plan: String, // "monthly", "yearly", "two_year"
    pub setup_fee: f64,
    pub monthly_fee: f64,
    pub total_amount: f64,
    pub currency: String, // "usd"

    pub status: PaymentStatus,
    pub stripe_customer_id: Option<String>,
    pub created_at: i64,           // Timestamp
    pub completed_at: Option<i64>, // Completion timestamp
}

// Model trait implementation is automatically generated by #[model] attribute

// --- Builder Pattern ---

impl Payment {
    pub fn new(
        payment_intent_id: String,
        company_id: u32,
        payment_plan: String,
        setup_fee: f64,
        monthly_fee: f64,
        total_amount: f64,
    ) -> Self {
        let now = chrono::Utc::now().timestamp();
        Self {
            base_data: BaseModelData::new(),
            payment_intent_id,
            company_id,
            payment_plan,
            setup_fee,
            monthly_fee,
            total_amount,
            currency: "usd".to_string(), // Default to USD
            status: PaymentStatus::default(),
            stripe_customer_id: None,
            created_at: now,
            completed_at: None,
        }
    }

    pub fn payment_intent_id(mut self, payment_intent_id: String) -> Self {
        self.payment_intent_id = payment_intent_id;
        self
    }

    pub fn company_id(mut self, company_id: u32) -> Self {
        self.company_id = company_id;
        self
    }

    pub fn payment_plan(mut self, payment_plan: String) -> Self {
        self.payment_plan = payment_plan;
        self
    }

    pub fn setup_fee(mut self, setup_fee: f64) -> Self {
        self.setup_fee = setup_fee;
        self
    }

    pub fn monthly_fee(mut self, monthly_fee: f64) -> Self {
        self.monthly_fee = monthly_fee;
        self
    }

    pub fn total_amount(mut self, total_amount: f64) -> Self {
        self.total_amount = total_amount;
        self
    }

    pub fn status(mut self, status: PaymentStatus) -> Self {
        self.status = status;
        self
    }

    pub fn stripe_customer_id(mut self, stripe_customer_id: Option<String>) -> Self {
        self.stripe_customer_id = stripe_customer_id;
        self
    }

    pub fn currency(mut self, currency: String) -> Self {
        self.currency = currency;
        self
    }

    pub fn created_at(mut self, created_at: i64) -> Self {
        self.created_at = created_at;
        self
    }

    pub fn completed_at(mut self, completed_at: Option<i64>) -> Self {
        self.completed_at = completed_at;
        self
    }

    // --- Business Logic Methods ---

    /// Complete the payment with optional Stripe customer ID
    pub fn complete_payment(mut self, stripe_customer_id: Option<String>) -> Self {
        self.status = PaymentStatus::Completed;
        self.stripe_customer_id = stripe_customer_id;
        self.completed_at = Some(chrono::Utc::now().timestamp());
        self.base_data.update_modified();
        self
    }

    /// Mark payment as processing
    pub fn process_payment(mut self) -> Self {
        self.status = PaymentStatus::Processing;
        self.base_data.update_modified();
        self
    }

    /// Mark payment as failed
    pub fn fail_payment(mut self) -> Self {
        self.status = PaymentStatus::Failed;
        self.base_data.update_modified();
        self
    }

    /// Refund the payment
    pub fn refund_payment(mut self) -> Self {
        self.status = PaymentStatus::Refunded;
        self.base_data.update_modified();
        self
    }

    /// Check if payment is completed
    pub fn is_completed(&self) -> bool {
        self.status == PaymentStatus::Completed
    }

    /// Check if payment is pending
    pub fn is_pending(&self) -> bool {
        self.status == PaymentStatus::Pending
    }

    /// Check if payment is processing
    pub fn is_processing(&self) -> bool {
        self.status == PaymentStatus::Processing
    }

    /// Check if payment has failed
    pub fn has_failed(&self) -> bool {
        self.status == PaymentStatus::Failed
    }

    /// Check if payment is refunded
    pub fn is_refunded(&self) -> bool {
        self.status == PaymentStatus::Refunded
    }

    // Setter for base_data fields if needed directly
    pub fn set_base_created_at(mut self, created_at: i64) -> Self {
        self.base_data.created_at = created_at;
        self
    }

    pub fn set_base_modified_at(mut self, modified_at: i64) -> Self {
        self.base_data.modified_at = modified_at;
        self
    }
}

// Tests for Payment model are located in tests/payment.rs

File: /Users/despiegk/code/git.threefold.info/herocode/db/heromodels/src/models/biz/product.rs

use heromodels_core::BaseModelData;
use heromodels_derive::model;
use rhai::{CustomType, TypeBuilder};
use serde::{Deserialize, Serialize};

// ProductType represents the type of a product
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
pub enum ProductType {
    #[default]
    Product,
    Service,
}

// ProductStatus represents the status of a product
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
pub enum ProductStatus {
    #[default]
    Available,
    Unavailable,
}

// ProductComponent represents a component or sub-part of a product.
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, CustomType)]
pub struct ProductComponent {
    pub name: String,
    pub description: String,
    pub quantity: u32,
}

impl ProductComponent {
    // Minimal constructor with no parameters
    pub fn new() -> Self {
        Self {
            name: String::new(),
            description: String::new(),
            quantity: 1, // Default quantity to 1
        }
    }

    // Builder methods
    pub fn description(mut self, description: impl ToString) -> Self {
        self.description = description.to_string();
        self
    }

    pub fn quantity(mut self, quantity: u32) -> Self {
        self.quantity = quantity;
        self
    }

    pub fn name(mut self, name: impl ToString) -> Self {
        self.name = name.to_string();
        self
    }
}

// Product represents a product or service offered
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
#[model]
pub struct Product {
    pub base_data: BaseModelData,
    pub name: String,
    pub description: String,
    pub price: f64, // Representing currency.Currency for now
    pub type_: ProductType,
    pub category: String,
    pub status: ProductStatus,
    pub max_amount: u16,
    pub purchase_till: i64, // Representing ourtime.OurTime
    pub active_till: i64,   // Representing ourtime.OurTime
    pub components: Vec<ProductComponent>,
}

impl Product {
    pub fn new() -> Self {
        Self {
            base_data: BaseModelData::new(),
            name: String::new(),
            description: String::new(),
            price: 0.0,
            type_: ProductType::default(),
            category: String::new(),
            status: ProductStatus::default(),
            max_amount: 0,
            purchase_till: 0,
            active_till: 0,
            components: Vec::new(),
        }
    }

    // Builder methods
    pub fn name(mut self, name: impl ToString) -> Self {
        self.name = name.to_string();
        self
    }

    pub fn description(mut self, description: impl ToString) -> Self {
        self.description = description.to_string();
        self
    }

    pub fn price(mut self, price: f64) -> Self {
        self.price = price;
        self
    }

    pub fn type_(mut self, type_: ProductType) -> Self {
        self.type_ = type_;
        self
    }

    pub fn category(mut self, category: impl ToString) -> Self {
        self.category = category.to_string();
        self
    }

    pub fn status(mut self, status: ProductStatus) -> Self {
        self.status = status;
        self
    }

    pub fn max_amount(mut self, max_amount: u16) -> Self {
        self.max_amount = max_amount;
        self
    }

    pub fn purchase_till(mut self, purchase_till: i64) -> Self {
        self.purchase_till = purchase_till;
        self
    }

    pub fn active_till(mut self, active_till: i64) -> Self {
        self.active_till = active_till;
        self
    }

    pub fn add_component(mut self, component: ProductComponent) -> Self {
        self.components.push(component);
        self
    }

    pub fn components(mut self, components: Vec<ProductComponent>) -> Self {
        self.components = components;
        self
    }

    // BaseModelData field operations are now handled by BaseModelDataOps trait
}

File: /Users/despiegk/code/git.threefold.info/herocode/db/heromodels/src/models/biz/README.md

# Business Models (`biz`)

The `biz` module provides a suite of models for handling core business operations, including company management, product catalogs, sales, payments, and shareholder records.

## Core Models

### `Company`

The `Company` struct is the central model, representing a business entity.

- **Key Fields**: `name`, `registration_number`, `incorporation_date`, `address`, `business_type`, and `status`.
- **Enums**:
  - `CompanyStatus`: Tracks the company's state (`PendingPayment`, `Active`, `Suspended`, `Inactive`).
  - `BusinessType`: Categorizes the company (e.g., `Coop`, `Single`, `Global`).
- **Functionality**: Provides a foundation for linking other business models like products, sales, and shareholders.

### `Product`

The `Product` model defines goods or services offered by a company.

- **Key Fields**: `name`, `description`, `price`, `category`, `status`, and `components`.
- **Nested Struct**: `ProductComponent` allows for defining complex products with sub-parts.
- **Enums**:
  - `ProductType`: Differentiates between a `Product` and a `Service`.
  - `ProductStatus`: Indicates if a product is `Available` or `Unavailable`.

### `Sale`

The `Sale` struct records a transaction, linking a buyer to products.

- **Key Fields**: `company_id`, `buyer_id`, `total_amount`, `sale_date`, and `status`.
- **Nested Struct**: `SaleItem` captures a snapshot of each product at the time of sale, including `product_id`, `quantity`, and `unit_price`.
- **Enum**: `SaleStatus` tracks the state of the sale (`Pending`, `Completed`, `Cancelled`).

### `Payment`

The `Payment` model handles financial transactions, often linked to sales or subscriptions.

- **Key Fields**: `payment_intent_id` (e.g., for Stripe), `company_id`, `total_amount`, `currency`, and `status`.
- **Functionality**: Includes methods to manage the payment lifecycle (`process_payment`, `complete_payment`, `fail_payment`, `refund_payment`).
- **Enum**: `PaymentStatus` provides a detailed state of the payment (`Pending`, `Processing`, `Completed`, `Failed`, `Refunded`).

### `Shareholder`

The `Shareholder` model tracks ownership of a company.

- **Key Fields**: `company_id`, `user_id`, `name`, `shares`, and `percentage`.
- **Enum**: `ShareholderType` distinguishes between `Individual` and `Corporate` shareholders.

## Workflow Example

1.  A `Company` is created.
2.  The company defines several `Product` models representing its offerings.
3.  A customer (buyer) initiates a purchase, which creates a `Sale` record containing multiple `SaleItem`s.
4.  A `Payment` record is generated to process the transaction for the `Sale`'s total amount.
5.  As the company grows, `Shareholder` records are created to track equity distribution.

All models use the builder pattern for easy and readable instance creation.

File: /Users/despiegk/code/git.threefold.info/herocode/db/heromodels/src/models/biz/sale.rs

use heromodels_core::{BaseModelData, BaseModelDataOps, Model};
use rhai::{CustomType, TypeBuilder};
use serde::{Deserialize, Serialize};

/// Represents the status of a sale.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum SaleStatus {
    Pending,
    Completed,
    Cancelled,
}

impl Default for SaleStatus {
    fn default() -> Self {
        SaleStatus::Pending
    }
}

/// Represents an individual item within a Sale.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, CustomType)]
pub struct SaleItem {
    pub product_id: u32,
    pub name: String, // Denormalized product name at time of sale
    pub quantity: i32,
    pub unit_price: f64, // Price per unit at time of sale
    pub subtotal: f64,
    pub service_active_until: Option<i64>, // Optional: For services, date until this specific purchased instance is active
}

impl SaleItem {
    /// Creates a new `SaleItem` with default values.
    pub fn new() -> Self {
        SaleItem {
            product_id: 0,
            name: String::new(),
            quantity: 0,
            unit_price: 0.0,
            subtotal: 0.0,
            service_active_until: None,
        }
    }

    // Builder methods
    pub fn product_id(mut self, product_id: u32) -> Self {
        self.product_id = product_id;
        self
    }

    pub fn name(mut self, name: impl ToString) -> Self {
        self.name = name.to_string();
        self
    }

    pub fn quantity(mut self, quantity: i32) -> Self {
        self.quantity = quantity;
        self
    }

    pub fn unit_price(mut self, unit_price: f64) -> Self {
        self.unit_price = unit_price;
        self
    }

    pub fn subtotal(mut self, subtotal: f64) -> Self {
        self.subtotal = subtotal;
        self
    }

    pub fn service_active_until(mut self, service_active_until: Option<i64>) -> Self {
        self.service_active_until = service_active_until;
        self
    }
}

/// Represents a sale of products or services.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, CustomType)]
pub struct Sale {
    pub base_data: BaseModelData,
    pub company_id: u32,
    pub buyer_id: u32,
    pub transaction_id: u32,
    pub total_amount: f64,
    pub status: SaleStatus,
    pub sale_date: i64,
    pub items: Vec<SaleItem>,
    pub notes: String,
}

impl Model for Sale {
    fn db_prefix() -> &'static str {
        "sale"
    }

    fn get_id(&self) -> u32 {
        self.base_data.id
    }

    fn base_data_mut(&mut self) -> &mut BaseModelData {
        &mut self.base_data
    }
}

impl BaseModelDataOps for Sale {
    fn get_base_data_mut(&mut self) -> &mut BaseModelData {
        &mut self.base_data
    }
}

impl Sale {
    /// Creates a new `Sale` with default values.
    pub fn new() -> Self {
        Sale {
            base_data: BaseModelData::new(),
            company_id: 0,
            buyer_id: 0,
            transaction_id: 0,
            total_amount: 0.0,
            status: SaleStatus::default(),
            sale_date: 0,
            items: Vec::new(),
            notes: String::new(),
        }
    }

    // Builder methods for Sale
    pub fn company_id(mut self, company_id: u32) -> Self {
        self.company_id = company_id;
        self
    }

    pub fn buyer_id(mut self, buyer_id: u32) -> Self {
        self.buyer_id = buyer_id;
        self
    }

    pub fn transaction_id(mut self, transaction_id: u32) -> Self {
        self.transaction_id = transaction_id;
        self
    }

    pub fn total_amount(mut self, total_amount: f64) -> Self {
        self.total_amount = total_amount;
        self
    }

    pub fn status(mut self, status: SaleStatus) -> Self {
        self.status = status;
        self
    }

    pub fn sale_date(mut self, sale_date: i64) -> Self {
        self.sale_date = sale_date;
        self
    }

    pub fn items(mut self, items: Vec<SaleItem>) -> Self {
        self.items = items;
        self
    }

    pub fn add_item(mut self, item: SaleItem) -> Self {
        self.items.push(item);
        self
    }

    pub fn notes(mut self, notes: impl ToString) -> Self {
        self.notes = notes.to_string();
        self
    }

    // BaseModelData operations are now handled by BaseModelDataOps trait
}

File: /Users/despiegk/code/git.threefold.info/herocode/db/heromodels/src/models/biz/shareholder.rs

use heromodels_core::BaseModelData;
use heromodels_derive::model;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ShareholderType {
    Individual,
    Corporate,
}

impl Default for ShareholderType {
    fn default() -> Self {
        ShareholderType::Individual
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[model]
pub struct Shareholder {
    pub base_data: BaseModelData,
    pub company_id: u32,
    pub user_id: u32, // Or other entity ID
    pub name: String,
    pub shares: f64,
    pub percentage: f64,
    pub type_: ShareholderType,
    pub since: i64, // Timestamp
}

impl Shareholder {
    pub fn new() -> Self {
        Self {
            base_data: BaseModelData::new(),
            company_id: 0,                     // Default, to be set by builder
            user_id: 0,                        // Default, to be set by builder
            name: String::new(),               // Default
            shares: 0.0,                       // Default
            percentage: 0.0,                   // Default
            type_: ShareholderType::default(), // Uses ShareholderType's Default impl
            since: 0,                          // Default timestamp, to be set by builder
        }
    }

    // Builder methods
    pub fn company_id(mut self, company_id: u32) -> Self {
        self.company_id = company_id;
        self
    }

    pub fn user_id(mut self, user_id: u32) -> Self {
        self.user_id = user_id;
        self
    }

    pub fn name(mut self, name: impl ToString) -> Self {
        self.name = name.to_string();
        self
    }

    pub fn shares(mut self, shares: f64) -> Self {
        self.shares = shares;
        self
    }

    pub fn percentage(mut self, percentage: f64) -> Self {
        self.percentage = percentage;
        self
    }

    pub fn type_(mut self, type_: ShareholderType) -> Self {
        self.type_ = type_;
        self
    }

    pub fn since(mut self, since: i64) -> Self {
        self.since = since;
        self
    }

    // Base data operations are now handled by BaseModelDataOps trait
}

</file_contents>

You are a senior software architect specializing in code design and implementation planning. Your role is to:
  1. Analyze the requested changes and break them down into clear, actionable steps
  2. Create a detailed implementation plan that includes:
    • Files that need to be modified
    • Specific code sections requiring changes
    • New functions, methods, or classes to be added
    • Dependencies or imports to be updated
    • Data structure modifications
    • Interface changes
    • Configuration updates

For each change:

  • Describe the exact location in the code where changes are needed
  • Explain the logic and reasoning behind each modification
  • Provide example signatures, parameters, and return types
  • Note any potential side effects or impacts on other parts of the codebase
  • Highlight critical architectural decisions that need to be made

You may include short code snippets to illustrate specific patterns, signatures, or structures, but do not implement the full solution.

Focus solely on the technical implementation plan - exclude testing, validation, and deployment considerations unless they directly impact the architecture.

Please proceed with your analysis based on the following

pub struct StructName{ pub mut: name string = “aname” //comment …

forget what rust does, there is no special module things needed, no re-exports of any of that complicates stuff

there is no defaults for empty strings or 0 ints, … defaults are only for non empty stuff

$NAME = finance

walk over all models from biz: db/heromodels/src/models/$NAME in the rust repo create nice structured public models in Vlang (V) see instructions in herlolib

put the results in /Users/despiegk/code/github/incubaid/herolib/lib/hero/models/$NAME

put decorator on fields which need to be indexed: use @[index] for that at end of line of the property of the struct

copy the documentation as well and put on the vstruct and on its fields

make instructions so a coding agent can execute it, put the models in files, ...

keep it all simple

don't do anything additional for modules, don't do import

at top of each file we have module $NAME

don't create management classes, only output the structs

</user_instructions>