Files
herolib/aiprompts/instructions_archive/models_from_v/complete.md
2025-10-12 12:30:19 +03:00

2523 lines
73 KiB
Markdown

<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
```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 incubaid.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.
```v
import incubaid.herolib.core.playbook { PlayBook }
import incubaid.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 incubaid.herolib.core.playbook
import incubaid.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 incubaid.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:
```v
// 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
```v
struct User {
id int
name string
email string
}
user := conn.get_json_generic[User](
prefix: 'users/1'
)!
```
### POST Request with JSON Data
```v
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:
```v
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:
```v
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
```md
# OSAL Core Module - Key Capabilities (incubaid.herolib.osal.core)
```v
//example how to get started
import incubaid.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 incubaid.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).
```v
// 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`.
```v
t1 := ourtime.new('2022-12-05 20:14:35')!
t2 := ourtime.new('2022-12-05')! // Time defaults to 00:00:00
```
## Methods Overview
### Creation
```v
now_time := ourtime.now()
from_string := ourtime.new('2023-01-15')!
from_epoch := ourtime.new_from_epoch(1673788800)
```
### Formatting
```v
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
```v
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.
```v
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
```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 incubaid.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:
```v
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 incubaid.herolib.core.pathlib
```
### Creating Path Objects
```v
// 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
```v
// 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
```v
// 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
```v
// 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
```v
// Write to file
file_path.write("Content to write")!
// Read from file
content := file_path.read()!
// Delete file
file_path.delete()!
```
### Directory Operations
```v
// 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()!
```
### Symlink Operations
```v
// Create symlink
file_path.link("path/to/symlink", delete_exists: true)!
// Resolve symlink
real_path := file_path.realpath()
```
## Advanced Operations
### Path Copying
```v
// Copy file to destination
file_path.copy(dest: "path/to/destination")!
```
### Recursive Operations
```v
// List directory recursively
mut recursive_list := dir.list(recursive: true)!
// Delete directory recursively
dir.delete()!
```
### Path Filtering
```v
// List files matching pattern
mut filtered_list := dir.list(
regex: [r".*\.txt$"],
recursive: true
)!
```
## Best Practices
### Error Handling
```v
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 incubaid.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.
```v
name := texttools.name_fix_snake_to_pascal("hello_world") // Result: "HelloWorld"
```
* `snake_case(name string) string`: Converts PascalCase to snake_case.
```v
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.
```v
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.
```v
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.
```v
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.
```v
text := texttools.indent("line1\nline2", " ") // Result: " line1\n line2\n"
```
* `dedent(text string) string`: Removes common leading whitespace from every line.
```v
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.
```v
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.
```v
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.
```v
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 incubaid.herolib.ui.console
```
## Methods
````v
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
```v
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
```v
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 incubaid.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
```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
```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
```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
```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
```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
```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>
<meta prompt 1 = "[Architect]">
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 <user instructions>
</meta prompt 1>
<meta prompt 2 = "models in V for rust import">
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
</meta prompt 2>
<user_instructions>
$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>