Compare commits
542 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 | |||
| b48abc474c | |||
| 672904d914 | |||
| fac783c58d | |||
| 6e7843f368 | |||
| 6a555a5fe3 | |||
| 4796e4fe82 | |||
| 3b1068a3a8 | |||
| 392f764acc | |||
| 122cba9f6b | |||
|
|
dc178f68c7 | ||
|
|
ef922d162e | ||
|
|
02e4ea180d | ||
|
|
8b9b0678b8 | ||
|
|
475e812ba3 | ||
|
|
0a953f2c09 | ||
|
|
1e26162e00 | ||
|
|
dd68bf950c | ||
|
|
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 | ||
| 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 | ||
| 29c2fccbe5 | |||
| 975c07fc2e | |||
|
|
814b61f25e | ||
|
|
1c264815c3 | ||
|
|
33150846cc | ||
| ff45beac09 | |||
| 24eb709293 | |||
| 49e2146152 | |||
| cdaf64b3cf | |||
| 49af31776e | |||
| 0880823576 | |||
| 1fa1ecb8ec | |||
| d6108c9836 | |||
|
|
2e7efdf229 | ||
|
|
f47703f599 | ||
|
|
383fc9fade | ||
|
|
cc344fa60e | ||
|
|
4691046d5f | ||
|
|
7b453962ca | ||
|
|
528d594056 | ||
|
|
6305cf159e | ||
|
|
5e468359a1 | ||
|
|
2317dd2d4c | ||
|
|
b92647c52e | ||
|
|
906f13b562 | ||
|
|
84142b60a7 | ||
|
|
54024ee222 | ||
|
|
66f29fcb02 | ||
|
|
73c3c3bdb5 | ||
|
|
fa677c01b2 | ||
| 60d6474a42 | |||
| 8c52326550 | |||
| 52aba347a8 | |||
|
|
acd1a4a61d | ||
|
|
ee1ac54dde | ||
|
|
2599fa6859 | ||
|
|
61a0fd2aa6 | ||
|
|
d604d739e3 | ||
|
|
a57f53fdb4 | ||
|
|
f276cdf697 | ||
|
|
7fb46a4c0b | ||
|
|
fc993a95d7 | ||
| c6ff7e7ba5 | |||
| 3f9a3fb1cd | |||
| 7ae4f7dbd0 | |||
| dbb44ec30a | |||
| 7f4fc42a7a | |||
| 01db4540b1 | |||
| 5c0c096a79 | |||
| c1719a057a | |||
| e969eacd06 | |||
| 8ed3439cdc | |||
|
|
5241dfddd4 | ||
|
|
6e0572b48a | ||
|
|
9a4a39b19a | ||
|
|
8abf113715 | ||
|
|
0fb8901ab5 | ||
|
|
6753b87873 | ||
|
|
715f481364 | ||
|
|
776942cd8b | ||
|
|
f0c23eb4ae | ||
| 25c997fec5 | |||
|
|
1546bf7f87 | ||
|
|
02d4adcff0 | ||
|
|
147c889b53 | ||
|
|
f6e7644284 | ||
|
|
582da6d7f0 | ||
|
|
3a337b7b0a | ||
|
|
2953dd0172 | ||
|
|
08f0620305 | ||
|
|
ec22a8e0ec | ||
|
|
6644d3b11c | ||
|
|
13471d4ca5 | ||
|
|
80254739b0 | ||
|
|
be4d2547e4 | ||
|
|
a7f8893399 | ||
|
|
d0b52f40b7 | ||
| 30cb80efcd | |||
| 3117d288b1 | |||
|
|
6ecd190de8 | ||
|
|
dacd6d5afb | ||
| 299f6dea06 | |||
| ed025f9acb | |||
|
|
de0e66a94a | ||
|
|
e86504ecd5 | ||
|
|
1b192328b2 | ||
|
|
77a77ff87e | ||
|
|
439dff4a64 | ||
|
|
f8cb6f25f7 | ||
| 5a8daa3feb | |||
|
|
c408934efd | ||
| abe81190e6 | |||
| c4ea066927 | |||
| e997946c56 | |||
| 5f9c6ff2bb | |||
|
|
dd4bb73a78 | ||
| 8965f7ae89 | |||
|
|
c157c86600 | ||
| 9a931b65e2 | |||
| 2c149507f6 | |||
|
|
34dea39c52 | ||
|
|
f1a4547961 | ||
|
|
8ae56a8df6 | ||
| cb0110ed20 | |||
| 2bbf814003 | |||
|
86e3fdb910
|
|||
| b731c4c388 | |||
| e929ce029d | |||
| 5160096a1a | |||
| f219a4041a | |||
| 674eae1c11 | |||
| f62369bd01 | |||
| 7a6660ebd8 | |||
| e20d1bdcc5 | |||
| 3e309b6379 | |||
| ae4e92e090 | |||
| 7b69719f0e | |||
| 1d631fec21 | |||
|
|
1005576814 | ||
| 690b1b68c3 | |||
| 6e619622d2 | |||
| eb38bc5e60 | |||
| b0da6d1bd2 | |||
| 1377953dcf | |||
|
|
963b31b087 | ||
|
|
2aafab50ad | ||
| aa85172700 | |||
| eff269e911 | |||
| 65ec6ee1a3 | |||
| a86b23b2e9 | |||
| bcccd5f247 | |||
| cb8c550ed1 | |||
| 5fc7019dcc | |||
| 8c9248fd94 | |||
| d1a5f1c268 | |||
| 96bc5c9e5d | |||
| 20927485d9 | |||
| a034708f21 | |||
| 19a2577564 | |||
| e34d804dda | |||
| cd6c899661 | |||
| 4b2f83ceaf | |||
| 69b0944fdd | |||
| e99f484249 | |||
| ebdd7060b0 | |||
| 6f78151f7e | |||
| 133a8c7441 | |||
| 393dc98c73 | |||
| 105d4dd054 | |||
| 4a738b966e | |||
| 4fd3095a75 | |||
| 737457dbad | |||
| fb05951c5b | |||
| 094c915a20 | |||
| c6e83252cf | |||
| 0a757e8634 | |||
| 21a7d7506a | |||
| 6bae1a98ea | |||
| 3d76bc9c04 | |||
| 4495df4d2e | |||
| 99d3e6c00c | |||
| 8a005a2fd2 | |||
| f37999c10c | |||
| 5842fb9f26 | |||
| df5aa1f1a3 | |||
| f079122be5 | |||
| a3daefa7ce | |||
| e5a3c2cae1 | |||
| 313e241a72 | |||
| a66ef2e8b3 | |||
|
4a2753d32c
|
|||
| f4f5eb06a4 | |||
| c93fe755fd | |||
| 6bdc4a5b8f | |||
| 048c72b294 | |||
| 5ad2062e5c | |||
|
babbb610d9
|
|||
| 5bbb99c3f9 | |||
| 6eec7dbda2 | |||
| be9f37a459 | |||
| 757358fded | |||
| 430586cc89 | |||
| 69b405ba65 | |||
| c2eef5a6ab | |||
|
b89a9e87c8
|
|||
| 01991027cc | |||
| 9b81061e22 | |||
|
1c0535a8b4
|
|||
|
|
2d30e6f9cf | ||
|
62f64862be
|
|||
| ee205c4b07 | |||
|
|
10c15f6f8e | ||
|
|
af2f33d4f6 | ||
|
a0c253fa05
|
|||
| 9aee672450 | |||
| 2d17938c75 | |||
| 67562cacc2 | |||
| c8d715126f | |||
| 1d6af5204b | |||
| a5398094da | |||
|
17a67870ef
|
|||
| 0fd5062408 | |||
|
54cfd4c353
|
|||
| 717eb1e7d8 | |||
|
|
c886f85d21 | ||
|
749fa94312
|
|||
|
c27fcc6983
|
|||
|
|
7bd997e368 | ||
|
|
d803a49a85 | ||
| cfa9f877b3 | |||
| e4f883d35a | |||
| 0ad1d27327 | |||
| 3bf2473c3a | |||
|
|
1db2c3ee54 | ||
|
|
7e8a4c5c45 | ||
|
|
f6fe3d4fda | ||
|
|
eeb2602bcf | ||
|
|
565eec0292 | ||
|
|
a98fad32d3 | ||
|
|
10f0c0bd31 | ||
| 84c2b43595 | |||
| 1135b8cee5 | |||
| 8322280066 | |||
| 99ecf1b0d8 | |||
| bb69ee0be9 | |||
| fb0754b3b2 | |||
| d6a13f81e0 | |||
| 6e1f23b702 | |||
| 74ab68d05f | |||
| 27cb6cb0c6 | |||
| 5670efc4cb | |||
| 5a8ad0a47b | |||
|
45098785e9
|
|||
|
|
01552145a8 | ||
|
|
09ed341b97 | ||
|
|
5cb30e6783 | ||
| 6a8bd5c205 | |||
|
|
2e5f618d0b | ||
| 112f5eecb2 | |||
| 8cf611ca51 | |||
| 0f095a691d | |||
| 8b0f692673 | |||
| 03f5885980 | |||
| 04d891a0b8 | |||
|
f8d675dcaf
|
|||
|
9f6e49963e
|
|||
| 0ae8e227fc | |||
| 623f1a289e | |||
|
|
85ac9e5104 | ||
|
|
266205363d | ||
|
|
b9ad95a99d | ||
| ca8799af39 | |||
| 1cd176a626 | |||
|
|
22918434c3 | ||
|
|
23410e6109 | ||
|
|
77809423fd | ||
|
|
ee8fbbca09 | ||
|
|
b9b21ac44b | ||
|
34b1aad175
|
|||
| d4d3713cad | |||
|
01fff39e41
|
|||
| 12968cb580 | |||
| 888aac4867 | |||
| 6637756088 | |||
|
|
70856f7348 | ||
|
|
ac19671469 | ||
| f2b9b73528 | |||
| d1c907fc3a | |||
| df0c4ca857 | |||
|
|
02128e69ba | ||
|
|
885c4d9b32 | ||
|
|
12db34ddb0 | ||
|
|
c7d7e8b954 | ||
|
|
a95ce8abb2 | ||
|
|
cab7a47050 | ||
|
|
dce0b71530 | ||
|
|
915951d84f | ||
|
|
b3509611a2 | ||
|
|
e82e367e95 | ||
|
|
6f9d570a93 | ||
|
|
7486d561ec | ||
|
|
50116651de | ||
|
|
3fe350abe9 | ||
|
|
9e51604286 | ||
|
|
309496ef5d | ||
|
|
d403f84b6c | ||
|
|
dfeeb8cd4c | ||
|
|
135866e5b0 | ||
|
|
eef88b5375 | ||
|
|
8b9717bb74 | ||
|
4422d67701
|
|||
|
|
d54a1e5a34 | ||
|
|
0d2307acc8 | ||
|
|
de45ed3a07 | ||
| 480894372c | |||
|
|
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 |
19
.github/workflows/documentation.yml
vendored
19
.github/workflows/documentation.yml
vendored
@@ -2,9 +2,9 @@ name: Deploy Documentation to Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
branches: ["development"]
|
||||
workflow_dispatch:
|
||||
branches: ["main"]
|
||||
branches: ["development"]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -17,34 +17,31 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
deploy-documentation:
|
||||
#if: startsWith(github.ref, 'refs/tags/')
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install Vlang dependencies
|
||||
run: sudo apt update && sudo apt install -y libgc-dev
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Vlang
|
||||
run: ./install_v.sh
|
||||
|
||||
- name: Generate documentation
|
||||
run: |
|
||||
./doc.vsh
|
||||
# ls /home/runner/work/herolib/docs
|
||||
./doc.vsh
|
||||
find .
|
||||
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v3
|
||||
uses: actions/configure-pages@v4
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v1
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: "/home/runner/work/herolib/herolib/docs"
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v1
|
||||
uses: actions/deploy-pages@v4
|
||||
|
||||
88
.github/workflows/hero_build.yml
vendored
Normal file
88
.github/workflows/hero_build.yml
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
name: Release Hero
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
timeout-minutes: 60
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- target: x86_64-unknown-linux-musl
|
||||
os: ubuntu-latest
|
||||
short-name: linux-i64
|
||||
- target: aarch64-unknown-linux-musl
|
||||
os: ubuntu-latest
|
||||
short-name: linux-arm64
|
||||
- target: aarch64-apple-darwin
|
||||
os: macos-latest
|
||||
short-name: macos-arm64
|
||||
- target: x86_64-apple-darwin
|
||||
os: macos-13
|
||||
short-name: macos-i64
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
|
||||
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
|
||||
- run: echo "🔎 The name of your branch is ${{ github.ref_name }} and your repository is ${{ github.repository }}."
|
||||
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup V & Herolib
|
||||
id: setup
|
||||
run: ./install_v.sh --herolib
|
||||
timeout-minutes: 10
|
||||
|
||||
|
||||
- name: Do all the basic tests
|
||||
timeout-minutes: 25
|
||||
run: ./test_basic.vsh
|
||||
|
||||
- name: Build Hero
|
||||
timeout-minutes: 15
|
||||
run: |
|
||||
set -e
|
||||
v -w -d use_openssl -enable-globals cli/hero.v -o cli/hero-${{ matrix.target }}
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: hero-${{ matrix.target }}
|
||||
path: cli/hero-${{ matrix.target }}
|
||||
|
||||
release_hero:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: cli/bins
|
||||
merge-multiple: true
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref_name }}
|
||||
name: Release ${{ github.ref_name }}
|
||||
draft: false
|
||||
fail_on_unmatched_files: true
|
||||
generate_release_notes: true
|
||||
files: cli/bins/*
|
||||
93
.github/workflows/hero_build_linux.yml
vendored
93
.github/workflows/hero_build_linux.yml
vendored
@@ -1,93 +0,0 @@
|
||||
name: Build Hero on Linux & Run tests
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- target: x86_64-unknown-linux-musl
|
||||
os: ubuntu-latest
|
||||
short-name: linux-i64
|
||||
# - target: aarch64-unknown-linux-musl
|
||||
# os: ubuntu-latest
|
||||
# short-name: linux-arm64
|
||||
# - target: aarch64-apple-darwin
|
||||
# os: macos-latest
|
||||
# short-name: macos-arm64
|
||||
# - target: x86_64-apple-darwin
|
||||
# os: macos-13
|
||||
# short-name: macos-i64
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
|
||||
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
|
||||
- run: echo "🔎 The name of your branch is ${{ github.ref_name }} and your repository is ${{ github.repository }}."
|
||||
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Vlang
|
||||
run: |
|
||||
git clone --depth=1 https://github.com/vlang/v
|
||||
cd v
|
||||
make
|
||||
sudo ./v symlink
|
||||
cd ..
|
||||
|
||||
- name: Setup Herolib
|
||||
run: |
|
||||
mkdir -p ~/.vmodules/freeflowuniverse
|
||||
ln -s $GITHUB_WORKSPACE/lib ~/.vmodules/freeflowuniverse/herolib
|
||||
|
||||
echo "Installing secp256k1..."
|
||||
# Install build dependencies
|
||||
sudo apt-get install -y build-essential wget autoconf libtool
|
||||
|
||||
# Download and extract secp256k1
|
||||
cd /tmp
|
||||
wget https://github.com/bitcoin-core/secp256k1/archive/refs/tags/v0.3.2.tar.gz
|
||||
tar -xvf v0.3.2.tar.gz
|
||||
|
||||
# Build and install
|
||||
cd secp256k1-0.3.2/
|
||||
./autogen.sh
|
||||
./configure
|
||||
make -j 5
|
||||
sudo make install
|
||||
|
||||
# Cleanup
|
||||
rm -rf secp256k1-0.3.2 v0.3.2.tar.gz
|
||||
|
||||
echo "secp256k1 installation complete!"
|
||||
|
||||
- name: Install and Start Redis
|
||||
run: |
|
||||
# Import Redis GPG key
|
||||
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
|
||||
# Add Redis repository
|
||||
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
|
||||
# Install Redis
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y redis
|
||||
|
||||
# Start Redis
|
||||
redis-server --daemonize yes
|
||||
|
||||
# Print versions
|
||||
redis-cli --version
|
||||
redis-server --version
|
||||
|
||||
- name: Build Hero
|
||||
run: |
|
||||
v -cg -enable-globals -w -n cli/hero.v
|
||||
|
||||
- name: Do all the basic tests
|
||||
run: |
|
||||
./test_basic.vsh
|
||||
66
.github/workflows/hero_build_macos.yml
vendored
66
.github/workflows/hero_build_macos.yml
vendored
@@ -1,66 +0,0 @@
|
||||
name: Build Hero on Macos & Run tests
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- target: aarch64-apple-darwin
|
||||
os: macos-latest
|
||||
short-name: macos-arm64
|
||||
- target: x86_64-apple-darwin
|
||||
os: macos-13
|
||||
short-name: macos-i64
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
|
||||
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
|
||||
- run: echo "🔎 The name of your branch is ${{ github.ref_name }} and your repository is ${{ github.repository }}."
|
||||
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Vlang
|
||||
run: |
|
||||
git clone --depth=1 https://github.com/vlang/v
|
||||
cd v
|
||||
make
|
||||
sudo ./v symlink
|
||||
cd ..
|
||||
|
||||
- name: Setup Herolib
|
||||
run: |
|
||||
mkdir -p ~/.vmodules/freeflowuniverse
|
||||
ln -s $GITHUB_WORKSPACE/lib ~/.vmodules/freeflowuniverse/herolib
|
||||
|
||||
echo "Installing secp256k1..."
|
||||
brew install secp256k1
|
||||
|
||||
echo "secp256k1 installation complete!"
|
||||
|
||||
- name: Install and Start Redis
|
||||
run: |
|
||||
brew update
|
||||
brew install redis
|
||||
|
||||
# Start Redis
|
||||
redis-server --daemonize yes
|
||||
|
||||
# Print versions
|
||||
redis-cli --version
|
||||
redis-server --version
|
||||
|
||||
- name: Build Hero
|
||||
run: |
|
||||
v -w -cg -gc none -no-retry-compilation -d use_openssl -enable-globals cli/hero.v
|
||||
|
||||
- name: Do all the basic tests
|
||||
run: |
|
||||
./test_basic.vsh
|
||||
132
.github/workflows/release.yml
vendored
132
.github/workflows/release.yml
vendored
@@ -1,132 +0,0 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
|
||||
jobs:
|
||||
upload:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- target: aarch64-apple-darwin
|
||||
os: macos-latest
|
||||
short-name: macos-arm64
|
||||
- target: x86_64-apple-darwin
|
||||
os: macos-13
|
||||
short-name: macos-i64
|
||||
- target: x86_64-unknown-linux-musl
|
||||
os: ubuntu-latest
|
||||
short-name: linux-i64
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Vlang
|
||||
run: |
|
||||
git clone --depth=1 https://github.com/vlang/v
|
||||
cd v
|
||||
make
|
||||
sudo ./v symlink
|
||||
cd ..
|
||||
|
||||
- name: Setup Herolib
|
||||
run: |
|
||||
mkdir -p ~/.vmodules/freeflowuniverse
|
||||
ln -s $GITHUB_WORKSPACE/lib ~/.vmodules/freeflowuniverse/herolib
|
||||
|
||||
echo "Installing secp256k1..."
|
||||
if [[ ${{ matrix.os }} == 'macos-latest' || ${{ matrix.os }} == 'macos-13' ]]; then
|
||||
brew install secp256k1
|
||||
|
||||
elif [[ ${{ matrix.os }} == 'ubuntu-latest' ]]; then
|
||||
# Install build dependencies
|
||||
sudo apt-get install -y build-essential wget autoconf libtool
|
||||
|
||||
# Download and extract secp256k1
|
||||
cd /tmp
|
||||
wget https://github.com/bitcoin-core/secp256k1/archive/refs/tags/v0.3.2.tar.gz
|
||||
tar -xvf v0.3.2.tar.gz
|
||||
|
||||
# Build and install
|
||||
cd secp256k1-0.3.2/
|
||||
./autogen.sh
|
||||
./configure
|
||||
make -j 5
|
||||
sudo make install
|
||||
|
||||
else
|
||||
echo "Unsupported OS: ${{ matrix.os }}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "secp256k1 installation complete!"
|
||||
|
||||
- name: Build Hero
|
||||
run: |
|
||||
v -w -cg -gc none -no-retry-compilation -d use_openssl -enable-globals cli/hero.v -o cli/hero-${{ matrix.target }}
|
||||
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: hero-${{ matrix.target }}
|
||||
path: cli/hero-${{ matrix.target }}
|
||||
|
||||
release_hero:
|
||||
needs: upload
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# TODO: this adds commits that don't belong to this branhc, check another action
|
||||
# - name: Generate changelog
|
||||
# id: changelog
|
||||
# uses: heinrichreimer/github-changelog-generator-action@v2.3
|
||||
# with:
|
||||
# token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# headerLabel: "# 📑 Changelog"
|
||||
# breakingLabel: "### 💥 Breaking"
|
||||
# enhancementLabel: "### 🚀 Enhancements"
|
||||
# bugsLabel: "### 🐛 Bug fixes"
|
||||
# securityLabel: "### 🛡️ Security"
|
||||
# issuesLabel: "### 📁 Other issues"
|
||||
# prLabel: "### 📁 Other pull requests"
|
||||
# addSections: '{"documentation":{"prefix":"### 📖 Documentation","labels":["documentation"]},"tests":{"prefix":"### ✅ Testing","labels":["tests"]}}'
|
||||
# onlyLastTag: true
|
||||
# issues: false
|
||||
# issuesWoLabels: false
|
||||
# pullRequests: true
|
||||
# prWoLabels: true
|
||||
# author: true
|
||||
# unreleased: true
|
||||
# compareLink: true
|
||||
# stripGeneratorNotice: true
|
||||
# verbose: true
|
||||
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: cli/bins
|
||||
merge-multiple: true
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
name: Release ${{ github.ref_name }}
|
||||
draft: false
|
||||
fail_on_unmatched_files: true
|
||||
# body: ${{ steps.changelog.outputs.changelog }}
|
||||
files: cli/bins/*
|
||||
32
.github/workflows/test.yml
vendored
Normal file
32
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: Build on Linux & Run tests
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- target: x86_64-unknown-linux-musl
|
||||
os: ubuntu-latest
|
||||
short-name: linux-i64
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
|
||||
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
|
||||
- run: echo "🔎 The name of your branch is ${{ github.ref_name }} and your repository is ${{ github.repository }}."
|
||||
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup V & Herolib
|
||||
run: ./install_v.sh --herolib
|
||||
|
||||
- name: Do all the basic tests
|
||||
run: ./test_basic.vsh
|
||||
|
||||
21
.gitignore
vendored
21
.gitignore
vendored
@@ -1,4 +1,13 @@
|
||||
|
||||
# Additional ignore files and directories
|
||||
Thumbs.db
|
||||
# Logs
|
||||
logs/
|
||||
*.log
|
||||
*.out
|
||||
# Compiled Python files
|
||||
*.pyc
|
||||
*.pyo
|
||||
__pycache__/
|
||||
*dSYM/
|
||||
.vmodules/
|
||||
.vscode
|
||||
@@ -7,6 +16,7 @@ vls.*
|
||||
vls.log
|
||||
node_modules/
|
||||
docs/
|
||||
vdocs/
|
||||
photonwrapper.so
|
||||
x
|
||||
.env
|
||||
@@ -25,7 +35,12 @@ dump.rdb
|
||||
output/
|
||||
*.db
|
||||
.stellar
|
||||
vdocs/
|
||||
data.ms/
|
||||
test_basic
|
||||
cli/hero
|
||||
cli/hero
|
||||
.aider*
|
||||
.compile_cache
|
||||
compile_results.log
|
||||
tmp
|
||||
compile_summary.log
|
||||
.summary_lock
|
||||
|
||||
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)
|
||||
147
README.md
147
README.md
@@ -1,23 +1,60 @@
|
||||
# herolib
|
||||
# Herolib
|
||||
|
||||
a smaller version of herolib with only the items we need for hero
|
||||
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 here](https://freeflowuniverse.github.io/herolib/)
|
||||
[](https://github.com/freeflowuniverse/herolib/actions/workflows/test.yml)
|
||||
[](https://github.com/freeflowuniverse/herolib/actions/workflows/documentation.yml)
|
||||
|
||||
## automated install
|
||||
> [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
|
||||
curl 'https://raw.githubusercontent.com/freeflowuniverse/herolib/refs/heads/main/install_v.sh' > /tmp/install_v.sh
|
||||
bash /tmp/install_v.sh --analyzer --herolib
|
||||
#DONT FORGET TO START A NEW SHELL (otherwise the paths will not be set)
|
||||
curl https://raw.githubusercontent.com/freeflowuniverse/herolib/refs/heads/development/install_hero.sh > /tmp/install_hero.sh
|
||||
bash /tmp/install_hero.sh
|
||||
```
|
||||
|
||||
### details
|
||||
Hero will be installed in:
|
||||
- `/usr/local/bin` for Linux
|
||||
- `~/hero/bin` for macOS
|
||||
|
||||
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
|
||||
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
|
||||
```
|
||||
|
||||
#~/code/github/freeflowuniverse/herolib/install_v.sh --help
|
||||
#### Installation Options
|
||||
|
||||
```
|
||||
V & HeroLib Installer Script
|
||||
|
||||
Usage: ~/code/github/freeflowuniverse/herolib/install_v.sh [options]
|
||||
@@ -36,29 +73,97 @@ Examples:
|
||||
~/code/github/freeflowuniverse/herolib/install_v.sh --analyzer
|
||||
~/code/github/freeflowuniverse/herolib/install_v.sh --herolib
|
||||
~/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
|
||||
# Run all basic tests
|
||||
~/code/github/freeflowuniverse/herolib/test_basic.vsh
|
||||
```
|
||||
|
||||
```bash
|
||||
# Run tests for a specific module
|
||||
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
|
||||
~/code/github/freeflowuniverse/herolib/test_basic.vsh
|
||||
# Run tests for an entire directory
|
||||
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
|
||||
|
||||
```vlang
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.osal
|
||||
|
||||
osal.ping...
|
||||
|
||||
@@ -70,14 +70,14 @@ mut pm:=process.processmap_get()?
|
||||
info returns like:
|
||||
|
||||
```json
|
||||
}, freeflowuniverse.herolib.process.ProcessInfo{
|
||||
}, freeflowuniverse.process.ProcessInfo{
|
||||
cpu_perc: 0
|
||||
mem_perc: 0
|
||||
cmd: 'mc'
|
||||
pid: 84455
|
||||
ppid: 84467
|
||||
rss: 3168
|
||||
}, freeflowuniverse.herolib.process.ProcessInfo{
|
||||
}, freeflowuniverse.process.ProcessInfo{
|
||||
cpu_perc: 0
|
||||
mem_perc: 0
|
||||
cmd: 'zsh -Z -g'
|
||||
@@ -195,13 +195,13 @@ fn initname() !string
|
||||
e.g. systemd, bash, zinit
|
||||
fn ipaddr_pub_get() !string
|
||||
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_intel() bool
|
||||
fn is_osx() bool
|
||||
fn is_osx_arm() bool
|
||||
fn is_osx_intel() bool
|
||||
fn is_ubuntu() bool
|
||||
fn is_linux_intel()! bool
|
||||
fn is_osx()! bool
|
||||
fn is_osx_arm()! bool
|
||||
fn is_osx_intel()! bool
|
||||
fn is_ubuntu()! bool
|
||||
fn load_env_file(file_path string) !
|
||||
fn memdb_exists(key string) bool
|
||||
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
|
||||
|
||||
93
aiprompts/ai_instruct/instruct.md
Normal file
93
aiprompts/ai_instruct/instruct.md
Normal file
@@ -0,0 +1,93 @@
|
||||
We have our own instruction language called heroscript, below you will find details how to use it.
|
||||
|
||||
## heroscript
|
||||
|
||||
|
||||
Heroscript is our small scripting language which is used for communicating with our digital tools like calendar management.
|
||||
|
||||
which has following structure
|
||||
|
||||
```heroscript
|
||||
|
||||
!!calendar.event_add
|
||||
title: 'go to dentist'
|
||||
start: '2025/03/01'
|
||||
description: '
|
||||
a description can be multiline
|
||||
|
||||
like this
|
||||
'
|
||||
|
||||
!!calendar.event_delete
|
||||
title: 'go to dentist'
|
||||
|
||||
```
|
||||
|
||||
- the format is !!$actor.$action (there is no space before !!)
|
||||
- every parameter comes on next line with spaces in front (4 spaces, always use 4 spaces, dont make variation)
|
||||
- every actor.action starts with !!
|
||||
- the first part is the actor e.g. calendar in this case
|
||||
- the 2e part is the action name
|
||||
- multilines are supported see the description field
|
||||
|
||||
below you will find the instructions for different actors, comments how to use it are behind # which means not part of the the definition itself
|
||||
|
||||
## remarks on parameters used
|
||||
|
||||
- date
|
||||
- format of the date is yyyy/mm/dd hh:mm:ss
|
||||
- +1h means 1 hour later than now
|
||||
- +1m means 1 min later than now
|
||||
- +1d means 1 day later than now
|
||||
- same for -1h, -1m, -1d
|
||||
- money expressed as
|
||||
- $val $cursymbol
|
||||
- $cursymbol is 3 letters e.g. USD, capital
|
||||
- lists are comma separated and '...' around
|
||||
|
||||
|
||||
## generic instructions
|
||||
|
||||
- do not add information if not specifically asked for
|
||||
|
||||
|
||||
## circle
|
||||
|
||||
every actor action happens in a circle, a user can ask to switch circles, command available is
|
||||
|
||||
```
|
||||
!!circle.switch
|
||||
name: 'project x'
|
||||
|
||||
```
|
||||
|
||||
## calendar
|
||||
|
||||
```heroscript
|
||||
|
||||
!!calendar.event_add
|
||||
title: 'go to dentist'
|
||||
start: '2025/03/01'
|
||||
end: '+1h' #if + notation used is later than the start
|
||||
description: '
|
||||
a description can be multiline
|
||||
|
||||
like this
|
||||
'
|
||||
attendees: 'tim, rob'
|
||||
|
||||
!!calendar.event_delete
|
||||
title: 'go to dentist'
|
||||
|
||||
```
|
||||
|
||||
## NOW DO ONE
|
||||
|
||||
schedule event tomorrow 10 am, for 1h, with tim & rob, we want to product management threefold
|
||||
now is friday jan 17
|
||||
|
||||
only give me the instructions needed, only return the heroscript no text around
|
||||
|
||||
if not clear enough ask the user for more info
|
||||
|
||||
if not sure do not invent, only give instructions as really asked for
|
||||
58
aiprompts/ai_instruct/instruct2.md
Normal file
58
aiprompts/ai_instruct/instruct2.md
Normal file
@@ -0,0 +1,58 @@
|
||||
|
||||
|
||||
# how to manage my agenda
|
||||
|
||||
## Metadata for function calling
|
||||
|
||||
functions_metadata = [
|
||||
{
|
||||
"name": "event_add",
|
||||
"description": "Adds a calendar event.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"title": {"type": "string", "description": "Title of the event."},
|
||||
"start": {"type": "string", "description": "Start date and time in 'YYYY/MM/DD hh:mm' format."},
|
||||
"end": {"type": "string", "description": "End date or duration (e.g., +2h)."},
|
||||
"description": {"type": "string", "description": "Event description."},
|
||||
"attendees": {"type": "string", "description": "Comma-separated list of attendees' emails."},
|
||||
},
|
||||
"required": ["title", "start"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "event_delete",
|
||||
"description": "Deletes a calendar event by title.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"title": {"type": "string", "description": "Title of the event to delete."},
|
||||
},
|
||||
"required": ["title"]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
## example call
|
||||
|
||||
{
|
||||
"function": "event_add",
|
||||
"parameters": {
|
||||
"title": "Team Sync",
|
||||
"start": "2025/02/01 10:00",
|
||||
"end": "+1h",
|
||||
"description": "",
|
||||
"attendees": "alice@example.com, bob@example.com"
|
||||
}
|
||||
}
|
||||
|
||||
## how to use
|
||||
|
||||
Parse the user query to determine intent (e.g., "schedule" maps to event_add, "cancel" maps to event_delete).
|
||||
|
||||
Extract required parameters (e.g., title, start date).
|
||||
|
||||
Invoke the appropriate function with the extracted parameters.
|
||||
|
||||
Return the function's result as the response.
|
||||
|
||||
72
aiprompts/ai_instruct/twin.md
Normal file
72
aiprompts/ai_instruct/twin.md
Normal file
@@ -0,0 +1,72 @@
|
||||
you represent a digital twin for a user, the user talks to you to get things done for his digital life
|
||||
|
||||
you will interprete the instructions the user prompts, and figure out the multiple instructions, break it up and categorize them as follows:
|
||||
|
||||
- cat: calendar
|
||||
- manage calendar for the user
|
||||
- cat: contacts
|
||||
- manage contacts for the user
|
||||
- cat: communicate
|
||||
- communicate with others using text
|
||||
- cat: tasks
|
||||
- manage my tasks
|
||||
- cat: circle
|
||||
- define circle we work in, a circle is like a project context in which we do above, so can be for a team or a project, try to find it
|
||||
- cat: sysadmin
|
||||
- system administration, e.g. creation of virtual machines (VM), containers, start stop see monitoring information
|
||||
- cat: notes
|
||||
- anything to do with transctiptions, note takings, summaries
|
||||
- how we recorded meetings e.g. zoom, google meet, ...
|
||||
- how we are looking for info in meeting
|
||||
- cat: unknown
|
||||
- anything we can't understand
|
||||
|
||||
try to understand what user wants and put it in blocks (one per category for the action e.g. calendar)
|
||||
|
||||
- before each block (instruction) put ###########################
|
||||
- in the first line mention the category as defined above, only mention this category once and there is only one per block
|
||||
- then reformulate in clear instructions what needs to be done after that
|
||||
- the instructions are put in lines following the instruction (not in the instruction line)
|
||||
- only make blocks for instructions as given
|
||||
|
||||
what you output will be used further to do more specific prompting
|
||||
|
||||
if circle, always put these instructions first
|
||||
|
||||
if time is specified put the time as follows
|
||||
|
||||
- if relative e.g. next week, tomorrow, after tomorrow, in one hour then start from the current time
|
||||
- time is in format: YYYY/MM/DD hh:mm format
|
||||
- current time is friday 2025/01/17 10:12
|
||||
- if e.g. next month jan, or next tuesday then don't repeat the browd instructions like tuesday, this just show the date as YYYY/MM/DD hh:mm
|
||||
|
||||
if not clear for a date, don't invent just repeat the original instruction
|
||||
|
||||
if the category is not clear, just use unknown
|
||||
|
||||
|
||||
NOW DO EXAMPLE 1
|
||||
|
||||
```
|
||||
hi good morning
|
||||
|
||||
Can you help me find meetings I have done around research of threefold in the last 2 weeks
|
||||
|
||||
I need to create a new VM, 4 GB of memory, 2 vcpu, in belgium, with ubuntu
|
||||
|
||||
I would like do schedule a meeting, need to go to the dentist tomorrow at 10am, its now friday jan 17
|
||||
|
||||
also remind me I need to do the dishes after tomorrow in the morning
|
||||
|
||||
can you also add jef as a contact, he lives in geneva, he is doing something about rocketscience
|
||||
|
||||
I need to paint my wall in my room next week wednesday
|
||||
|
||||
cancel all my meetings next sunday
|
||||
|
||||
can you give me list of my contacts who live in geneva and name sounds like tom
|
||||
|
||||
send a message to my mother, I am seeing here in 3 days at 7pm
|
||||
|
||||
```
|
||||
|
||||
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')
|
||||
```
|
||||
187
aiprompts/reflection.md
Normal file
187
aiprompts/reflection.md
Normal file
@@ -0,0 +1,187 @@
|
||||
## Compile time reflection
|
||||
|
||||
$ is used as a prefix for compile time (also referred to as 'comptime') operations.
|
||||
|
||||
Having built-in JSON support is nice, but V also allows you to create efficient serializers for any data format. V has compile time if and for constructs:
|
||||
|
||||
.fields
|
||||
You can iterate over struct fields using .fields, it also works with generic types (e.g. T.fields) and generic arguments (e.g. param.fields where fn gen[T](param T) {).
|
||||
|
||||
struct User {
|
||||
name string
|
||||
age int
|
||||
}
|
||||
|
||||
fn main() {
|
||||
$for field in User.fields {
|
||||
$if field.typ is string {
|
||||
println('${field.name} is of type string')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Output:
|
||||
// name is of type string
|
||||
.values
|
||||
You can read Enum values and their attributes.
|
||||
|
||||
enum Color {
|
||||
red @[RED] // first attribute
|
||||
blue @[BLUE] // second attribute
|
||||
}
|
||||
|
||||
fn main() {
|
||||
$for e in Color.values {
|
||||
println(e.name)
|
||||
println(e.attrs)
|
||||
}
|
||||
}
|
||||
|
||||
// Output:
|
||||
// red
|
||||
// ['RED']
|
||||
// blue
|
||||
// ['BLUE']
|
||||
.attributes
|
||||
You can read Struct attributes.
|
||||
|
||||
@[COLOR]
|
||||
struct Foo {
|
||||
a int
|
||||
}
|
||||
|
||||
fn main() {
|
||||
$for e in Foo.attributes {
|
||||
println(e)
|
||||
}
|
||||
}
|
||||
|
||||
// Output:
|
||||
// StructAttribute{
|
||||
// name: 'COLOR'
|
||||
// has_arg: false
|
||||
// arg: ''
|
||||
// kind: plain
|
||||
// }
|
||||
.variants
|
||||
You can read variant types from Sum type.
|
||||
|
||||
type MySum = int | string
|
||||
|
||||
fn main() {
|
||||
$for v in MySum.variants {
|
||||
$if v.typ is int {
|
||||
println('has int type')
|
||||
} $else $if v.typ is string {
|
||||
println('has string type')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Output:
|
||||
// has int type
|
||||
// has string type
|
||||
.methods
|
||||
You can retrieve information about struct methods.
|
||||
|
||||
struct Foo {
|
||||
}
|
||||
|
||||
fn (f Foo) test() int {
|
||||
return 123
|
||||
}
|
||||
|
||||
fn (f Foo) test2() string {
|
||||
return 'foo'
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo := Foo{}
|
||||
$for m in Foo.methods {
|
||||
$if m.return_type is int {
|
||||
print('${m.name} returns int: ')
|
||||
println(foo.$method())
|
||||
} $else $if m.return_type is string {
|
||||
print('${m.name} returns string: ')
|
||||
println(foo.$method())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Output:
|
||||
// test returns int: 123
|
||||
// test2 returns string: foo
|
||||
.params
|
||||
You can retrieve information about struct method params.
|
||||
|
||||
struct Test {
|
||||
}
|
||||
|
||||
fn (t Test) foo(arg1 int, arg2 string) {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
$for m in Test.methods {
|
||||
$for param in m.params {
|
||||
println('${typeof(param.typ).name}: ${param.name}')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Output:
|
||||
// int: arg1
|
||||
// string: arg2
|
||||
|
||||
## Example
|
||||
|
||||
```v
|
||||
// An example deserializer implementation
|
||||
|
||||
struct User {
|
||||
name string
|
||||
age int
|
||||
}
|
||||
|
||||
fn main() {
|
||||
data := 'name=Alice\nage=18'
|
||||
user := decode[User](data)
|
||||
println(user)
|
||||
}
|
||||
|
||||
fn decode[T](data string) T {
|
||||
mut result := T{}
|
||||
// compile-time `for` loop
|
||||
// T.fields gives an array of a field metadata type
|
||||
$for field in T.fields {
|
||||
$if field.typ is string {
|
||||
// $(string_expr) produces an identifier
|
||||
result.$(field.name) = get_string(data, field.name)
|
||||
} $else $if field.typ is int {
|
||||
result.$(field.name) = get_int(data, field.name)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fn get_string(data string, field_name string) string {
|
||||
for line in data.split_into_lines() {
|
||||
key_val := line.split('=')
|
||||
if key_val[0] == field_name {
|
||||
return key_val[1]
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
fn get_int(data string, field string) int {
|
||||
return get_string(data, field).int()
|
||||
}
|
||||
|
||||
// `decode<User>` generates:
|
||||
// fn decode_User(data string) User {
|
||||
// mut result := User{}
|
||||
// result.name = get_string(data, 'name')
|
||||
// result.age = get_int(data, 'age')
|
||||
// return result
|
||||
// }
|
||||
```
|
||||
@@ -11,7 +11,7 @@
|
||||
when I generate vlang scripts I will always use .vsh extension and use following as first line:
|
||||
|
||||
```
|
||||
#!/usr/bin/env -S v -n -w -gc none -no-retry-compilation -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
|
||||
```
|
||||
|
||||
- a .vsh is a v shell script and can be executed as is, no need to use v ...
|
||||
@@ -21,7 +21,7 @@ when I generate vlang scripts I will always use .vsh extension and use following
|
||||
## to do argument parsing use following examples
|
||||
|
||||
```v
|
||||
#!/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 -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import os
|
||||
import flag
|
||||
|
||||
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
|
||||
|
||||
@@ -2238,7 +2238,7 @@ be faster, since there is no need for a re-compilation of a script, that has not
|
||||
An example `deploy.vsh`:
|
||||
|
||||
```v oksyntax
|
||||
#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||
#!/usr/bin/env -S v -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
// Note: The shebang line above, associates the .vsh file to V on Unix-like systems,
|
||||
// so it can be run just by specifying the path to the .vsh file, once it's made
|
||||
@@ -2300,11 +2300,11 @@ Whilst V does normally not allow vsh scripts without the designated file extensi
|
||||
to circumvent this rule and have a file with a fully custom name and shebang. Whilst this feature
|
||||
exists it is only recommended for specific usecases like scripts that will be put in the path and
|
||||
should **not** be used for things like build or deploy scripts. To access this feature start the
|
||||
file with `#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||
file with `#!/usr/bin/env -S v -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
the built executable. This will run in crun mode so it will only rebuild if changes to the script
|
||||
were made and keep the binary as `tmp.<scriptfilename>`. **Caution**: if this filename already
|
||||
exists the file will be overridden. If you want to rebuild each time and not keep this binary
|
||||
instead use `#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||
instead use `#!/usr/bin/env -S v -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
# Appendices
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
this is how we want example scripts to be, see the first line
|
||||
|
||||
```vlang
|
||||
#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||
#!/usr/bin/env -S v -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.sysadmintools.daguserver
|
||||
|
||||
|
||||
3
cli/.gitignore
vendored
3
cli/.gitignore
vendored
@@ -1 +1,4 @@
|
||||
hero
|
||||
compile
|
||||
compile_upload
|
||||
vdo
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env -S v -parallel-cc -enable-globals run
|
||||
// #!/usr/bin/env -S v -n -w -gc none -no-retry-compilation -cc tcc -d use_openssl -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
|
||||
|
||||
import os
|
||||
import flag
|
||||
@@ -45,7 +45,7 @@ compile_cmd := if os.user_os() == 'macos' {
|
||||
if prod_mode {
|
||||
'v -enable-globals -w -n -prod hero.v'
|
||||
} else {
|
||||
'v -w -cg -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals hero.v'
|
||||
'v -w -cg -gc none -cc tcc -d use_openssl -enable-globals hero.v'
|
||||
}
|
||||
} else {
|
||||
if prod_mode {
|
||||
@@ -66,7 +66,7 @@ os.chmod('hero', 0o755) or { panic('Failed to make hero binary executable: ${err
|
||||
|
||||
// Ensure destination directory exists
|
||||
os.mkdir_all(os.dir(heropath)) or { panic('Failed to create directory ${os.dir(heropath)}: ${err}') }
|
||||
|
||||
println(heropath)
|
||||
// Copy to destination paths
|
||||
os.cp('hero', heropath) or { panic('Failed to copy hero binary to ${heropath}: ${err}') }
|
||||
os.cp('hero', '/tmp/hero') or { panic('Failed to copy hero binary to /tmp/hero: ${err}') }
|
||||
|
||||
@@ -89,5 +89,9 @@ fn hero_upload() ! {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
//os.execute_or_panic('${os.home_dir()}/code/github/freeflowuniverse/herolib/cli/compile.vsh -p')
|
||||
println("compile hero can take 60 sec+ on osx.")
|
||||
os.execute_or_panic('${os.home_dir()}/code/github/freeflowuniverse/herolib/cli/compile.vsh -p')
|
||||
println( "upload:")
|
||||
hero_upload() or { eprintln(err) exit(1) }
|
||||
}
|
||||
|
||||
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**')
|
||||
26
cli/hero.v
26
cli/hero.v
@@ -19,6 +19,26 @@ fn playcmds_do(path string) ! {
|
||||
}
|
||||
|
||||
fn do() ! {
|
||||
|
||||
if ! core.is_osx()! {
|
||||
if os.getenv('SUDO_COMMAND') != '' || os.getenv('SUDO_USER') != '' {
|
||||
println('Error: Please do not run this program with sudo!')
|
||||
exit(1) // Exit with error code
|
||||
}
|
||||
}
|
||||
|
||||
if os.getuid() == 0 {
|
||||
if core.is_osx()! {
|
||||
eprintln("please do not run hero as root in osx.")
|
||||
exit(1)
|
||||
}
|
||||
} else {
|
||||
if ! core.is_osx()! {
|
||||
eprintln("please do run hero as root, don't use sudo.")
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
if os.args.len == 2 {
|
||||
mypath := os.args[1]
|
||||
if mypath.to_lower().ends_with('.hero') {
|
||||
@@ -31,7 +51,7 @@ fn do() ! {
|
||||
mut cmd := Command{
|
||||
name: 'hero'
|
||||
description: 'Your HERO toolset.'
|
||||
version: '2.0.0'
|
||||
version: '1.0.22'
|
||||
}
|
||||
|
||||
// herocmds.cmd_run_add_flags(mut cmd)
|
||||
@@ -81,6 +101,8 @@ fn do() ! {
|
||||
// herocmds.cmd_zola(mut cmd)
|
||||
// herocmds.cmd_juggler(mut cmd)
|
||||
herocmds.cmd_generator(mut cmd)
|
||||
herocmds.cmd_docusaurus(mut cmd)
|
||||
herocmds.cmd_starlight(mut cmd)
|
||||
// herocmds.cmd_docsorter(mut cmd)
|
||||
// cmd.add_command(publishing.cmd_publisher(pre_func))
|
||||
cmd.setup()
|
||||
@@ -93,4 +115,4 @@ fn main() {
|
||||
|
||||
fn pre_func(cmd Command) ! {
|
||||
herocmds.plbook_run(cmd)!
|
||||
}
|
||||
}
|
||||
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
|
||||
40
doc.vsh
40
doc.vsh
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -no-retry-compilation -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
|
||||
|
||||
@@ -26,9 +26,9 @@ os.chdir(herolib_path) or {
|
||||
panic('Failed to change directory to herolib: ${err}')
|
||||
}
|
||||
|
||||
os.rmdir_all('_docs') or {}
|
||||
os.rmdir_all('docs') or {}
|
||||
os.rmdir_all('vdocs') or {}
|
||||
os.mkdir_all('_docs') or {}
|
||||
os.mkdir_all('docs') or {}
|
||||
os.mkdir_all('vdocs') or {}
|
||||
|
||||
// Generate HTML documentation
|
||||
println('Generating HTML documentation...')
|
||||
@@ -42,13 +42,12 @@ os.chdir(abs_dir_of_script) or {
|
||||
|
||||
// Generate Markdown documentation
|
||||
println('Generating Markdown documentation...')
|
||||
os.rmdir_all('vdocs') or {}
|
||||
|
||||
// if os.system('v doc -m -no-color -f md -o ../vdocs/v/') != 0 {
|
||||
// panic('Failed to generate V markdown documentation')
|
||||
// }
|
||||
|
||||
if os.system('v doc -m -no-color -f md -o vdocs/herolib/') != 0 {
|
||||
if os.system('v doc -m -no-color -f md -o vdocs/') != 0 {
|
||||
panic('Failed to generate Hero markdown documentation')
|
||||
}
|
||||
|
||||
@@ -62,4 +61,33 @@ $if !linux {
|
||||
}
|
||||
}
|
||||
|
||||
// Create Jekyll required files
|
||||
println('Creating Jekyll files...')
|
||||
os.mkdir_all('docs/assets/css') or {}
|
||||
|
||||
// Create style.scss
|
||||
style_content := '---\n---\n\n@import "{{ site.theme }}";'
|
||||
os.write_file('docs/assets/css/style.scss', style_content) or {
|
||||
panic('Failed to create style.scss: ${err}')
|
||||
}
|
||||
|
||||
// Create _config.yml
|
||||
config_content := 'title: HeroLib Documentation
|
||||
description: Documentation for the HeroLib project
|
||||
theme: jekyll-theme-primer
|
||||
baseurl: /herolib
|
||||
|
||||
exclude:
|
||||
- Gemfile
|
||||
- Gemfile.lock
|
||||
- node_modules
|
||||
- vendor/bundle/
|
||||
- vendor/cache/
|
||||
- vendor/gems/
|
||||
- vendor/ruby/'
|
||||
|
||||
os.write_file('docs/_config.yml', config_content) or {
|
||||
panic('Failed to create _config.yml: ${err}')
|
||||
}
|
||||
|
||||
println('Documentation generation completed successfully!')
|
||||
|
||||
3
docker/docusaurus/.gitignore
vendored
3
docker/docusaurus/.gitignore
vendored
@@ -1,3 +0,0 @@
|
||||
.bash_history
|
||||
.openvscode-server/
|
||||
.cache/
|
||||
@@ -1,48 +0,0 @@
|
||||
# Use Ubuntu 24.04 as the base image
|
||||
FROM ubuntu:24.04
|
||||
|
||||
# Set the working directory
|
||||
WORKDIR /root
|
||||
|
||||
# Copy local installation scripts into the container
|
||||
COPY scripts/install_v.sh /tmp/install_v.sh
|
||||
COPY scripts/install_herolib.vsh /tmp/install_herolib.vsh
|
||||
COPY scripts/install_vscode.sh /tmp/install_vscode.sh
|
||||
COPY scripts/ourinit.sh /usr/local/bin/
|
||||
|
||||
# Make the scripts executable
|
||||
RUN chmod +x /tmp/install_v.sh /tmp/install_herolib.vsh
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
curl bash sudo mc wget tmux htop openssh-server
|
||||
|
||||
RUN bash /tmp/install_v.sh
|
||||
|
||||
RUN yes y | bash /tmp/install_v.sh --analyzer
|
||||
|
||||
RUN bash /tmp/install_vscode.sh
|
||||
|
||||
RUN /tmp/install_herolib.vsh && \
|
||||
mkdir -p /var/run/sshd && \
|
||||
echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config && \
|
||||
echo 'PasswordAuthentication no' >> /etc/ssh/sshd_config && \
|
||||
chown -R root:root /root/.ssh && \
|
||||
chmod -R 700 /root/.ssh/ && \
|
||||
chmod 600 /root/.ssh/authorized_keys && \
|
||||
service ssh start && \
|
||||
apt-get clean && \
|
||||
echo "PS1='HERO: \w \$ '" >> ~/.bashrc \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
#SSH
|
||||
RUN mkdir -p /var/run/sshd && \
|
||||
echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config && \
|
||||
echo 'PasswordAuthentication no' >> /etc/ssh/sshd_config && \
|
||||
chown -R root:root /root/.ssh && \
|
||||
chmod -R 700 /root/.ssh/ && \
|
||||
chmod 600 /root/.ssh/authorized_keys && \
|
||||
service ssh start
|
||||
|
||||
ENTRYPOINT ["/bin/bash"]
|
||||
CMD ["/bin/bash"]
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
# Get the directory where the script is located
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
# Docker image and container names
|
||||
DOCKER_IMAGE_NAME="docusaurus"
|
||||
DEBUG_CONTAINER_NAME="herolib"
|
||||
|
||||
function cleanup {
|
||||
if docker ps -aq -f name="$DEBUG_CONTAINER_NAME" &>/dev/null; then
|
||||
echo "Cleaning up leftover debug container..."
|
||||
docker rm -f "$DEBUG_CONTAINER_NAME" &>/dev/null || true
|
||||
fi
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# Attempt to build the Docker image
|
||||
BUILD_LOG=$(mktemp)
|
||||
set +e
|
||||
docker build --name herolib --progress=plain -t "$DOCKER_IMAGE_NAME" .
|
||||
BUILD_EXIT_CODE=$?
|
||||
set -e
|
||||
|
||||
# Handle build failure
|
||||
if [ $BUILD_EXIT_CODE -ne 0 ]; then
|
||||
echo -e "\\n[ERROR] Docker build failed.\n"
|
||||
echo -e "remove the part which didn't build in the Dockerfile, the run again and to debug do:"
|
||||
echo docker run --name herolib -it --entrypoint=/bin/bash "herolib"
|
||||
exit $BUILD_EXIT_CODE
|
||||
else
|
||||
echo -e "\\n[INFO] Docker build completed successfully."
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/bin/bash -ex
|
||||
|
||||
# Get the directory where the script is located
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
# Remove any existing container named 'debug' (ignore errors)
|
||||
docker rm -f herolib > /dev/null 2>&1
|
||||
|
||||
docker run --name herolib -it \
|
||||
--entrypoint="/usr/local/bin/ourinit.sh" \
|
||||
-v "${SCRIPT_DIR}/scripts:/scripts" \
|
||||
-v "$HOME/code:/root/code" \
|
||||
-p 4100:8100 \
|
||||
-p 4101:8101 \
|
||||
-p 4102:8102 \
|
||||
-p 4379:6379 \
|
||||
-p 4022:22 \
|
||||
-p 4000:3000 herolib
|
||||
@@ -1,34 +0,0 @@
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:latest
|
||||
container_name: postgres_service
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: planetfirst
|
||||
POSTGRES_DB: mydb
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
herolib:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: herolib:latest
|
||||
container_name: herolib
|
||||
volumes:
|
||||
- ~/code:/root/code
|
||||
stdin_open: true
|
||||
tty: true
|
||||
ports:
|
||||
- "4100:8100"
|
||||
- "4101:8101"
|
||||
- "4102:8102"
|
||||
- "4379:6379"
|
||||
- "4000:3000"
|
||||
- "4022:22"
|
||||
command: ["/usr/local/bin/ourinit.sh"]
|
||||
volumes:
|
||||
postgres_data:
|
||||
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
# Set version and file variables
|
||||
OPENVSCODE_SERVER_VERSION="1.97.0"
|
||||
TMP_DIR="/tmp"
|
||||
FILENAME="openvscode.tar.gz"
|
||||
FILE_PATH="$TMP_DIR/$FILENAME"
|
||||
INSTALL_DIR="/opt/openvscode"
|
||||
BIN_PATH="/usr/local/bin/openvscode-server"
|
||||
TMUX_SESSION="openvscode-server"
|
||||
|
||||
# Function to detect architecture
|
||||
get_architecture() {
|
||||
ARCH=$(uname -m)
|
||||
case "$ARCH" in
|
||||
x86_64)
|
||||
echo "x64"
|
||||
;;
|
||||
aarch64)
|
||||
echo "arm64"
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported architecture: $ARCH" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Check if OpenVSCode Server is already installed
|
||||
if [ -d "$INSTALL_DIR" ] && [ -x "$BIN_PATH" ]; then
|
||||
echo "OpenVSCode Server is already installed at $INSTALL_DIR. Skipping download and installation."
|
||||
else
|
||||
# Determine architecture-specific URL
|
||||
ARCH=$(get_architecture)
|
||||
if [ "$ARCH" == "x64" ]; then
|
||||
DOWNLOAD_URL="https://github.com/gitpod-io/openvscode-server/releases/download/openvscode-server-insiders-v${OPENVSCODE_SERVER_VERSION}/openvscode-server-insiders-v${OPENVSCODE_SERVER_VERSION}-linux-x64.tar.gz"
|
||||
elif [ "$ARCH" == "arm64" ]; then
|
||||
DOWNLOAD_URL="https://github.com/gitpod-io/openvscode-server/releases/download/openvscode-server-insiders-v${OPENVSCODE_SERVER_VERSION}/openvscode-server-insiders-v${OPENVSCODE_SERVER_VERSION}-linux-arm64.tar.gz"
|
||||
fi
|
||||
|
||||
# Navigate to temporary directory
|
||||
cd "$TMP_DIR"
|
||||
|
||||
# Remove existing file if it exists
|
||||
if [ -f "$FILE_PATH" ]; then
|
||||
rm -f "$FILE_PATH"
|
||||
fi
|
||||
|
||||
# Download file using curl
|
||||
curl -L "$DOWNLOAD_URL" -o "$FILE_PATH"
|
||||
|
||||
# Verify file size is greater than 40 MB (40 * 1024 * 1024 bytes)
|
||||
FILE_SIZE=$(stat -c%s "$FILE_PATH")
|
||||
if [ "$FILE_SIZE" -le $((40 * 1024 * 1024)) ]; then
|
||||
echo "Error: Downloaded file size is less than 40 MB." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract the tar.gz file
|
||||
EXTRACT_DIR="openvscode-server-insiders-v${OPENVSCODE_SERVER_VERSION}-linux-${ARCH}"
|
||||
tar -xzf "$FILE_PATH"
|
||||
|
||||
# Move the extracted directory to the install location
|
||||
if [ -d "$INSTALL_DIR" ]; then
|
||||
rm -rf "$INSTALL_DIR"
|
||||
fi
|
||||
mv "$EXTRACT_DIR" "$INSTALL_DIR"
|
||||
|
||||
# Create a symlink for easy access
|
||||
ln -sf "$INSTALL_DIR/bin/openvscode-server" "$BIN_PATH"
|
||||
|
||||
# Verify installation
|
||||
if ! command -v openvscode-server >/dev/null 2>&1; then
|
||||
echo "Error: Failed to create symlink for openvscode-server." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Install default plugins
|
||||
PLUGINS=("ms-python.python" "esbenp.prettier-vscode" "saoudrizwan.claude-dev" "yzhang.markdown-all-in-one" "ms-vscode-remote.remote-ssh" "ms-vscode.remote-explorer" "charliermarsh.ruff" "qwtel.sqlite-viewer" "vosca.vscode-v-analyzer" "tomoki1207.pdf")
|
||||
for PLUGIN in "${PLUGINS[@]}"; do
|
||||
"$INSTALL_DIR/bin/openvscode-server" --install-extension "$PLUGIN"
|
||||
done
|
||||
|
||||
echo "Default plugins installed: ${PLUGINS[*]}"
|
||||
|
||||
# Clean up temporary directory
|
||||
if [ -d "$TMP_DIR" ]; then
|
||||
find "$TMP_DIR" -maxdepth 1 -type f -name "openvscode*" -exec rm -f {} \;
|
||||
fi
|
||||
fi
|
||||
|
||||
# Start OpenVSCode Server in a tmux session
|
||||
if tmux has-session -t "$TMUX_SESSION" 2>/dev/null; then
|
||||
tmux kill-session -t "$TMUX_SESSION"
|
||||
fi
|
||||
tmux new-session -d -s "$TMUX_SESSION" "$INSTALL_DIR/bin/openvscode-server"
|
||||
|
||||
echo "OpenVSCode Server is running in a tmux session named '$TMUX_SESSION'."
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
# redis-server --daemonize yes
|
||||
|
||||
# TMUX_SESSION="vscode"
|
||||
# # Start OpenVSCode Server in a tmux session
|
||||
# if tmux has-session -t "$TMUX_SESSION" 2>/dev/null; then
|
||||
# tmux kill-session -t "$TMUX_SESSION"
|
||||
# fi
|
||||
# tmux new-session -d -s "$TMUX_SESSION" "/usr/local/bin/openvscode-server --host 0.0.0.0 --without-connection-token"
|
||||
|
||||
# service ssh start
|
||||
|
||||
exec /bin/bash
|
||||
@@ -1,61 +0,0 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
# Get the directory where the script is located
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
CONTAINER_NAME="herolib"
|
||||
TARGET_PORT=4000
|
||||
|
||||
# Function to check if a container is running
|
||||
is_container_running() {
|
||||
docker ps --filter "name=$CONTAINER_NAME" --filter "status=running" -q
|
||||
}
|
||||
|
||||
# Function to check if a port is accessible
|
||||
is_port_accessible() {
|
||||
nc -zv 127.0.0.1 "$1" &>/dev/null
|
||||
}
|
||||
|
||||
# Check if the container exists and is running
|
||||
if ! is_container_running; then
|
||||
echo "Container $CONTAINER_NAME is not running."
|
||||
|
||||
# Check if the container exists but is stopped
|
||||
if docker ps -a --filter "name=$CONTAINER_NAME" -q | grep -q .; then
|
||||
echo "Starting existing container $CONTAINER_NAME..."
|
||||
docker start "$CONTAINER_NAME"
|
||||
else
|
||||
echo "Container $CONTAINER_NAME does not exist. Attempting to start with start.sh..."
|
||||
if [[ -f "$SCRIPT_DIR/start.sh" ]]; then
|
||||
bash "$SCRIPT_DIR/start.sh"
|
||||
else
|
||||
echo "Error: start.sh not found in $SCRIPT_DIR."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Wait for the container to be fully up
|
||||
sleep 5
|
||||
fi
|
||||
|
||||
# Verify the container is running
|
||||
if ! is_container_running; then
|
||||
echo "Error: Failed to start container $CONTAINER_NAME."
|
||||
exit 1
|
||||
fi
|
||||
echo "Container $CONTAINER_NAME is running."
|
||||
|
||||
# Check if the target port is accessible
|
||||
if is_port_accessible "$TARGET_PORT"; then
|
||||
echo "Port $TARGET_PORT is accessible."
|
||||
else
|
||||
echo "Port $TARGET_PORT is not accessible. Please check the service inside the container."
|
||||
fi
|
||||
|
||||
# Enter the container
|
||||
echo
|
||||
echo " ** WE NOW LOGIN TO THE CONTAINER ** "
|
||||
echo
|
||||
docker exec -it herolib bash
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
ssh root@localhost -p 4022
|
||||
@@ -1,63 +0,0 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
# Get the directory where the script is located
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
# Define variables
|
||||
CONTAINER_NAME="herolib"
|
||||
CONTAINER_SSH_DIR="/root/.ssh"
|
||||
AUTHORIZED_KEYS="authorized_keys"
|
||||
TEMP_AUTH_KEYS="/tmp/authorized_keys"
|
||||
|
||||
# Step 1: Create a temporary file to store public keys
|
||||
> $TEMP_AUTH_KEYS # Clear the file if it exists
|
||||
|
||||
# Step 2: Add public keys from ~/.ssh/ if they exist
|
||||
if ls ~/.ssh/*.pub 1>/dev/null 2>&1; then
|
||||
cat ~/.ssh/*.pub >> $TEMP_AUTH_KEYS
|
||||
fi
|
||||
|
||||
# Step 3: Check if ssh-agent is running and get public keys from it
|
||||
if pgrep ssh-agent >/dev/null; then
|
||||
echo "ssh-agent is running. Fetching keys..."
|
||||
ssh-add -L >> $TEMP_AUTH_KEYS 2>/dev/null
|
||||
else
|
||||
echo "ssh-agent is not running or no keys loaded."
|
||||
fi
|
||||
|
||||
# Step 4: Ensure the temporary file is not empty
|
||||
if [ ! -s $TEMP_AUTH_KEYS ]; then
|
||||
echo "No public keys found. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Step 5: Ensure the container's SSH directory exists
|
||||
docker exec -it $CONTAINER_NAME mkdir -p $CONTAINER_SSH_DIR
|
||||
docker exec -it $CONTAINER_NAME chmod 700 $CONTAINER_SSH_DIR
|
||||
|
||||
# Step 6: Copy the public keys into the container's authorized_keys file
|
||||
docker cp $TEMP_AUTH_KEYS $CONTAINER_NAME:$CONTAINER_SSH_DIR/$AUTHORIZED_KEYS
|
||||
|
||||
# Step 7: Set proper permissions for authorized_keys
|
||||
docker exec -it $CONTAINER_NAME chmod 600 $CONTAINER_SSH_DIR/$AUTHORIZED_KEYS
|
||||
|
||||
# Step 8: Install and start the SSH server inside the container
|
||||
docker exec -it $CONTAINER_NAME bash -c "
|
||||
apt-get update &&
|
||||
apt-get install -y openssh-server &&
|
||||
mkdir -p /var/run/sshd &&
|
||||
echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config &&
|
||||
echo 'PasswordAuthentication no' >> /etc/ssh/sshd_config &&
|
||||
chown -R root:root /root/.ssh &&
|
||||
chmod -R 700 /root/.ssh/ &&
|
||||
chmod 600 /root/.ssh/authorized_keys &&
|
||||
service ssh start
|
||||
"
|
||||
|
||||
# Step 9: Clean up temporary file on the host
|
||||
rm $TEMP_AUTH_KEYS
|
||||
|
||||
echo "SSH keys added and SSH server configured. You can now SSH into the container."
|
||||
|
||||
ssh root@localhost -p 4022
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
# Get the directory where the script is located
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +17,76 @@ docker run --name herolib \
|
||||
|
||||
docker exec -it herolib /scripts/cleanup.sh
|
||||
|
||||
docker export herolib | gzip > ${HOME}/Downloads/herolib.tar.gz
|
||||
|
||||
docker kill herolib
|
||||
# Detect the OS
|
||||
detect_os() {
|
||||
if [[ "$(uname)" == "Darwin" ]]; then
|
||||
echo "osx"
|
||||
elif [[ -f /etc/os-release ]]; then
|
||||
. /etc/os-release
|
||||
if [[ "$ID" == "ubuntu" ]]; then
|
||||
echo "ubuntu"
|
||||
fi
|
||||
else
|
||||
echo "unknown"
|
||||
fi
|
||||
}
|
||||
|
||||
OS=$(detect_os)
|
||||
|
||||
if [[ "$OS" == "osx" ]]; then
|
||||
echo "Running on macOS..."
|
||||
docker export herolib | gzip > "${HOME}/Downloads/herolib.tar.gz"
|
||||
echo "Docker image exported to ${HOME}/Downloads/herolib.tar.gz"
|
||||
elif [[ "$OS" == "ubuntu" ]]; then
|
||||
echo "Running on Ubuntu..."
|
||||
export TEMP_TAR="/tmp/herolib.tar"
|
||||
|
||||
# Export the Docker container to a tar file
|
||||
docker export herolib > "$TEMP_TAR"
|
||||
echo "Docker container exported to $TEMP_TAR"
|
||||
|
||||
# Import the tar file back as a single-layer image
|
||||
docker import "$TEMP_TAR" herolib:single-layer
|
||||
echo "Docker image imported as single-layer: herolib:single-layer"
|
||||
|
||||
# Log in to Docker Hub and push the image
|
||||
docker login --username despiegk
|
||||
docker tag herolib:single-layer despiegk/herolib:single-layer
|
||||
docker push despiegk/herolib:single-layer
|
||||
echo "Docker image pushed to Docker Hub as despiegk/herolib:single-layer"
|
||||
|
||||
# Optionally remove the tar file after importing
|
||||
rm -f "$TEMP_TAR"
|
||||
echo "Temporary file $TEMP_TAR removed"
|
||||
|
||||
else
|
||||
echo "Unsupported OS detected. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
docker kill herolib
|
||||
|
||||
|
||||
# Test the pushed Docker image locally
|
||||
echo "Testing the Docker image locally..."
|
||||
TEST_CONTAINER_NAME="test_herolib_container"
|
||||
|
||||
docker pull despiegk/herolib:single-layer
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Failed to pull the Docker image from Docker Hub. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
docker run --name "$TEST_CONTAINER_NAME" -d despiegk/herolib:single-layer
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Failed to run the Docker image as a container. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
docker ps | grep "$TEST_CONTAINER_NAME"
|
||||
if [[ $? -eq 0 ]]; then
|
||||
echo "Container $TEST_CONTAINER_NAME is running successfully."
|
||||
else
|
||||
echo "Container $TEST_CONTAINER_NAME is not running. Check the logs for details."
|
||||
fi
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import os
|
||||
import flag
|
||||
@@ -64,7 +64,7 @@ os.symlink('${abs_dir_of_script}/lib', '${os.home_dir()}/.vmodules/freeflowunive
|
||||
println('Herolib installation completed successfully!')
|
||||
|
||||
// Add vtest alias
|
||||
addtoscript('alias vtest=', 'alias vtest=\'v -stats -enable-globals -n -w -cg -gc none -no-retry-compilation -cc tcc test\' ') or {
|
||||
addtoscript('alias vtest=', 'alias vtest=\'v -stats -enable-globals -n -w -cg -gc none -cc tcc test\' ') or {
|
||||
eprintln('Failed to add vtest alias: ${err}')
|
||||
}
|
||||
|
||||
|
||||
22
docker/postgresql/docker-compose.yml
Normal file
22
docker/postgresql/docker-compose.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
version: '3.9'
|
||||
services:
|
||||
db:
|
||||
image: 'postgres:17.2-alpine3.21'
|
||||
restart: always
|
||||
ports:
|
||||
- 5432:5432
|
||||
environment:
|
||||
POSTGRES_PASSWORD: 1234
|
||||
networks:
|
||||
- my_network
|
||||
|
||||
adminer:
|
||||
image: adminer
|
||||
restart: always
|
||||
ports:
|
||||
- 8080:8080
|
||||
networks:
|
||||
- my_network
|
||||
|
||||
networks:
|
||||
my_network:
|
||||
6
docker/postgresql/readme.md
Normal file
6
docker/postgresql/readme.md
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
Server (Host): db (because Docker Compose creates an internal network and uses service names as hostnames)
|
||||
Username: postgres (default PostgreSQL username)
|
||||
Password: 1234 (as set in your POSTGRES_PASSWORD environment variable)
|
||||
Database: Leave it empty or enter postgres (default database)
|
||||
13
docker/postgresql/start.sh
Executable file
13
docker/postgresql/start.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
# Get the directory where the script is located
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
# Stop any existing containers and remove them
|
||||
docker compose down
|
||||
|
||||
# Start the services in detached mode
|
||||
docker compose up -d
|
||||
|
||||
echo "PostgreSQL is ready"
|
||||
@@ -34,7 +34,7 @@ The examples directory demonstrates various capabilities of HeroLib:
|
||||
When creating V scripts (.vsh files), always use the following shebang:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env -S v -n -w -gc none -no-retry-compilation -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
|
||||
```
|
||||
|
||||
This shebang ensures:
|
||||
|
||||
69
examples/aiexamples/openai_chat_completion.vsh
Executable file
69
examples/aiexamples/openai_chat_completion.vsh
Executable file
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.clients.jina
|
||||
import freeflowuniverse.herolib.osal
|
||||
import os
|
||||
|
||||
// Example of using the Jina client
|
||||
|
||||
fn main() {
|
||||
// Set environment variable for testing
|
||||
// In production, you would set this in your environment
|
||||
// osal.env_set(key: 'JINAKEY', value: 'your-api-key')
|
||||
|
||||
// Check if JINAKEY environment variable exists
|
||||
if !osal.env_exists('JINAKEY') {
|
||||
println('JINAKEY environment variable not set. Please set it before running this example.')
|
||||
exit(1)
|
||||
}
|
||||
|
||||
// Create a Jina client instance
|
||||
mut client := jina.get(name: 'default')!
|
||||
|
||||
println('Jina client initialized successfully.')
|
||||
|
||||
// Example: Create embeddings
|
||||
model := 'jina-embeddings-v3'
|
||||
texts := ['Hello, world!', 'How are you doing?']
|
||||
|
||||
println('Creating embeddings for texts: ${texts}')
|
||||
result := client.create_embeddings(texts, model, 'retrieval.query')!
|
||||
|
||||
println('Embeddings created successfully.')
|
||||
println('Model: ${result['model']}')
|
||||
println('Data count: ${result['data'].arr().len}')
|
||||
|
||||
// Example: List classifiers
|
||||
println('\nListing classifiers:')
|
||||
classifiers := client.list_classifiers() or {
|
||||
println('Failed to list classifiers: ${err}')
|
||||
return
|
||||
}
|
||||
|
||||
println('Classifiers retrieved successfully.')
|
||||
|
||||
// Example: Create a classifier
|
||||
println('\nTraining a classifier:')
|
||||
examples := [
|
||||
jina.TrainingExample{
|
||||
text: 'This movie was great!'
|
||||
label: 'positive'
|
||||
},
|
||||
jina.TrainingExample{
|
||||
text: 'I did not like this movie.'
|
||||
label: 'negative'
|
||||
},
|
||||
jina.TrainingExample{
|
||||
text: 'The movie was okay.'
|
||||
label: 'neutral'
|
||||
}
|
||||
]
|
||||
|
||||
training_result := client.train(examples, model, 'private') or {
|
||||
println('Failed to train classifier: ${err}')
|
||||
return
|
||||
}
|
||||
|
||||
println('Classifier trained successfully.')
|
||||
println('Classifier ID: ${training_result['classifier_id']}')
|
||||
}
|
||||
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.
|
||||
23
examples/baobab/generator/basic/generate_actor_module.vsh
Executable file
23
examples/baobab/generator/basic/generate_actor_module.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.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.
25
examples/baobab/generator/geomind_poc/generate.vsh
Executable file
25
examples/baobab/generator/geomind_poc/generate.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.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.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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
190
examples/baobab/generator/geomind_poc/server.v
Normal file
190
examples/baobab/generator/geomind_poc/server.v
Normal file
@@ -0,0 +1,190 @@
|
||||
module geomind_poc
|
||||
|
||||
import crypto.rand
|
||||
|
||||
// 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)!
|
||||
}
|
||||
24
examples/baobab/generator/mcc_example.vsh
Executable file
24
examples/baobab/generator/mcc_example.vsh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/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
|
||||
28
examples/baobab/generator/openapi_e2e/generate_actor_module.vsh
Executable file
28
examples/baobab/generator/openapi_e2e/generate_actor_module.vsh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/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))
|
||||
11
examples/biztools/_archive/investor_tool.vsh
Executable file
11
examples/biztools/_archive/investor_tool.vsh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.biz.investortool
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import os
|
||||
|
||||
mut plbook := playbook.new(
|
||||
path: '${os.home_dir()}/code/git.ourworld.tf/ourworld_holding/investorstool/output'
|
||||
)!
|
||||
mut it := investortool.play(mut plbook)!
|
||||
it.check()!
|
||||
48
examples/biztools/_archive/tf9_biz.vsh
Executable file
48
examples/biztools/_archive/tf9_biz.vsh
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env -S v -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.ui.console
|
||||
import freeflowuniverse.herolib.biz.bizmodel
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import freeflowuniverse.herolib.core.playcmds
|
||||
import freeflowuniverse.herolib.web.mdbook
|
||||
import freeflowuniverse.herolib.biz.spreadsheet
|
||||
import os
|
||||
|
||||
const name = 'tf9_budget'
|
||||
|
||||
const wikipath = '${os.home_dir()}/code/git.ourworld.tf/ourworld_holding/info_ourworld/collections/${name}'
|
||||
const summarypath = '${wikipath}/summary.md'
|
||||
|
||||
// mut sh := spreadsheet.sheet_new(name: 'test2') or { panic(err) }
|
||||
// println(sh)
|
||||
// sh.row_new(descr: 'this is a description', name: 'something', growth: '0:100aed,55:1000eur')!
|
||||
// println(sh)
|
||||
// println(sh.wiki()!)
|
||||
|
||||
// exit(0)
|
||||
|
||||
// execute the actions so we have the info populated
|
||||
// mut plb:=playbook.new(path: wikipath)!
|
||||
// playcmds.run(mut plb,false)!
|
||||
|
||||
buildpath := '${os.home_dir()}/hero/var/mdbuild/bizmodel'
|
||||
|
||||
// just run the doctree & mdbook and it should
|
||||
// load the doctree, these are all collections
|
||||
mut tree := doctree.new(name: name)!
|
||||
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 ${name}'
|
||||
)!
|
||||
mdbook.book_open('bizmodel')!
|
||||
12
examples/biztools/_archive/todo.md
Normal file
12
examples/biztools/_archive/todo.md
Normal file
@@ -0,0 +1,12 @@
|
||||
need to find where the manual is
|
||||
|
||||
- [manual](bizmodel_example/configuration.md)
|
||||
- [widgets](bizmodel_example/widgets.md)
|
||||
- [graph_bar_row](bizmodel_example/graph_bar_row.md)
|
||||
- [sheet_tables](bizmodel_example/sheet_tables.md)
|
||||
- [widget_args](bizmodel_example/widget_args.md)
|
||||
- [params](bizmodel_example/configuration.md)
|
||||
- [revenue params](bizmodel_example/revenue_params.md)
|
||||
- [funding params](bizmodel_example/funding_params.md)
|
||||
- [hr params](bizmodel_example/hr_params.md)
|
||||
- [costs params](bizmodel_example/costs_params.md)
|
||||
20
examples/biztools/bizmodel.vsh
Executable file
20
examples/biztools/bizmodel.vsh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/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")!
|
||||
|
||||
|
||||
|
||||
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
|
||||
1
examples/biztools/bizmodel_docusaurus/archive/img/.done
Normal file
1
examples/biztools/bizmodel_docusaurus/archive/img/.done
Normal file
@@ -0,0 +1 @@
|
||||
ms1bmodel.png
|
||||
BIN
examples/biztools/bizmodel_docusaurus/archive/img/ms1bmodel.png
Normal file
BIN
examples/biztools/bizmodel_docusaurus/archive/img/ms1bmodel.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
13
examples/biztools/bizmodel_docusaurus/archive/revenue.md
Normal file
13
examples/biztools/bizmodel_docusaurus/archive/revenue.md
Normal file
@@ -0,0 +1,13 @@
|
||||
## Revenue
|
||||
|
||||
Overview of achieved revenue.
|
||||
|
||||
Unit is in Million USD.
|
||||
|
||||
!!bizmodel.sheet_wiki title:'REVENUE' includefilter:rev sheetname:'bizmodel_test'
|
||||
|
||||
!!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'
|
||||
13
examples/biztools/bizmodel_docusaurus/archive/summary.md
Normal file
13
examples/biztools/bizmodel_docusaurus/archive/summary.md
Normal file
@@ -0,0 +1,13 @@
|
||||
- [bizmodel](bizmodel_example/bizmodel.md)
|
||||
- [Revenue](bizmodel_example/revenue.md)
|
||||
- [Result](bizmodel_example/overview.md)
|
||||
- [parameters](bizmodel_example/params.md)
|
||||
- [revenue_params](bizmodel_example/params/revenue_params.md)
|
||||
- [funding_params](bizmodel_example/params/funding_params.md)
|
||||
- [hr_params](bizmodel_example/params/hr_params.md)
|
||||
- [costs_params](bizmodel_example/params/costs_params.md)
|
||||
- [rows overview](bizmodel_example/rows_overview.md)
|
||||
- [employees](bizmodel_example/employees.md)
|
||||
- [debug](bizmodel_example/debug.md)
|
||||
- [worksheet](bizmodel_example/worksheet.md)
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# Overview of the rows in the biz model sheet
|
||||
|
||||
|
||||
!!bizmodel.sheet_wiki sheetname:'bizmodel_test'
|
||||
37
examples/biztools/bizmodel_docusaurus/bizmodel_docusaurus.vsh
Executable file
37
examples/biztools/bizmodel_docusaurus/bizmodel_docusaurus.vsh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/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
|
||||
10
examples/biztools/bizmodel_docusaurus/load.md
Normal file
10
examples/biztools/bizmodel_docusaurus/load.md
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
## Loader instructions
|
||||
|
||||
this will make sure we load the appropriate biz model
|
||||
|
||||
|
||||
```js
|
||||
!!bizmodel.load name:'default' url:'https://github.com/freeflowuniverse/herolib/tree/development/bizmodel/example/data'
|
||||
```
|
||||
|
||||
1
examples/biztools/playbook/.collection
Normal file
1
examples/biztools/playbook/.collection
Normal file
@@ -0,0 +1 @@
|
||||
name:bizmodel_example
|
||||
10
examples/biztools/playbook/bizmodel.md
Normal file
10
examples/biztools/playbook/bizmodel.md
Normal file
@@ -0,0 +1,10 @@
|
||||

|
||||
|
||||
# bizmodel
|
||||
|
||||
OurWorld has developed a tool to generate and keep business models up to date.
|
||||
|
||||
Our aim is to make it easy for ourworld to track changes in planning over the multiple projects and even be able to aggregated them. Because the input for such a plan is text (as you can see in this ebook) its easy to see how the modelling and parameters change over time.
|
||||
|
||||
This is a very flexible tool which will be extended for budgetting, cashflow management, shareholder tables, ...
|
||||
|
||||
31
examples/biztools/playbook/cost_centers.md
Normal file
31
examples/biztools/playbook/cost_centers.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# HR Params
|
||||
|
||||
## Engineering
|
||||
|
||||
Costs can be grouped in cost centers which can then be used to futher process e.g. transcactions between companies.
|
||||
|
||||
```js
|
||||
|
||||
!!bizmodel.costcenter_define bizname:'test'
|
||||
name:'tfdmcc'
|
||||
descr:'TFDMCC executes on near source agreement for TFTech'
|
||||
min_month:'10000USD'
|
||||
max_month:'100000USD'
|
||||
end_date:'1/1/2026' //when does agreement stop
|
||||
|
||||
!!bizmodel.costcenter_define bizname:'test'
|
||||
name:'cs_tftech'
|
||||
descr:'Nearsource agreement for TFTech towards Codescalers'
|
||||
min_month:'10000USD'
|
||||
max_month:'100000USD'
|
||||
end_date:'1/1/2026'
|
||||
|
||||
!!bizmodel.costcenter_define bizname:'test'
|
||||
name:'cs_tfcloud'
|
||||
descr:'Nearsource agreement for TFCloud towards Codescalers'
|
||||
min_month:'10000USD'
|
||||
max_month:'100000USD'
|
||||
end_date:'1/1/2026'
|
||||
|
||||
|
||||
```
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user