Compare commits
385 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 39c6c37dee | |||
| 3438f74e60 | |||
| 4f79712570 | |||
| 8e85ce0678 | |||
| ff09e7bf1b | |||
| 46e1c6706c | |||
| d8a59d0726 | |||
| 108d2019cd | |||
| 3682ef2420 | |||
| a066db6624 | |||
| 7458d64c05 | |||
| 2a1787f28f | |||
| de78c229ce | |||
|
|
f386c67acf | ||
|
|
75f98bf349 | ||
|
|
9870fcbc5d | ||
|
|
d2b8379505 | ||
|
|
2dcb97255c | ||
|
|
f7dd227cd0 | ||
| e2c18c3a24 | |||
| 1bc6c6eab8 | |||
|
|
4b39b137de | ||
| e5de293919 | |||
| 8a10374570 | |||
| ad37a041ab | |||
| 44daea4447 | |||
| 6989a4da13 | |||
| de4583691c | |||
| d8c9b07a51 | |||
| 54d31f40b2 | |||
| ec73b5ff34 | |||
| 9fcdcc3aff | |||
| 05ab2b68f4 | |||
| 79330ef8f5 | |||
| 45ed369a78 | |||
| 37c17fc7da | |||
| 23640d2647 | |||
| be54ec8302 | |||
| 638f81a781 | |||
| e00306b6f8 | |||
| 3fec1c38a1 | |||
| edc9e3c150 | |||
| a155122898 | |||
| f0552f38a0 | |||
|
|
f99419371a | ||
|
|
86d47c218b | ||
|
|
bd5cafbad7 | ||
|
|
b71362eb9a | ||
|
|
673d982360 | ||
|
|
712b46864a | ||
|
|
186c3aae59 | ||
|
|
0794fe948b | ||
|
|
ba2d6e4310 | ||
|
|
b9e5d14b48 | ||
|
|
bf26b0af1d | ||
|
|
8e82b2865b | ||
|
|
367340d69d | ||
|
|
0b77c73809 | ||
|
|
51b432d911 | ||
|
|
f7a679b2a3 | ||
|
|
15c9d60760 | ||
|
|
c69b53fd4e | ||
|
|
9cdab1f392 | ||
|
|
34656cf1f9 | ||
|
|
cf98822749 | ||
|
|
2335d14623 | ||
| 4a72698402 | |||
| fcb857f756 | |||
|
|
ba07f85fd8 | ||
|
|
7b621243d0 | ||
| 598b312140 | |||
| 0df10f5cb3 | |||
| 2c748a9fc8 | |||
| a2e1b4fb27 | |||
| 9b0da9f245 | |||
| 5b9426ba11 | |||
| 8b6ad4d076 | |||
|
|
7d4565e56f | ||
|
|
92cceeb64b | ||
|
|
3d90e39781 | ||
|
|
efbf00830a | ||
|
|
b9969c69fd | ||
|
|
15d998bf76 | ||
|
|
8c966ae853 | ||
|
|
3e10db326f | ||
|
|
dc6f1bdf52 | ||
|
|
429f3b1fea | ||
|
|
70009f1846 | ||
|
|
5f9024c7bf | ||
|
|
f2138f104f | ||
|
|
04ee73e8dd | ||
|
|
bd83ad37bf | ||
|
|
7b175c8804 | ||
|
|
22cbc806dc | ||
|
|
02e0a073aa | ||
|
|
b2e5a84ff9 | ||
|
|
abd694015b | ||
|
|
57d30eab2d | ||
| b27f0a5017 | |||
|
|
c47002430e | ||
|
|
bd3abade55 | ||
|
|
ea0637423e | ||
|
|
a6756bfe5a | ||
|
|
4cdbc51343 | ||
|
|
2e5210a0b7 | ||
|
|
e8574383ee | ||
|
|
21da15da0a | ||
|
|
dca1d877ac | ||
|
|
007f65c27e | ||
|
|
ef572f402d | ||
|
|
133e7c9809 | ||
| 0d38c1b471 | |||
| cf7bfb7650 | |||
|
|
228abe36a3 | ||
| b48abc474c | |||
|
|
c3fe788a5b | ||
|
|
025e8fba69 | ||
| 672904d914 | |||
| fac783c58d | |||
| 6e7843f368 | |||
| 6a555a5fe3 | |||
| 4796e4fe82 | |||
| 3b1068a3a8 | |||
| 392f764acc | |||
| 122cba9f6b | |||
|
|
dc178f68c7 | ||
|
|
59a0519b4e | ||
|
|
dfcaeec85f | ||
|
|
ef922d162e | ||
|
|
02e4ea180d | ||
|
|
8b9b0678b8 | ||
|
|
475e812ba3 | ||
|
|
0a953f2c09 | ||
|
|
1e26162e00 | ||
|
|
dd68bf950c | ||
|
|
e374520654 | ||
|
|
47c95f76e9 | ||
|
|
918cfd83ec | ||
|
|
83387c47ec | ||
|
|
f6c22c733b | ||
|
|
269d0474c5 | ||
|
|
28359984ff | ||
|
|
c09e424890 | ||
| a55af220bf | |||
| 9c09af83a2 | |||
| e69d67d238 | |||
| 01c6ea66ac | |||
| f9ea731a6e | |||
|
|
a974091442 | ||
|
|
413b805823 | ||
|
|
46069ba924 | ||
|
|
f3e7b979a5 | ||
|
|
f6733a67af | ||
|
|
4988b241ef | ||
|
|
7807a8e736 | ||
| 5ba11aab46 | |||
|
|
4abb46b4bf | ||
|
|
a7976c45f9 | ||
|
|
5194fabe62 | ||
|
|
ff430c2e4d | ||
| 1581628ea3 | |||
| 237f9bd742 | |||
|
|
cf27e7880e | ||
|
|
ad300c068f | ||
|
|
1a02dcaf0f | ||
|
|
9ecc2444aa | ||
|
|
0e1836c5d0 | ||
|
|
7965883744 | ||
|
|
b006bb1e41 | ||
|
|
27c9018c48 | ||
|
|
f1991d89b3 | ||
| 9448ae85cf | |||
|
|
a64e964d83 | ||
|
|
5e321b6b0f | ||
| b1453e3580 | |||
| 3da895083b | |||
| ac583741a4 | |||
| 4358ba6471 | |||
| 46afb63f31 | |||
| f773ce168e | |||
| aa79df1fcd | |||
| 420c9cb9e5 | |||
| 83d935930f | |||
| 2e2c94e897 | |||
| a96903da0e | |||
| 3dbcf00e9f | |||
| 708147435e | |||
| 26289bb00f | |||
| 1489b9f44f | |||
| e4045ef179 | |||
| 13f482fa12 | |||
| 3e2013576f | |||
| e5aa8bca09 | |||
| 4dd3908ff7 | |||
| 09f388e2ff | |||
| baecb9bbe4 | |||
| 2c5986295e | |||
| 126f23dfa2 | |||
|
|
407f3f85bc | ||
|
|
94da4fff5e | ||
|
|
0fa54f1354 | ||
|
|
80677f7177 | ||
|
|
01cac0f741 | ||
|
|
30546a34f9 | ||
|
|
0ccf317564 | ||
|
|
0c49e83a68 | ||
| 51db8257f5 | |||
| ecc2977581 | |||
| ffafef0c88 | |||
| ca3bac1d76 | |||
| 43f7bc7943 | |||
| b3555aa54e | |||
|
|
afad769066 | ||
|
|
2da37ee4a5 | ||
|
|
90c81a1234 | ||
|
|
34ea12ca23 | ||
|
|
d2c1be5396 | ||
|
|
fe934bba36 | ||
|
|
b01e40da40 | ||
|
|
ae7e7ecb84 | ||
|
|
fdf540cbd0 | ||
|
|
7cb26e5569 | ||
|
|
913b0cb790 | ||
|
|
485b47d145 | ||
| fb9c9b8070 | |||
|
|
5b69f935a5 | ||
|
|
9dbc36d634 | ||
|
|
42b0c4d48f | ||
|
|
5343d9bff6 | ||
|
|
eb47c8490d | ||
|
|
1de9be2a8a | ||
|
|
d852ecc5b1 | ||
|
|
368edcd93a | ||
|
|
71906fd891 | ||
|
|
dbd187a017 | ||
|
|
52a3546325 | ||
|
|
a23eb0ff0b | ||
|
|
b40c366335 | ||
|
|
d2ad18e8ec | ||
|
|
9b737c9280 | ||
| 834c413cfc | |||
| da9965bdc6 | |||
| 6bbaa0d1f7 | |||
| 834f612bfe | |||
|
|
171e54a68c | ||
|
|
a690f98cc1 | ||
|
|
400ea6e80e | ||
|
|
84c19ca9a4 | ||
|
|
3b7ec028f9 | ||
| 83f7bf41e3 | |||
| 634b8c5bad | |||
| 4aabc8d1b0 | |||
| 75255d8cd0 | |||
|
|
a0b53126ca | ||
|
|
38cd933d41 | ||
|
|
2da014c407 | ||
|
|
9d1752f4ed | ||
|
|
d06a806184 | ||
|
|
fe1becabaf | ||
| 2d0d196cd3 | |||
| 37573b0b59 | |||
| 35dace9155 | |||
| 69e7c1cce9 | |||
| d21e71e615 | |||
|
|
972bb9f755 | ||
|
|
a798b2347f | ||
|
|
17979b4fde | ||
|
|
68d25d3622 | ||
|
|
f38d4249ef | ||
| ded4a0b102 | |||
| 6184441706 | |||
| 293dc3f1ac | |||
| 6492e42358 | |||
| 4aaf1bd6db | |||
| a56a251d7f | |||
| f306ff728f | |||
| a10a6d6507 | |||
|
|
59efa18bce | ||
|
|
4ed80481aa | ||
| fff14183a4 | |||
|
|
1f58676278 | ||
|
|
b67db23e07 | ||
|
|
4fe1e70881 | ||
|
|
988602f90f | ||
| 6a2e143b98 | |||
|
|
306de32de8 | ||
|
|
c0b57e2a01 | ||
|
|
aeeacc877b | ||
| 6820a7e9c8 | |||
| 1c7621f20a | |||
| 5263798b11 | |||
|
|
0d96c5fc65 | ||
|
|
6b0cf48292 | ||
|
|
9160e95e4a | ||
|
|
296cb9adf5 | ||
|
|
88fe8f503f | ||
|
|
a26bb56b15 | ||
|
|
2f54f05cfd | ||
|
|
f61d6808e8 | ||
|
|
4719876feb | ||
|
|
975cca77b1 | ||
|
|
eb80294b0a | ||
|
|
0704c9421d | ||
|
|
f08af0e2c5 | ||
|
|
814b61f25e | ||
|
|
1c264815c3 | ||
|
|
33150846cc | ||
|
|
2e7efdf229 | ||
|
|
f47703f599 | ||
|
|
383fc9fade | ||
|
|
4691046d5f | ||
|
|
7b453962ca | ||
|
|
528d594056 | ||
|
|
6305cf159e | ||
|
|
906f13b562 | ||
|
|
84142b60a7 | ||
|
|
66f29fcb02 | ||
|
|
73c3c3bdb5 | ||
|
|
fa677c01b2 | ||
|
|
acd1a4a61d | ||
|
|
ee1ac54dde | ||
|
|
2599fa6859 | ||
|
|
0fb8901ab5 | ||
|
|
6753b87873 | ||
|
|
715f481364 | ||
|
|
776942cd8b | ||
|
|
f0c23eb4ae | ||
|
|
6644d3b11c | ||
|
|
13471d4ca5 | ||
|
|
80254739b0 | ||
| 30cb80efcd | |||
| 5a8daa3feb | |||
|
|
c408934efd | ||
| abe81190e6 | |||
| e997946c56 | |||
|
|
dd4bb73a78 | ||
|
|
1005576814 | ||
|
|
963b31b087 | ||
|
|
2aafab50ad | ||
|
|
10c15f6f8e | ||
|
|
af2f33d4f6 | ||
|
|
1db2c3ee54 | ||
|
|
7e8a4c5c45 | ||
|
|
f6fe3d4fda | ||
|
|
eeb2602bcf | ||
|
|
565eec0292 | ||
|
|
a98fad32d3 | ||
|
|
10f0c0bd31 | ||
|
|
01552145a8 | ||
|
|
09ed341b97 | ||
|
|
5cb30e6783 | ||
|
|
ee8fbbca09 | ||
|
|
b9b21ac44b | ||
|
|
d403f84b6c | ||
|
|
dfeeb8cd4c | ||
|
|
135866e5b0 | ||
|
|
eef88b5375 | ||
|
|
8b9717bb74 | ||
|
|
9a7a66192b | ||
|
|
df950143b4 | ||
|
|
038c563843 | ||
|
|
4733e05c58 | ||
|
|
c9496f0973 | ||
|
|
31dffa14ce | ||
|
|
7459501c8f | ||
|
|
bc9fd08f7e | ||
|
|
be1cee5d6a | ||
|
|
c91f9ba43c | ||
|
|
357000ef13 | ||
|
|
6ba89a8b9c | ||
|
|
d5af1d19b8 | ||
|
|
ce1ce722d5 | ||
|
|
fa192e10b8 | ||
|
|
7ae3296ef5 | ||
|
|
a6ba22b0b1 | ||
|
|
d49e94e412 | ||
|
|
ff8ee3693c | ||
|
|
d43d4d8a9f | ||
|
|
6f814b5d09 | ||
|
|
5d3df608e1 | ||
|
|
86af42bf4a | ||
|
|
5869998f6e | ||
|
|
cbdc0fd313 | ||
|
|
bada9508ef | ||
|
|
7bc4da97ab |
20
.gitignore
vendored
20
.gitignore
vendored
@@ -1,4 +1,13 @@
|
|||||||
|
# Additional ignore files and directories
|
||||||
|
Thumbs.db
|
||||||
|
# Logs
|
||||||
|
logs/
|
||||||
|
*.log
|
||||||
|
*.out
|
||||||
|
# Compiled Python files
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
__pycache__/
|
||||||
*dSYM/
|
*dSYM/
|
||||||
.vmodules/
|
.vmodules/
|
||||||
.vscode
|
.vscode
|
||||||
@@ -29,3 +38,12 @@ output/
|
|||||||
data.ms/
|
data.ms/
|
||||||
test_basic
|
test_basic
|
||||||
cli/hero
|
cli/hero
|
||||||
|
.aider*
|
||||||
|
storage/
|
||||||
|
.qdrant-initialized
|
||||||
|
.compile_cache
|
||||||
|
compile_results.log
|
||||||
|
tmp
|
||||||
|
compile_summary.log
|
||||||
|
.summary_lock
|
||||||
|
.aider*
|
||||||
|
|||||||
183
CONTRIBUTING.md
Normal file
183
CONTRIBUTING.md
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
# Contributing to Herolib
|
||||||
|
|
||||||
|
Thank you for your interest in contributing to Herolib! This document provides guidelines and instructions for contributing to the project.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Getting Started](#getting-started)
|
||||||
|
- [Setting Up Development Environment](#setting-up-development-environment)
|
||||||
|
- [Repository Structure](#repository-structure)
|
||||||
|
- [Development Workflow](#development-workflow)
|
||||||
|
- [Branching Strategy](#branching-strategy)
|
||||||
|
- [Making Changes](#making-changes)
|
||||||
|
- [Testing](#testing)
|
||||||
|
- [Pull Requests](#pull-requests)
|
||||||
|
- [Code Guidelines](#code-guidelines)
|
||||||
|
- [CI/CD Process](#cicd-process)
|
||||||
|
- [Documentation](#documentation)
|
||||||
|
- [Troubleshooting](#troubleshooting)
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### Setting Up Development Environment
|
||||||
|
|
||||||
|
For developers, you can use the automated installation script:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl 'https://raw.githubusercontent.com/freeflowuniverse/herolib/refs/heads/development/install_v.sh' > /tmp/install_v.sh
|
||||||
|
bash /tmp/install_v.sh --analyzer --herolib
|
||||||
|
# IMPORTANT: Start a new shell after installation for paths to be set correctly
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, you can manually set up the environment:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p ~/code/github/freeflowuniverse
|
||||||
|
cd ~/code/github/freeflowuniverse
|
||||||
|
git clone git@github.com:freeflowuniverse/herolib.git
|
||||||
|
cd herolib
|
||||||
|
# checkout development branch for most recent changes
|
||||||
|
git checkout development
|
||||||
|
bash install.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Repository Structure
|
||||||
|
|
||||||
|
Herolib is an opinionated library primarily used by ThreeFold to automate cloud environments. The repository is organized into several key directories:
|
||||||
|
|
||||||
|
- `/lib`: Core library code
|
||||||
|
- `/cli`: Command-line interface tools, including the Hero tool
|
||||||
|
- `/cookbook`: Examples and guides for using Herolib
|
||||||
|
- `/scripts`: Installation and utility scripts
|
||||||
|
- `/docs`: Generated documentation
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
|
||||||
|
### Branching Strategy
|
||||||
|
|
||||||
|
- `development`: Main development branch where all features and fixes are merged
|
||||||
|
- `main`: Stable release branch
|
||||||
|
|
||||||
|
For new features or bug fixes, create a branch from `development` with a descriptive name.
|
||||||
|
|
||||||
|
### Making Changes
|
||||||
|
|
||||||
|
1. Create a new branch from `development`:
|
||||||
|
```bash
|
||||||
|
git checkout development
|
||||||
|
git pull
|
||||||
|
git checkout -b feature/your-feature-name
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Make your changes, following the code guidelines.
|
||||||
|
|
||||||
|
3. Run tests to ensure your changes don't break existing functionality:
|
||||||
|
```bash
|
||||||
|
./test_basic.vsh
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Commit your changes with clear, descriptive commit messages.
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
Before submitting a pull request, ensure all tests pass:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run all basic tests
|
||||||
|
./test_basic.vsh
|
||||||
|
|
||||||
|
# Run tests for a specific module
|
||||||
|
vtest ~/code/github/freeflowuniverse/herolib/lib/osal/package_test.v
|
||||||
|
|
||||||
|
# Run tests for an entire directory
|
||||||
|
vtest ~/code/github/freeflowuniverse/herolib/lib/osal
|
||||||
|
```
|
||||||
|
|
||||||
|
The test script (`test_basic.vsh`) manages test execution and caching to optimize performance. It automatically skips tests listed in the ignore or error sections of the script.
|
||||||
|
|
||||||
|
### Pull Requests
|
||||||
|
|
||||||
|
1. Push your branch to the repository:
|
||||||
|
```bash
|
||||||
|
git push origin feature/your-feature-name
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Create a pull request against the `development` branch.
|
||||||
|
|
||||||
|
3. Ensure your PR includes:
|
||||||
|
- A clear description of the changes
|
||||||
|
- Any related issue numbers
|
||||||
|
- Documentation updates if applicable
|
||||||
|
|
||||||
|
4. Wait for CI checks to pass and address any feedback from reviewers.
|
||||||
|
|
||||||
|
## Code Guidelines
|
||||||
|
|
||||||
|
- Follow the existing code style and patterns in the repository
|
||||||
|
- Write clear, concise code with appropriate comments
|
||||||
|
- Keep modules separate and focused on specific functionality
|
||||||
|
- Maintain separation between the jsonschema and jsonrpc modules rather than merging them
|
||||||
|
|
||||||
|
## CI/CD Process
|
||||||
|
|
||||||
|
The repository uses GitHub Actions for continuous integration and deployment:
|
||||||
|
|
||||||
|
### 1. Testing Workflow (`test.yml`)
|
||||||
|
|
||||||
|
This workflow runs on every push and pull request to ensure code quality:
|
||||||
|
- Sets up V and Herolib
|
||||||
|
- Runs all basic tests using `test_basic.vsh`
|
||||||
|
|
||||||
|
All tests must pass before a PR can be merged to the `development` branch.
|
||||||
|
|
||||||
|
### 2. Hero Build Workflow (`hero_build.yml`)
|
||||||
|
|
||||||
|
This workflow builds the Hero tool for multiple platforms when a new tag is created:
|
||||||
|
- Builds for Linux (x86_64, aarch64) and macOS (x86_64, aarch64)
|
||||||
|
- Runs all basic tests
|
||||||
|
- Creates GitHub releases with the built binaries
|
||||||
|
|
||||||
|
### 3. Documentation Workflow (`documentation.yml`)
|
||||||
|
|
||||||
|
This workflow automatically updates the documentation on GitHub Pages when changes are pushed to the `development` branch:
|
||||||
|
- Generates documentation using `doc.vsh`
|
||||||
|
- Deploys the documentation to GitHub Pages
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
To generate documentation locally:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/code/github/freeflowuniverse/herolib
|
||||||
|
bash doc.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
The documentation is automatically published to [https://freeflowuniverse.github.io/herolib/](https://freeflowuniverse.github.io/herolib/) when changes are pushed to the `development` branch.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### TCC Compiler Error on macOS
|
||||||
|
|
||||||
|
If you encounter the following error when using TCC compiler on macOS:
|
||||||
|
|
||||||
|
```
|
||||||
|
In file included from /Users/timurgordon/code/github/vlang/v/thirdparty/cJSON/cJSON.c:42:
|
||||||
|
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/math.h:614: error: ';' expected (got "__fabsf16")
|
||||||
|
```
|
||||||
|
|
||||||
|
This is caused by incompatibility between TCC and the half precision math functions in the macOS SDK. To fix this issue:
|
||||||
|
|
||||||
|
1. Open the math.h file:
|
||||||
|
```bash
|
||||||
|
sudo nano /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/math.h
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Comment out the half precision math functions (around line 612-626).
|
||||||
|
|
||||||
|
For more details, see the [README.md](README.md) troubleshooting section.
|
||||||
|
|
||||||
|
## Additional Resources
|
||||||
|
|
||||||
|
- [Herolib Documentation](https://freeflowuniverse.github.io/herolib/)
|
||||||
|
- [Cookbook Examples](https://github.com/freeflowuniverse/herolib/tree/development/cookbook)
|
||||||
|
- [AI Prompts](aiprompts/starter/0_start_here.md)
|
||||||
144
README.md
144
README.md
@@ -1,32 +1,60 @@
|
|||||||
# herolib
|
# Herolib
|
||||||
|
|
||||||
|
Herolib is an opinionated library primarily used by ThreeFold to automate cloud environments. It provides a comprehensive set of tools and utilities for cloud automation, git operations, documentation building, and more.
|
||||||
|
|
||||||
> [documentation of the library](https://freeflowuniverse.github.io/herolib/)
|
[](https://github.com/freeflowuniverse/herolib/actions/workflows/test.yml)
|
||||||
|
[](https://github.com/freeflowuniverse/herolib/actions/workflows/documentation.yml)
|
||||||
|
|
||||||
## hero install for users
|
> [Complete Documentation](https://freeflowuniverse.github.io/herolib/)
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Installation](#installation)
|
||||||
|
- [For Users](#for-users)
|
||||||
|
- [For Developers](#for-developers)
|
||||||
|
- [Features](#features)
|
||||||
|
- [Testing](#testing)
|
||||||
|
- [Contributing](#contributing)
|
||||||
|
- [Troubleshooting](#troubleshooting)
|
||||||
|
- [Additional Resources](#additional-resources)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### For Users
|
||||||
|
|
||||||
|
The Hero tool can be installed with a single command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl https://raw.githubusercontent.com/freeflowuniverse/herolib/refs/heads/development/install_hero.sh > /tmp/install_hero.sh
|
curl https://raw.githubusercontent.com/freeflowuniverse/herolib/refs/heads/development/install_hero.sh > /tmp/install_hero.sh
|
||||||
bash /tmp/install_hero.sh
|
bash /tmp/install_hero.sh
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
this tool can be used to work with git, build books, play with hero AI, ...
|
Hero will be installed in:
|
||||||
|
- `/usr/local/bin` for Linux
|
||||||
|
- `~/hero/bin` for macOS
|
||||||
|
|
||||||
## automated install for developers
|
After installation on macOS, you may need to:
|
||||||
|
```bash
|
||||||
|
source ~/.zprofile
|
||||||
|
# Or copy to system bin directory
|
||||||
|
cp ~/hero/bin/hero /usr/local/bin
|
||||||
|
```
|
||||||
|
|
||||||
|
The Hero tool can be used to work with git, build documentation, interact with Hero AI, and more.
|
||||||
|
|
||||||
|
### For Developers
|
||||||
|
|
||||||
|
For development purposes, use the automated installation script:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl 'https://raw.githubusercontent.com/freeflowuniverse/herolib/refs/heads/development/install_v.sh' > /tmp/install_v.sh
|
curl 'https://raw.githubusercontent.com/freeflowuniverse/herolib/refs/heads/development/install_v.sh' > /tmp/install_v.sh
|
||||||
bash /tmp/install_v.sh --analyzer --herolib
|
bash /tmp/install_v.sh --analyzer --herolib
|
||||||
#DONT FORGET TO START A NEW SHELL (otherwise the paths will not be set)
|
# IMPORTANT: Start a new shell after installation for paths to be set correctly
|
||||||
```
|
```
|
||||||
|
|
||||||
### details
|
#### Installation Options
|
||||||
|
|
||||||
```bash
|
|
||||||
|
|
||||||
~/code/github/freeflowuniverse/herolib/install_v.sh --help
|
|
||||||
|
|
||||||
|
```
|
||||||
V & HeroLib Installer Script
|
V & HeroLib Installer Script
|
||||||
|
|
||||||
Usage: ~/code/github/freeflowuniverse/herolib/install_v.sh [options]
|
Usage: ~/code/github/freeflowuniverse/herolib/install_v.sh [options]
|
||||||
@@ -45,29 +73,97 @@ Examples:
|
|||||||
~/code/github/freeflowuniverse/herolib/install_v.sh --analyzer
|
~/code/github/freeflowuniverse/herolib/install_v.sh --analyzer
|
||||||
~/code/github/freeflowuniverse/herolib/install_v.sh --herolib
|
~/code/github/freeflowuniverse/herolib/install_v.sh --herolib
|
||||||
~/code/github/freeflowuniverse/herolib/install_v.sh --reset --analyzer # Fresh install of both
|
~/code/github/freeflowuniverse/herolib/install_v.sh --reset --analyzer # Fresh install of both
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### to test
|
## Features
|
||||||
|
|
||||||
to run the basic tests, important !!!
|
Herolib provides a wide range of functionality:
|
||||||
|
|
||||||
|
- Cloud automation tools
|
||||||
|
- Git operations and management
|
||||||
|
- Documentation building
|
||||||
|
- Hero AI integration
|
||||||
|
- System management utilities
|
||||||
|
- And much more
|
||||||
|
|
||||||
|
Check the [cookbook](https://github.com/freeflowuniverse/herolib/tree/development/cookbook) for examples and use cases.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Running tests is an essential part of development. To run the basic tests:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Run all basic tests
|
||||||
~/code/github/freeflowuniverse/herolib/test_basic.vsh
|
~/code/github/freeflowuniverse/herolib/test_basic.vsh
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
# Run tests for a specific module
|
||||||
vtest ~/code/github/freeflowuniverse/herolib/lib/osal/package_test.v
|
vtest ~/code/github/freeflowuniverse/herolib/lib/osal/package_test.v
|
||||||
#for a full dir
|
|
||||||
vtest ~/code/github/freeflowuniverse/herolib/lib/osal
|
|
||||||
|
|
||||||
#to do al basic tests
|
# Run tests for an entire directory
|
||||||
~/code/github/freeflowuniverse/herolib/test_basic.vsh
|
vtest ~/code/github/freeflowuniverse/herolib/lib/osal
|
||||||
|
```
|
||||||
|
|
||||||
|
The `vtest` command is an alias for testing functionality.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
We welcome contributions to Herolib! Please see our [CONTRIBUTING.md](CONTRIBUTING.md) file for detailed information on:
|
||||||
|
|
||||||
|
- Setting up your development environment
|
||||||
|
- Understanding the repository structure
|
||||||
|
- Following our development workflow
|
||||||
|
- Making pull requests
|
||||||
|
- CI/CD processes
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### TCC Compiler Error on macOS
|
||||||
|
|
||||||
|
If you encounter the following error when using TCC compiler on macOS:
|
||||||
|
|
||||||
```
|
```
|
||||||
vtest is an alias to test functionality
|
In file included from /Users/timurgordon/code/github/vlang/v/thirdparty/cJSON/cJSON.c:42:
|
||||||
|
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/math.h:614: error: ';' expected (got "__fabsf16")
|
||||||
|
```
|
||||||
|
|
||||||
|
This is caused by incompatibility between TCC and the half precision math functions in the macOS SDK. To fix this issue:
|
||||||
|
|
||||||
## important to read
|
1. Open the math.h file:
|
||||||
|
```bash
|
||||||
|
sudo nano /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/math.h
|
||||||
|
```
|
||||||
|
|
||||||
- [aiprompts/starter/0_start_here.md](aiprompts/starter/0_start_here.md)
|
2. Comment out the following lines (around line 612-626):
|
||||||
|
```c
|
||||||
|
/* half precision math functions */
|
||||||
|
// extern _Float16 __fabsf16(_Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __hypotf16(_Float16, _Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __sqrtf16(_Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __ceilf16(_Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __floorf16(_Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __rintf16(_Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __roundf16(_Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __truncf16(_Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __copysignf16(_Float16, _Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __nextafterf16(_Float16, _Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __fmaxf16(_Float16, _Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __fminf16(_Float16, _Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __fmaf16(_Float16, _Float16, _Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Save the file and try compiling again.
|
||||||
|
|
||||||
|
## Additional Resources
|
||||||
|
|
||||||
|
- [Complete Documentation](https://freeflowuniverse.github.io/herolib/)
|
||||||
|
- [Cookbook Examples](https://github.com/freeflowuniverse/herolib/tree/development/cookbook)
|
||||||
|
- [AI Prompts](aiprompts/starter/0_start_here.md)
|
||||||
|
|
||||||
|
## Generating Documentation
|
||||||
|
|
||||||
|
To generate documentation locally:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/code/github/freeflowuniverse/herolib
|
||||||
|
bash doc.sh
|
||||||
|
```
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import as
|
import as
|
||||||
|
|
||||||
```vlang
|
```vlang
|
||||||
import freeflowuniverse.herolib.osal
|
import freeflowuniverse.osal
|
||||||
|
|
||||||
osal.ping...
|
osal.ping...
|
||||||
|
|
||||||
@@ -70,14 +70,14 @@ mut pm:=process.processmap_get()?
|
|||||||
info returns like:
|
info returns like:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
}, freeflowuniverse.herolib.process.ProcessInfo{
|
}, freeflowuniverse.process.ProcessInfo{
|
||||||
cpu_perc: 0
|
cpu_perc: 0
|
||||||
mem_perc: 0
|
mem_perc: 0
|
||||||
cmd: 'mc'
|
cmd: 'mc'
|
||||||
pid: 84455
|
pid: 84455
|
||||||
ppid: 84467
|
ppid: 84467
|
||||||
rss: 3168
|
rss: 3168
|
||||||
}, freeflowuniverse.herolib.process.ProcessInfo{
|
}, freeflowuniverse.process.ProcessInfo{
|
||||||
cpu_perc: 0
|
cpu_perc: 0
|
||||||
mem_perc: 0
|
mem_perc: 0
|
||||||
cmd: 'zsh -Z -g'
|
cmd: 'zsh -Z -g'
|
||||||
@@ -195,13 +195,13 @@ fn initname() !string
|
|||||||
e.g. systemd, bash, zinit
|
e.g. systemd, bash, zinit
|
||||||
fn ipaddr_pub_get() !string
|
fn ipaddr_pub_get() !string
|
||||||
Returns the ipaddress as known on the public side is using resolver4.opendns.com
|
Returns the ipaddress as known on the public side is using resolver4.opendns.com
|
||||||
fn is_linux() bool
|
fn is_linux()! bool
|
||||||
fn is_linux_arm()! bool
|
fn is_linux_arm()! bool
|
||||||
fn is_linux_intel() bool
|
fn is_linux_intel()! bool
|
||||||
fn is_osx() bool
|
fn is_osx()! bool
|
||||||
fn is_osx_arm() bool
|
fn is_osx_arm()! bool
|
||||||
fn is_osx_intel() bool
|
fn is_osx_intel()! bool
|
||||||
fn is_ubuntu() bool
|
fn is_ubuntu()! bool
|
||||||
fn load_env_file(file_path string) !
|
fn load_env_file(file_path string) !
|
||||||
fn memdb_exists(key string) bool
|
fn memdb_exists(key string) bool
|
||||||
fn memdb_get(key string) string
|
fn memdb_get(key string) string
|
||||||
|
|||||||
39
aiprompts/ai_instruct/generate_player_for_models.md
Normal file
39
aiprompts/ai_instruct/generate_player_for_models.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
generate specs for /Users/despiegk/code/github/freeflowuniverse/herolib/lib/circles/actions
|
||||||
|
|
||||||
|
use mcp
|
||||||
|
|
||||||
|
get the output of it un actions/specs.v
|
||||||
|
|
||||||
|
then use these specs.v
|
||||||
|
|
||||||
|
to generate play command instructions see @3_heroscript_vlang.md
|
||||||
|
|
||||||
|
this play command gets heroscript in and will then call the methods for actions as are ONLY in @lib/circles/actions/db
|
||||||
|
|
||||||
|
so the play only calls the methods in @lib/circles/actions/db
|
||||||
|
|
||||||
|
|
||||||
|
# put the play commands in
|
||||||
|
|
||||||
|
/Users/despiegk/code/github/freeflowuniverse/herolib/lib/circles/actions/play
|
||||||
|
|
||||||
|
do one file in the module per action
|
||||||
|
|
||||||
|
each method is an action
|
||||||
|
|
||||||
|
put them all on one Struct called Player
|
||||||
|
in this Player we have a method per action
|
||||||
|
|
||||||
|
Player has a property called actor: which is the name of the actor as is used in the heroscript
|
||||||
|
Player has also a output called return format which is enum for heroscript or json
|
||||||
|
|
||||||
|
input of the method - action is a params object
|
||||||
|
|
||||||
|
on player there is a method play which takes the text as input or playbook
|
||||||
|
|
||||||
|
if text then playbook is created
|
||||||
|
|
||||||
|
then we walk over all actions
|
||||||
|
|
||||||
|
all the ones starting with actions in this case are given to the right method
|
||||||
|
|
||||||
15
aiprompts/code/opeapi.md
Normal file
15
aiprompts/code/opeapi.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
for @lib/circles/mcc
|
||||||
|
|
||||||
|
generate openapi 3.1 spec
|
||||||
|
do it as one file called openapi.yaml and put in the dir as mentioned above
|
||||||
|
|
||||||
|
based on the models and db implementation
|
||||||
|
|
||||||
|
implement well chosen examples in the openapi spec
|
||||||
|
|
||||||
|
note: in OpenAPI 3.1.0, the example property is deprecated in favor of examples
|
||||||
|
|
||||||
|
do this for the models & methods as defined below
|
||||||
|
|
||||||
|
do it also for the custom and generic methods, don't forget any
|
||||||
|
|
||||||
197
aiprompts/code/opeapi_full.md
Normal file
197
aiprompts/code/opeapi_full.md
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
in @lib/circles/mcc
|
||||||
|
generate openapi 3.1 spec
|
||||||
|
based on the models and db implementation
|
||||||
|
|
||||||
|
implement well chosen examples in the openapi spec
|
||||||
|
|
||||||
|
note: in OpenAPI 3.1.0, the example property is deprecated in favor of examples.
|
||||||
|
|
||||||
|
do this for the models & methods as defined below
|
||||||
|
|
||||||
|
do it for custom and generic methods, don't forget any
|
||||||
|
|
||||||
|
```v
|
||||||
|
|
||||||
|
// CalendarEvent represents a calendar event with all its properties
|
||||||
|
pub struct CalendarEvent {
|
||||||
|
pub mut:
|
||||||
|
id u32 // Unique identifier
|
||||||
|
title string // Event title
|
||||||
|
description string // Event details
|
||||||
|
location string // Event location
|
||||||
|
start_time ourtime.OurTime
|
||||||
|
end_time ourtime.OurTime // End time
|
||||||
|
all_day bool // True if it's an all-day event
|
||||||
|
recurrence string // RFC 5545 Recurrence Rule (e.g., "FREQ=DAILY;COUNT=10")
|
||||||
|
attendees []string // List of emails or user IDs
|
||||||
|
organizer string // Organizer email
|
||||||
|
status string // "CONFIRMED", "CANCELLED", "TENTATIVE"
|
||||||
|
caldav_uid string // CalDAV UID for syncing
|
||||||
|
sync_token string // Sync token for tracking changes
|
||||||
|
etag string // ETag for caching
|
||||||
|
color string // User-friendly color categorization
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Email represents an email message with all its metadata and content
|
||||||
|
pub struct Email {
|
||||||
|
pub mut:
|
||||||
|
// Database ID
|
||||||
|
id u32 // Database ID (assigned by DBHandler)
|
||||||
|
// Content fields
|
||||||
|
uid u32 // Unique identifier of the message (in the circle)
|
||||||
|
seq_num u32 // IMAP sequence number (in the mailbox)
|
||||||
|
mailbox string // The mailbox this email belongs to
|
||||||
|
message string // The email body content
|
||||||
|
attachments []Attachment // Any file attachments
|
||||||
|
|
||||||
|
// IMAP specific fields
|
||||||
|
flags []string // IMAP flags like \Seen, \Deleted, etc.
|
||||||
|
internal_date i64 // Unix timestamp when the email was received
|
||||||
|
size u32 // Size of the message in bytes
|
||||||
|
envelope ?Envelope // IMAP envelope information (contains From, To, Subject, etc.)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attachment represents an email attachment
|
||||||
|
pub struct Attachment {
|
||||||
|
pub mut:
|
||||||
|
filename string
|
||||||
|
content_type string
|
||||||
|
data string // Base64 encoded binary data
|
||||||
|
}
|
||||||
|
|
||||||
|
// Envelope represents an IMAP envelope structure
|
||||||
|
pub struct Envelope {
|
||||||
|
pub mut:
|
||||||
|
date i64
|
||||||
|
subject string
|
||||||
|
from []string
|
||||||
|
sender []string
|
||||||
|
reply_to []string
|
||||||
|
to []string
|
||||||
|
cc []string
|
||||||
|
bcc []string
|
||||||
|
in_reply_to string
|
||||||
|
message_id string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
methods
|
||||||
|
|
||||||
|
```v
|
||||||
|
pub fn (mut m MailDB) new() Email {
|
||||||
|
}
|
||||||
|
|
||||||
|
// set adds or updates an email
|
||||||
|
pub fn (mut m MailDB) set(email Email) !Email {
|
||||||
|
}
|
||||||
|
|
||||||
|
// get retrieves an email by its ID
|
||||||
|
pub fn (mut m MailDB) get(id u32) !Email {
|
||||||
|
}
|
||||||
|
|
||||||
|
// list returns all email IDs
|
||||||
|
pub fn (mut m MailDB) list() ![]u32 {
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut m MailDB) getall() ![]Email {
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete removes an email by its ID
|
||||||
|
pub fn (mut m MailDB) delete(id u32) ! {
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////CUSTOM METHODS//////////////////////////////////
|
||||||
|
|
||||||
|
// get_by_uid retrieves an email by its UID
|
||||||
|
pub fn (mut m MailDB) get_by_uid(uid u32) !Email {
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_by_mailbox retrieves all emails in a specific mailbox
|
||||||
|
pub fn (mut m MailDB) get_by_mailbox(mailbox string) ![]Email {
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete_by_uid removes an email by its UID
|
||||||
|
pub fn (mut m MailDB) delete_by_uid(uid u32) ! {
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete_by_mailbox removes all emails in a specific mailbox
|
||||||
|
pub fn (mut m MailDB) delete_by_mailbox(mailbox string) ! {
|
||||||
|
}
|
||||||
|
|
||||||
|
// update_flags updates the flags of an email
|
||||||
|
pub fn (mut m MailDB) update_flags(uid u32, flags []string) !Email {
|
||||||
|
}
|
||||||
|
|
||||||
|
// search_by_subject searches for emails with a specific subject substring
|
||||||
|
pub fn (mut m MailDB) search_by_subject(subject string) ![]Email {
|
||||||
|
}
|
||||||
|
|
||||||
|
// search_by_address searches for emails with a specific email address in from, to, cc, or bcc fields
|
||||||
|
pub fn (mut m MailDB) search_by_address(address string) ![]Email {
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut c CalendarDB) new() CalendarEvent {
|
||||||
|
CalendarEvent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set adds or updates a calendar event
|
||||||
|
pub fn (mut c CalendarDB) set(event CalendarEvent) CalendarEvent {
|
||||||
|
CalendarEvent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get retrieves a calendar event by its ID
|
||||||
|
pub fn (mut c CalendarDB) get(id u32) CalendarEvent {
|
||||||
|
CalendarEvent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// list returns all calendar event IDs
|
||||||
|
pub fn (mut c CalendarDB) list() []u32 {
|
||||||
|
[]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut c CalendarDB) getall() []CalendarEvent {
|
||||||
|
[]
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete removes a calendar event by its ID
|
||||||
|
pub fn (mut c CalendarDB) delete(id u32) {
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////CUSTOM METHODS//////////////////////////////////
|
||||||
|
|
||||||
|
// get_by_caldav_uid retrieves a calendar event by its CalDAV UID
|
||||||
|
pub fn (mut c CalendarDB) get_by_caldav_uid(caldav_uid String) CalendarEvent {
|
||||||
|
CalendarEvent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_events_by_date retrieves all events that occur on a specific date
|
||||||
|
pub fn (mut c CalendarDB) get_events_by_date(date String) []CalendarEvent {
|
||||||
|
[]
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_events_by_organizer retrieves all events organized by a specific person
|
||||||
|
pub fn (mut c CalendarDB) get_events_by_organizer(organizer String) []CalendarEvent {
|
||||||
|
[]
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_events_by_attendee retrieves all events that a specific person is attending
|
||||||
|
pub fn (mut c CalendarDB) get_events_by_attendee(attendee String) []CalendarEvent {
|
||||||
|
[]
|
||||||
|
}
|
||||||
|
|
||||||
|
// search_events_by_title searches for events with a specific title substring
|
||||||
|
pub fn (mut c CalendarDB) search_events_by_title(title String) []CalendarEvent {
|
||||||
|
[]
|
||||||
|
}
|
||||||
|
|
||||||
|
// update_status updates the status of an event
|
||||||
|
pub fn (mut c CalendarDB) update_status(id u32, status String) CalendarEvent {
|
||||||
|
CalendarEvent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete_by_caldav_uid removes an event by its CalDAV UID
|
||||||
|
pub fn (mut c CalendarDB) delete_by_caldav_uid(caldav_uid String) {
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
26
aiprompts/code/vfs.md
Normal file
26
aiprompts/code/vfs.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
create a module vfs_mail in @lib/vfs
|
||||||
|
check the interface as defined in @lib/vfs/interface.v and @metadata.v
|
||||||
|
|
||||||
|
see example how a vfs is made in @lib/vfs/vfs_local
|
||||||
|
|
||||||
|
create the vfs to represent mail objects in @lib/circles/dbs/core/mail_db.v
|
||||||
|
|
||||||
|
mailbox propery on the Email object defines the path in the vfs
|
||||||
|
this mailbox property can be e.g. Draft/something/somethingelse
|
||||||
|
|
||||||
|
in that dir show a subdir /id:
|
||||||
|
- which show the Email as a json underneith the ${email.id}.json
|
||||||
|
|
||||||
|
in that dir show subdir /subject:
|
||||||
|
- which show the Email as a json underneith the name_fix(${email.envelope.subject}.json
|
||||||
|
|
||||||
|
so basically we have 2 representations of the same mail in the vfs, both have the. json as content of the file
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
14
aiprompts/env.md
Normal file
14
aiprompts/env.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
```v
|
||||||
|
import freeflowuniverse.herolib.osal
|
||||||
|
|
||||||
|
// Get environment variable
|
||||||
|
value := osal.env_get('PATH')!
|
||||||
|
|
||||||
|
// Set environment variable
|
||||||
|
osal.env_set('MY_VAR', 'value')!
|
||||||
|
|
||||||
|
// Check if environment variable exists
|
||||||
|
exists := osal.env_exists('MY_VAR')
|
||||||
|
```
|
||||||
78
aiprompts/starter/1_heroscript.md
Normal file
78
aiprompts/starter/1_heroscript.md
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
# HeroScript
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
HeroScript is a simple, declarative scripting language designed to define workflows and execute commands in a structured manner. It follows a straightforward syntax where each action is prefixed with `!!`, indicating the actor and action name.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
A basic HeroScript script for virtual machine management looks like this:
|
||||||
|
|
||||||
|
```heroscript
|
||||||
|
!!vm.define name:'test_vm' cpu:4
|
||||||
|
memory: '8GB'
|
||||||
|
storage: '100GB'
|
||||||
|
description: '
|
||||||
|
A virtual machine configuration
|
||||||
|
with specific resources.
|
||||||
|
'
|
||||||
|
|
||||||
|
!!vm.start name:'test_vm'
|
||||||
|
|
||||||
|
!!vm.disk_add
|
||||||
|
name: 'test_vm'
|
||||||
|
size: '50GB'
|
||||||
|
type: 'SSD'
|
||||||
|
|
||||||
|
!!vm.delete
|
||||||
|
name: 'test_vm'
|
||||||
|
force: true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Features
|
||||||
|
|
||||||
|
- Every action starts with `!!`.
|
||||||
|
- The first part after `!!` is the actor (e.g., `vm`).
|
||||||
|
- The second part is the action name (e.g., `define`, `start`, `delete`).
|
||||||
|
- Multi-line values are supported (e.g., the `description` field).
|
||||||
|
- Lists are comma-separated where applicable and inside ''.
|
||||||
|
- If items one 1 line, then no space between name & argument e.g. name:'test_vm'
|
||||||
|
|
||||||
|
## Parsing HeroScript
|
||||||
|
|
||||||
|
Internally, HeroScript gets parsed into an action object with parameters. Each parameter follows a `key: value` format.
|
||||||
|
|
||||||
|
### Parsing Example
|
||||||
|
|
||||||
|
```heroscript
|
||||||
|
!!actor.action
|
||||||
|
id:a1 name6:aaaaa
|
||||||
|
name:'need to do something 1'
|
||||||
|
description:
|
||||||
|
'
|
||||||
|
## markdown works in it
|
||||||
|
description can be multiline
|
||||||
|
lets see what happens
|
||||||
|
|
||||||
|
- a
|
||||||
|
- something else
|
||||||
|
|
||||||
|
### subtitle
|
||||||
|
'
|
||||||
|
|
||||||
|
name2: test
|
||||||
|
name3: hi
|
||||||
|
name10:'this is with space' name11:aaa11
|
||||||
|
|
||||||
|
name4: 'aaa'
|
||||||
|
|
||||||
|
//somecomment
|
||||||
|
name5: 'aab'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parsing Details
|
||||||
|
- Each parameter follows a `key: value` format.
|
||||||
|
- Multi-line values (such as descriptions) support Markdown formatting.
|
||||||
|
- Comments can be added using `//`.
|
||||||
|
- Keys and values can have spaces, and values can be enclosed in single quotes.
|
||||||
|
|
||||||
@@ -1,45 +1,3 @@
|
|||||||
# how to work with heroscript in vlang
|
|
||||||
|
|
||||||
## heroscript
|
|
||||||
|
|
||||||
Heroscript is our small scripting language which has following structure
|
|
||||||
|
|
||||||
an example of a heroscript is
|
|
||||||
|
|
||||||
```heroscript
|
|
||||||
|
|
||||||
!!dagu.script_define
|
|
||||||
name: 'test_dag'
|
|
||||||
homedir:''
|
|
||||||
title:'a title'
|
|
||||||
reset:1
|
|
||||||
start:true //trie or 1 is same
|
|
||||||
colors: 'green,red,purple' //lists are comma separated
|
|
||||||
description: '
|
|
||||||
a description can be multiline
|
|
||||||
|
|
||||||
like this
|
|
||||||
'
|
|
||||||
|
|
||||||
|
|
||||||
!!dagu.add_step
|
|
||||||
dag: 'test_dag'
|
|
||||||
name: 'hello_world'
|
|
||||||
command: 'echo hello world'
|
|
||||||
|
|
||||||
!!dagu.add_step
|
|
||||||
dag: 'test_dag'
|
|
||||||
name: 'last_step'
|
|
||||||
command: 'echo last step'
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
Notice how:
|
|
||||||
- every action starts with !!
|
|
||||||
- the first part is the actor e.g. dagu in this case
|
|
||||||
- the 2e part is the action name
|
|
||||||
- multilines are supported see the description field
|
|
||||||
|
|
||||||
## how to process heroscript in Vlang
|
## how to process heroscript in Vlang
|
||||||
|
|
||||||
1
cli/.gitignore
vendored
1
cli/.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
hero
|
hero
|
||||||
compile
|
compile
|
||||||
compile_upload
|
compile_upload
|
||||||
|
vdo
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env -S v -n -w -parallel-cc -enable-globals run
|
#!/usr/bin/env -S v -n -cg -w -parallel-cc -enable-globals run
|
||||||
// #!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
// #!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import flag
|
import flag
|
||||||
|
|||||||
77
cli/compile_vdo.vsh
Executable file
77
cli/compile_vdo.vsh
Executable file
@@ -0,0 +1,77 @@
|
|||||||
|
#!/usr/bin/env -S v -n -cg -w -parallel-cc -enable-globals run
|
||||||
|
// #!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import os
|
||||||
|
import flag
|
||||||
|
|
||||||
|
mut fp := flag.new_flag_parser(os.args)
|
||||||
|
fp.application('compile_vdo.vsh')
|
||||||
|
fp.version('v0.1.0')
|
||||||
|
fp.description('Compile vdo binary in debug or production mode')
|
||||||
|
fp.skip_executable()
|
||||||
|
|
||||||
|
prod_mode := fp.bool('prod', `p`, false, 'Build production version (optimized)')
|
||||||
|
help_requested := fp.bool('help', `h`, false, 'Show help message')
|
||||||
|
|
||||||
|
if help_requested {
|
||||||
|
println(fp.usage())
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
additional_args := fp.finalize() or {
|
||||||
|
eprintln(err)
|
||||||
|
println(fp.usage())
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if additional_args.len > 0 {
|
||||||
|
eprintln('Unexpected arguments: ${additional_args.join(' ')}')
|
||||||
|
println(fp.usage())
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change to the vdo directory
|
||||||
|
hero_dir := os.join_path(os.home_dir(), 'code/github/freeflowuniverse/herolib/cli')
|
||||||
|
os.chdir(hero_dir) or { panic('Failed to change directory to ${hero_dir}: ${err}') }
|
||||||
|
|
||||||
|
// Set HEROPATH based on OS
|
||||||
|
mut heropath := '/usr/local/bin/vdo'
|
||||||
|
if os.user_os() == 'macos' {
|
||||||
|
heropath = os.join_path(os.home_dir(), 'hero/bin/vdo')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set compilation command based on OS and mode
|
||||||
|
compile_cmd := if os.user_os() == 'macos' {
|
||||||
|
if prod_mode {
|
||||||
|
'v -enable-globals -w -n -prod vdo.v'
|
||||||
|
} else {
|
||||||
|
'v -w -cg -gc none -cc tcc -d use_openssl -enable-globals vdo.v'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if prod_mode {
|
||||||
|
'v -cg -enable-globals -parallel-cc -w -n vdo.v'
|
||||||
|
} else {
|
||||||
|
'v -cg -enable-globals -w -n vdo.v'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println('Building in ${if prod_mode { 'production' } else { 'debug' }} mode...')
|
||||||
|
|
||||||
|
if os.system(compile_cmd) != 0 {
|
||||||
|
panic('Failed to compile vdo.v with command: ${compile_cmd}')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make executable
|
||||||
|
os.chmod('vdo', 0o755) or { panic('Failed to make vdo binary executable: ${err}') }
|
||||||
|
|
||||||
|
// Ensure destination directory exists
|
||||||
|
os.mkdir_all(os.dir(heropath)) or { panic('Failed to create directory ${os.dir(heropath)}: ${err}') }
|
||||||
|
println(heropath)
|
||||||
|
// Copy to destination paths
|
||||||
|
os.cp('vdo', heropath) or { panic('Failed to copy vdo binary to ${heropath}: ${err}') }
|
||||||
|
os.cp('vdo', '/tmp/vdo') or { panic('Failed to copy vdo binary to /tmp/vdo: ${err}') }
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
os.rm('vdo') or { panic('Failed to remove temporary vdo binary: ${err}') }
|
||||||
|
|
||||||
|
println('**COMPILE OK**')
|
||||||
@@ -51,7 +51,7 @@ fn do() ! {
|
|||||||
mut cmd := Command{
|
mut cmd := Command{
|
||||||
name: 'hero'
|
name: 'hero'
|
||||||
description: 'Your HERO toolset.'
|
description: 'Your HERO toolset.'
|
||||||
version: '1.0.14'
|
version: '1.0.25'
|
||||||
}
|
}
|
||||||
|
|
||||||
// herocmds.cmd_run_add_flags(mut cmd)
|
// herocmds.cmd_run_add_flags(mut cmd)
|
||||||
@@ -102,6 +102,7 @@ fn do() ! {
|
|||||||
// herocmds.cmd_juggler(mut cmd)
|
// herocmds.cmd_juggler(mut cmd)
|
||||||
herocmds.cmd_generator(mut cmd)
|
herocmds.cmd_generator(mut cmd)
|
||||||
herocmds.cmd_docusaurus(mut cmd)
|
herocmds.cmd_docusaurus(mut cmd)
|
||||||
|
herocmds.cmd_starlight(mut cmd)
|
||||||
// herocmds.cmd_docsorter(mut cmd)
|
// herocmds.cmd_docsorter(mut cmd)
|
||||||
// cmd.add_command(publishing.cmd_publisher(pre_func))
|
// cmd.add_command(publishing.cmd_publisher(pre_func))
|
||||||
cmd.setup()
|
cmd.setup()
|
||||||
|
|||||||
12
cli/vdo.v
Normal file
12
cli/vdo.v
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.mcp.v_do
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Create and start the MCP server
|
||||||
|
mut server := v_do.new_server()
|
||||||
|
server.start() or {
|
||||||
|
eprintln('Error starting server: $err')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
480
compile.sh
Executable file
480
compile.sh
Executable file
@@ -0,0 +1,480 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# compile.sh - Script to compile each module in the herolib/lib directory
|
||||||
|
# This script compiles each module in the lib directory to ensure they build correctly
|
||||||
|
|
||||||
|
set -e # Exit on error
|
||||||
|
|
||||||
|
# Default settings
|
||||||
|
CONCURRENT=false
|
||||||
|
MAX_JOBS=4 # Default number of concurrent jobs
|
||||||
|
|
||||||
|
# Parse command line arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-c|--concurrent)
|
||||||
|
CONCURRENT=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-j|--jobs)
|
||||||
|
MAX_JOBS="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
echo "Usage: $0 [options]"
|
||||||
|
echo "Options:"
|
||||||
|
echo " -c, --concurrent Enable concurrent compilation"
|
||||||
|
echo " -j, --jobs N Set maximum number of concurrent jobs (default: 4)"
|
||||||
|
echo " -h, --help Show this help message"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
echo "Use -h or --help for usage information"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Color codes for output
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Get the directory of this script
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
LIB_DIR="$SCRIPT_DIR/lib"
|
||||||
|
|
||||||
|
# V compiler flags based on the project's test script
|
||||||
|
V_FLAGS="-stats -enable-globals -n -w -gc none -d use_openssl -shared"
|
||||||
|
|
||||||
|
# Log file for compilation results
|
||||||
|
LOG_FILE="$SCRIPT_DIR/compile_results.log"
|
||||||
|
> "$LOG_FILE" # Clear log file
|
||||||
|
|
||||||
|
# Summary log file
|
||||||
|
SUMMARY_FILE="$SCRIPT_DIR/compile_summary.log"
|
||||||
|
> "$SUMMARY_FILE" # Clear summary file
|
||||||
|
|
||||||
|
# Cache directory for storing timestamps of last successful compilation
|
||||||
|
CACHE_DIR="$SCRIPT_DIR/.compile_cache"
|
||||||
|
mkdir -p "$CACHE_DIR"
|
||||||
|
|
||||||
|
# Create temporary directory for compiled binaries
|
||||||
|
mkdir -p "$SCRIPT_DIR/tmp"
|
||||||
|
|
||||||
|
# Create a directory for temporary output files
|
||||||
|
TEMP_DIR="$SCRIPT_DIR/.temp_compile"
|
||||||
|
mkdir -p "$TEMP_DIR"
|
||||||
|
|
||||||
|
# Trap for cleaning up on exit
|
||||||
|
cleanup() {
|
||||||
|
echo "Cleaning up..."
|
||||||
|
# Kill any remaining child processes
|
||||||
|
jobs -p | xargs kill -9 2>/dev/null || true
|
||||||
|
# Remove temporary directories
|
||||||
|
rm -rf "$TEMP_DIR" "$SCRIPT_DIR/tmp" 2>/dev/null || true
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set up traps for various signals
|
||||||
|
trap cleanup EXIT INT TERM
|
||||||
|
|
||||||
|
# Define modules to skip entirely due to known compilation issues
|
||||||
|
SKIP_MODULES=("flist" "openai" "mycelium" "vastai" "rclone" "sendgrid" "mailclient" "ipapi" "runpod" "postgresql_client" "meilisearch" "livekit" "wireguard" "_archive" "clients")
|
||||||
|
|
||||||
|
# Function to check if a module should be skipped
|
||||||
|
should_skip_module() {
|
||||||
|
local module_name="$1"
|
||||||
|
|
||||||
|
for skip_module in "${SKIP_MODULES[@]}"; do
|
||||||
|
if [[ "$module_name" == "$skip_module" ]]; then
|
||||||
|
return 0 # true, should skip
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1 # false, should not skip
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check if a module needs recompilation
|
||||||
|
needs_module_recompilation() {
|
||||||
|
local module_path="$1"
|
||||||
|
local module_name="$(basename "$module_path")"
|
||||||
|
local cache_file="$CACHE_DIR/$module_name.timestamp"
|
||||||
|
|
||||||
|
# If cache file doesn't exist, module needs recompilation
|
||||||
|
if [ ! -f "$cache_file" ]; then
|
||||||
|
return 0 # true, needs recompilation
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if any .v file in the module is newer than the last compilation
|
||||||
|
if find "$module_path" -name "*.v" -type f -newer "$cache_file" | grep -q .; then
|
||||||
|
return 0 # true, needs recompilation
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1 # false, doesn't need recompilation
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to update the cache timestamp for a module
|
||||||
|
update_module_cache() {
|
||||||
|
local module_path="$1"
|
||||||
|
local module_name="$(basename "$module_path")"
|
||||||
|
local cache_file="$CACHE_DIR/$module_name.timestamp"
|
||||||
|
|
||||||
|
# Update the timestamp
|
||||||
|
touch "$cache_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check if a directory is a module (contains .v files directly, not just in subdirectories)
|
||||||
|
is_module() {
|
||||||
|
local dir_path="$1"
|
||||||
|
|
||||||
|
# Check if there are any .v files directly in this directory (not in subdirectories)
|
||||||
|
if [ -n "$(find "$dir_path" -maxdepth 1 -name "*.v" -type f -print -quit)" ]; then
|
||||||
|
return 0 # true, is a module
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1 # false, not a module
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to compile a module
|
||||||
|
compile_module() {
|
||||||
|
local module_path="$1"
|
||||||
|
local module_name="$(basename "$module_path")"
|
||||||
|
local output_file="$TEMP_DIR/${module_name}.log"
|
||||||
|
local result_file="$TEMP_DIR/${module_name}.result"
|
||||||
|
|
||||||
|
# Initialize the result file
|
||||||
|
echo "pending" > "$result_file"
|
||||||
|
|
||||||
|
# Check if this module should be skipped
|
||||||
|
if should_skip_module "$module_name"; then
|
||||||
|
echo "Skipping problematic module: $module_name" > "$output_file"
|
||||||
|
echo "skipped|${module_path#$LIB_DIR/}|" >> "$SUMMARY_FILE"
|
||||||
|
echo "skipped" > "$result_file"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if this is actually a module (has .v files directly)
|
||||||
|
if ! is_module "$module_path"; then
|
||||||
|
echo "$module_name is not a module (no direct .v files), skipping" > "$output_file"
|
||||||
|
echo "not_module|${module_path#$LIB_DIR/}|" >> "$SUMMARY_FILE"
|
||||||
|
echo "skipped" > "$result_file"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Compiling module: $module_name" > "$output_file"
|
||||||
|
|
||||||
|
# Check if the module needs recompilation
|
||||||
|
if ! needs_module_recompilation "$module_path"; then
|
||||||
|
echo " No changes detected in $module_name, skipping compilation" >> "$output_file"
|
||||||
|
echo "cached|${module_path#$LIB_DIR/}|" >> "$SUMMARY_FILE"
|
||||||
|
echo "cached" > "$result_file"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Record start time
|
||||||
|
local start_time=$(date +%s.%N)
|
||||||
|
|
||||||
|
# Try to compile the module - redirect both stdout and stderr to the output file
|
||||||
|
if v $V_FLAGS -o "$SCRIPT_DIR/tmp/$module_name" "$module_path" >> "$output_file" 2>&1; then
|
||||||
|
# Calculate compilation time
|
||||||
|
local end_time=$(date +%s.%N)
|
||||||
|
local compile_time=$(echo "$end_time - $start_time" | bc)
|
||||||
|
|
||||||
|
echo " Successfully compiled $module_name" >> "$output_file"
|
||||||
|
# Update the cache timestamp
|
||||||
|
update_module_cache "$module_path"
|
||||||
|
|
||||||
|
# Log result
|
||||||
|
echo "success|${module_path#$LIB_DIR/}|$compile_time" >> "$SUMMARY_FILE"
|
||||||
|
echo "success" > "$result_file"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo " Failed to compile $module_name" >> "$output_file"
|
||||||
|
|
||||||
|
# Log result
|
||||||
|
echo "failed|${module_path#$LIB_DIR/}|" >> "$SUMMARY_FILE"
|
||||||
|
echo "failed" > "$result_file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to run modules in parallel with a maximum number of concurrent jobs
|
||||||
|
run_parallel() {
|
||||||
|
local modules=("$@")
|
||||||
|
local total=${#modules[@]}
|
||||||
|
local completed=0
|
||||||
|
local running=0
|
||||||
|
local pids=()
|
||||||
|
local module_indices=()
|
||||||
|
|
||||||
|
echo "Running $total modules in parallel (max $MAX_JOBS jobs at once)"
|
||||||
|
|
||||||
|
# Initialize arrays to track jobs
|
||||||
|
for ((i=0; i<$total; i++)); do
|
||||||
|
pids[$i]=-1
|
||||||
|
done
|
||||||
|
|
||||||
|
# Start initial batch of jobs
|
||||||
|
local next_job=0
|
||||||
|
while [[ $next_job -lt $total && $running -lt $MAX_JOBS ]]; do
|
||||||
|
compile_module "${modules[$next_job]}" > /dev/null 2>&1 &
|
||||||
|
pids[$next_job]=$!
|
||||||
|
((running++))
|
||||||
|
((next_job++))
|
||||||
|
done
|
||||||
|
|
||||||
|
# Display progress indicator
|
||||||
|
display_progress() {
|
||||||
|
local current=$1
|
||||||
|
local total=$2
|
||||||
|
local percent=$((current * 100 / total))
|
||||||
|
local bar_length=50
|
||||||
|
local filled_length=$((percent * bar_length / 100))
|
||||||
|
|
||||||
|
printf "\r[" >&2
|
||||||
|
for ((i=0; i<bar_length; i++)); do
|
||||||
|
if [ $i -lt $filled_length ]; then
|
||||||
|
printf "#" >&2
|
||||||
|
else
|
||||||
|
printf " " >&2
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
printf "] %d%% (%d/%d modules)" $percent $current $total >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
# Monitor running jobs and start new ones as needed
|
||||||
|
while [[ $completed -lt $total ]]; do
|
||||||
|
display_progress $completed $total
|
||||||
|
|
||||||
|
# Check for completed jobs
|
||||||
|
for ((i=0; i<$total; i++)); do
|
||||||
|
if [[ ${pids[$i]} -gt 0 ]]; then
|
||||||
|
if ! kill -0 ${pids[$i]} 2>/dev/null; then
|
||||||
|
# Job completed
|
||||||
|
local module_path="${modules[$i]}"
|
||||||
|
local module_name="$(basename "$module_path")"
|
||||||
|
local output_file="$TEMP_DIR/${module_name}.log"
|
||||||
|
|
||||||
|
# Add output to log file
|
||||||
|
if [[ -f "$output_file" ]]; then
|
||||||
|
cat "$output_file" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Mark job as completed
|
||||||
|
pids[$i]=-2
|
||||||
|
((completed++))
|
||||||
|
((running--))
|
||||||
|
|
||||||
|
# Start a new job if available
|
||||||
|
if [[ $next_job -lt $total ]]; then
|
||||||
|
compile_module "${modules[$next_job]}" > /dev/null 2>&1 &
|
||||||
|
pids[$next_job]=$!
|
||||||
|
((running++))
|
||||||
|
((next_job++))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Brief pause to avoid excessive CPU usage
|
||||||
|
sleep 0.1
|
||||||
|
done
|
||||||
|
|
||||||
|
# Clear the progress line
|
||||||
|
printf "\r%$(tput cols)s\r" ""
|
||||||
|
|
||||||
|
# Wait for any remaining background jobs
|
||||||
|
wait
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to find all modules in a directory (recursively)
|
||||||
|
find_modules() {
|
||||||
|
local dir_path="$1"
|
||||||
|
local modules=()
|
||||||
|
|
||||||
|
# Check if this directory is a module itself
|
||||||
|
if is_module "$dir_path"; then
|
||||||
|
modules+=("$dir_path")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Look for modules in subdirectories (only one level deep)
|
||||||
|
for subdir in "$dir_path"/*; do
|
||||||
|
if [ -d "$subdir" ]; then
|
||||||
|
local subdir_name="$(basename "$subdir")"
|
||||||
|
|
||||||
|
# Skip if this is in the skip list
|
||||||
|
if should_skip_module "$subdir_name"; then
|
||||||
|
echo -e "${YELLOW}Skipping problematic module: $subdir_name${NC}"
|
||||||
|
echo "Skipping problematic module: $subdir_name" >> "$LOG_FILE"
|
||||||
|
echo "skipped|${subdir#$LIB_DIR/}|" >> "$SUMMARY_FILE"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if this subdirectory is a module
|
||||||
|
if is_module "$subdir"; then
|
||||||
|
modules+=("$subdir")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "${modules[@]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "===== Starting compilation of all modules in lib ====="
|
||||||
|
echo "===== Starting compilation of all modules in lib =====" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Define priority modules to compile first
|
||||||
|
PRIORITY_MODULES=("biz" "builder" "core" "crystallib" "jsonrpc" "jsonschema")
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Attempting to compile each module as a whole...${NC}"
|
||||||
|
echo "Attempting to compile each module as a whole..." >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Collect all modules to compile
|
||||||
|
all_modules=()
|
||||||
|
|
||||||
|
# First add priority modules
|
||||||
|
for module_name in "${PRIORITY_MODULES[@]}"; do
|
||||||
|
module_dir="$LIB_DIR/$module_name"
|
||||||
|
if [ -d "$module_dir" ]; then
|
||||||
|
# Find all modules in this directory
|
||||||
|
modules=($(find_modules "$module_dir"))
|
||||||
|
all_modules+=("${modules[@]}")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Then add remaining modules
|
||||||
|
for module_dir in "$LIB_DIR"/*; do
|
||||||
|
if [ -d "$module_dir" ]; then
|
||||||
|
module_name="$(basename "$module_dir")"
|
||||||
|
# Skip modules already compiled in priority list
|
||||||
|
if [[ " ${PRIORITY_MODULES[*]} " =~ " $module_name " ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Find all modules in this directory
|
||||||
|
modules=($(find_modules "$module_dir"))
|
||||||
|
all_modules+=("${modules[@]}")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Debug: print all modules found
|
||||||
|
echo "Found ${#all_modules[@]} modules to compile" >> "$LOG_FILE"
|
||||||
|
for module in "${all_modules[@]}"; do
|
||||||
|
echo " - $module" >> "$LOG_FILE"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Compile modules (either in parallel or sequentially)
|
||||||
|
if $CONCURRENT; then
|
||||||
|
run_parallel "${all_modules[@]}"
|
||||||
|
else
|
||||||
|
# Sequential compilation
|
||||||
|
for module_path in "${all_modules[@]}"; do
|
||||||
|
# Display module being compiled
|
||||||
|
module_name="$(basename "$module_path")"
|
||||||
|
echo -e "${YELLOW}Compiling module: $module_name${NC}"
|
||||||
|
|
||||||
|
# Compile the module
|
||||||
|
compile_module "$module_path" > /dev/null 2>&1
|
||||||
|
|
||||||
|
# Display result
|
||||||
|
output_file="$TEMP_DIR/${module_name}.log"
|
||||||
|
result_file="$TEMP_DIR/${module_name}.result"
|
||||||
|
|
||||||
|
if [[ -f "$output_file" ]]; then
|
||||||
|
cat "$output_file" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Display with color based on result
|
||||||
|
result=$(cat "$result_file")
|
||||||
|
if [[ "$result" == "success" ]]; then
|
||||||
|
echo -e "${GREEN} Successfully compiled $module_name${NC}"
|
||||||
|
elif [[ "$result" == "failed" ]]; then
|
||||||
|
echo -e "${RED} Failed to compile $module_name${NC}"
|
||||||
|
elif [[ "$result" == "cached" ]]; then
|
||||||
|
echo -e "${GREEN} No changes detected in $module_name, skipping compilation${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW} Skipped $module_name${NC}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Count successes and failures
|
||||||
|
success_count=$(grep -c "^success|" "$SUMMARY_FILE" || echo 0)
|
||||||
|
failure_count=$(grep -c "^failed|" "$SUMMARY_FILE" || echo 0)
|
||||||
|
cached_count=$(grep -c "^cached|" "$SUMMARY_FILE" || echo 0)
|
||||||
|
skipped_count=$(grep -c "^skipped|" "$SUMMARY_FILE" || echo 0)
|
||||||
|
not_module_count=$(grep -c "^not_module|" "$SUMMARY_FILE" || echo 0)
|
||||||
|
|
||||||
|
echo "===== Compilation complete ====="
|
||||||
|
echo -e "${GREEN}Successfully compiled: $success_count modules${NC}"
|
||||||
|
echo -e "${GREEN}Cached (no changes): $cached_count modules${NC}"
|
||||||
|
echo -e "${YELLOW}Skipped: $skipped_count modules${NC}"
|
||||||
|
echo -e "${YELLOW}Not modules: $not_module_count directories${NC}"
|
||||||
|
echo -e "${RED}Failed to compile: $failure_count modules${NC}"
|
||||||
|
echo "See $LOG_FILE for detailed compilation results"
|
||||||
|
|
||||||
|
echo "===== Compilation complete =====" >> "$LOG_FILE"
|
||||||
|
echo "Successfully compiled: $success_count modules" >> "$LOG_FILE"
|
||||||
|
echo "Cached (no changes): $cached_count modules" >> "$LOG_FILE"
|
||||||
|
echo "Skipped: $skipped_count modules" >> "$LOG_FILE"
|
||||||
|
echo "Not modules: $not_module_count directories" >> "$LOG_FILE"
|
||||||
|
echo "Failed to compile: $failure_count modules" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Print detailed summary
|
||||||
|
echo ""
|
||||||
|
echo "===== Module Compilation Summary ====="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Print successful modules first, sorted by compilation time
|
||||||
|
echo "Successful compilations:"
|
||||||
|
grep "^success|" "$SUMMARY_FILE" | sort -t'|' -k3,3n | while IFS='|' read -r status path time; do
|
||||||
|
# Color code based on compilation time
|
||||||
|
time_color="$GREEN"
|
||||||
|
if (( $(echo "$time > 10.0" | bc -l) )); then
|
||||||
|
time_color="$RED"
|
||||||
|
elif (( $(echo "$time > 1.0" | bc -l) )); then
|
||||||
|
time_color="$YELLOW"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "✅ $path\t${time_color}${time}s${NC}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Print cached modules
|
||||||
|
echo ""
|
||||||
|
echo "Cached modules (no changes detected):"
|
||||||
|
grep "^cached|" "$SUMMARY_FILE" | sort | while IFS='|' read -r status path time; do
|
||||||
|
echo -e "🔄 $path\t${GREEN}CACHED${NC}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Print skipped modules
|
||||||
|
echo ""
|
||||||
|
echo "Skipped modules:"
|
||||||
|
grep "^skipped|" "$SUMMARY_FILE" | sort | while IFS='|' read -r status path time; do
|
||||||
|
echo -e "⏭️ $path\t${YELLOW}SKIPPED${NC}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Print not modules
|
||||||
|
echo ""
|
||||||
|
echo "Not modules (directories without direct .v files):"
|
||||||
|
grep "^not_module|" "$SUMMARY_FILE" | sort | while IFS='|' read -r status path time; do
|
||||||
|
echo -e "📁 $path\t${YELLOW}NOT MODULE${NC}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Print failed modules
|
||||||
|
echo ""
|
||||||
|
echo "Failed modules:"
|
||||||
|
grep "^failed|" "$SUMMARY_FILE" | sort | while IFS='|' read -r status path time; do
|
||||||
|
echo -e "❌ $path\t${RED}FAILED${NC}"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "===== End of Summary ====="
|
||||||
|
|
||||||
|
# Exit with error code if any module failed to compile
|
||||||
|
if [ $failure_count -gt 0 ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
71
examples/aiexamples/groq.vsh
Executable file
71
examples/aiexamples/groq.vsh
Executable file
@@ -0,0 +1,71 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
module main
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.clients.openai
|
||||||
|
import os
|
||||||
|
|
||||||
|
fn test1(mut client openai.OpenAI) ! {
|
||||||
|
instruction := '
|
||||||
|
You are a template language converter. You convert Pug templates to Jet templates.
|
||||||
|
|
||||||
|
The target template language, Jet, is defined as follows:
|
||||||
|
'
|
||||||
|
|
||||||
|
// Create a chat completion request
|
||||||
|
res := client.chat_completion(
|
||||||
|
msgs: openai.Messages{
|
||||||
|
messages: [
|
||||||
|
openai.Message{
|
||||||
|
role: .user
|
||||||
|
content: 'What are the key differences between Groq and other AI inference providers?'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)!
|
||||||
|
|
||||||
|
// Print the response
|
||||||
|
println('\nGroq AI Response:')
|
||||||
|
println('==================')
|
||||||
|
println(res.choices[0].message.content)
|
||||||
|
println('\nUsage Statistics:')
|
||||||
|
println('Prompt tokens: ${res.usage.prompt_tokens}')
|
||||||
|
println('Completion tokens: ${res.usage.completion_tokens}')
|
||||||
|
println('Total tokens: ${res.usage.total_tokens}')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test2(mut client openai.OpenAI) ! {
|
||||||
|
// Create a chat completion request
|
||||||
|
res := client.chat_completion(
|
||||||
|
model: 'deepseek-r1-distill-llama-70b'
|
||||||
|
msgs: openai.Messages{
|
||||||
|
messages: [
|
||||||
|
openai.Message{
|
||||||
|
role: .user
|
||||||
|
content: 'A story of 10 lines?'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)!
|
||||||
|
|
||||||
|
println('\nGroq AI Response:')
|
||||||
|
println('==================')
|
||||||
|
println(res.choices[0].message.content)
|
||||||
|
println('\nUsage Statistics:')
|
||||||
|
println('Prompt tokens: ${res.usage.prompt_tokens}')
|
||||||
|
println('Completion tokens: ${res.usage.completion_tokens}')
|
||||||
|
println('Total tokens: ${res.usage.total_tokens}')
|
||||||
|
}
|
||||||
|
|
||||||
|
println("
|
||||||
|
TO USE:
|
||||||
|
export AIKEY='gsk_...'
|
||||||
|
export AIURL='https://api.groq.com/openai/v1'
|
||||||
|
export AIMODEL='llama-3.3-70b-versatile'
|
||||||
|
")
|
||||||
|
|
||||||
|
mut client := openai.get(name: 'test')!
|
||||||
|
println(client)
|
||||||
|
|
||||||
|
// test1(mut client)!
|
||||||
|
test2(mut client)!
|
||||||
7
examples/aiexamples/jetconvertor.vsh
Executable file
7
examples/aiexamples/jetconvertor.vsh
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.mcp.aitools
|
||||||
|
|
||||||
|
// aitools.convert_pug("/root/code/github/freeflowuniverse/herolauncher/pkg/herolauncher/web/templates/admin")!
|
||||||
|
|
||||||
|
aitools.convert_pug('/root/code/github/freeflowuniverse/herolauncher/pkg/zaz/webui/templates')!
|
||||||
86
examples/aiexamples/jina.vsh
Executable file
86
examples/aiexamples/jina.vsh
Executable file
@@ -0,0 +1,86 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.clients.jina
|
||||||
|
|
||||||
|
mut jina_client := jina.get()!
|
||||||
|
health := jina_client.health()!
|
||||||
|
println('Server health: ${health}')
|
||||||
|
|
||||||
|
// Create embeddings
|
||||||
|
embeddings := jina_client.create_embeddings(
|
||||||
|
input: ['Hello', 'World']
|
||||||
|
model: .jina_embeddings_v3
|
||||||
|
task: 'separation'
|
||||||
|
) or { panic('Error while creating embeddings: ${err}') }
|
||||||
|
|
||||||
|
println('Created embeddings: ${embeddings}')
|
||||||
|
|
||||||
|
// Rerank
|
||||||
|
rerank_result := jina_client.rerank(
|
||||||
|
model: .reranker_v2_base_multilingual
|
||||||
|
query: 'skincare products'
|
||||||
|
documents: ['Product A', 'Product B', 'Product C']
|
||||||
|
top_n: 2
|
||||||
|
) or { panic('Error while reranking: ${err}') }
|
||||||
|
|
||||||
|
println('Rerank result: ${rerank_result}')
|
||||||
|
|
||||||
|
// Train
|
||||||
|
train_result := jina_client.train(
|
||||||
|
model: .jina_clip_v1
|
||||||
|
input: [
|
||||||
|
jina.TrainingExample{
|
||||||
|
text: 'Sample text'
|
||||||
|
label: 'positive'
|
||||||
|
},
|
||||||
|
jina.TrainingExample{
|
||||||
|
image: 'https://letsenhance.io/static/73136da51c245e80edc6ccfe44888a99/1015f/MainBefore.jpg'
|
||||||
|
label: 'negative'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
) or { panic('Error while training: ${err}') }
|
||||||
|
|
||||||
|
println('Train result: ${train_result}')
|
||||||
|
|
||||||
|
// Classify
|
||||||
|
classify_result := jina_client.classify(
|
||||||
|
model: .jina_clip_v1
|
||||||
|
input: [
|
||||||
|
jina.ClassificationInput{
|
||||||
|
text: 'A photo of a cat'
|
||||||
|
},
|
||||||
|
jina.ClassificationInput{
|
||||||
|
image: 'https://letsenhance.io/static/73136da51c245e80edc6ccfe44888a99/1015f/MainBefore.jpg'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
labels: ['cat', 'dog']
|
||||||
|
) or { panic('Error while classifying: ${err}') }
|
||||||
|
|
||||||
|
println('Classification result: ${classify_result}')
|
||||||
|
|
||||||
|
// List classifiers
|
||||||
|
classifiers := jina_client.list_classifiers() or { panic('Error fetching classifiers: ${err}') }
|
||||||
|
println('Classifiers: ${classifiers}')
|
||||||
|
|
||||||
|
// Delete classifier
|
||||||
|
delete_result := jina_client.delete_classifier(classifier_id: classifiers[0].classifier_id) or {
|
||||||
|
panic('Error deleting classifier: ${err}')
|
||||||
|
}
|
||||||
|
println('Delete result: ${delete_result}')
|
||||||
|
|
||||||
|
// Create multi vector
|
||||||
|
multi_vector := jina_client.create_multi_vector(
|
||||||
|
input: [
|
||||||
|
jina.MultiVectorTextDoc{
|
||||||
|
text: 'Hello world'
|
||||||
|
input_type: .document
|
||||||
|
},
|
||||||
|
jina.MultiVectorTextDoc{
|
||||||
|
text: "What's up?"
|
||||||
|
input_type: .query
|
||||||
|
},
|
||||||
|
]
|
||||||
|
embedding_type: ['float']
|
||||||
|
// dimensions: 96
|
||||||
|
)!
|
||||||
|
println('Multi vector: ${multi_vector}')
|
||||||
128
examples/aiexamples/qdrant.vsh
Executable file
128
examples/aiexamples/qdrant.vsh
Executable file
@@ -0,0 +1,128 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.clients.qdrant
|
||||||
|
import freeflowuniverse.herolib.installers.db.qdrant_installer
|
||||||
|
import freeflowuniverse.herolib.core.httpconnection
|
||||||
|
import rand
|
||||||
|
import os
|
||||||
|
|
||||||
|
println('Starting Qdrant example script')
|
||||||
|
|
||||||
|
// Print environment information
|
||||||
|
println('Current directory: ${os.getwd()}')
|
||||||
|
println('Home directory: ${os.home_dir()}')
|
||||||
|
|
||||||
|
mut i := qdrant_installer.get()!
|
||||||
|
i.install()!
|
||||||
|
|
||||||
|
// 1. Get the qdrant client
|
||||||
|
println('Getting Qdrant client...')
|
||||||
|
mut qdrant_client := qdrant.get()!
|
||||||
|
println('Qdrant client URL: ${qdrant_client.url}')
|
||||||
|
|
||||||
|
// Check if Qdrant server is running
|
||||||
|
println('Checking Qdrant server health...')
|
||||||
|
health := qdrant_client.health_check() or {
|
||||||
|
println('Error checking health: ${err}')
|
||||||
|
false
|
||||||
|
}
|
||||||
|
println('Qdrant server health: ${health}')
|
||||||
|
|
||||||
|
// Get service info
|
||||||
|
println('Getting Qdrant service info...')
|
||||||
|
service_info := qdrant_client.get_service_info() or {
|
||||||
|
println('Error getting service info: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
println('Qdrant service info: ${service_info}')
|
||||||
|
|
||||||
|
// 2. Generate collection name
|
||||||
|
collection_name := 'collection_' + rand.string(4)
|
||||||
|
println('Generated collection name: ${collection_name}')
|
||||||
|
|
||||||
|
// 3. Create a new collection
|
||||||
|
println('Creating collection...')
|
||||||
|
created_collection := qdrant_client.create_collection(
|
||||||
|
collection_name: collection_name
|
||||||
|
size: 15
|
||||||
|
distance: 'Cosine'
|
||||||
|
) or {
|
||||||
|
println('Error creating collection: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
println('Created Collection: ${created_collection}')
|
||||||
|
|
||||||
|
// 4. Get the created collection
|
||||||
|
println('Getting collection...')
|
||||||
|
get_collection := qdrant_client.get_collection(
|
||||||
|
collection_name: collection_name
|
||||||
|
) or {
|
||||||
|
println('Error getting collection: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
println('Get Collection: ${get_collection}')
|
||||||
|
|
||||||
|
// 5. List all collections
|
||||||
|
println('Listing collections...')
|
||||||
|
list_collection := qdrant_client.list_collections() or {
|
||||||
|
println('Error listing collections: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
println('List Collection: ${list_collection}')
|
||||||
|
|
||||||
|
// 6. Check collection existence
|
||||||
|
println('Checking collection existence...')
|
||||||
|
collection_existence := qdrant_client.is_collection_exists(
|
||||||
|
collection_name: collection_name
|
||||||
|
) or {
|
||||||
|
println('Error checking collection existence: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
println('Collection Existence: ${collection_existence}')
|
||||||
|
|
||||||
|
// 7. Retrieve points
|
||||||
|
println('Retrieving points...')
|
||||||
|
collection_points := qdrant_client.retrieve_points(
|
||||||
|
collection_name: collection_name
|
||||||
|
ids: [
|
||||||
|
0,
|
||||||
|
3,
|
||||||
|
100,
|
||||||
|
]
|
||||||
|
) or {
|
||||||
|
println('Error retrieving points: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
println('Collection Points: ${collection_points}')
|
||||||
|
|
||||||
|
// 8. Upsert points
|
||||||
|
println('Upserting points...')
|
||||||
|
upsert_points := qdrant_client.upsert_points(
|
||||||
|
collection_name: collection_name
|
||||||
|
points: [
|
||||||
|
qdrant.Point{
|
||||||
|
payload: {
|
||||||
|
'key': 'value'
|
||||||
|
}
|
||||||
|
vector: [1.0, 2.0, 3.0]
|
||||||
|
},
|
||||||
|
qdrant.Point{
|
||||||
|
payload: {
|
||||||
|
'key': 'value'
|
||||||
|
}
|
||||||
|
vector: [4.0, 5.0, 6.0]
|
||||||
|
},
|
||||||
|
qdrant.Point{
|
||||||
|
payload: {
|
||||||
|
'key': 'value'
|
||||||
|
}
|
||||||
|
vector: [7.0, 8.0, 9.0]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
) or {
|
||||||
|
println('Error upserting points: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
println('Upsert Points: ${upsert_points}')
|
||||||
|
|
||||||
|
println('Qdrant example script completed successfully')
|
||||||
3
examples/baobab/generator/basic/.gitignore
vendored
Normal file
3
examples/baobab/generator/basic/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
methods.v
|
||||||
|
pet_store_actor
|
||||||
|
docs
|
||||||
9
examples/baobab/generator/basic/README.md
Normal file
9
examples/baobab/generator/basic/README.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Actor Generation Examples
|
||||||
|
|
||||||
|
## `generate_methods.vsh`
|
||||||
|
|
||||||
|
This example generates actor method prototypes from an actor specification.
|
||||||
|
|
||||||
|
## `generate_actor_module.vsh`
|
||||||
|
|
||||||
|
This example generates an entire actor module from an actor specification with the support for the specified interfaces.
|
||||||
22
examples/baobab/generator/basic/generate_actor_module.vsh
Executable file
22
examples/baobab/generator/basic/generate_actor_module.vsh
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.baobab.generator
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.schemas.openrpc
|
||||||
|
import os
|
||||||
|
|
||||||
|
const example_dir = os.dir(@FILE)
|
||||||
|
const openrpc_spec_path = os.join_path(example_dir, 'openrpc.json')
|
||||||
|
|
||||||
|
// the actor specification obtained from the OpenRPC Specification
|
||||||
|
openrpc_spec := openrpc.new(path: openrpc_spec_path)!
|
||||||
|
actor_spec := specification.from_openrpc(openrpc_spec)!
|
||||||
|
|
||||||
|
actor_module := generator.generate_actor_module(actor_spec,
|
||||||
|
interfaces: [.openrpc]
|
||||||
|
)!
|
||||||
|
|
||||||
|
actor_module.write(example_dir,
|
||||||
|
format: true
|
||||||
|
overwrite: true
|
||||||
|
)!
|
||||||
19
examples/baobab/generator/basic/generate_methods.vsh
Executable file
19
examples/baobab/generator/basic/generate_methods.vsh
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.baobab.generator
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.schemas.openrpc
|
||||||
|
import os
|
||||||
|
|
||||||
|
const example_dir = os.dir(@FILE)
|
||||||
|
const openrpc_spec_path = os.join_path(example_dir, 'openrpc.json')
|
||||||
|
|
||||||
|
// the actor specification obtained from the OpenRPC Specification
|
||||||
|
openrpc_spec := openrpc.new(path: openrpc_spec_path)!
|
||||||
|
actor_spec := specification.from_openrpc(openrpc_spec)!
|
||||||
|
|
||||||
|
methods_file := generator.generate_methods_file(actor_spec)!
|
||||||
|
methods_file.write(example_dir,
|
||||||
|
format: true
|
||||||
|
overwrite: true
|
||||||
|
)!
|
||||||
19
examples/baobab/generator/basic/generate_openrpc_file.vsh
Executable file
19
examples/baobab/generator/basic/generate_openrpc_file.vsh
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.baobab.generator
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.schemas.openrpc
|
||||||
|
import os
|
||||||
|
|
||||||
|
const example_dir = os.dir(@FILE)
|
||||||
|
const openrpc_spec_path = os.join_path(example_dir, 'openrpc.json')
|
||||||
|
|
||||||
|
// the actor specification obtained from the OpenRPC Specification
|
||||||
|
openrpc_spec_ := openrpc.new(path: openrpc_spec_path)!
|
||||||
|
actor_spec := specification.from_openrpc(openrpc_spec_)!
|
||||||
|
openrpc_spec := actor_spec.to_openrpc()
|
||||||
|
|
||||||
|
openrpc_file := generator.generate_openrpc_file(openrpc_spec)!
|
||||||
|
openrpc_file.write(os.join_path(example_dir, 'docs'),
|
||||||
|
overwrite: true
|
||||||
|
)!
|
||||||
132
examples/baobab/generator/basic/openrpc.json
Normal file
132
examples/baobab/generator/basic/openrpc.json
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
{
|
||||||
|
"openrpc": "1.0.0",
|
||||||
|
"info": {
|
||||||
|
"title": "PetStore",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"methods": [
|
||||||
|
{
|
||||||
|
"name": "GetPets",
|
||||||
|
"description": "finds pets in the system that the user has access to by tags and within a limit",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "tags",
|
||||||
|
"description": "tags to filter by",
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "limit",
|
||||||
|
"description": "maximum number of results to return",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"result": {
|
||||||
|
"name": "pet_list",
|
||||||
|
"description": "all pets from the system, that mathes the tags",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#\/components\/schemas\/Pet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CreatePet",
|
||||||
|
"description": "creates a new pet in the store. Duplicates are allowed.",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "new_pet",
|
||||||
|
"description": "Pet to add to the store.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#\/components\/schemas\/NewPet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"result": {
|
||||||
|
"name": "pet",
|
||||||
|
"description": "the newly created pet",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#\/components\/schemas\/Pet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GetPetById",
|
||||||
|
"description": "gets a pet based on a single ID, if the user has access to the pet",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"description": "ID of pet to fetch",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"result": {
|
||||||
|
"name": "pet",
|
||||||
|
"description": "pet response",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#\/components\/schemas\/Pet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DeletePetById",
|
||||||
|
"description": "deletes a single pet based on the ID supplied",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"description": "ID of pet to delete",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"result": {
|
||||||
|
"name": "pet",
|
||||||
|
"description": "pet deleted",
|
||||||
|
"schema": {
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"NewPet": {
|
||||||
|
"title": "NewPet",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Pet": {
|
||||||
|
"title": "Pet",
|
||||||
|
"description": "a pet struct that represents a pet",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"description": "name of the pet",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"description": "a tag of the pet, helps finding pet",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"description": "unique indentifier",
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
examples/baobab/generator/geomind_poc/.gitignore
vendored
Normal file
3
examples/baobab/generator/geomind_poc/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
merchant
|
||||||
|
profiler
|
||||||
|
farmer
|
||||||
344
examples/baobab/generator/geomind_poc/farmer.json
Normal file
344
examples/baobab/generator/geomind_poc/farmer.json
Normal file
@@ -0,0 +1,344 @@
|
|||||||
|
{
|
||||||
|
"openapi": "3.0.1",
|
||||||
|
"info": {
|
||||||
|
"title": "Farmer",
|
||||||
|
"description": "API for managing farms and nodes, tracking rewards, capacity, and location.",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "http://localhost:8080",
|
||||||
|
"description": "Local development server"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"Farm": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Amsterdam Data Center"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Enterprise-grade data center with renewable energy focus"
|
||||||
|
},
|
||||||
|
"owner": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"owner"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Node": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "n47ac10b-58cc-4372-a567-0e02b2c3d479"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "High-performance GPU compute node with 4x NVIDIA A100"
|
||||||
|
},
|
||||||
|
"farm_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"$ref": "#/components/schemas/Location"
|
||||||
|
},
|
||||||
|
"capacity": {
|
||||||
|
"$ref": "#/components/schemas/Capacity"
|
||||||
|
},
|
||||||
|
"grid_version": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "3.16.2"
|
||||||
|
},
|
||||||
|
"reward": {
|
||||||
|
"$ref": "#/components/schemas/Reward"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"description",
|
||||||
|
"farm_id",
|
||||||
|
"location",
|
||||||
|
"capacity",
|
||||||
|
"reward"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Location": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"coordinates": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "52.3740, 4.8897"
|
||||||
|
},
|
||||||
|
"continent": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Europe"
|
||||||
|
},
|
||||||
|
"country": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Netherlands"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"coordinates",
|
||||||
|
"continent",
|
||||||
|
"country"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Capacity": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"cpu": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 128
|
||||||
|
},
|
||||||
|
"memory_gb": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 1024
|
||||||
|
},
|
||||||
|
"storage_tb": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"cpu",
|
||||||
|
"memory_gb",
|
||||||
|
"storage_tb"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Reward": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"reward_promised": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double",
|
||||||
|
"example": 25000.50
|
||||||
|
},
|
||||||
|
"reward_given": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double",
|
||||||
|
"example": 12500.25
|
||||||
|
},
|
||||||
|
"duration_months": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 36
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"reward_promised",
|
||||||
|
"reward_given",
|
||||||
|
"duration_months"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"NodeStats": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"node_id": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32",
|
||||||
|
"example": "42"
|
||||||
|
},
|
||||||
|
"uptime_hours": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 8760
|
||||||
|
},
|
||||||
|
"bandwidth_gb": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 25000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"node_id",
|
||||||
|
"uptime_hours",
|
||||||
|
"bandwidth_gb"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"/farms": {
|
||||||
|
"get": {
|
||||||
|
"summary": "List all farms",
|
||||||
|
"operationId": "getFarms",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "List of farms",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Farm"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": [
|
||||||
|
{
|
||||||
|
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
||||||
|
"name": "Amsterdam Data Center",
|
||||||
|
"description": "Enterprise-grade data center with renewable energy focus",
|
||||||
|
"owner": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "d47ac10b-58cc-4372-a567-0e02b2c3d480",
|
||||||
|
"name": "Dubai Compute Hub",
|
||||||
|
"description": "High-density compute farm with advanced cooling",
|
||||||
|
"owner": "0x842d35Cc6634C0532925a3b844Bc454e4438f55f"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/farms/{farmId}/nodes": {
|
||||||
|
"get": {
|
||||||
|
"summary": "List nodes in a farm",
|
||||||
|
"operationId": "getNodesByFarm",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "farmId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"example": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "List of nodes in the farm",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Node"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": [
|
||||||
|
{
|
||||||
|
"id": "n47ac10b-58cc-4372-a567-0e02b2c3d479",
|
||||||
|
"description": "High-performance GPU compute node with 4x NVIDIA A100",
|
||||||
|
"farm_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
||||||
|
"location": {
|
||||||
|
"coordinates": "52.3740, 4.8897",
|
||||||
|
"continent": "Europe",
|
||||||
|
"country": "Netherlands"
|
||||||
|
},
|
||||||
|
"capacity": {
|
||||||
|
"cpu": 128,
|
||||||
|
"memory_gb": 1024,
|
||||||
|
"storage_tb": 100
|
||||||
|
},
|
||||||
|
"grid_version": "3.16.2",
|
||||||
|
"reward": {
|
||||||
|
"reward_promised": 25000.50,
|
||||||
|
"reward_given": 12500.25,
|
||||||
|
"duration_months": 36
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Farm not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 404
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Farm with ID f47ac10b-58cc-4372-a567-0e02b2c3d479 not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/nodes/{nodeId}/stats": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get node statistics",
|
||||||
|
"operationId": "getNodeStats",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "nodeId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32"
|
||||||
|
},
|
||||||
|
"example": "42"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Node statistics",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/NodeStats"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"node_id": "42",
|
||||||
|
"uptime_hours": 8760,
|
||||||
|
"bandwidth_gb": 25000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Node not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 404
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Node with ID n47ac10b-58cc-4372-a567-0e02b2c3d479 not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
examples/baobab/generator/geomind_poc/generate
Executable file
BIN
examples/baobab/generator/geomind_poc/generate
Executable file
Binary file not shown.
23
examples/baobab/generator/geomind_poc/generate.vsh
Executable file
23
examples/baobab/generator/geomind_poc/generate.vsh
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.baobab.generator
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.schemas.openapi
|
||||||
|
import os
|
||||||
|
|
||||||
|
const example_dir = os.dir(@FILE)
|
||||||
|
const specs = ['merchant', 'profiler', 'farmer']
|
||||||
|
|
||||||
|
for spec in specs {
|
||||||
|
openapi_spec_path := os.join_path(example_dir, '${spec}.json')
|
||||||
|
openapi_spec := openapi.new(path: openapi_spec_path, process: true)!
|
||||||
|
actor_spec := specification.from_openapi(openapi_spec)!
|
||||||
|
actor_module := generator.generate_actor_folder(actor_spec,
|
||||||
|
interfaces: [.openapi, .http]
|
||||||
|
)!
|
||||||
|
actor_module.write(example_dir,
|
||||||
|
format: true
|
||||||
|
overwrite: true
|
||||||
|
compile: false
|
||||||
|
)!
|
||||||
|
}
|
||||||
997
examples/baobab/generator/geomind_poc/merchant.json
Normal file
997
examples/baobab/generator/geomind_poc/merchant.json
Normal file
@@ -0,0 +1,997 @@
|
|||||||
|
{
|
||||||
|
"openapi": "3.0.1",
|
||||||
|
"info": {
|
||||||
|
"title": "Merchant",
|
||||||
|
"description": "API for e-commerce operations including stores, products, and orders",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"servers": [{
|
||||||
|
"url": "http://localhost:8080",
|
||||||
|
"description": "Local development server"
|
||||||
|
},{
|
||||||
|
"url": "http://localhost:8080/openapi/example",
|
||||||
|
"description": "Local example server"
|
||||||
|
}],
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"Store": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174000"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Tech Gadgets Store"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Premium electronics and gadgets retailer"
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "contact@techgadgets.com"
|
||||||
|
},
|
||||||
|
"active": {
|
||||||
|
"type": "boolean",
|
||||||
|
"example": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"contact",
|
||||||
|
"active"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ProductComponentTemplate": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174001"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "4K Display Panel"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "55-inch 4K UHD Display Panel"
|
||||||
|
},
|
||||||
|
"specs": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"resolution": "3840x2160",
|
||||||
|
"refreshRate": "120Hz",
|
||||||
|
"panel_type": "OLED"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"price": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double",
|
||||||
|
"example": 599.99
|
||||||
|
},
|
||||||
|
"currency": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[A-Z]{3}$",
|
||||||
|
"example": "USD"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"price",
|
||||||
|
"currency"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ProductTemplate": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174002"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Smart TV 55-inch"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "55-inch Smart TV with 4K Display"
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/ProductComponentTemplate"
|
||||||
|
},
|
||||||
|
"example": [
|
||||||
|
{
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174001",
|
||||||
|
"name": "4K Display Panel",
|
||||||
|
"description": "55-inch 4K UHD Display Panel",
|
||||||
|
"specs": {
|
||||||
|
"resolution": "3840x2160",
|
||||||
|
"refreshRate": "120Hz"
|
||||||
|
},
|
||||||
|
"price": 599.99,
|
||||||
|
"currency": "USD"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"store_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174000"
|
||||||
|
},
|
||||||
|
"category": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Electronics"
|
||||||
|
},
|
||||||
|
"active": {
|
||||||
|
"type": "boolean",
|
||||||
|
"example": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"components",
|
||||||
|
"store_id",
|
||||||
|
"active"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Product": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174003"
|
||||||
|
},
|
||||||
|
"template_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174002"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Smart TV 55-inch"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "55-inch Smart TV with 4K Display"
|
||||||
|
},
|
||||||
|
"price": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double",
|
||||||
|
"example": 899.99
|
||||||
|
},
|
||||||
|
"currency": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[A-Z]{3}$",
|
||||||
|
"example": "USD"
|
||||||
|
},
|
||||||
|
"store_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174000"
|
||||||
|
},
|
||||||
|
"stock_quantity": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"example": 50
|
||||||
|
},
|
||||||
|
"available": {
|
||||||
|
"type": "boolean",
|
||||||
|
"example": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"template_id",
|
||||||
|
"name",
|
||||||
|
"price",
|
||||||
|
"currency",
|
||||||
|
"store_id",
|
||||||
|
"stock_quantity",
|
||||||
|
"available"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"OrderItem": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"product_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174003"
|
||||||
|
},
|
||||||
|
"quantity": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
"example": 2
|
||||||
|
},
|
||||||
|
"price": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double",
|
||||||
|
"example": 899.99
|
||||||
|
},
|
||||||
|
"currency": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[A-Z]{3}$",
|
||||||
|
"example": "USD"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"product_id",
|
||||||
|
"quantity",
|
||||||
|
"price",
|
||||||
|
"currency"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Order": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174004"
|
||||||
|
},
|
||||||
|
"customer_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174005"
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/OrderItem"
|
||||||
|
},
|
||||||
|
"example": [
|
||||||
|
{
|
||||||
|
"product_id": "123e4567-e89b-12d3-a456-426614174003",
|
||||||
|
"quantity": 2,
|
||||||
|
"price": 899.99,
|
||||||
|
"currency": "USD"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"total_amount": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double",
|
||||||
|
"example": 1799.98
|
||||||
|
},
|
||||||
|
"currency": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[A-Z]{3}$",
|
||||||
|
"example": "USD"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"pending",
|
||||||
|
"confirmed",
|
||||||
|
"shipped",
|
||||||
|
"delivered"
|
||||||
|
],
|
||||||
|
"example": "pending"
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time",
|
||||||
|
"example": "2024-02-10T10:30:00Z"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time",
|
||||||
|
"example": "2024-02-10T10:30:00Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"customer_id",
|
||||||
|
"items",
|
||||||
|
"total_amount",
|
||||||
|
"currency",
|
||||||
|
"status",
|
||||||
|
"created_at",
|
||||||
|
"updated_at"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Error": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 404
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Resource not found"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"code",
|
||||||
|
"message"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"/stores": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Create a new store",
|
||||||
|
"operationId": "createStore",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Tech Gadgets Store"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Premium electronics and gadgets retailer"
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "contact@techgadgets.com"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"contact"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"newStore": {
|
||||||
|
"summary": "Create a new electronics store",
|
||||||
|
"value": {
|
||||||
|
"name": "Tech Gadgets Store",
|
||||||
|
"description": "Premium electronics and gadgets retailer",
|
||||||
|
"contact": "contact@techgadgets.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Store created successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Store"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174000",
|
||||||
|
"name": "Tech Gadgets Store",
|
||||||
|
"description": "Premium electronics and gadgets retailer",
|
||||||
|
"contact": "contact@techgadgets.com",
|
||||||
|
"active": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Invalid input",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"code": 400,
|
||||||
|
"message": "Invalid store data provided"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/products/templates/components": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Create a new product component template",
|
||||||
|
"operationId": "createProductComponentTemplate",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"specs": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"price": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"currency": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"price",
|
||||||
|
"currency"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"displayPanel": {
|
||||||
|
"summary": "Create a display panel component",
|
||||||
|
"value": {
|
||||||
|
"name": "4K Display Panel",
|
||||||
|
"description": "55-inch 4K UHD Display Panel",
|
||||||
|
"specs": {
|
||||||
|
"resolution": "3840x2160",
|
||||||
|
"refreshRate": "120Hz",
|
||||||
|
"panel_type": "OLED"
|
||||||
|
},
|
||||||
|
"price": 599.99,
|
||||||
|
"currency": "USD"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Component template created successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ProductComponentTemplate"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174001",
|
||||||
|
"name": "4K Display Panel",
|
||||||
|
"description": "55-inch 4K UHD Display Panel",
|
||||||
|
"specs": {
|
||||||
|
"resolution": "3840x2160",
|
||||||
|
"refreshRate": "120Hz",
|
||||||
|
"panel_type": "OLED"
|
||||||
|
},
|
||||||
|
"price": 599.99,
|
||||||
|
"currency": "USD"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Invalid input",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"code": 400,
|
||||||
|
"message": "Invalid component template data"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/products/templates": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Create a new product template",
|
||||||
|
"operationId": "createProductTemplate",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"store_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"category": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"components",
|
||||||
|
"store_id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"smartTV": {
|
||||||
|
"summary": "Create a Smart TV template",
|
||||||
|
"value": {
|
||||||
|
"name": "Smart TV 55-inch",
|
||||||
|
"description": "55-inch Smart TV with 4K Display",
|
||||||
|
"components": [
|
||||||
|
"123e4567-e89b-12d3-a456-426614174001"
|
||||||
|
],
|
||||||
|
"store_id": "123e4567-e89b-12d3-a456-426614174000",
|
||||||
|
"category": "Electronics"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Product template created successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ProductTemplate"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174002",
|
||||||
|
"name": "Smart TV 55-inch",
|
||||||
|
"description": "55-inch Smart TV with 4K Display",
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174001",
|
||||||
|
"name": "4K Display Panel",
|
||||||
|
"description": "55-inch 4K UHD Display Panel",
|
||||||
|
"specs": {
|
||||||
|
"resolution": "3840x2160",
|
||||||
|
"refreshRate": "120Hz"
|
||||||
|
},
|
||||||
|
"price": 599.99,
|
||||||
|
"currency": "USD"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"store_id": "123e4567-e89b-12d3-a456-426614174000",
|
||||||
|
"category": "Electronics",
|
||||||
|
"active": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Store not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"code": 404,
|
||||||
|
"message": "Store not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/products": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Create a new product from template",
|
||||||
|
"operationId": "createProduct",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"template_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"store_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"stock_quantity": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"template_id",
|
||||||
|
"store_id",
|
||||||
|
"stock_quantity"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"newProduct": {
|
||||||
|
"summary": "Create a new Smart TV product",
|
||||||
|
"value": {
|
||||||
|
"template_id": "123e4567-e89b-12d3-a456-426614174002",
|
||||||
|
"store_id": "123e4567-e89b-12d3-a456-426614174000",
|
||||||
|
"stock_quantity": 50
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Product created successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Product"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174003",
|
||||||
|
"template_id": "123e4567-e89b-12d3-a456-426614174002",
|
||||||
|
"name": "Smart TV 55-inch",
|
||||||
|
"description": "55-inch Smart TV with 4K Display",
|
||||||
|
"price": 899.99,
|
||||||
|
"currency": "USD",
|
||||||
|
"store_id": "123e4567-e89b-12d3-a456-426614174000",
|
||||||
|
"stock_quantity": 50,
|
||||||
|
"available": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Template or store not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"code": 404,
|
||||||
|
"message": "Product template not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/orders": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Create a new order",
|
||||||
|
"operationId": "createOrder",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"customer_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/OrderItem"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"customer_id",
|
||||||
|
"items"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"newOrder": {
|
||||||
|
"summary": "Create an order for two Smart TVs",
|
||||||
|
"value": {
|
||||||
|
"customer_id": "123e4567-e89b-12d3-a456-426614174005",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"product_id": "123e4567-e89b-12d3-a456-426614174003",
|
||||||
|
"quantity": 2,
|
||||||
|
"price": 899.99,
|
||||||
|
"currency": "USD"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Order created successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Order"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174004",
|
||||||
|
"customer_id": "123e4567-e89b-12d3-a456-426614174005",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"product_id": "123e4567-e89b-12d3-a456-426614174003",
|
||||||
|
"quantity": 2,
|
||||||
|
"price": 899.99,
|
||||||
|
"currency": "USD"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total_amount": 1799.98,
|
||||||
|
"currency": "USD",
|
||||||
|
"status": "pending",
|
||||||
|
"created_at": "2024-02-10T10:30:00Z",
|
||||||
|
"updated_at": "2024-02-10T10:30:00Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Invalid input or insufficient stock",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"code": 400,
|
||||||
|
"message": "Insufficient stock for product"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/orders/{orderId}/status": {
|
||||||
|
"put": {
|
||||||
|
"summary": "Update order status",
|
||||||
|
"operationId": "updateOrderStatus",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "orderId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174004"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"pending",
|
||||||
|
"confirmed",
|
||||||
|
"shipped",
|
||||||
|
"delivered"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"status"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"updateStatus": {
|
||||||
|
"summary": "Update order to shipped status",
|
||||||
|
"value": {
|
||||||
|
"status": "shipped"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Order status updated successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Order"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174004",
|
||||||
|
"customer_id": "123e4567-e89b-12d3-a456-426614174005",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"product_id": "123e4567-e89b-12d3-a456-426614174003",
|
||||||
|
"quantity": 2,
|
||||||
|
"price": 899.99,
|
||||||
|
"currency": "USD"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total_amount": 1799.98,
|
||||||
|
"currency": "USD",
|
||||||
|
"status": "shipped",
|
||||||
|
"created_at": "2024-02-10T10:30:00Z",
|
||||||
|
"updated_at": "2024-02-10T10:35:00Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Order not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"code": 404,
|
||||||
|
"message": "Order not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/stores/{storeId}/products": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get all products for a store",
|
||||||
|
"operationId": "getStoreProducts",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "storeId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174000"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "List of store's products",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Product"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": [
|
||||||
|
{
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174003",
|
||||||
|
"template_id": "123e4567-e89b-12d3-a456-426614174002",
|
||||||
|
"name": "Smart TV 55-inch",
|
||||||
|
"description": "55-inch Smart TV with 4K Display",
|
||||||
|
"price": 899.99,
|
||||||
|
"currency": "USD",
|
||||||
|
"store_id": "123e4567-e89b-12d3-a456-426614174000",
|
||||||
|
"stock_quantity": 48,
|
||||||
|
"available": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Store not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"code": 404,
|
||||||
|
"message": "Store not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/stores/{storeId}/orders": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get all orders for a store's products",
|
||||||
|
"operationId": "getStoreOrders",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "storeId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174000"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "List of orders containing store's products",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Order"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": [
|
||||||
|
{
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174004",
|
||||||
|
"customer_id": "123e4567-e89b-12d3-a456-426614174005",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"product_id": "123e4567-e89b-12d3-a456-426614174003",
|
||||||
|
"quantity": 2,
|
||||||
|
"price": 899.99,
|
||||||
|
"currency": "USD"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total_amount": 1799.98,
|
||||||
|
"currency": "USD",
|
||||||
|
"status": "shipped",
|
||||||
|
"created_at": "2024-02-10T10:30:00Z",
|
||||||
|
"updated_at": "2024-02-10T10:35:00Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Store not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"code": 404,
|
||||||
|
"message": "Store not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
81
examples/baobab/generator/geomind_poc/model.v
Normal file
81
examples/baobab/generator/geomind_poc/model.v
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
module geomind_poc
|
||||||
|
|
||||||
|
pub struct Merchant {
|
||||||
|
pub:
|
||||||
|
id string
|
||||||
|
name string
|
||||||
|
description string
|
||||||
|
contact string
|
||||||
|
active bool
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ProductComponentTemplate {
|
||||||
|
pub:
|
||||||
|
id string
|
||||||
|
name string
|
||||||
|
description string
|
||||||
|
// technical specifications
|
||||||
|
specs map[string]string
|
||||||
|
// price per unit
|
||||||
|
price f64
|
||||||
|
// currency code (e.g., 'USD', 'EUR')
|
||||||
|
currency string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ProductTemplate {
|
||||||
|
pub:
|
||||||
|
id string
|
||||||
|
name string
|
||||||
|
description string
|
||||||
|
// components that make up this product template
|
||||||
|
components []ProductComponentTemplate
|
||||||
|
// merchant who created this template
|
||||||
|
merchant_id string
|
||||||
|
// category of the product (e.g., 'electronics', 'clothing')
|
||||||
|
category string
|
||||||
|
// whether this template is available for use
|
||||||
|
active bool
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Product {
|
||||||
|
pub:
|
||||||
|
id string
|
||||||
|
template_id string
|
||||||
|
// specific instance details that may differ from template
|
||||||
|
name string
|
||||||
|
description string
|
||||||
|
// actual price of this product instance
|
||||||
|
price f64
|
||||||
|
currency string
|
||||||
|
// merchant selling this product
|
||||||
|
merchant_id string
|
||||||
|
// current stock level
|
||||||
|
stock_quantity int
|
||||||
|
// whether this product is available for purchase
|
||||||
|
available bool
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OrderItem {
|
||||||
|
pub:
|
||||||
|
product_id string
|
||||||
|
quantity int
|
||||||
|
price f64
|
||||||
|
currency string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Order {
|
||||||
|
pub:
|
||||||
|
id string
|
||||||
|
// customer identifier
|
||||||
|
customer_id string
|
||||||
|
// items in the order
|
||||||
|
items []OrderItem
|
||||||
|
// total order amount
|
||||||
|
total_amount f64
|
||||||
|
currency string
|
||||||
|
// order status (e.g., 'pending', 'confirmed', 'shipped', 'delivered')
|
||||||
|
status string
|
||||||
|
// timestamps
|
||||||
|
created_at string
|
||||||
|
updated_at string
|
||||||
|
}
|
||||||
148
examples/baobab/generator/geomind_poc/play.v
Normal file
148
examples/baobab/generator/geomind_poc/play.v
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
module geomind_poc
|
||||||
|
|
||||||
|
import freeflowuniverse.crystallib.core.playbook { PlayBook }
|
||||||
|
|
||||||
|
// play_commerce processes heroscript actions for the commerce system
|
||||||
|
pub fn play_commerce(mut plbook PlayBook) ! {
|
||||||
|
commerce_actions := plbook.find(filter: 'commerce.')!
|
||||||
|
mut c := Commerce{}
|
||||||
|
|
||||||
|
for action in commerce_actions {
|
||||||
|
match action.name {
|
||||||
|
'merchant' {
|
||||||
|
mut p := action.params
|
||||||
|
merchant := c.create_merchant(
|
||||||
|
name: p.get('name')!
|
||||||
|
description: p.get_default('description', '')!
|
||||||
|
contact: p.get('contact')!
|
||||||
|
)!
|
||||||
|
println('Created merchant: ${merchant.name}')
|
||||||
|
}
|
||||||
|
'component' {
|
||||||
|
mut p := action.params
|
||||||
|
component := c.create_product_component_template(
|
||||||
|
name: p.get('name')!
|
||||||
|
description: p.get_default('description', '')!
|
||||||
|
specs: p.get_map()
|
||||||
|
price: p.get_float('price')!
|
||||||
|
currency: p.get('currency')!
|
||||||
|
)!
|
||||||
|
println('Created component: ${component.name}')
|
||||||
|
}
|
||||||
|
'template' {
|
||||||
|
mut p := action.params
|
||||||
|
// Get component IDs as a list
|
||||||
|
component_ids := p.get_list('components')!
|
||||||
|
// Convert component IDs to actual components
|
||||||
|
mut components := []ProductComponentTemplate{}
|
||||||
|
for id in component_ids {
|
||||||
|
// In a real implementation, you would fetch the component from storage
|
||||||
|
// For this example, we create a dummy component
|
||||||
|
component := ProductComponentTemplate{
|
||||||
|
id: id
|
||||||
|
name: 'Component'
|
||||||
|
description: ''
|
||||||
|
specs: map[string]string{}
|
||||||
|
price: 0
|
||||||
|
currency: 'USD'
|
||||||
|
}
|
||||||
|
components << component
|
||||||
|
}
|
||||||
|
|
||||||
|
template := c.create_product_template(
|
||||||
|
name: p.get('name')!
|
||||||
|
description: p.get_default('description', '')!
|
||||||
|
components: components
|
||||||
|
merchant_id: p.get('merchant_id')!
|
||||||
|
category: p.get_default('category', 'General')!
|
||||||
|
)!
|
||||||
|
println('Created template: ${template.name}')
|
||||||
|
}
|
||||||
|
'product' {
|
||||||
|
mut p := action.params
|
||||||
|
product := c.create_product(
|
||||||
|
template_id: p.get('template_id')!
|
||||||
|
merchant_id: p.get('merchant_id')!
|
||||||
|
stock_quantity: p.get_int('stock_quantity')!
|
||||||
|
)!
|
||||||
|
println('Created product: ${product.name} with stock: ${product.stock_quantity}')
|
||||||
|
}
|
||||||
|
'order' {
|
||||||
|
mut p := action.params
|
||||||
|
// Get order items as a list of maps
|
||||||
|
items_data := p.get_list('items')!
|
||||||
|
mut items := []OrderItem{}
|
||||||
|
for item_data in items_data {
|
||||||
|
// Parse item data (format: "product_id:quantity:price:currency")
|
||||||
|
parts := item_data.split(':')
|
||||||
|
if parts.len != 4 {
|
||||||
|
return error('Invalid order item format: ${item_data}')
|
||||||
|
}
|
||||||
|
item := OrderItem{
|
||||||
|
product_id: parts[0]
|
||||||
|
quantity: parts[1].int()
|
||||||
|
price: parts[2].f64()
|
||||||
|
currency: parts[3]
|
||||||
|
}
|
||||||
|
items << item
|
||||||
|
}
|
||||||
|
|
||||||
|
order := c.create_order(
|
||||||
|
customer_id: p.get('customer_id')!
|
||||||
|
items: items
|
||||||
|
)!
|
||||||
|
println('Created order: ${order.id} with ${order.items.len} items')
|
||||||
|
}
|
||||||
|
'update_order' {
|
||||||
|
mut p := action.params
|
||||||
|
order := c.update_order_status(
|
||||||
|
order_id: p.get('order_id')!
|
||||||
|
new_status: p.get('status')!
|
||||||
|
)!
|
||||||
|
println('Updated order ${order.id} status to: ${order.status}')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return error('Unknown commerce action: ${action.name}')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example heroscript usage:
|
||||||
|
/*
|
||||||
|
!!commerce.merchant
|
||||||
|
name: "Tech Gadgets Store"
|
||||||
|
description: "Premium electronics and gadgets retailer"
|
||||||
|
contact: "contact@techgadgets.com"
|
||||||
|
|
||||||
|
!!commerce.component
|
||||||
|
name: "4K Display Panel"
|
||||||
|
description: "55-inch 4K UHD Display Panel"
|
||||||
|
specs:
|
||||||
|
resolution: "3840x2160"
|
||||||
|
refreshRate: "120Hz"
|
||||||
|
panel_type: "OLED"
|
||||||
|
price: 599.99
|
||||||
|
currency: "USD"
|
||||||
|
|
||||||
|
!!commerce.template
|
||||||
|
name: "Smart TV 55-inch"
|
||||||
|
description: "55-inch Smart TV with 4K Display"
|
||||||
|
components: "123e4567-e89b-12d3-a456-426614174001"
|
||||||
|
merchant_id: "123e4567-e89b-12d3-a456-426614174000"
|
||||||
|
category: "Electronics"
|
||||||
|
|
||||||
|
!!commerce.product
|
||||||
|
template_id: "123e4567-e89b-12d3-a456-426614174002"
|
||||||
|
merchant_id: "123e4567-e89b-12d3-a456-426614174000"
|
||||||
|
stock_quantity: 50
|
||||||
|
|
||||||
|
!!commerce.order
|
||||||
|
customer_id: "123e4567-e89b-12d3-a456-426614174005"
|
||||||
|
items:
|
||||||
|
- "123e4567-e89b-12d3-a456-426614174003:2:899.99:USD"
|
||||||
|
|
||||||
|
!!commerce.update_order
|
||||||
|
order_id: "123e4567-e89b-12d3-a456-426614174004"
|
||||||
|
status: "shipped"
|
||||||
|
*/
|
||||||
286
examples/baobab/generator/geomind_poc/profiler.json
Normal file
286
examples/baobab/generator/geomind_poc/profiler.json
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
{
|
||||||
|
"openapi": "3.0.1",
|
||||||
|
"info": {
|
||||||
|
"title": "Profiler",
|
||||||
|
"description": "API for managing user profiles with name, public key, and KYC verification",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "http://localhost:8080",
|
||||||
|
"description": "Local development server"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"Profile": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174000"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Alice Doe"
|
||||||
|
},
|
||||||
|
"public_key": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "028a8f8b59f7283a47f9f6d4bc8176e847ad2b6c6d8bdfd041e5e7f3b4ac28c9fc"
|
||||||
|
},
|
||||||
|
"kyc_verified": {
|
||||||
|
"type": "boolean",
|
||||||
|
"example": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["id", "name", "public_key", "kyc_verified"]
|
||||||
|
},
|
||||||
|
"Error": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 400
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Invalid request"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["code", "message"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"/profiles": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Create a new profile",
|
||||||
|
"operationId": "createProfile",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Bob Smith"
|
||||||
|
},
|
||||||
|
"public_key": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "03a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["name", "public_key"]
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"newProfile": {
|
||||||
|
"summary": "Example of creating a new profile",
|
||||||
|
"value": {
|
||||||
|
"name": "Bob Smith",
|
||||||
|
"public_key": "03a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Profile created successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Profile"
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"successResponse": {
|
||||||
|
"summary": "Example of successful profile creation",
|
||||||
|
"value": {
|
||||||
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"name": "Bob Smith",
|
||||||
|
"public_key": "03a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
|
||||||
|
"kyc_verified": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Invalid input",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"invalidInput": {
|
||||||
|
"summary": "Example of invalid input error",
|
||||||
|
"value": {
|
||||||
|
"code": 400,
|
||||||
|
"message": "Invalid public key format"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/profiles/{profileId}": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get profile details",
|
||||||
|
"operationId": "getProfile",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "profileId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32"
|
||||||
|
},
|
||||||
|
"example": "42"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Profile retrieved successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Profile"
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"existingProfile": {
|
||||||
|
"summary": "Example of retrieved profile",
|
||||||
|
"value": {
|
||||||
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"name": "Bob Smith",
|
||||||
|
"public_key": "03a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
|
||||||
|
"kyc_verified": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Profile not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"notFound": {
|
||||||
|
"summary": "Example of profile not found error",
|
||||||
|
"value": {
|
||||||
|
"code": 404,
|
||||||
|
"message": "Profile with ID '550e8400-e29b-41d4-a716-446655440000' not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/profiles/{profileId}/kyc": {
|
||||||
|
"put": {
|
||||||
|
"summary": "Update KYC verification status",
|
||||||
|
"operationId": "updateKYCStatus",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "profileId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32"
|
||||||
|
},
|
||||||
|
"example": "42"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"kyc_verified": {
|
||||||
|
"type": "boolean",
|
||||||
|
"example": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["kyc_verified"]
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"verifyKYC": {
|
||||||
|
"summary": "Example of verifying KYC",
|
||||||
|
"value": {
|
||||||
|
"kyc_verified": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"unverifyKYC": {
|
||||||
|
"summary": "Example of unverifying KYC",
|
||||||
|
"value": {
|
||||||
|
"kyc_verified": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "KYC status updated successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Profile"
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"updatedProfile": {
|
||||||
|
"summary": "Example of profile with updated KYC status",
|
||||||
|
"value": {
|
||||||
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"name": "Bob Smith",
|
||||||
|
"public_key": "03a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
|
||||||
|
"kyc_verified": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Profile not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"notFound": {
|
||||||
|
"summary": "Example of profile not found error",
|
||||||
|
"value": {
|
||||||
|
"code": 404,
|
||||||
|
"message": "Profile with ID '550e8400-e29b-41d4-a716-446655440000' not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
191
examples/baobab/generator/geomind_poc/server.v
Normal file
191
examples/baobab/generator/geomind_poc/server.v
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
module geomind_poc
|
||||||
|
|
||||||
|
import crypto.rand
|
||||||
|
import time
|
||||||
|
|
||||||
|
// Commerce represents the main e-commerce server handling all operations
|
||||||
|
pub struct Commerce {
|
||||||
|
mut:
|
||||||
|
merchants map[string]Merchant
|
||||||
|
templates map[string]ProductTemplate
|
||||||
|
products map[string]Product
|
||||||
|
orders map[string]Order
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate_id creates a unique identifier
|
||||||
|
fn generate_id() string {
|
||||||
|
return rand.uuid_v4()
|
||||||
|
}
|
||||||
|
|
||||||
|
// create_merchant adds a new merchant to the system
|
||||||
|
pub fn (mut c Commerce) create_merchant(name string, description string, contact string) !Merchant {
|
||||||
|
merchant_id := generate_id()
|
||||||
|
merchant := Merchant{
|
||||||
|
id: merchant_id
|
||||||
|
name: name
|
||||||
|
description: description
|
||||||
|
contact: contact
|
||||||
|
active: true
|
||||||
|
}
|
||||||
|
c.merchants[merchant_id] = merchant
|
||||||
|
return merchant
|
||||||
|
}
|
||||||
|
|
||||||
|
// create_product_component_template creates a new component template
|
||||||
|
pub fn (mut c Commerce) create_product_component_template(name string, description string, specs map[string]string, price f64, currency string) !ProductComponentTemplate {
|
||||||
|
component := ProductComponentTemplate{
|
||||||
|
id: generate_id()
|
||||||
|
name: name
|
||||||
|
description: description
|
||||||
|
specs: specs
|
||||||
|
price: price
|
||||||
|
currency: currency
|
||||||
|
}
|
||||||
|
return component
|
||||||
|
}
|
||||||
|
|
||||||
|
// create_product_template creates a new product template
|
||||||
|
pub fn (mut c Commerce) create_product_template(name string, description string, components []ProductComponentTemplate, merchant_id string, category string) !ProductTemplate {
|
||||||
|
if merchant_id !in c.merchants {
|
||||||
|
return error('Merchant not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
template := ProductTemplate{
|
||||||
|
id: generate_id()
|
||||||
|
name: name
|
||||||
|
description: description
|
||||||
|
components: components
|
||||||
|
merchant_id: merchant_id
|
||||||
|
category: category
|
||||||
|
active: true
|
||||||
|
}
|
||||||
|
c.templates[template.id] = template
|
||||||
|
return template
|
||||||
|
}
|
||||||
|
|
||||||
|
// create_product creates a new product instance from a template
|
||||||
|
pub fn (mut c Commerce) create_product(template_id string, merchant_id string, stock_quantity int) !Product {
|
||||||
|
if template_id !in c.templates {
|
||||||
|
return error('Template not found')
|
||||||
|
}
|
||||||
|
if merchant_id !in c.merchants {
|
||||||
|
return error('Merchant not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
template := c.templates[template_id]
|
||||||
|
mut total_price := 0.0
|
||||||
|
for component in template.components {
|
||||||
|
total_price += component.price
|
||||||
|
}
|
||||||
|
|
||||||
|
product := Product{
|
||||||
|
id: generate_id()
|
||||||
|
template_id: template_id
|
||||||
|
name: template.name
|
||||||
|
description: template.description
|
||||||
|
price: total_price
|
||||||
|
currency: template.components[0].currency // assuming all components use same currency
|
||||||
|
merchant_id: merchant_id
|
||||||
|
stock_quantity: stock_quantity
|
||||||
|
available: true
|
||||||
|
}
|
||||||
|
c.products[product.id] = product
|
||||||
|
return product
|
||||||
|
}
|
||||||
|
|
||||||
|
// create_order creates a new order
|
||||||
|
pub fn (mut c Commerce) create_order(customer_id string, items []OrderItem) !Order {
|
||||||
|
mut total_amount := 0.0
|
||||||
|
mut currency := ''
|
||||||
|
|
||||||
|
for item in items {
|
||||||
|
if item.product_id !in c.products {
|
||||||
|
return error('Product not found: ${item.product_id}')
|
||||||
|
}
|
||||||
|
product := c.products[item.product_id]
|
||||||
|
if !product.available || product.stock_quantity < item.quantity {
|
||||||
|
return error('Product ${product.name} is not available in requested quantity')
|
||||||
|
}
|
||||||
|
total_amount += item.price * item.quantity
|
||||||
|
if currency == '' {
|
||||||
|
currency = item.currency
|
||||||
|
} else if currency != item.currency {
|
||||||
|
return error('Mixed currencies are not supported')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
order := Order{
|
||||||
|
id: generate_id()
|
||||||
|
customer_id: customer_id
|
||||||
|
items: items
|
||||||
|
total_amount: total_amount
|
||||||
|
currency: currency
|
||||||
|
status: 'pending'
|
||||||
|
created_at: time.now().str()
|
||||||
|
updated_at: time.now().str()
|
||||||
|
}
|
||||||
|
c.orders[order.id] = order
|
||||||
|
|
||||||
|
// Update stock quantities
|
||||||
|
for item in items {
|
||||||
|
mut product := c.products[item.product_id]
|
||||||
|
product.stock_quantity -= item.quantity
|
||||||
|
if product.stock_quantity == 0 {
|
||||||
|
product.available = false
|
||||||
|
}
|
||||||
|
c.products[item.product_id] = product
|
||||||
|
}
|
||||||
|
|
||||||
|
return order
|
||||||
|
}
|
||||||
|
|
||||||
|
// update_order_status updates the status of an order
|
||||||
|
pub fn (mut c Commerce) update_order_status(order_id string, new_status string) !Order {
|
||||||
|
if order_id !in c.orders {
|
||||||
|
return error('Order not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
mut order := c.orders[order_id]
|
||||||
|
order.status = new_status
|
||||||
|
order.updated_at = time.now().str()
|
||||||
|
c.orders[order_id] = order
|
||||||
|
return order
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_merchant_products returns all products for a given merchant
|
||||||
|
pub fn (c Commerce) get_merchant_products(merchant_id string) ![]Product {
|
||||||
|
if merchant_id !in c.merchants {
|
||||||
|
return error('Merchant not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
mut products := []Product{}
|
||||||
|
for product in c.products.values() {
|
||||||
|
if product.merchant_id == merchant_id {
|
||||||
|
products << product
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return products
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_merchant_orders returns all orders for products sold by a merchant
|
||||||
|
pub fn (c Commerce) get_merchant_orders(merchant_id string) ![]Order {
|
||||||
|
if merchant_id !in c.merchants {
|
||||||
|
return error('Merchant not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
mut orders := []Order{}
|
||||||
|
for order in c.orders.values() {
|
||||||
|
mut includes_merchant := false
|
||||||
|
for item in order.items {
|
||||||
|
product := c.products[item.product_id]
|
||||||
|
if product.merchant_id == merchant_id {
|
||||||
|
includes_merchant = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if includes_merchant {
|
||||||
|
orders << order
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return orders
|
||||||
|
}
|
||||||
57
examples/baobab/generator/geomind_poc/specs.md
Normal file
57
examples/baobab/generator/geomind_poc/specs.md
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
|
||||||
|
- profile management
|
||||||
|
- my name
|
||||||
|
- my pub key
|
||||||
|
- kyc
|
||||||
|
- ...
|
||||||
|
- product has components
|
||||||
|
- admin items
|
||||||
|
- supported_currencies
|
||||||
|
- countries
|
||||||
|
- continents
|
||||||
|
- farming
|
||||||
|
- farms
|
||||||
|
- default farm exists, users don't have to chose
|
||||||
|
- name
|
||||||
|
- description
|
||||||
|
- owner (pubkey)
|
||||||
|
- nodes
|
||||||
|
- reward (nr of INCA per month and time e.g. 24 months)
|
||||||
|
- reward_promised
|
||||||
|
- reward_given
|
||||||
|
- location
|
||||||
|
- coordinates
|
||||||
|
- continent
|
||||||
|
- country
|
||||||
|
- description
|
||||||
|
- farmid
|
||||||
|
- capacity (disks, mem, ...)
|
||||||
|
- gridversion (eg. 3.16)
|
||||||
|
- nodestats
|
||||||
|
- ...
|
||||||
|
- uptime
|
||||||
|
- bandwidth
|
||||||
|
- referral system
|
||||||
|
- coupons for discounts (one product can have multiple coupons and discounts)
|
||||||
|
- data gets imported with heroscript for what we sell
|
||||||
|
- minimal wallet function (BTC, CHF, MGLD, TFT, INCA)
|
||||||
|
- transactions, so they can see what they spend money on
|
||||||
|
- transfer/exchange
|
||||||
|
- basic communication (messages in/out)
|
||||||
|
- to allow us to communicate with user
|
||||||
|
- news
|
||||||
|
- basic news feed with topics, which we can set
|
||||||
|
- vdc
|
||||||
|
- name
|
||||||
|
- description (optional)
|
||||||
|
- spendinglimit
|
||||||
|
- currency per month, week or day e.g. 0.1 BTC/month
|
||||||
|
- each spending limit has name
|
||||||
|
- admins, list of pubkeys who have access to this and can add capacity to it, or delete, ...
|
||||||
|
- deployment
|
||||||
|
- deploymentid
|
||||||
|
- vdcid
|
||||||
|
- heroscript
|
||||||
|
- status
|
||||||
|
- links (name, link, description, category)
|
||||||
47
examples/baobab/generator/geomind_poc/test_commerce.vsh
Normal file
47
examples/baobab/generator/geomind_poc/test_commerce.vsh
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/env -S v
|
||||||
|
|
||||||
|
import freeflowuniverse.crystallib.core.playbook
|
||||||
|
import geomind_poc
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
test_script := "
|
||||||
|
!!commerce.merchant
|
||||||
|
name: 'Tech Gadgets Store'
|
||||||
|
description: 'Premium electronics and gadgets retailer'
|
||||||
|
contact: 'contact@techgadgets.com'
|
||||||
|
|
||||||
|
!!commerce.component
|
||||||
|
name: '4K Display Panel'
|
||||||
|
description: '55-inch 4K UHD Display Panel'
|
||||||
|
specs:
|
||||||
|
resolution: '3840x2160'
|
||||||
|
refreshRate: '120Hz'
|
||||||
|
panel_type: 'OLED'
|
||||||
|
price: 599.99
|
||||||
|
currency: 'USD'
|
||||||
|
|
||||||
|
!!commerce.template
|
||||||
|
name: 'Smart TV 55-inch'
|
||||||
|
description: '55-inch Smart TV with 4K Display'
|
||||||
|
components: '123e4567-e89b-12d3-a456-426614174001'
|
||||||
|
merchant_id: '123e4567-e89b-12d3-a456-426614174000'
|
||||||
|
category: 'Electronics'
|
||||||
|
|
||||||
|
!!commerce.product
|
||||||
|
template_id: '123e4567-e89b-12d3-a456-426614174002'
|
||||||
|
merchant_id: '123e4567-e89b-12d3-a456-426614174000'
|
||||||
|
stock_quantity: 50
|
||||||
|
|
||||||
|
!!commerce.order
|
||||||
|
customer_id: '123e4567-e89b-12d3-a456-426614174005'
|
||||||
|
items:
|
||||||
|
- '123e4567-e89b-12d3-a456-426614174003:2:899.99:USD'
|
||||||
|
|
||||||
|
!!commerce.update_order
|
||||||
|
order_id: '123e4567-e89b-12d3-a456-426614174004'
|
||||||
|
status: 'shipped'
|
||||||
|
"
|
||||||
|
|
||||||
|
mut plbook := playbook.new(text: test_script)!
|
||||||
|
geomind_poc.play_commerce(mut plbook)!
|
||||||
|
}
|
||||||
25
examples/baobab/generator/mcc_example.vsh
Executable file
25
examples/baobab/generator/mcc_example.vsh
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.baobab.generator
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.schemas.openapi
|
||||||
|
import os
|
||||||
|
|
||||||
|
const example_dir = os.join_path('${os.home_dir()}/code/github/freeflowuniverse/herolib/lib/circles/mcc',
|
||||||
|
'baobab')
|
||||||
|
const openapi_spec_path = os.join_path('${os.home_dir()}/code/github/freeflowuniverse/herolib/lib/circles/mcc',
|
||||||
|
'openapi.json')
|
||||||
|
|
||||||
|
// the actor specification obtained from the OpenRPC Specification
|
||||||
|
openapi_spec := openapi.new(path: openapi_spec_path)!
|
||||||
|
actor_spec := specification.from_openapi(openapi_spec)!
|
||||||
|
|
||||||
|
actor_module := generator.generate_actor_module(actor_spec,
|
||||||
|
interfaces: [.openapi, .http]
|
||||||
|
)!
|
||||||
|
|
||||||
|
actor_module.write(example_dir,
|
||||||
|
format: true
|
||||||
|
overwrite: true
|
||||||
|
compile: false
|
||||||
|
)!
|
||||||
4
examples/baobab/generator/openapi_e2e/.gitignore
vendored
Normal file
4
examples/baobab/generator/openapi_e2e/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
methods.v
|
||||||
|
meeting_scheduler_actor
|
||||||
|
generate_actor_module
|
||||||
|
src
|
||||||
27
examples/baobab/generator/openapi_e2e/generate_actor_module.vsh
Executable file
27
examples/baobab/generator/openapi_e2e/generate_actor_module.vsh
Executable file
@@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.baobab.generator
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.schemas.openapi
|
||||||
|
import os
|
||||||
|
|
||||||
|
const example_dir = os.dir(@FILE)
|
||||||
|
const openapi_spec_path = os.join_path(example_dir, 'openapi.json')
|
||||||
|
|
||||||
|
// the actor specification obtained from the OpenRPC Specification
|
||||||
|
openapi_spec := openapi.new(path: openapi_spec_path)!
|
||||||
|
actor_spec := specification.from_openapi(openapi_spec)!
|
||||||
|
|
||||||
|
println(actor_spec)
|
||||||
|
|
||||||
|
actor_module := generator.generate_actor_module(actor_spec,
|
||||||
|
interfaces: [.openapi, .http]
|
||||||
|
)!
|
||||||
|
|
||||||
|
actor_module.write(example_dir,
|
||||||
|
format: false
|
||||||
|
overwrite: true
|
||||||
|
compile: false
|
||||||
|
)!
|
||||||
|
|
||||||
|
// os.execvp('bash', ['${example_dir}/meeting_scheduler_actor/scripts/run.sh'])!
|
||||||
311
examples/baobab/generator/openapi_e2e/openapi.json
Normal file
311
examples/baobab/generator/openapi_e2e/openapi.json
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
{
|
||||||
|
"openapi": "3.0.0",
|
||||||
|
"info": {
|
||||||
|
"title": "Meeting Scheduler",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "An API for managing meetings, availability, and scheduling."
|
||||||
|
},
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "http://localhost:8080/openapi/v1",
|
||||||
|
"description": "Production server"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "http://localhost:8081/openapi/v1",
|
||||||
|
"description": "Example server"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"/users": {
|
||||||
|
"get": {
|
||||||
|
"summary": "List all users",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A list of users",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/User"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": [
|
||||||
|
{
|
||||||
|
"id": "1",
|
||||||
|
"name": "Alice",
|
||||||
|
"email": "alice@example.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2",
|
||||||
|
"name": "Bob",
|
||||||
|
"email": "bob@example.com"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/users/{userId}": {
|
||||||
|
"get": {
|
||||||
|
"operationId": "get_user",
|
||||||
|
"summary": "Get user by ID",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "userId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32"
|
||||||
|
},
|
||||||
|
"description": "The ID of the user",
|
||||||
|
"example": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "User details",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/User"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"id": "1",
|
||||||
|
"name": "Alice",
|
||||||
|
"email": "alice@example.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "User not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/events": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Create an event",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Event"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"title": "Team Meeting",
|
||||||
|
"description": "Weekly sync",
|
||||||
|
"startTime": "2023-10-10T10:00:00Z",
|
||||||
|
"endTime": "2023-10-10T11:00:00Z",
|
||||||
|
"userId": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Event created",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Event"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"id": "101",
|
||||||
|
"title": "Team Meeting",
|
||||||
|
"description": "Weekly sync",
|
||||||
|
"startTime": "2023-10-10T10:00:00Z",
|
||||||
|
"endTime": "2023-10-10T11:00:00Z",
|
||||||
|
"userId": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/availability": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get availability for a user",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "userId",
|
||||||
|
"in": "query",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "The ID of the user",
|
||||||
|
"example": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "date",
|
||||||
|
"in": "query",
|
||||||
|
"required": false,
|
||||||
|
"schema": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date"
|
||||||
|
},
|
||||||
|
"description": "The date to check availability (YYYY-MM-DD)",
|
||||||
|
"example": "2023-10-10"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Availability details",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/TimeSlot"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": [
|
||||||
|
{
|
||||||
|
"startTime": "10:00:00",
|
||||||
|
"endTime": "11:00:00",
|
||||||
|
"available": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"startTime": "11:00:00",
|
||||||
|
"endTime": "12:00:00",
|
||||||
|
"available": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/bookings": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Book a meeting",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Booking"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"userId": "1",
|
||||||
|
"eventId": "101",
|
||||||
|
"timeSlot": {
|
||||||
|
"startTime": "10:00:00",
|
||||||
|
"endTime": "11:00:00",
|
||||||
|
"available": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Booking created",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Booking"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"id": "5001",
|
||||||
|
"userId": "1",
|
||||||
|
"eventId": "101",
|
||||||
|
"timeSlot": {
|
||||||
|
"startTime": "10:00:00",
|
||||||
|
"endTime": "11:00:00",
|
||||||
|
"available": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"User": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "email"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Event": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"startTime": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
|
"endTime": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
|
"userId": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"TimeSlot": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"startTime": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "time"
|
||||||
|
},
|
||||||
|
"endTime": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "time"
|
||||||
|
},
|
||||||
|
"available": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Booking": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"userId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"eventId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"timeSlot": {
|
||||||
|
"$ref": "#/components/schemas/TimeSlot"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
examples/baobab/specification/README.md
Normal file
3
examples/baobab/specification/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Actor Specification Examples
|
||||||
|
|
||||||
|
These examples show how `OpenRPC` and `OpenAPI` specifications can be translated back and forth into an `ActorSpecification`. This is an important step of actor generation as actor code is generated from actor specification.
|
||||||
346
examples/baobab/specification/openapi.json
Normal file
346
examples/baobab/specification/openapi.json
Normal file
@@ -0,0 +1,346 @@
|
|||||||
|
{
|
||||||
|
"openapi": "3.0.3",
|
||||||
|
"info": {
|
||||||
|
"title": "Pet Store API",
|
||||||
|
"description": "A sample API for a pet store",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "https://api.petstore.example.com/v1",
|
||||||
|
"description": "Production server"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://staging.petstore.example.com/v1",
|
||||||
|
"description": "Staging server"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"/pets": {
|
||||||
|
"get": {
|
||||||
|
"summary": "List all pets",
|
||||||
|
"operationId": "listPets",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "limit",
|
||||||
|
"in": "query",
|
||||||
|
"description": "Maximum number of pets to return",
|
||||||
|
"required": false,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A paginated list of pets",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Pets"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Invalid request"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"post": {
|
||||||
|
"summary": "Create a new pet",
|
||||||
|
"operationId": "createPet",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/NewPet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Pet created",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Pet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Invalid input"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/pets/{petId}": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get a pet by ID",
|
||||||
|
"operationId": "getPet",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "petId",
|
||||||
|
"in": "path",
|
||||||
|
"description": "ID of the pet to retrieve",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A pet",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Pet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Pet not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"delete": {
|
||||||
|
"summary": "Delete a pet by ID",
|
||||||
|
"operationId": "deletePet",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "petId",
|
||||||
|
"in": "path",
|
||||||
|
"description": "ID of the pet to delete",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"description": "Pet deleted"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Pet not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/orders": {
|
||||||
|
"get": {
|
||||||
|
"summary": "List all orders",
|
||||||
|
"operationId": "listOrders",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A list of orders",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Order"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/orders/{orderId}": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get an order by ID",
|
||||||
|
"operationId": "getOrder",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "orderId",
|
||||||
|
"in": "path",
|
||||||
|
"description": "ID of the order to retrieve",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "An order",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Order"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Order not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"delete": {
|
||||||
|
"summary": "Delete an order by ID",
|
||||||
|
"operationId": "deleteOrder",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "orderId",
|
||||||
|
"in": "path",
|
||||||
|
"description": "ID of the order to delete",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"description": "Order deleted"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Order not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/users": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Create a user",
|
||||||
|
"operationId": "createUser",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/NewUser"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "User created",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/User"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"Pet": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["id", "name"],
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NewPet": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["name"],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Pets": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Pet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Order": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["id", "petId", "quantity", "shipDate"],
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
|
"petId": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
|
"quantity": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"shipDate": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["placed", "approved", "delivered"]
|
||||||
|
},
|
||||||
|
"complete": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"User": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["id", "username"],
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"phone": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NewUser": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["username"],
|
||||||
|
"properties": {
|
||||||
|
"username": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"phone": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
examples/baobab/specification/openapi_to_specification.vsh
Executable file
13
examples/baobab/specification/openapi_to_specification.vsh
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env -S v -w -n -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.schemas.openapi
|
||||||
|
import os
|
||||||
|
|
||||||
|
const example_dir = os.dir(@FILE)
|
||||||
|
const openapi_spec_path = os.join_path(example_dir, 'openapi.json')
|
||||||
|
|
||||||
|
// the actor specification obtained from the OpenRPC Specification
|
||||||
|
openapi_spec := openapi.new(path: openapi_spec_path)!
|
||||||
|
actor_specification := specification.from_openapi(openapi_spec)!
|
||||||
|
println(actor_specification)
|
||||||
132
examples/baobab/specification/openrpc.json
Normal file
132
examples/baobab/specification/openrpc.json
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
{
|
||||||
|
"openrpc": "1.0.0",
|
||||||
|
"info": {
|
||||||
|
"title": "PetStore",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"methods": [
|
||||||
|
{
|
||||||
|
"name": "GetPets",
|
||||||
|
"description": "finds pets in the system that the user has access to by tags and within a limit",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "tags",
|
||||||
|
"description": "tags to filter by",
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "limit",
|
||||||
|
"description": "maximum number of results to return",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"result": {
|
||||||
|
"name": "pet_list",
|
||||||
|
"description": "all pets from the system, that mathes the tags",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#\/components\/schemas\/Pet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CreatePet",
|
||||||
|
"description": "creates a new pet in the store. Duplicates are allowed.",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "new_pet",
|
||||||
|
"description": "Pet to add to the store.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#\/components\/schemas\/NewPet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"result": {
|
||||||
|
"name": "pet",
|
||||||
|
"description": "the newly created pet",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#\/components\/schemas\/Pet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GetPetById",
|
||||||
|
"description": "gets a pet based on a single ID, if the user has access to the pet",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"description": "ID of pet to fetch",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"result": {
|
||||||
|
"name": "pet",
|
||||||
|
"description": "pet response",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#\/components\/schemas\/Pet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DeletePetById",
|
||||||
|
"description": "deletes a single pet based on the ID supplied",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"description": "ID of pet to delete",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"result": {
|
||||||
|
"name": "pet",
|
||||||
|
"description": "pet deleted",
|
||||||
|
"schema": {
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"NewPet": {
|
||||||
|
"title": "NewPet",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Pet": {
|
||||||
|
"title": "Pet",
|
||||||
|
"description": "a pet struct that represents a pet",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"description": "name of the pet",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"description": "a tag of the pet, helps finding pet",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"description": "unique indentifier",
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
examples/baobab/specification/openrpc_to_specification.vsh
Executable file
13
examples/baobab/specification/openrpc_to_specification.vsh
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env -S v -w -n -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.schemas.openrpc
|
||||||
|
import os
|
||||||
|
|
||||||
|
const example_dir = os.dir(@FILE)
|
||||||
|
const openrpc_spec_path = os.join_path(example_dir, 'openrpc.json')
|
||||||
|
|
||||||
|
// the actor specification obtained from the OpenRPC Specification
|
||||||
|
openrpc_spec := openrpc.new(path: openrpc_spec_path)!
|
||||||
|
actor_specification := specification.from_openrpc(openrpc_spec)!
|
||||||
|
println(actor_specification)
|
||||||
107
examples/baobab/specification/specification_to_openapi.vsh
Executable file
107
examples/baobab/specification/specification_to_openapi.vsh
Executable file
@@ -0,0 +1,107 @@
|
|||||||
|
#!/usr/bin/env -S v -w -n -enable-globals run
|
||||||
|
|
||||||
|
import json
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.schemas.jsonschema
|
||||||
|
import freeflowuniverse.herolib.schemas.openrpc
|
||||||
|
import os
|
||||||
|
|
||||||
|
const actor_specification = specification.ActorSpecification{
|
||||||
|
name: 'PetStore'
|
||||||
|
interfaces: [.openrpc]
|
||||||
|
methods: [
|
||||||
|
specification.ActorMethod{
|
||||||
|
name: 'GetPets'
|
||||||
|
description: 'finds pets in the system that the user has access to by tags and within a limit'
|
||||||
|
parameters: [
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'tags'
|
||||||
|
description: 'tags to filter by'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'array'
|
||||||
|
items: jsonschema.Items(jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'string'
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'limit'
|
||||||
|
description: 'maximum number of results to return'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'integer'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
]
|
||||||
|
result: openrpc.ContentDescriptor{
|
||||||
|
name: 'pet_list'
|
||||||
|
description: 'all pets from the system, that matches the tags'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||||
|
ref: '#/components/schemas/Pet'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
specification.ActorMethod{
|
||||||
|
name: 'CreatePet'
|
||||||
|
description: 'creates a new pet in the store. Duplicates are allowed.'
|
||||||
|
parameters: [
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'new_pet'
|
||||||
|
description: 'Pet to add to the store.'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||||
|
ref: '#/components/schemas/NewPet'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
]
|
||||||
|
result: openrpc.ContentDescriptor{
|
||||||
|
name: 'pet'
|
||||||
|
description: 'the newly created pet'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||||
|
ref: '#/components/schemas/Pet'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
specification.ActorMethod{
|
||||||
|
name: 'GetPetById'
|
||||||
|
description: 'gets a pet based on a single ID, if the user has access to the pet'
|
||||||
|
parameters: [
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'id'
|
||||||
|
description: 'ID of pet to fetch'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'integer'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
]
|
||||||
|
result: openrpc.ContentDescriptor{
|
||||||
|
name: 'pet'
|
||||||
|
description: 'pet response'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||||
|
ref: '#/components/schemas/Pet'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
specification.ActorMethod{
|
||||||
|
name: 'DeletePetById'
|
||||||
|
description: 'deletes a single pet based on the ID supplied'
|
||||||
|
parameters: [
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'id'
|
||||||
|
description: 'ID of pet to delete'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'integer'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
]
|
||||||
|
result: openrpc.ContentDescriptor{
|
||||||
|
name: 'pet'
|
||||||
|
description: 'pet deleted'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'null'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
openapi_specification := actor_specification.to_openapi()
|
||||||
|
println(json.encode_pretty(openapi_specification))
|
||||||
109
examples/baobab/specification/specification_to_openrpc.vsh
Executable file
109
examples/baobab/specification/specification_to_openrpc.vsh
Executable file
@@ -0,0 +1,109 @@
|
|||||||
|
#!/usr/bin/env -S v -w -n -enable-globals run
|
||||||
|
|
||||||
|
import json
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.core.code
|
||||||
|
import freeflowuniverse.herolib.schemas.jsonschema
|
||||||
|
import freeflowuniverse.herolib.schemas.openrpc
|
||||||
|
import os
|
||||||
|
|
||||||
|
const actor_specification = specification.ActorSpecification{
|
||||||
|
name: 'PetStore'
|
||||||
|
structure: code.Struct{}
|
||||||
|
interfaces: [.openrpc]
|
||||||
|
methods: [
|
||||||
|
specification.ActorMethod{
|
||||||
|
name: 'GetPets'
|
||||||
|
description: 'finds pets in the system that the user has access to by tags and within a limit'
|
||||||
|
parameters: [
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'tags'
|
||||||
|
description: 'tags to filter by'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'array'
|
||||||
|
items: jsonschema.Items(jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'string'
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'limit'
|
||||||
|
description: 'maximum number of results to return'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'integer'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
]
|
||||||
|
result: openrpc.ContentDescriptor{
|
||||||
|
name: 'pet_list'
|
||||||
|
description: 'all pets from the system, that matches the tags'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||||
|
ref: '#/components/schemas/Pet'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
specification.ActorMethod{
|
||||||
|
name: 'CreatePet'
|
||||||
|
description: 'creates a new pet in the store. Duplicates are allowed.'
|
||||||
|
parameters: [
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'new_pet'
|
||||||
|
description: 'Pet to add to the store.'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||||
|
ref: '#/components/schemas/NewPet'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
]
|
||||||
|
result: openrpc.ContentDescriptor{
|
||||||
|
name: 'pet'
|
||||||
|
description: 'the newly created pet'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||||
|
ref: '#/components/schemas/Pet'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
specification.ActorMethod{
|
||||||
|
name: 'GetPetById'
|
||||||
|
description: 'gets a pet based on a single ID, if the user has access to the pet'
|
||||||
|
parameters: [
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'id'
|
||||||
|
description: 'ID of pet to fetch'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'integer'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
]
|
||||||
|
result: openrpc.ContentDescriptor{
|
||||||
|
name: 'pet'
|
||||||
|
description: 'pet response'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||||
|
ref: '#/components/schemas/Pet'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
specification.ActorMethod{
|
||||||
|
name: 'DeletePetById'
|
||||||
|
description: 'deletes a single pet based on the ID supplied'
|
||||||
|
parameters: [
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'id'
|
||||||
|
description: 'ID of pet to delete'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'integer'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
]
|
||||||
|
result: openrpc.ContentDescriptor{
|
||||||
|
name: 'pet'
|
||||||
|
description: 'pet deleted'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'null'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
openrpc_specification := actor_specification.to_openrpc()
|
||||||
|
println(json.encode_pretty(openrpc_specification))
|
||||||
17
examples/biztools/bizmodel.vsh
Executable file
17
examples/biztools/bizmodel.vsh
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.biz.bizmodel
|
||||||
|
import os
|
||||||
|
|
||||||
|
const playbook_path = os.dir(@FILE) + '/playbook'
|
||||||
|
const build_path = os.join_path(os.dir(@FILE), '/docusaurus')
|
||||||
|
|
||||||
|
buildpath := '${os.home_dir()}/hero/var/mdbuild/bizmodel'
|
||||||
|
|
||||||
|
mut model := bizmodel.generate('test', playbook_path)!
|
||||||
|
|
||||||
|
println(model.sheet)
|
||||||
|
println(model.sheet.export()!)
|
||||||
|
|
||||||
|
model.sheet.export(path: '~/Downloads/test.csv')!
|
||||||
|
model.sheet.export(path: '~/code/github/freeflowuniverse/starlight_template/src/content/test.csv')!
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
bizmodel
|
|
||||||
dest
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
#!/usr/bin/env -S v -n -w -cg -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
|
||||||
|
|
||||||
//#!/usr/bin/env -S v -cg -enable-globals run
|
|
||||||
import freeflowuniverse.herolib.data.doctree
|
|
||||||
import freeflowuniverse.herolib.biz.bizmodel
|
|
||||||
import freeflowuniverse.herolib.core.playbook
|
|
||||||
import freeflowuniverse.herolib.core.playcmds
|
|
||||||
import freeflowuniverse.herolib.web.mdbook
|
|
||||||
import os
|
|
||||||
|
|
||||||
const wikipath = os.dir(@FILE) + '/wiki'
|
|
||||||
const summarypath = os.dir(@FILE) + '/wiki/summary.md'
|
|
||||||
|
|
||||||
buildpath := '${os.home_dir()}/hero/var/mdbuild/bizmodel'
|
|
||||||
|
|
||||||
mut m := bizmodel.getset('example')!
|
|
||||||
m.workdir = wikipath
|
|
||||||
m.play(mut playbook.new(path: wikipath)!)!
|
|
||||||
m.export_sheets()!
|
|
||||||
bizmodel.set(m)
|
|
||||||
|
|
||||||
// // execute the actions so we have the info populated
|
|
||||||
// // playcmds.run(mut plb,false)!
|
|
||||||
|
|
||||||
// // just run the doctree & mdbook and it should
|
|
||||||
// // load the doctree, these are all collections
|
|
||||||
// mut tree := doctree.new(name: 'bizmodel')!
|
|
||||||
// tree.scan(path: wikipath)!
|
|
||||||
// tree.export(dest: buildpath, reset: true)!
|
|
||||||
|
|
||||||
// // mut bm:=bizmodel.get("test")!
|
|
||||||
// // println(bm)
|
|
||||||
|
|
||||||
// mut mdbooks := mdbook.get()!
|
|
||||||
// mdbooks.generate(
|
|
||||||
// name: 'bizmodel'
|
|
||||||
// summary_path: summarypath
|
|
||||||
// doctree_path: buildpath
|
|
||||||
// title: 'bizmodel example'
|
|
||||||
// )!
|
|
||||||
// mdbook.book_open('bizmodel')!
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
# Hr Overview
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
!!!bizmodel.employees_wiki bizname:'test'
|
|
||||||
|
|
||||||
|
|
||||||
> note: Nr People like 0:5,20:5 means, month 0 (start) is 5, month 20 its 5 people
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# CTO
|
|
||||||
|
|
||||||
!!!bizmodel.employee_wiki bizname:'test' name:'despiegk'
|
|
||||||
|
|
||||||
!!wiki.include page:cto_description.md
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
## CTO Description
|
|
||||||
|
|
||||||
this is a page to test nested includes
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
# This is our business model planner
|
|
||||||
|
|
||||||
## P&L Overview
|
|
||||||
|
|
||||||
|
|
||||||
<!-- period is in months, 3 means every quarter -->
|
|
||||||
|
|
||||||
|
|
||||||
!!bizmodel.graph_bar_row rowname:revenue_total unit:million title:'A Title' title_sub:'Sub' sheetname:'bizmodel_test'
|
|
||||||
|
|
||||||
Unit is in Million USD.
|
|
||||||
|
|
||||||
!!bizmodel.graph_bar_row rowname:revenue_total unit:million sheetname:'bizmodel_test'
|
|
||||||
|
|
||||||
!!bizmodel.graph_line_row rowname:revenue_total unit:million sheetname:'bizmodel_test'
|
|
||||||
|
|
||||||
!!bizmodel.graph_pie_row rowname:revenue_total unit:million size:'80%' sheetname:'bizmodel_test'
|
|
||||||
|
|
||||||
## FUNDING
|
|
||||||
|
|
||||||
!!bizmodel.sheet_wiki includefilter:'funding' sheetname:'bizmodel_test'
|
|
||||||
|
|
||||||
!!bizmodel.sheet_wiki title:'REVENUE' includefilter:rev sheetname:'bizmodel_test'
|
|
||||||
|
|
||||||
!!bizmodel.sheet_wiki title:'Revenue Total' includefilter:'revtotal' sheetname:'bizmodel_test'
|
|
||||||
|
|
||||||
!!bizmodel.sheet_wiki title:'REVENUE' includefilter:'revtotal2' sheetname:'bizmodel_test'
|
|
||||||
|
|
||||||
!!bizmodel.sheet_wiki title:'COGS' includefilter:'cogs' sheetname:'bizmodel_test'
|
|
||||||
|
|
||||||
!!bizmodel.sheet_wiki title:'Margin' includefilter:'margin' sheetname:'bizmodel_test'
|
|
||||||
|
|
||||||
!!bizmodel.sheet_wiki title:'HR Teams' includefilter:'hrnr' sheetname:'bizmodel_test'
|
|
||||||
|
|
||||||
!!bizmodel.sheet_wiki title:'HR Costs' includefilter:'hrcost' sheetname:'bizmodel_test'
|
|
||||||
|
|
||||||
!!bizmodel.sheet_wiki title:'COSTS' includefilter:'ocost' sheetname:'bizmodel_test'
|
|
||||||
|
|
||||||
!!bizmodel.sheet_wiki title:'HR Costs' includefilter:'hrcost' sheetname:'bizmodel_test'
|
|
||||||
|
|
||||||
!!bizmodel.sheet_wiki title:'P&L Overview' includefilter:'pl' sheetname:'bizmodel_test'
|
|
||||||
|
|
||||||
!!bizmodel.sheet_wiki title:'P&L Overview' includefilter:'pl' sheetname:'bizmodel_test'
|
|
||||||
|
|
||||||
## Some Details
|
|
||||||
|
|
||||||
> show how we can do per month
|
|
||||||
|
|
||||||
!!bizmodel.sheet_wiki includefilter:'pl' period_months:1 sheetname:'bizmodel_test'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
4
examples/biztools/bizmodel_docusaurus/.gitignore
vendored
Normal file
4
examples/biztools/bizmodel_docusaurus/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
bizmodel
|
||||||
|
dest
|
||||||
|
wiki
|
||||||
|
build
|
||||||
|
Before Width: | Height: | Size: 1.8 MiB After Width: | Height: | Size: 1.8 MiB |
34
examples/biztools/bizmodel_docusaurus/bizmodel_docusaurus.vsh
Executable file
34
examples/biztools/bizmodel_docusaurus/bizmodel_docusaurus.vsh
Executable file
@@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
//#!/usr/bin/env -S v -cg -enable-globals run
|
||||||
|
import freeflowuniverse.herolib.biz.bizmodel
|
||||||
|
import freeflowuniverse.herolib.core.playbook
|
||||||
|
import freeflowuniverse.herolib.core.playcmds
|
||||||
|
import os
|
||||||
|
|
||||||
|
// TODO: need to fix wrong location
|
||||||
|
const playbook_path = os.dir(@FILE) + '/playbook'
|
||||||
|
const build_path = os.join_path(os.dir(@FILE), '/docusaurus')
|
||||||
|
|
||||||
|
buildpath := '${os.home_dir()}/hero/var/mdbuild/bizmodel'
|
||||||
|
|
||||||
|
mut model := bizmodel.getset('example')!
|
||||||
|
model.workdir = build_path
|
||||||
|
model.play(mut playbook.new(path: playbook_path)!)!
|
||||||
|
|
||||||
|
println(model.sheet)
|
||||||
|
println(model.sheet.export()!)
|
||||||
|
|
||||||
|
// model.sheet.export(path:"~/Downloads/test.csv")!
|
||||||
|
// model.sheet.export(path:"~/code/github/freeflowuniverse/starlight_template/src/content/test.csv")!
|
||||||
|
|
||||||
|
report := model.new_report(
|
||||||
|
name: 'example_report'
|
||||||
|
title: 'Example Business Model'
|
||||||
|
)!
|
||||||
|
|
||||||
|
report.export(
|
||||||
|
path: build_path
|
||||||
|
overwrite: true
|
||||||
|
format: .docusaurus
|
||||||
|
)!
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
output dir of example
|
||||||
22
examples/biztools/bizmodel_docusaurus/docusaurus/build.sh
Executable file
22
examples/biztools/bizmodel_docusaurus/docusaurus/build.sh
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
cd "${script_dir}"
|
||||||
|
|
||||||
|
echo "Docs directory: $script_dir"
|
||||||
|
|
||||||
|
cd "${HOME}/hero/var/docusaurus"
|
||||||
|
|
||||||
|
export PATH=/tmp/docusaurus_build/node_modules/.bin:${HOME}/.bun/bin/:$PATH
|
||||||
|
|
||||||
|
rm -rf /Users/despiegk/hero/var/docusaurus/build/
|
||||||
|
|
||||||
|
. ${HOME}/.zprofile
|
||||||
|
|
||||||
|
bun docusaurus build
|
||||||
|
|
||||||
|
mkdir -p /Users/despiegk/code/github/freeflowuniverse/herolib/examples/biztools/bizmodel/example/docusaurus
|
||||||
|
echo SYNC TO /Users/despiegk/code/github/freeflowuniverse/herolib/examples/biztools/bizmodel/example/docusaurus
|
||||||
|
rsync -rv --delete /Users/despiegk/hero/var/docusaurus/build/ /Users/despiegk/code/github/freeflowuniverse/herolib/examples/biztools/bizmodel/example/docusaurus/
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"style":"dark","links":[]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"name":"","title":"Docusaurus","tagline":"","favicon":"img/favicon.png","url":"http://localhost","url_home":"docs/introduction","baseUrl":"/","image":"img/tf_graph.png","metadata":{"description":"Docusaurus","image":"Docusaurus","title":"Docusaurus"},"buildDest":[],"buildDestDev":[]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"title":"Business Model","items":[{"href":"https://threefold.info/kristof/","label":"ThreeFold Technology","position":"right"},{"href":"https://threefold.io","label":"Operational Plan","position":"left"}]}
|
||||||
16
examples/biztools/bizmodel_docusaurus/docusaurus/develop.sh
Executable file
16
examples/biztools/bizmodel_docusaurus/docusaurus/develop.sh
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
cd "${script_dir}"
|
||||||
|
|
||||||
|
echo "Docs directory: $script_dir"
|
||||||
|
|
||||||
|
cd "${HOME}/hero/var/docusaurus"
|
||||||
|
|
||||||
|
export PATH=/tmp/docusaurus_build/node_modules/.bin:${HOME}/.bun/bin/:$PATH
|
||||||
|
|
||||||
|
. ${HOME}/.zprofile
|
||||||
|
|
||||||
|
bun run start -p 3100
|
||||||
@@ -4,11 +4,31 @@
|
|||||||
|
|
||||||
This company is a cloud company ...
|
This company is a cloud company ...
|
||||||
|
|
||||||
|
- name, e.g. for a specific project
|
||||||
|
- descr, description of the revenue line item
|
||||||
|
- revenue_items: does one of revenue, is not exterpolated
|
||||||
|
- revenue_growth: is a revenue stream which is being extrapolated
|
||||||
|
- revenue_setup, revenue for 1 item '1000usd'
|
||||||
|
- revenue_setup_delay
|
||||||
|
- revenue_monthly, revenue per month for 1 item
|
||||||
|
- revenue_monthly_delay, how many months before monthly revenue starts
|
||||||
|
- maintenance_month_perc, how much percent of revenue_setup will come back over months
|
||||||
|
- cogs_setup, cost of good for 1 item at setup
|
||||||
|
- cogs_setup_delay, how many months before setup cogs starts, after sales
|
||||||
|
- cogs_setup_perc: what is percentage of the cogs (can change over time) for setup e.g. 0:50%
|
||||||
|
|
||||||
|
- cogs_monthly, cost of goods for the monthly per 1 item
|
||||||
|
- cogs_monthly_delay, how many months before monthly cogs starts, after sales
|
||||||
|
- cogs_monthly_perc: what is percentage of the cogs (can change over time) for monthly e.g. 0:5%,12:10%
|
||||||
|
|
||||||
|
- nr_sold: how many do we sell per month (is in growth format e.g. 10:100,20:200, default is 1)
|
||||||
|
- nr_months_recurring: how many months is recurring, if 0 then no recurring
|
||||||
|
|
||||||
```js
|
```js
|
||||||
!!bizmodel.revenue_define bizname:'test'
|
!!bizmodel.revenue_define bizname:'test'
|
||||||
descr:'OEM Deals'
|
descr:'OEM Deals'
|
||||||
revenue_time:'10:1000000EUR,15:3333,20:1200000'
|
revenue_items:'10:1000000EUR,15:3333,20:1200000'
|
||||||
cogs_perc: '1:5%,20:10%'
|
cogs_setup_perc: '1:5%,20:10%'
|
||||||
|
|
||||||
!!bizmodel.revenue_define bizname:'test'
|
!!bizmodel.revenue_define bizname:'test'
|
||||||
descr:'License Deals'
|
descr:'License Deals'
|
||||||
@@ -23,6 +43,7 @@ This company is a cloud company ...
|
|||||||
revenue_nr:'10:1000,24:2000,60:40000'
|
revenue_nr:'10:1000,24:2000,60:40000'
|
||||||
cogs_perc: '10%'
|
cogs_perc: '10%'
|
||||||
rev_delay_month: 1
|
rev_delay_month: 1
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Revenue Items Recurring
|
## Revenue Items Recurring
|
||||||
50
examples/clients/jina_example.vsh
Executable file
50
examples/clients/jina_example.vsh
Executable file
@@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.clients.jina
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Initialize Jina client
|
||||||
|
mut j := jina.Jina{
|
||||||
|
name: 'test_client'
|
||||||
|
secret: os.getenv('JINAKEY')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the client
|
||||||
|
j = jina.obj_init(j) or {
|
||||||
|
println('Error initializing Jina client: ${err}')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if authentication works
|
||||||
|
auth_ok := j.check_auth() or {
|
||||||
|
println('Authentication failed: ${err}')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
println('Authentication successful: ${auth_ok}')
|
||||||
|
|
||||||
|
// Create embeddings
|
||||||
|
model := 'jina-embeddings-v2-base-en'
|
||||||
|
input := ['Hello world', 'This is a test']
|
||||||
|
|
||||||
|
embeddings := j.create_embeddings(input, model, 'search') or {
|
||||||
|
println('Error creating embeddings: ${err}')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
println('Embeddings created successfully!')
|
||||||
|
println('Model: ${embeddings.model}')
|
||||||
|
println('Dimension: ${embeddings.dimension}')
|
||||||
|
println('Number of embeddings: ${embeddings.data.len}')
|
||||||
|
|
||||||
|
// If there are embeddings, print the first one (truncated)
|
||||||
|
if embeddings.data.len > 0 {
|
||||||
|
first_embedding := embeddings.data[0]
|
||||||
|
println('First embedding (first 5 values): ${first_embedding.embedding[0..5]}')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage information
|
||||||
|
println('Token usage: ${embeddings.usage.total_tokens} ${embeddings.usage.unit}')
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
import freeflowuniverse.herolib.clients.mycelium
|
import freeflowuniverse.herolib.clients.mycelium
|
||||||
import freeflowuniverse.herolib.installers.net.mycelium as mycelium_installer
|
import freeflowuniverse.herolib.installers.net.mycelium_installer
|
||||||
import freeflowuniverse.herolib.osal
|
import freeflowuniverse.herolib.osal
|
||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
|
|||||||
115
examples/core/agent_encoding.vsh
Executable file
115
examples/core/agent_encoding.vsh
Executable file
@@ -0,0 +1,115 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.data.ourtime
|
||||||
|
import freeflowuniverse.herolib.core.jobs.model
|
||||||
|
|
||||||
|
// Create a test agent with some sample data
|
||||||
|
mut agent := model.Agent{
|
||||||
|
pubkey: 'ed25519:1234567890abcdef'
|
||||||
|
address: '192.168.1.100'
|
||||||
|
port: 9999
|
||||||
|
description: 'Test agent for binary encoding'
|
||||||
|
status: model.AgentStatus{
|
||||||
|
guid: 'agent-123'
|
||||||
|
timestamp_first: ourtime.now()
|
||||||
|
timestamp_last: ourtime.now()
|
||||||
|
status: model.AgentState.ok
|
||||||
|
}
|
||||||
|
services: []
|
||||||
|
signature: 'signature-data-here'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a service
|
||||||
|
mut service := model.AgentService{
|
||||||
|
actor: 'vm'
|
||||||
|
description: 'Virtual machine management'
|
||||||
|
status: model.AgentServiceState.ok
|
||||||
|
public: true
|
||||||
|
actions: []
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an action to the service
|
||||||
|
mut action := model.AgentServiceAction{
|
||||||
|
action: 'create'
|
||||||
|
description: 'Create a new virtual machine'
|
||||||
|
status: model.AgentServiceState.ok
|
||||||
|
public: true
|
||||||
|
params: {
|
||||||
|
'name': 'Name of the VM'
|
||||||
|
'memory': 'Memory in MB'
|
||||||
|
'cpu': 'Number of CPU cores'
|
||||||
|
}
|
||||||
|
params_example: {
|
||||||
|
'name': 'my-test-vm'
|
||||||
|
'memory': '2048'
|
||||||
|
'cpu': '2'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
service.actions << action
|
||||||
|
agent.services << service
|
||||||
|
|
||||||
|
// Test binary encoding
|
||||||
|
binary_data := agent.dumps() or {
|
||||||
|
println('Failed to encode agent: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
println('Successfully encoded agent to binary, size: ${binary_data.len} bytes')
|
||||||
|
|
||||||
|
// Test binary decoding
|
||||||
|
decoded_agent := model.loads(binary_data) or {
|
||||||
|
println('Failed to decode agent: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the decoded data matches the original
|
||||||
|
assert decoded_agent.pubkey == agent.pubkey
|
||||||
|
assert decoded_agent.address == agent.address
|
||||||
|
assert decoded_agent.port == agent.port
|
||||||
|
assert decoded_agent.description == agent.description
|
||||||
|
assert decoded_agent.signature == agent.signature
|
||||||
|
|
||||||
|
// Verify status
|
||||||
|
assert decoded_agent.status.guid == agent.status.guid
|
||||||
|
assert decoded_agent.status.status == agent.status.status
|
||||||
|
|
||||||
|
// Verify services
|
||||||
|
assert decoded_agent.services.len == agent.services.len
|
||||||
|
if decoded_agent.services.len > 0 {
|
||||||
|
service1 := decoded_agent.services[0]
|
||||||
|
original_service := agent.services[0]
|
||||||
|
|
||||||
|
assert service1.actor == original_service.actor
|
||||||
|
assert service1.description == original_service.description
|
||||||
|
assert service1.status == original_service.status
|
||||||
|
assert service1.public == original_service.public
|
||||||
|
|
||||||
|
// Verify actions
|
||||||
|
assert service1.actions.len == original_service.actions.len
|
||||||
|
if service1.actions.len > 0 {
|
||||||
|
action1 := service1.actions[0]
|
||||||
|
original_action := original_service.actions[0]
|
||||||
|
|
||||||
|
assert action1.action == original_action.action
|
||||||
|
assert action1.description == original_action.description
|
||||||
|
assert action1.status == original_action.status
|
||||||
|
assert action1.public == original_action.public
|
||||||
|
|
||||||
|
// Verify params
|
||||||
|
assert action1.params.len == original_action.params.len
|
||||||
|
for key, value in original_action.params {
|
||||||
|
assert key in action1.params
|
||||||
|
assert action1.params[key] == value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify params_example
|
||||||
|
assert action1.params_example.len == original_action.params_example.len
|
||||||
|
for key, value in original_action.params_example {
|
||||||
|
assert key in action1.params_example
|
||||||
|
assert action1.params_example[key] == value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println('Agent binary encoding/decoding test passed successfully')
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
module embedding
|
|
||||||
|
|
||||||
pub struct Embedder {
|
|
||||||
Embedded
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Embedded {
|
|
||||||
id int
|
|
||||||
related_ids []int
|
|
||||||
name string
|
|
||||||
tags []string
|
|
||||||
date time.Time
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
|
||||||
|
|
||||||
import os
|
|
||||||
import freeflowuniverse.herolib.core.codeparser
|
|
||||||
import freeflowuniverse.herolib.core.codemodel { Struct }
|
|
||||||
|
|
||||||
code_path := '${os.dir(@FILE)}/embedding.v'
|
|
||||||
|
|
||||||
code := codeparser.parse_v(code_path)!
|
|
||||||
assert code.len == 2
|
|
||||||
assert code[0] is Struct
|
|
||||||
embedder_struct := code[0] as Struct
|
|
||||||
println(embedder_struct.fields.map('${it.name}: ${it.typ.symbol}'))
|
|
||||||
@@ -7,7 +7,7 @@ import os
|
|||||||
const testpath3 = os.dir(@FILE) + '/../..'
|
const testpath3 = os.dir(@FILE) + '/../..'
|
||||||
|
|
||||||
// if we return True then it means the dir or file is processed
|
// if we return True then it means the dir or file is processed
|
||||||
fn filter_1(mut path pathlib.Path, mut params paramsparser.Params) !bool {
|
fn filter_1(mut path pathlib.Path) !bool {
|
||||||
if path.is_dir() {
|
if path.is_dir() {
|
||||||
if path.path.ends_with('.dSYM') {
|
if path.path.ends_with('.dSYM') {
|
||||||
return false
|
return false
|
||||||
|
|||||||
42
examples/data/deduped_mycelium_master.vsh
Executable file
42
examples/data/deduped_mycelium_master.vsh
Executable file
@@ -0,0 +1,42 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.data.ourdb
|
||||||
|
import time
|
||||||
|
|
||||||
|
// Known worker public key
|
||||||
|
worker1_public_key := '46a9f9cee1ce98ef7478f3dea759589bbf6da9156533e63fed9f233640ac072c'
|
||||||
|
// worker2_public_key := '46a9f9cee1ce98ef7478f3dea759589bbf6da9156533e63fed9f233640ac072c'
|
||||||
|
|
||||||
|
// Create master node
|
||||||
|
println('Starting master node...')
|
||||||
|
mut streamer := ourdb.new_streamer(
|
||||||
|
incremental_mode: false
|
||||||
|
server_port: 9000 // Master uses default port
|
||||||
|
is_worker: false
|
||||||
|
)!
|
||||||
|
|
||||||
|
println('Initializing workers...')
|
||||||
|
// Add workers and initialize its database
|
||||||
|
// You should run the deduped_mycelium_worker.vsh script for each worker
|
||||||
|
streamer.add_worker(worker1_public_key)!
|
||||||
|
// streamer.add_worker(worker2_public_key)!
|
||||||
|
|
||||||
|
// When we preforming a write, we get the ID of the record
|
||||||
|
// We basically write to the master database, and read from the workers normally
|
||||||
|
mut id1 := streamer.write(id: 1, value: 'Record 1')!
|
||||||
|
mut id2 := streamer.write(id: 2, value: 'Record 2')!
|
||||||
|
println('Master record 1 data: ${id1}')
|
||||||
|
println('Master record 2 data: ${id2}')
|
||||||
|
|
||||||
|
// Read data from master
|
||||||
|
master_id1 := streamer.read(id: 1)!
|
||||||
|
master_id2 := streamer.read(id: 2)!
|
||||||
|
println('Master 1 data: ${master_id1.bytestr()}')
|
||||||
|
println('Master 2 data: ${master_id2.bytestr()}')
|
||||||
|
|
||||||
|
// Read data from workers
|
||||||
|
worker_id1 := streamer.read(id: 1, worker_public_key: worker1_public_key)!
|
||||||
|
worker_id2 := streamer.read(id: 2, worker_public_key: worker1_public_key)!
|
||||||
|
|
||||||
|
println('Worker 1 data: ${worker_id1.bytestr()}')
|
||||||
|
println('Worker 2 data: ${worker_id2.bytestr()}')
|
||||||
17
examples/data/deduped_mycelium_worker.vsh
Executable file
17
examples/data/deduped_mycelium_worker.vsh
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.data.ourdb
|
||||||
|
|
||||||
|
worker_public_key := '46a9f9cee1ce98ef7478f3dea759589bbf6da9156533e63fed9f233640ac072c'
|
||||||
|
|
||||||
|
// Create a worker node with a unique database path
|
||||||
|
mut streamer := ourdb.new_streamer(
|
||||||
|
incremental_mode: false
|
||||||
|
server_port: 9000 // Use different port than master
|
||||||
|
is_worker: true
|
||||||
|
)!
|
||||||
|
|
||||||
|
streamer.add_worker(worker_public_key)!
|
||||||
|
|
||||||
|
// Initialize and run worker node
|
||||||
|
streamer.listen()!
|
||||||
23
examples/data/ourdb_client.vsh
Executable file
23
examples/data/ourdb_client.vsh
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
// Please note that before running this script you need to run the server first
|
||||||
|
// See examples/data/ourdb_server.vsh
|
||||||
|
import freeflowuniverse.herolib.data.ourdb
|
||||||
|
import os
|
||||||
|
|
||||||
|
mut client := ourdb.new_client(
|
||||||
|
port: 3000
|
||||||
|
host: 'localhost'
|
||||||
|
)!
|
||||||
|
|
||||||
|
set := client.set('hello')!
|
||||||
|
get := client.get(set.id)!
|
||||||
|
|
||||||
|
assert set.id == get.id
|
||||||
|
|
||||||
|
println('Set result: ${set}')
|
||||||
|
println('Get result: ${get}')
|
||||||
|
|
||||||
|
// test delete functionality
|
||||||
|
|
||||||
|
client.delete(set.id)!
|
||||||
17
examples/data/ourdb_server.vsh
Executable file
17
examples/data/ourdb_server.vsh
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.data.ourdb
|
||||||
|
import os
|
||||||
|
|
||||||
|
mut server := ourdb.new_server(
|
||||||
|
port: 3000
|
||||||
|
allowed_hosts: ['localhost']
|
||||||
|
allowed_operations: ['set', 'get', 'delete']
|
||||||
|
secret_key: 'secret'
|
||||||
|
config: ourdb.OurDBConfig{
|
||||||
|
path: '/tmp/ourdb'
|
||||||
|
incremental_mode: true
|
||||||
|
}
|
||||||
|
)!
|
||||||
|
|
||||||
|
server.run()
|
||||||
18
examples/data/ourdb_syncer/db_example.v
Normal file
18
examples/data/ourdb_syncer/db_example.v
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.data.ourdb_syncer.streamer
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
master_public_key := '570c1069736786f06c4fd2a6dc6c17cd88347604593b60e34b5688c369fa1b39'
|
||||||
|
|
||||||
|
// Create a new streamer
|
||||||
|
mut streamer_ := streamer.connect_streamer(
|
||||||
|
name: 'streamer'
|
||||||
|
port: 8080
|
||||||
|
master_public_key: master_public_key
|
||||||
|
)!
|
||||||
|
|
||||||
|
workers := streamer_.get_workers()!
|
||||||
|
|
||||||
|
println('workers: ${workers}')
|
||||||
|
}
|
||||||
20
examples/data/ourdb_syncer/master_example.v
Normal file
20
examples/data/ourdb_syncer/master_example.v
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.data.ourdb_syncer.streamer
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println('Strating the streamer first!')
|
||||||
|
|
||||||
|
// Create a new streamer
|
||||||
|
mut streamer_ := streamer.new_streamer(
|
||||||
|
name: 'streamer'
|
||||||
|
port: 8080
|
||||||
|
)!
|
||||||
|
|
||||||
|
mut master_node := streamer_.add_master(
|
||||||
|
address: '4ff:3da9:f2b2:4103:fa6e:7ea:7cbe:8fef'
|
||||||
|
public_key: '570c1069736786f06c4fd2a6dc6c17cd88347604593b60e34b5688c369fa1b39'
|
||||||
|
)!
|
||||||
|
|
||||||
|
master_node.start_and_listen()!
|
||||||
|
}
|
||||||
19
examples/data/ourdb_syncer/worker_example.v
Normal file
19
examples/data/ourdb_syncer/worker_example.v
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.data.ourdb_syncer.streamer
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Create a new streamer
|
||||||
|
mut streamer_ := streamer.connect_streamer(
|
||||||
|
name: 'streamer'
|
||||||
|
port: 8080
|
||||||
|
master_public_key: '570c1069736786f06c4fd2a6dc6c17cd88347604593b60e34b5688c369fa1b39'
|
||||||
|
)!
|
||||||
|
|
||||||
|
mut worker_node := streamer_.add_worker(
|
||||||
|
public_key: '46a9f9cee1ce98ef7478f3dea759589bbf6da9156533e63fed9f233640ac072c'
|
||||||
|
address: '4ff:3da9:f2b2:4103:fa6e:7ea:7cbe:8fef'
|
||||||
|
)!
|
||||||
|
|
||||||
|
worker_node.start_and_listen()!
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ msg << op.Message{
|
|||||||
mut msgs := op.Messages{
|
mut msgs := op.Messages{
|
||||||
messages: msg
|
messages: msg
|
||||||
}
|
}
|
||||||
res := ai_cli.chat_completion(op.ModelType.gpt_3_5_turbo, msgs)!
|
res := ai_cli.chat_completion(op.ModelType.gpt_3_5_turbo.str(), msgs)!
|
||||||
print(res)
|
print(res)
|
||||||
|
|
||||||
models := ai_cli.list_models()!
|
models := ai_cli.list_models()!
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
module example_actor
|
module example_actor
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import freeflowuniverse.herolib.hero.baobab.actor { IActor, RunParams }
|
import freeflowuniverse.herolib.hero.baobab.stage { IActor, RunParams }
|
||||||
import freeflowuniverse.herolib.web.openapi
|
import freeflowuniverse.herolib.web.openapi
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@@ -10,11 +10,11 @@ const openapi_spec_json = os.read_file(openapi_spec_path) or { panic(err) }
|
|||||||
const openapi_specification = openapi.json_decode(openapi_spec_json)!
|
const openapi_specification = openapi.json_decode(openapi_spec_json)!
|
||||||
|
|
||||||
struct ExampleActor {
|
struct ExampleActor {
|
||||||
actor.Actor
|
stage.Actor
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new() !ExampleActor {
|
fn new() !ExampleActor {
|
||||||
return ExampleActor{actor.new('example')}
|
return ExampleActor{stage.new_actor('example')}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run() ! {
|
pub fn run() ! {
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ fn (mut actor Actor) listen() ! {
|
|||||||
|
|
||||||
// Handle method invocations
|
// Handle method invocations
|
||||||
fn (mut actor Actor) handle_method(cmd string, data string) !string {
|
fn (mut actor Actor) handle_method(cmd string, data string) !string {
|
||||||
println('debugzo received rpc ${cmd}:${data}')
|
|
||||||
param_anys := json2.raw_decode(data)!.arr()
|
param_anys := json2.raw_decode(data)!.arr()
|
||||||
match cmd {
|
match cmd {
|
||||||
'listPets' {
|
'listPets' {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user