Compare commits
693 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
483b6e3de3 | ||
| f769c34466 | |||
|
|
c0242a0729 | ||
|
|
df452ce258 | ||
| 7de290ae55 | |||
| fe161c5bea | |||
|
|
fca7c7364a | ||
|
|
ef705d1be0 | ||
|
|
3154733be1 | ||
| b285e85eb5 | |||
| 89b7f0d465 | |||
|
|
256d4e9bca | ||
|
|
54f4e83627 | ||
|
|
f7a770989b | ||
|
|
c5759ea30e | ||
|
|
aef9c84eb5 | ||
| d0baac83a9 | |||
| b6a2671665 | |||
| a96ae1252c | |||
| ac4db0f789 | |||
| 37f9ab78ec | |||
|
|
9b3ac150bd | ||
|
|
dd577d51b9 | ||
| 92f9714229 | |||
|
|
632a1c11c2 | ||
|
|
63d41352bc | ||
|
|
da8eef3711 | ||
|
|
f0a4732206 | ||
|
|
1f053edefc | ||
|
|
f93db1d23c | ||
|
|
105611bbfb | ||
|
|
4977c6de30 | ||
|
|
eb956bca3d | ||
|
|
5e511367c3 | ||
|
|
484bfe393e | ||
| a1404584d6 | |||
| 3ef1698c2c | |||
| a7fb704627 | |||
| 91ba6001cb | |||
| 345a79d8ff | |||
| 15d886e5e9 | |||
| d6224d1e60 | |||
| 83fb647ac3 | |||
| b410544ee1 | |||
| 2d5d1befae | |||
| fd8b8c8f42 | |||
| 8ffb8c8caf | |||
| b8b339b85c | |||
| 0789a38ea9 | |||
| 995d3c3f6d | |||
|
|
822b179ef4 | ||
| 4691971bd0 | |||
| 9226e8b490 | |||
| b7fc7734b6 | |||
| 8749e3a8cb | |||
| 61f9f2868a | |||
| 97dfcbeb51 | |||
| 238fabbcb2 | |||
| 49542b4bff | |||
| 46898112f5 | |||
| f9bdb22c67 | |||
| cb664b2115 | |||
|
|
761b9e031e | ||
|
|
0d8d11fe26 | ||
|
|
2d5fbd3337 | ||
| cd3c98280e | |||
| 39c6c37dee | |||
| 3438f74e60 | |||
| 4f79712570 | |||
| 8e85ce0678 | |||
| ff09e7bf1b | |||
| 46e1c6706c | |||
| d8a59d0726 | |||
| 108d2019cd | |||
| 3682ef2420 | |||
| a066db6624 | |||
| 7458d64c05 | |||
| 2a1787f28f | |||
| de78c229ce | |||
|
|
f386c67acf | ||
|
|
75f98bf349 | ||
|
|
9870fcbc5d | ||
|
|
d2b8379505 | ||
|
|
2dcb97255c | ||
|
|
f7dd227cd0 | ||
| e2c18c3a24 | |||
| 1bc6c6eab8 | |||
|
|
4b39b137de | ||
| e5de293919 | |||
| 8a10374570 | |||
| ad37a041ab | |||
| 44daea4447 | |||
| 6989a4da13 | |||
| de4583691c | |||
| d8c9b07a51 | |||
| 54d31f40b2 | |||
| ec73b5ff34 | |||
| 9fcdcc3aff | |||
| 05ab2b68f4 | |||
| 79330ef8f5 | |||
| 45ed369a78 | |||
| 37c17fc7da | |||
| 23640d2647 | |||
| be54ec8302 | |||
| 638f81a781 | |||
| e00306b6f8 | |||
| 3fec1c38a1 | |||
| edc9e3c150 | |||
| a155122898 | |||
| f0552f38a0 | |||
|
|
f99419371a | ||
|
|
86d47c218b | ||
|
|
bd5cafbad7 | ||
|
|
b71362eb9a | ||
|
|
673d982360 | ||
|
|
712b46864a | ||
|
|
186c3aae59 | ||
|
|
0794fe948b | ||
|
|
ba2d6e4310 | ||
|
|
b9e5d14b48 | ||
|
|
bf26b0af1d | ||
|
|
8e82b2865b | ||
|
|
367340d69d | ||
|
|
0b77c73809 | ||
|
|
51b432d911 | ||
|
|
f7a679b2a3 | ||
|
|
15c9d60760 | ||
|
|
c69b53fd4e | ||
|
|
9cdab1f392 | ||
|
|
34656cf1f9 | ||
|
|
cf98822749 | ||
|
|
2335d14623 | ||
| 4a72698402 | |||
| fcb857f756 | |||
|
|
ba07f85fd8 | ||
|
|
7b621243d0 | ||
| 598b312140 | |||
| 0df10f5cb3 | |||
| 2c748a9fc8 | |||
| a2e1b4fb27 | |||
| 9b0da9f245 | |||
| 5b9426ba11 | |||
| 8b6ad4d076 | |||
|
|
7d4565e56f | ||
|
|
92cceeb64b | ||
|
|
3d90e39781 | ||
|
|
efbf00830a | ||
|
|
b9969c69fd | ||
|
|
15d998bf76 | ||
|
|
8c966ae853 | ||
|
|
3e10db326f | ||
|
|
dc6f1bdf52 | ||
|
|
429f3b1fea | ||
|
|
70009f1846 | ||
|
|
5f9024c7bf | ||
|
|
f2138f104f | ||
|
|
04ee73e8dd | ||
|
|
bd83ad37bf | ||
|
|
7b175c8804 | ||
|
|
22cbc806dc | ||
|
|
02e0a073aa | ||
|
|
b2e5a84ff9 | ||
|
|
abd694015b | ||
|
|
57d30eab2d | ||
| b27f0a5017 | |||
|
|
c47002430e | ||
|
|
bd3abade55 | ||
|
|
ea0637423e | ||
|
|
a6756bfe5a | ||
|
|
4cdbc51343 | ||
|
|
2e5210a0b7 | ||
|
|
e8574383ee | ||
|
|
21da15da0a | ||
|
|
dca1d877ac | ||
|
|
007f65c27e | ||
|
|
ef572f402d | ||
|
|
133e7c9809 | ||
| 0d38c1b471 | |||
| cf7bfb7650 | |||
|
|
228abe36a3 | ||
| b48abc474c | |||
|
|
c3fe788a5b | ||
|
|
025e8fba69 | ||
| 672904d914 | |||
| fac783c58d | |||
| 6e7843f368 | |||
| 6a555a5fe3 | |||
| 4796e4fe82 | |||
| 3b1068a3a8 | |||
| 392f764acc | |||
| 122cba9f6b | |||
|
|
dc178f68c7 | ||
|
|
59a0519b4e | ||
|
|
dfcaeec85f | ||
|
|
ef922d162e | ||
|
|
02e4ea180d | ||
|
|
8b9b0678b8 | ||
|
|
475e812ba3 | ||
|
|
0a953f2c09 | ||
|
|
1e26162e00 | ||
|
|
dd68bf950c | ||
|
|
e374520654 | ||
|
|
47c95f76e9 | ||
|
|
918cfd83ec | ||
|
|
83387c47ec | ||
|
|
f6c22c733b | ||
|
|
269d0474c5 | ||
|
|
28359984ff | ||
|
|
c09e424890 | ||
| a55af220bf | |||
| 9c09af83a2 | |||
| e69d67d238 | |||
| 01c6ea66ac | |||
| f9ea731a6e | |||
|
|
a974091442 | ||
|
|
413b805823 | ||
|
|
46069ba924 | ||
|
|
f3e7b979a5 | ||
|
|
f6733a67af | ||
|
|
4988b241ef | ||
|
|
7807a8e736 | ||
| 5ba11aab46 | |||
|
|
4abb46b4bf | ||
|
|
a7976c45f9 | ||
|
|
5194fabe62 | ||
|
|
ff430c2e4d | ||
| 1581628ea3 | |||
| 237f9bd742 | |||
|
|
cf27e7880e | ||
|
|
ad300c068f | ||
|
|
1a02dcaf0f | ||
|
|
9ecc2444aa | ||
|
|
0e1836c5d0 | ||
|
|
7965883744 | ||
|
|
b006bb1e41 | ||
|
|
27c9018c48 | ||
|
|
f1991d89b3 | ||
| 9448ae85cf | |||
|
|
a64e964d83 | ||
|
|
5e321b6b0f | ||
| b1453e3580 | |||
| 3da895083b | |||
| ac583741a4 | |||
| 4358ba6471 | |||
| 46afb63f31 | |||
| f773ce168e | |||
| aa79df1fcd | |||
| 420c9cb9e5 | |||
| 83d935930f | |||
| 2e2c94e897 | |||
| a96903da0e | |||
| 3dbcf00e9f | |||
| 708147435e | |||
| 26289bb00f | |||
| 1489b9f44f | |||
| e4045ef179 | |||
| 13f482fa12 | |||
| 3e2013576f | |||
| e5aa8bca09 | |||
| 4dd3908ff7 | |||
| 09f388e2ff | |||
| baecb9bbe4 | |||
| 2c5986295e | |||
| 126f23dfa2 | |||
|
|
407f3f85bc | ||
|
|
94da4fff5e | ||
|
|
0fa54f1354 | ||
|
|
80677f7177 | ||
|
|
01cac0f741 | ||
|
|
30546a34f9 | ||
|
|
0ccf317564 | ||
|
|
0c49e83a68 | ||
| 51db8257f5 | |||
| ecc2977581 | |||
| ffafef0c88 | |||
| ca3bac1d76 | |||
| 43f7bc7943 | |||
| b3555aa54e | |||
|
|
54dc3d3f1f | ||
|
|
afad769066 | ||
|
|
2da37ee4a5 | ||
|
|
90c81a1234 | ||
|
|
34ea12ca23 | ||
|
|
d2c1be5396 | ||
|
|
fe934bba36 | ||
|
|
b01e40da40 | ||
|
|
ae7e7ecb84 | ||
|
|
fdf540cbd0 | ||
|
|
7cb26e5569 | ||
|
|
913b0cb790 | ||
|
|
485b47d145 | ||
| fb9c9b8070 | |||
|
|
5b69f935a5 | ||
|
|
9dbc36d634 | ||
|
|
42b0c4d48f | ||
|
|
5343d9bff6 | ||
|
|
eb47c8490d | ||
|
|
1de9be2a8a | ||
|
|
d852ecc5b1 | ||
|
|
368edcd93a | ||
|
|
71906fd891 | ||
|
|
dbd187a017 | ||
|
|
52a3546325 | ||
|
|
a23eb0ff0b | ||
|
|
b40c366335 | ||
|
|
d2ad18e8ec | ||
|
|
9b737c9280 | ||
| 834c413cfc | |||
| da9965bdc6 | |||
| 6bbaa0d1f7 | |||
| 834f612bfe | |||
|
|
171e54a68c | ||
|
|
a690f98cc1 | ||
|
|
400ea6e80e | ||
|
|
84c19ca9a4 | ||
|
|
3b7ec028f9 | ||
| 83f7bf41e3 | |||
| 634b8c5bad | |||
| 4aabc8d1b0 | |||
| 75255d8cd0 | |||
|
|
a0b53126ca | ||
|
|
38cd933d41 | ||
|
|
2da014c407 | ||
|
|
9d1752f4ed | ||
|
|
d06a806184 | ||
|
|
fe1becabaf | ||
| 2d0d196cd3 | |||
| 37573b0b59 | |||
| 35dace9155 | |||
| 69e7c1cce9 | |||
| d21e71e615 | |||
|
|
972bb9f755 | ||
|
|
a798b2347f | ||
|
|
17979b4fde | ||
|
|
68d25d3622 | ||
|
|
f38d4249ef | ||
| ded4a0b102 | |||
| 6184441706 | |||
| 293dc3f1ac | |||
| 6492e42358 | |||
| 4aaf1bd6db | |||
| a56a251d7f | |||
| f306ff728f | |||
| a10a6d6507 | |||
|
|
59efa18bce | ||
|
|
4ed80481aa | ||
| fff14183a4 | |||
|
|
1f58676278 | ||
|
|
b67db23e07 | ||
|
|
4fe1e70881 | ||
|
|
988602f90f | ||
| 6a2e143b98 | |||
|
|
306de32de8 | ||
|
|
c0b57e2a01 | ||
|
|
aeeacc877b | ||
| 6820a7e9c8 | |||
| 1c7621f20a | |||
| 5263798b11 | |||
|
|
0d96c5fc65 | ||
|
|
6b0cf48292 | ||
|
|
9160e95e4a | ||
|
|
296cb9adf5 | ||
|
|
88fe8f503f | ||
|
|
a26bb56b15 | ||
|
|
2f54f05cfd | ||
|
|
f61d6808e8 | ||
|
|
4719876feb | ||
|
|
975cca77b1 | ||
|
|
eb80294b0a | ||
|
|
0704c9421d | ||
|
|
f08af0e2c5 | ||
| 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 |
17
.github/workflows/documentation.yml
vendored
17
.github/workflows/documentation.yml
vendored
@@ -2,9 +2,9 @@ name: Deploy Documentation to Pages
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: ["main"]
|
branches: ["development"]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
branches: ["main"]
|
branches: ["development"]
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -17,16 +17,14 @@ concurrency:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy-documentation:
|
deploy-documentation:
|
||||||
|
#if: startsWith(github.ref, 'refs/tags/')
|
||||||
environment:
|
environment:
|
||||||
name: github-pages
|
name: github-pages
|
||||||
url: ${{ steps.deployment.outputs.page_url }}
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Install Vlang dependencies
|
|
||||||
run: sudo apt update && sudo apt install -y libgc-dev
|
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Vlang
|
- name: Setup Vlang
|
||||||
run: ./install_v.sh
|
run: ./install_v.sh
|
||||||
@@ -34,17 +32,16 @@ jobs:
|
|||||||
- name: Generate documentation
|
- name: Generate documentation
|
||||||
run: |
|
run: |
|
||||||
./doc.vsh
|
./doc.vsh
|
||||||
# ls /home/runner/work/herolib/docs
|
|
||||||
find .
|
find .
|
||||||
|
|
||||||
- name: Setup Pages
|
- name: Setup Pages
|
||||||
uses: actions/configure-pages@v3
|
uses: actions/configure-pages@v4
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-pages-artifact@v1
|
uses: actions/upload-pages-artifact@v3
|
||||||
with:
|
with:
|
||||||
path: "/home/runner/work/herolib/herolib/docs"
|
path: "/home/runner/work/herolib/herolib/docs"
|
||||||
|
|
||||||
- name: Deploy to GitHub Pages
|
- name: Deploy to GitHub Pages
|
||||||
id: deployment
|
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
|
||||||
|
|
||||||
23
.gitignore
vendored
23
.gitignore
vendored
@@ -1,4 +1,13 @@
|
|||||||
|
# Additional ignore files and directories
|
||||||
|
Thumbs.db
|
||||||
|
# Logs
|
||||||
|
logs/
|
||||||
|
*.log
|
||||||
|
*.out
|
||||||
|
# Compiled Python files
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
__pycache__/
|
||||||
*dSYM/
|
*dSYM/
|
||||||
.vmodules/
|
.vmodules/
|
||||||
.vscode
|
.vscode
|
||||||
@@ -7,6 +16,7 @@ vls.*
|
|||||||
vls.log
|
vls.log
|
||||||
node_modules/
|
node_modules/
|
||||||
docs/
|
docs/
|
||||||
|
vdocs/
|
||||||
photonwrapper.so
|
photonwrapper.so
|
||||||
x
|
x
|
||||||
.env
|
.env
|
||||||
@@ -25,7 +35,16 @@ dump.rdb
|
|||||||
output/
|
output/
|
||||||
*.db
|
*.db
|
||||||
.stellar
|
.stellar
|
||||||
vdocs/
|
|
||||||
data.ms/
|
data.ms/
|
||||||
test_basic
|
test_basic
|
||||||
cli/hero
|
cli/hero
|
||||||
|
.aider*
|
||||||
|
storage/
|
||||||
|
.qdrant-initialized
|
||||||
|
.compile_cache
|
||||||
|
compile_results.log
|
||||||
|
tmp
|
||||||
|
compile_summary.log
|
||||||
|
.summary_lock
|
||||||
|
.aider*
|
||||||
|
*.dylib
|
||||||
3
.roo/mcp.json
Normal file
3
.roo/mcp.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"mcpServers": {}
|
||||||
|
}
|
||||||
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
|
```bash
|
||||||
curl 'https://raw.githubusercontent.com/freeflowuniverse/herolib/refs/heads/main/install_v.sh' > /tmp/install_v.sh
|
curl https://raw.githubusercontent.com/freeflowuniverse/herolib/refs/heads/development/install_hero.sh > /tmp/install_hero.sh
|
||||||
bash /tmp/install_v.sh --analyzer --herolib
|
bash /tmp/install_hero.sh
|
||||||
#DONT FORGET TO START A NEW SHELL (otherwise the paths will not be set)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 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
|
```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
|
V & HeroLib Installer Script
|
||||||
|
|
||||||
Usage: ~/code/github/freeflowuniverse/herolib/install_v.sh [options]
|
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 --analyzer
|
||||||
~/code/github/freeflowuniverse/herolib/install_v.sh --herolib
|
~/code/github/freeflowuniverse/herolib/install_v.sh --herolib
|
||||||
~/code/github/freeflowuniverse/herolib/install_v.sh --reset --analyzer # Fresh install of both
|
~/code/github/freeflowuniverse/herolib/install_v.sh --reset --analyzer # Fresh install of both
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### to test
|
## Features
|
||||||
|
|
||||||
to run the basic tests, important !!!
|
Herolib provides a wide range of functionality:
|
||||||
|
|
||||||
|
- Cloud automation tools
|
||||||
|
- Git operations and management
|
||||||
|
- Documentation building
|
||||||
|
- Hero AI integration
|
||||||
|
- System management utilities
|
||||||
|
- And much more
|
||||||
|
|
||||||
|
Check the [cookbook](https://github.com/freeflowuniverse/herolib/tree/development/cookbook) for examples and use cases.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Running tests is an essential part of development. To run the basic tests:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Run all basic tests
|
||||||
~/code/github/freeflowuniverse/herolib/test_basic.vsh
|
~/code/github/freeflowuniverse/herolib/test_basic.vsh
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
# Run tests for a specific module
|
||||||
vtest ~/code/github/freeflowuniverse/herolib/lib/osal/package_test.v
|
vtest ~/code/github/freeflowuniverse/herolib/lib/osal/package_test.v
|
||||||
#for a full dir
|
|
||||||
vtest ~/code/github/freeflowuniverse/herolib/lib/osal
|
|
||||||
|
|
||||||
#to do al basic tests
|
# Run tests for an entire directory
|
||||||
~/code/github/freeflowuniverse/herolib/test_basic.vsh
|
vtest ~/code/github/freeflowuniverse/herolib/lib/osal
|
||||||
|
```
|
||||||
|
|
||||||
|
The `vtest` command is an alias for testing functionality.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
We welcome contributions to Herolib! Please see our [CONTRIBUTING.md](CONTRIBUTING.md) file for detailed information on:
|
||||||
|
|
||||||
|
- Setting up your development environment
|
||||||
|
- Understanding the repository structure
|
||||||
|
- Following our development workflow
|
||||||
|
- Making pull requests
|
||||||
|
- CI/CD processes
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### TCC Compiler Error on macOS
|
||||||
|
|
||||||
|
If you encounter the following error when using TCC compiler on macOS:
|
||||||
|
|
||||||
```
|
```
|
||||||
vtest is an alias to test functionality
|
In file included from /Users/timurgordon/code/github/vlang/v/thirdparty/cJSON/cJSON.c:42:
|
||||||
|
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/math.h:614: error: ';' expected (got "__fabsf16")
|
||||||
|
```
|
||||||
|
|
||||||
|
This is caused by incompatibility between TCC and the half precision math functions in the macOS SDK. To fix this issue:
|
||||||
|
|
||||||
## important to read
|
1. Open the math.h file:
|
||||||
|
```bash
|
||||||
|
sudo nano /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/math.h
|
||||||
|
```
|
||||||
|
|
||||||
- [aiprompts/starter/0_start_here.md](aiprompts/starter/0_start_here.md)
|
2. Comment out the following lines (around line 612-626):
|
||||||
|
```c
|
||||||
|
/* half precision math functions */
|
||||||
|
// extern _Float16 __fabsf16(_Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __hypotf16(_Float16, _Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __sqrtf16(_Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __ceilf16(_Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __floorf16(_Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __rintf16(_Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __roundf16(_Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __truncf16(_Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __copysignf16(_Float16, _Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __nextafterf16(_Float16, _Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __fmaxf16(_Float16, _Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __fminf16(_Float16, _Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
// extern _Float16 __fmaf16(_Float16, _Float16, _Float16) __API_AVAILABLE(macos(15.0), ios(18.0), watchos(11.0), tvos(18.0));
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Save the file and try compiling again.
|
||||||
|
|
||||||
|
## Additional Resources
|
||||||
|
|
||||||
|
- [Complete Documentation](https://freeflowuniverse.github.io/herolib/)
|
||||||
|
- [Cookbook Examples](https://github.com/freeflowuniverse/herolib/tree/development/cookbook)
|
||||||
|
- [AI Prompts](aiprompts/starter/0_start_here.md)
|
||||||
|
|
||||||
|
## Generating Documentation
|
||||||
|
|
||||||
|
To generate documentation locally:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/code/github/freeflowuniverse/herolib
|
||||||
|
bash doc.sh
|
||||||
|
```
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import as
|
import as
|
||||||
|
|
||||||
```vlang
|
```vlang
|
||||||
import freeflowuniverse.herolib.osal
|
import freeflowuniverse.osal
|
||||||
|
|
||||||
osal.ping...
|
osal.ping...
|
||||||
|
|
||||||
@@ -70,14 +70,14 @@ mut pm:=process.processmap_get()?
|
|||||||
info returns like:
|
info returns like:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
}, freeflowuniverse.herolib.process.ProcessInfo{
|
}, freeflowuniverse.process.ProcessInfo{
|
||||||
cpu_perc: 0
|
cpu_perc: 0
|
||||||
mem_perc: 0
|
mem_perc: 0
|
||||||
cmd: 'mc'
|
cmd: 'mc'
|
||||||
pid: 84455
|
pid: 84455
|
||||||
ppid: 84467
|
ppid: 84467
|
||||||
rss: 3168
|
rss: 3168
|
||||||
}, freeflowuniverse.herolib.process.ProcessInfo{
|
}, freeflowuniverse.process.ProcessInfo{
|
||||||
cpu_perc: 0
|
cpu_perc: 0
|
||||||
mem_perc: 0
|
mem_perc: 0
|
||||||
cmd: 'zsh -Z -g'
|
cmd: 'zsh -Z -g'
|
||||||
@@ -195,13 +195,13 @@ fn initname() !string
|
|||||||
e.g. systemd, bash, zinit
|
e.g. systemd, bash, zinit
|
||||||
fn ipaddr_pub_get() !string
|
fn ipaddr_pub_get() !string
|
||||||
Returns the ipaddress as known on the public side is using resolver4.opendns.com
|
Returns the ipaddress as known on the public side is using resolver4.opendns.com
|
||||||
fn is_linux() bool
|
fn is_linux()! bool
|
||||||
fn is_linux_arm()! bool
|
fn is_linux_arm()! bool
|
||||||
fn is_linux_intel() bool
|
fn is_linux_intel()! bool
|
||||||
fn is_osx() bool
|
fn is_osx()! bool
|
||||||
fn is_osx_arm() bool
|
fn is_osx_arm()! bool
|
||||||
fn is_osx_intel() bool
|
fn is_osx_intel()! bool
|
||||||
fn is_ubuntu() bool
|
fn is_ubuntu()! bool
|
||||||
fn load_env_file(file_path string) !
|
fn load_env_file(file_path string) !
|
||||||
fn memdb_exists(key string) bool
|
fn memdb_exists(key string) bool
|
||||||
fn memdb_get(key string) string
|
fn memdb_get(key string) string
|
||||||
|
|||||||
39
aiprompts/ai_instruct/generate_player_for_models.md
Normal file
39
aiprompts/ai_instruct/generate_player_for_models.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
generate specs for /Users/despiegk/code/github/freeflowuniverse/herolib/lib/circles/actions
|
||||||
|
|
||||||
|
use mcp
|
||||||
|
|
||||||
|
get the output of it un actions/specs.v
|
||||||
|
|
||||||
|
then use these specs.v
|
||||||
|
|
||||||
|
to generate play command instructions see @3_heroscript_vlang.md
|
||||||
|
|
||||||
|
this play command gets heroscript in and will then call the methods for actions as are ONLY in @lib/circles/actions/db
|
||||||
|
|
||||||
|
so the play only calls the methods in @lib/circles/actions/db
|
||||||
|
|
||||||
|
|
||||||
|
# put the play commands in
|
||||||
|
|
||||||
|
/Users/despiegk/code/github/freeflowuniverse/herolib/lib/circles/actions/play
|
||||||
|
|
||||||
|
do one file in the module per action
|
||||||
|
|
||||||
|
each method is an action
|
||||||
|
|
||||||
|
put them all on one Struct called Player
|
||||||
|
in this Player we have a method per action
|
||||||
|
|
||||||
|
Player has a property called actor: which is the name of the actor as is used in the heroscript
|
||||||
|
Player has also a output called return format which is enum for heroscript or json
|
||||||
|
|
||||||
|
input of the method - action is a params object
|
||||||
|
|
||||||
|
on player there is a method play which takes the text as input or playbook
|
||||||
|
|
||||||
|
if text then playbook is created
|
||||||
|
|
||||||
|
then we walk over all actions
|
||||||
|
|
||||||
|
all the ones starting with actions in this case are given to the right method
|
||||||
|
|
||||||
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:
|
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 ...
|
- 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
|
## to do argument parsing use following examples
|
||||||
|
|
||||||
```v
|
```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 os
|
||||||
import flag
|
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
|
## 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`:
|
An example `deploy.vsh`:
|
||||||
|
|
||||||
```v oksyntax
|
```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,
|
// 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
|
// 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
|
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
|
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
|
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
|
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
|
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
|
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
|
# Appendices
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
this is how we want example scripts to be, see the first line
|
this is how we want example scripts to be, see the first line
|
||||||
|
|
||||||
```vlang
|
```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
|
import freeflowuniverse.herolib.installers.sysadmintools.daguserver
|
||||||
|
|
||||||
|
|||||||
77
cfg/config.heroscript
Normal file
77
cfg/config.heroscript
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
!!docusaurus.config
|
||||||
|
name:"my-documentation"
|
||||||
|
title:"My Documentation Site"
|
||||||
|
tagline:"Documentation made simple with V and Docusaurus"
|
||||||
|
url:"https://docs.example.com"
|
||||||
|
url_home:"docs/"
|
||||||
|
base_url:"/"
|
||||||
|
favicon:"img/favicon.png"
|
||||||
|
image:"img/hero.png"
|
||||||
|
copyright:"© 2025 Example Organization"
|
||||||
|
|
||||||
|
!!docusaurus.config_meta
|
||||||
|
description:"Comprehensive documentation for our amazing project"
|
||||||
|
image:"https://docs.example.com/img/social-card.png"
|
||||||
|
title:"My Documentation | Official Docs"
|
||||||
|
|
||||||
|
!!docusaurus.ssh_connection
|
||||||
|
name:"production"
|
||||||
|
host:"example.com"
|
||||||
|
login:"deploy"
|
||||||
|
port:22
|
||||||
|
key_path:"~/.ssh/id_rsa"
|
||||||
|
|
||||||
|
!!docusaurus.build_dest
|
||||||
|
ssh_name:"production"
|
||||||
|
path:"/var/www/docs"
|
||||||
|
|
||||||
|
!!docusaurus.navbar
|
||||||
|
title:"My Project"
|
||||||
|
|
||||||
|
!!docusaurus.navbar_item
|
||||||
|
label:"Documentation"
|
||||||
|
href:"/docs"
|
||||||
|
position:"left"
|
||||||
|
|
||||||
|
!!docusaurus.navbar_item
|
||||||
|
label:"API"
|
||||||
|
href:"/api"
|
||||||
|
position:"left"
|
||||||
|
|
||||||
|
!!docusaurus.navbar_item
|
||||||
|
label:"GitHub"
|
||||||
|
href:"https://github.com/example/repo"
|
||||||
|
position:"right"
|
||||||
|
|
||||||
|
!!docusaurus.footer
|
||||||
|
style:"dark"
|
||||||
|
|
||||||
|
!!docusaurus.footer_item
|
||||||
|
title:"Documentation"
|
||||||
|
label:"Introduction"
|
||||||
|
to:"/docs"
|
||||||
|
|
||||||
|
!!docusaurus.footer_item
|
||||||
|
title:"Documentation"
|
||||||
|
label:"API Reference"
|
||||||
|
to:"/api"
|
||||||
|
|
||||||
|
!!docusaurus.footer_item
|
||||||
|
title:"Community"
|
||||||
|
label:"GitHub"
|
||||||
|
href:"https://github.com/example/repo"
|
||||||
|
|
||||||
|
!!docusaurus.footer_item
|
||||||
|
title:"Community"
|
||||||
|
label:"Discord"
|
||||||
|
href:"https://discord.gg/example"
|
||||||
|
|
||||||
|
!!docusaurus.footer_item
|
||||||
|
title:"More"
|
||||||
|
label:"Blog"
|
||||||
|
href:"https://blog.example.com"
|
||||||
|
|
||||||
|
!!docusaurus.import_source
|
||||||
|
url:"https://github.com/example/external-docs"
|
||||||
|
dest:"external"
|
||||||
|
replace:"PROJECT_NAME:My Project, VERSION:1.0.0"
|
||||||
3
cli/.gitignore
vendored
3
cli/.gitignore
vendored
@@ -1 +1,4 @@
|
|||||||
hero
|
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 -cg -w -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 -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import flag
|
import flag
|
||||||
@@ -45,7 +45,7 @@ compile_cmd := if os.user_os() == 'macos' {
|
|||||||
if prod_mode {
|
if prod_mode {
|
||||||
'v -enable-globals -w -n -prod hero.v'
|
'v -enable-globals -w -n -prod hero.v'
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
if prod_mode {
|
if prod_mode {
|
||||||
@@ -66,7 +66,7 @@ os.chmod('hero', 0o755) or { panic('Failed to make hero binary executable: ${err
|
|||||||
|
|
||||||
// Ensure destination directory exists
|
// Ensure destination directory exists
|
||||||
os.mkdir_all(os.dir(heropath)) or { panic('Failed to create directory ${os.dir(heropath)}: ${err}') }
|
os.mkdir_all(os.dir(heropath)) or { panic('Failed to create directory ${os.dir(heropath)}: ${err}') }
|
||||||
|
println(heropath)
|
||||||
// Copy to destination paths
|
// Copy to destination paths
|
||||||
os.cp('hero', heropath) or { panic('Failed to copy hero binary to ${heropath}: ${err}') }
|
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}') }
|
os.cp('hero', '/tmp/hero') or { panic('Failed to copy hero binary to /tmp/hero: ${err}') }
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ fn get_platform_id() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn read_secrets() ! {
|
fn read_secrets() ! {
|
||||||
secret_file := os.join_path(os.home_dir(), 'code/git.ourworld.tf/despiegk/hero_secrets/mysecrets.sh')
|
secret_file := os.join_path(os.home_dir(), 'code/git.threefold.info/despiegk/hero_secrets/mysecrets.sh')
|
||||||
if os.exists(secret_file) {
|
if os.exists(secret_file) {
|
||||||
println('Reading secrets from ${secret_file}')
|
println('Reading secrets from ${secret_file}')
|
||||||
content := os.read_file(secret_file)!
|
content := os.read_file(secret_file)!
|
||||||
@@ -89,5 +89,9 @@ fn hero_upload() ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
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) }
|
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**')
|
||||||
23
cli/hero.v
23
cli/hero.v
@@ -19,6 +19,25 @@ fn playcmds_do(path string) ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn do() ! {
|
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 {
|
if os.args.len == 2 {
|
||||||
mypath := os.args[1]
|
mypath := os.args[1]
|
||||||
if mypath.to_lower().ends_with('.hero') {
|
if mypath.to_lower().ends_with('.hero') {
|
||||||
@@ -31,7 +50,7 @@ fn do() ! {
|
|||||||
mut cmd := Command{
|
mut cmd := Command{
|
||||||
name: 'hero'
|
name: 'hero'
|
||||||
description: 'Your HERO toolset.'
|
description: 'Your HERO toolset.'
|
||||||
version: '2.0.0'
|
version: '1.0.26'
|
||||||
}
|
}
|
||||||
|
|
||||||
// herocmds.cmd_run_add_flags(mut cmd)
|
// herocmds.cmd_run_add_flags(mut cmd)
|
||||||
@@ -81,6 +100,8 @@ fn do() ! {
|
|||||||
// herocmds.cmd_zola(mut cmd)
|
// herocmds.cmd_zola(mut cmd)
|
||||||
// herocmds.cmd_juggler(mut cmd)
|
// herocmds.cmd_juggler(mut cmd)
|
||||||
herocmds.cmd_generator(mut cmd)
|
herocmds.cmd_generator(mut cmd)
|
||||||
|
herocmds.cmd_docusaurus(mut cmd)
|
||||||
|
herocmds.cmd_starlight(mut cmd)
|
||||||
// herocmds.cmd_docsorter(mut cmd)
|
// herocmds.cmd_docsorter(mut cmd)
|
||||||
// cmd.add_command(publishing.cmd_publisher(pre_func))
|
// cmd.add_command(publishing.cmd_publisher(pre_func))
|
||||||
cmd.setup()
|
cmd.setup()
|
||||||
|
|||||||
12
cli/vdo.v
Normal file
12
cli/vdo.v
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.mcp.v_do
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Create and start the MCP server
|
||||||
|
mut server := v_do.new_server()
|
||||||
|
server.start() or {
|
||||||
|
eprintln('Error starting server: $err')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
480
compile.sh
Executable file
480
compile.sh
Executable file
@@ -0,0 +1,480 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# compile.sh - Script to compile each module in the herolib/lib directory
|
||||||
|
# This script compiles each module in the lib directory to ensure they build correctly
|
||||||
|
|
||||||
|
set -e # Exit on error
|
||||||
|
|
||||||
|
# Default settings
|
||||||
|
CONCURRENT=false
|
||||||
|
MAX_JOBS=4 # Default number of concurrent jobs
|
||||||
|
|
||||||
|
# Parse command line arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-c|--concurrent)
|
||||||
|
CONCURRENT=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-j|--jobs)
|
||||||
|
MAX_JOBS="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
echo "Usage: $0 [options]"
|
||||||
|
echo "Options:"
|
||||||
|
echo " -c, --concurrent Enable concurrent compilation"
|
||||||
|
echo " -j, --jobs N Set maximum number of concurrent jobs (default: 4)"
|
||||||
|
echo " -h, --help Show this help message"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
echo "Use -h or --help for usage information"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Color codes for output
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Get the directory of this script
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
LIB_DIR="$SCRIPT_DIR/lib"
|
||||||
|
|
||||||
|
# V compiler flags based on the project's test script
|
||||||
|
V_FLAGS="-stats -enable-globals -n -w -gc none -d use_openssl -shared"
|
||||||
|
|
||||||
|
# Log file for compilation results
|
||||||
|
LOG_FILE="$SCRIPT_DIR/compile_results.log"
|
||||||
|
> "$LOG_FILE" # Clear log file
|
||||||
|
|
||||||
|
# Summary log file
|
||||||
|
SUMMARY_FILE="$SCRIPT_DIR/compile_summary.log"
|
||||||
|
> "$SUMMARY_FILE" # Clear summary file
|
||||||
|
|
||||||
|
# Cache directory for storing timestamps of last successful compilation
|
||||||
|
CACHE_DIR="$SCRIPT_DIR/.compile_cache"
|
||||||
|
mkdir -p "$CACHE_DIR"
|
||||||
|
|
||||||
|
# Create temporary directory for compiled binaries
|
||||||
|
mkdir -p "$SCRIPT_DIR/tmp"
|
||||||
|
|
||||||
|
# Create a directory for temporary output files
|
||||||
|
TEMP_DIR="$SCRIPT_DIR/.temp_compile"
|
||||||
|
mkdir -p "$TEMP_DIR"
|
||||||
|
|
||||||
|
# Trap for cleaning up on exit
|
||||||
|
cleanup() {
|
||||||
|
echo "Cleaning up..."
|
||||||
|
# Kill any remaining child processes
|
||||||
|
jobs -p | xargs kill -9 2>/dev/null || true
|
||||||
|
# Remove temporary directories
|
||||||
|
rm -rf "$TEMP_DIR" "$SCRIPT_DIR/tmp" 2>/dev/null || true
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set up traps for various signals
|
||||||
|
trap cleanup EXIT INT TERM
|
||||||
|
|
||||||
|
# Define modules to skip entirely due to known compilation issues
|
||||||
|
SKIP_MODULES=("flist" "openai" "mycelium" "vastai" "rclone" "sendgrid" "mailclient" "ipapi" "runpod" "postgresql_client" "meilisearch" "livekit" "wireguard" "_archive" "clients")
|
||||||
|
|
||||||
|
# Function to check if a module should be skipped
|
||||||
|
should_skip_module() {
|
||||||
|
local module_name="$1"
|
||||||
|
|
||||||
|
for skip_module in "${SKIP_MODULES[@]}"; do
|
||||||
|
if [[ "$module_name" == "$skip_module" ]]; then
|
||||||
|
return 0 # true, should skip
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1 # false, should not skip
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check if a module needs recompilation
|
||||||
|
needs_module_recompilation() {
|
||||||
|
local module_path="$1"
|
||||||
|
local module_name="$(basename "$module_path")"
|
||||||
|
local cache_file="$CACHE_DIR/$module_name.timestamp"
|
||||||
|
|
||||||
|
# If cache file doesn't exist, module needs recompilation
|
||||||
|
if [ ! -f "$cache_file" ]; then
|
||||||
|
return 0 # true, needs recompilation
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if any .v file in the module is newer than the last compilation
|
||||||
|
if find "$module_path" -name "*.v" -type f -newer "$cache_file" | grep -q .; then
|
||||||
|
return 0 # true, needs recompilation
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1 # false, doesn't need recompilation
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to update the cache timestamp for a module
|
||||||
|
update_module_cache() {
|
||||||
|
local module_path="$1"
|
||||||
|
local module_name="$(basename "$module_path")"
|
||||||
|
local cache_file="$CACHE_DIR/$module_name.timestamp"
|
||||||
|
|
||||||
|
# Update the timestamp
|
||||||
|
touch "$cache_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check if a directory is a module (contains .v files directly, not just in subdirectories)
|
||||||
|
is_module() {
|
||||||
|
local dir_path="$1"
|
||||||
|
|
||||||
|
# Check if there are any .v files directly in this directory (not in subdirectories)
|
||||||
|
if [ -n "$(find "$dir_path" -maxdepth 1 -name "*.v" -type f -print -quit)" ]; then
|
||||||
|
return 0 # true, is a module
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1 # false, not a module
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to compile a module
|
||||||
|
compile_module() {
|
||||||
|
local module_path="$1"
|
||||||
|
local module_name="$(basename "$module_path")"
|
||||||
|
local output_file="$TEMP_DIR/${module_name}.log"
|
||||||
|
local result_file="$TEMP_DIR/${module_name}.result"
|
||||||
|
|
||||||
|
# Initialize the result file
|
||||||
|
echo "pending" > "$result_file"
|
||||||
|
|
||||||
|
# Check if this module should be skipped
|
||||||
|
if should_skip_module "$module_name"; then
|
||||||
|
echo "Skipping problematic module: $module_name" > "$output_file"
|
||||||
|
echo "skipped|${module_path#$LIB_DIR/}|" >> "$SUMMARY_FILE"
|
||||||
|
echo "skipped" > "$result_file"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if this is actually a module (has .v files directly)
|
||||||
|
if ! is_module "$module_path"; then
|
||||||
|
echo "$module_name is not a module (no direct .v files), skipping" > "$output_file"
|
||||||
|
echo "not_module|${module_path#$LIB_DIR/}|" >> "$SUMMARY_FILE"
|
||||||
|
echo "skipped" > "$result_file"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Compiling module: $module_name" > "$output_file"
|
||||||
|
|
||||||
|
# Check if the module needs recompilation
|
||||||
|
if ! needs_module_recompilation "$module_path"; then
|
||||||
|
echo " No changes detected in $module_name, skipping compilation" >> "$output_file"
|
||||||
|
echo "cached|${module_path#$LIB_DIR/}|" >> "$SUMMARY_FILE"
|
||||||
|
echo "cached" > "$result_file"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Record start time
|
||||||
|
local start_time=$(date +%s.%N)
|
||||||
|
|
||||||
|
# Try to compile the module - redirect both stdout and stderr to the output file
|
||||||
|
if v $V_FLAGS -o "$SCRIPT_DIR/tmp/$module_name" "$module_path" >> "$output_file" 2>&1; then
|
||||||
|
# Calculate compilation time
|
||||||
|
local end_time=$(date +%s.%N)
|
||||||
|
local compile_time=$(echo "$end_time - $start_time" | bc)
|
||||||
|
|
||||||
|
echo " Successfully compiled $module_name" >> "$output_file"
|
||||||
|
# Update the cache timestamp
|
||||||
|
update_module_cache "$module_path"
|
||||||
|
|
||||||
|
# Log result
|
||||||
|
echo "success|${module_path#$LIB_DIR/}|$compile_time" >> "$SUMMARY_FILE"
|
||||||
|
echo "success" > "$result_file"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo " Failed to compile $module_name" >> "$output_file"
|
||||||
|
|
||||||
|
# Log result
|
||||||
|
echo "failed|${module_path#$LIB_DIR/}|" >> "$SUMMARY_FILE"
|
||||||
|
echo "failed" > "$result_file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to run modules in parallel with a maximum number of concurrent jobs
|
||||||
|
run_parallel() {
|
||||||
|
local modules=("$@")
|
||||||
|
local total=${#modules[@]}
|
||||||
|
local completed=0
|
||||||
|
local running=0
|
||||||
|
local pids=()
|
||||||
|
local module_indices=()
|
||||||
|
|
||||||
|
echo "Running $total modules in parallel (max $MAX_JOBS jobs at once)"
|
||||||
|
|
||||||
|
# Initialize arrays to track jobs
|
||||||
|
for ((i=0; i<$total; i++)); do
|
||||||
|
pids[$i]=-1
|
||||||
|
done
|
||||||
|
|
||||||
|
# Start initial batch of jobs
|
||||||
|
local next_job=0
|
||||||
|
while [[ $next_job -lt $total && $running -lt $MAX_JOBS ]]; do
|
||||||
|
compile_module "${modules[$next_job]}" > /dev/null 2>&1 &
|
||||||
|
pids[$next_job]=$!
|
||||||
|
((running++))
|
||||||
|
((next_job++))
|
||||||
|
done
|
||||||
|
|
||||||
|
# Display progress indicator
|
||||||
|
display_progress() {
|
||||||
|
local current=$1
|
||||||
|
local total=$2
|
||||||
|
local percent=$((current * 100 / total))
|
||||||
|
local bar_length=50
|
||||||
|
local filled_length=$((percent * bar_length / 100))
|
||||||
|
|
||||||
|
printf "\r[" >&2
|
||||||
|
for ((i=0; i<bar_length; i++)); do
|
||||||
|
if [ $i -lt $filled_length ]; then
|
||||||
|
printf "#" >&2
|
||||||
|
else
|
||||||
|
printf " " >&2
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
printf "] %d%% (%d/%d modules)" $percent $current $total >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
# Monitor running jobs and start new ones as needed
|
||||||
|
while [[ $completed -lt $total ]]; do
|
||||||
|
display_progress $completed $total
|
||||||
|
|
||||||
|
# Check for completed jobs
|
||||||
|
for ((i=0; i<$total; i++)); do
|
||||||
|
if [[ ${pids[$i]} -gt 0 ]]; then
|
||||||
|
if ! kill -0 ${pids[$i]} 2>/dev/null; then
|
||||||
|
# Job completed
|
||||||
|
local module_path="${modules[$i]}"
|
||||||
|
local module_name="$(basename "$module_path")"
|
||||||
|
local output_file="$TEMP_DIR/${module_name}.log"
|
||||||
|
|
||||||
|
# Add output to log file
|
||||||
|
if [[ -f "$output_file" ]]; then
|
||||||
|
cat "$output_file" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Mark job as completed
|
||||||
|
pids[$i]=-2
|
||||||
|
((completed++))
|
||||||
|
((running--))
|
||||||
|
|
||||||
|
# Start a new job if available
|
||||||
|
if [[ $next_job -lt $total ]]; then
|
||||||
|
compile_module "${modules[$next_job]}" > /dev/null 2>&1 &
|
||||||
|
pids[$next_job]=$!
|
||||||
|
((running++))
|
||||||
|
((next_job++))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Brief pause to avoid excessive CPU usage
|
||||||
|
sleep 0.1
|
||||||
|
done
|
||||||
|
|
||||||
|
# Clear the progress line
|
||||||
|
printf "\r%$(tput cols)s\r" ""
|
||||||
|
|
||||||
|
# Wait for any remaining background jobs
|
||||||
|
wait
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to find all modules in a directory (recursively)
|
||||||
|
find_modules() {
|
||||||
|
local dir_path="$1"
|
||||||
|
local modules=()
|
||||||
|
|
||||||
|
# Check if this directory is a module itself
|
||||||
|
if is_module "$dir_path"; then
|
||||||
|
modules+=("$dir_path")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Look for modules in subdirectories (only one level deep)
|
||||||
|
for subdir in "$dir_path"/*; do
|
||||||
|
if [ -d "$subdir" ]; then
|
||||||
|
local subdir_name="$(basename "$subdir")"
|
||||||
|
|
||||||
|
# Skip if this is in the skip list
|
||||||
|
if should_skip_module "$subdir_name"; then
|
||||||
|
echo -e "${YELLOW}Skipping problematic module: $subdir_name${NC}"
|
||||||
|
echo "Skipping problematic module: $subdir_name" >> "$LOG_FILE"
|
||||||
|
echo "skipped|${subdir#$LIB_DIR/}|" >> "$SUMMARY_FILE"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if this subdirectory is a module
|
||||||
|
if is_module "$subdir"; then
|
||||||
|
modules+=("$subdir")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "${modules[@]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "===== Starting compilation of all modules in lib ====="
|
||||||
|
echo "===== Starting compilation of all modules in lib =====" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Define priority modules to compile first
|
||||||
|
PRIORITY_MODULES=("biz" "builder" "core" "crystallib" "jsonrpc" "jsonschema")
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Attempting to compile each module as a whole...${NC}"
|
||||||
|
echo "Attempting to compile each module as a whole..." >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Collect all modules to compile
|
||||||
|
all_modules=()
|
||||||
|
|
||||||
|
# First add priority modules
|
||||||
|
for module_name in "${PRIORITY_MODULES[@]}"; do
|
||||||
|
module_dir="$LIB_DIR/$module_name"
|
||||||
|
if [ -d "$module_dir" ]; then
|
||||||
|
# Find all modules in this directory
|
||||||
|
modules=($(find_modules "$module_dir"))
|
||||||
|
all_modules+=("${modules[@]}")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Then add remaining modules
|
||||||
|
for module_dir in "$LIB_DIR"/*; do
|
||||||
|
if [ -d "$module_dir" ]; then
|
||||||
|
module_name="$(basename "$module_dir")"
|
||||||
|
# Skip modules already compiled in priority list
|
||||||
|
if [[ " ${PRIORITY_MODULES[*]} " =~ " $module_name " ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Find all modules in this directory
|
||||||
|
modules=($(find_modules "$module_dir"))
|
||||||
|
all_modules+=("${modules[@]}")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Debug: print all modules found
|
||||||
|
echo "Found ${#all_modules[@]} modules to compile" >> "$LOG_FILE"
|
||||||
|
for module in "${all_modules[@]}"; do
|
||||||
|
echo " - $module" >> "$LOG_FILE"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Compile modules (either in parallel or sequentially)
|
||||||
|
if $CONCURRENT; then
|
||||||
|
run_parallel "${all_modules[@]}"
|
||||||
|
else
|
||||||
|
# Sequential compilation
|
||||||
|
for module_path in "${all_modules[@]}"; do
|
||||||
|
# Display module being compiled
|
||||||
|
module_name="$(basename "$module_path")"
|
||||||
|
echo -e "${YELLOW}Compiling module: $module_name${NC}"
|
||||||
|
|
||||||
|
# Compile the module
|
||||||
|
compile_module "$module_path" > /dev/null 2>&1
|
||||||
|
|
||||||
|
# Display result
|
||||||
|
output_file="$TEMP_DIR/${module_name}.log"
|
||||||
|
result_file="$TEMP_DIR/${module_name}.result"
|
||||||
|
|
||||||
|
if [[ -f "$output_file" ]]; then
|
||||||
|
cat "$output_file" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Display with color based on result
|
||||||
|
result=$(cat "$result_file")
|
||||||
|
if [[ "$result" == "success" ]]; then
|
||||||
|
echo -e "${GREEN} Successfully compiled $module_name${NC}"
|
||||||
|
elif [[ "$result" == "failed" ]]; then
|
||||||
|
echo -e "${RED} Failed to compile $module_name${NC}"
|
||||||
|
elif [[ "$result" == "cached" ]]; then
|
||||||
|
echo -e "${GREEN} No changes detected in $module_name, skipping compilation${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW} Skipped $module_name${NC}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Count successes and failures
|
||||||
|
success_count=$(grep -c "^success|" "$SUMMARY_FILE" || echo 0)
|
||||||
|
failure_count=$(grep -c "^failed|" "$SUMMARY_FILE" || echo 0)
|
||||||
|
cached_count=$(grep -c "^cached|" "$SUMMARY_FILE" || echo 0)
|
||||||
|
skipped_count=$(grep -c "^skipped|" "$SUMMARY_FILE" || echo 0)
|
||||||
|
not_module_count=$(grep -c "^not_module|" "$SUMMARY_FILE" || echo 0)
|
||||||
|
|
||||||
|
echo "===== Compilation complete ====="
|
||||||
|
echo -e "${GREEN}Successfully compiled: $success_count modules${NC}"
|
||||||
|
echo -e "${GREEN}Cached (no changes): $cached_count modules${NC}"
|
||||||
|
echo -e "${YELLOW}Skipped: $skipped_count modules${NC}"
|
||||||
|
echo -e "${YELLOW}Not modules: $not_module_count directories${NC}"
|
||||||
|
echo -e "${RED}Failed to compile: $failure_count modules${NC}"
|
||||||
|
echo "See $LOG_FILE for detailed compilation results"
|
||||||
|
|
||||||
|
echo "===== Compilation complete =====" >> "$LOG_FILE"
|
||||||
|
echo "Successfully compiled: $success_count modules" >> "$LOG_FILE"
|
||||||
|
echo "Cached (no changes): $cached_count modules" >> "$LOG_FILE"
|
||||||
|
echo "Skipped: $skipped_count modules" >> "$LOG_FILE"
|
||||||
|
echo "Not modules: $not_module_count directories" >> "$LOG_FILE"
|
||||||
|
echo "Failed to compile: $failure_count modules" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Print detailed summary
|
||||||
|
echo ""
|
||||||
|
echo "===== Module Compilation Summary ====="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Print successful modules first, sorted by compilation time
|
||||||
|
echo "Successful compilations:"
|
||||||
|
grep "^success|" "$SUMMARY_FILE" | sort -t'|' -k3,3n | while IFS='|' read -r status path time; do
|
||||||
|
# Color code based on compilation time
|
||||||
|
time_color="$GREEN"
|
||||||
|
if (( $(echo "$time > 10.0" | bc -l) )); then
|
||||||
|
time_color="$RED"
|
||||||
|
elif (( $(echo "$time > 1.0" | bc -l) )); then
|
||||||
|
time_color="$YELLOW"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "✅ $path\t${time_color}${time}s${NC}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Print cached modules
|
||||||
|
echo ""
|
||||||
|
echo "Cached modules (no changes detected):"
|
||||||
|
grep "^cached|" "$SUMMARY_FILE" | sort | while IFS='|' read -r status path time; do
|
||||||
|
echo -e "🔄 $path\t${GREEN}CACHED${NC}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Print skipped modules
|
||||||
|
echo ""
|
||||||
|
echo "Skipped modules:"
|
||||||
|
grep "^skipped|" "$SUMMARY_FILE" | sort | while IFS='|' read -r status path time; do
|
||||||
|
echo -e "⏭️ $path\t${YELLOW}SKIPPED${NC}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Print not modules
|
||||||
|
echo ""
|
||||||
|
echo "Not modules (directories without direct .v files):"
|
||||||
|
grep "^not_module|" "$SUMMARY_FILE" | sort | while IFS='|' read -r status path time; do
|
||||||
|
echo -e "📁 $path\t${YELLOW}NOT MODULE${NC}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Print failed modules
|
||||||
|
echo ""
|
||||||
|
echo "Failed modules:"
|
||||||
|
grep "^failed|" "$SUMMARY_FILE" | sort | while IFS='|' read -r status path time; do
|
||||||
|
echo -e "❌ $path\t${RED}FAILED${NC}"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "===== End of Summary ====="
|
||||||
|
|
||||||
|
# Exit with error code if any module failed to compile
|
||||||
|
if [ $failure_count -gt 0 ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
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
|
import os
|
||||||
|
|
||||||
@@ -26,9 +26,9 @@ os.chdir(herolib_path) or {
|
|||||||
panic('Failed to change directory to herolib: ${err}')
|
panic('Failed to change directory to herolib: ${err}')
|
||||||
}
|
}
|
||||||
|
|
||||||
os.rmdir_all('_docs') or {}
|
os.mkdir_all('_docs') or {}
|
||||||
os.rmdir_all('docs') or {}
|
os.mkdir_all('docs') or {}
|
||||||
os.rmdir_all('vdocs') or {}
|
os.mkdir_all('vdocs') or {}
|
||||||
|
|
||||||
// Generate HTML documentation
|
// Generate HTML documentation
|
||||||
println('Generating HTML documentation...')
|
println('Generating HTML documentation...')
|
||||||
@@ -42,13 +42,12 @@ os.chdir(abs_dir_of_script) or {
|
|||||||
|
|
||||||
// Generate Markdown documentation
|
// Generate Markdown documentation
|
||||||
println('Generating 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 {
|
// if os.system('v doc -m -no-color -f md -o ../vdocs/v/') != 0 {
|
||||||
// panic('Failed to generate V markdown documentation')
|
// 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')
|
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!')
|
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 exec -it herolib /scripts/cleanup.sh
|
||||||
|
|
||||||
docker export herolib | gzip > ${HOME}/Downloads/herolib.tar.gz
|
|
||||||
|
# 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
|
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 os
|
||||||
import flag
|
import flag
|
||||||
@@ -64,7 +64,7 @@ os.symlink('${abs_dir_of_script}/lib', '${os.home_dir()}/.vmodules/freeflowunive
|
|||||||
println('Herolib installation completed successfully!')
|
println('Herolib installation completed successfully!')
|
||||||
|
|
||||||
// Add vtest alias
|
// 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}')
|
eprintln('Failed to add vtest alias: ${err}')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,9 +73,9 @@ function sshknownkeysadd {
|
|||||||
then
|
then
|
||||||
ssh-keyscan github.com >> ~/.ssh/known_hosts
|
ssh-keyscan github.com >> ~/.ssh/known_hosts
|
||||||
fi
|
fi
|
||||||
if ! grep git.ourworld.tf ~/.ssh/known_hosts > /dev/null
|
if ! grep git.threefold.info ~/.ssh/known_hosts > /dev/null
|
||||||
then
|
then
|
||||||
ssh-keyscan git.ourworld.tf >> ~/.ssh/known_hosts
|
ssh-keyscan git.threefold.info >> ~/.ssh/known_hosts
|
||||||
fi
|
fi
|
||||||
git config --global pull.rebase false
|
git config --global pull.rebase false
|
||||||
|
|
||||||
|
|||||||
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:
|
When creating V scripts (.vsh files), always use the following shebang:
|
||||||
|
|
||||||
```bash
|
```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:
|
This shebang ensures:
|
||||||
|
|||||||
71
examples/aiexamples/groq.vsh
Executable file
71
examples/aiexamples/groq.vsh
Executable file
@@ -0,0 +1,71 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
module main
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.clients.openai
|
||||||
|
import os
|
||||||
|
|
||||||
|
fn test1(mut client openai.OpenAI) ! {
|
||||||
|
instruction := '
|
||||||
|
You are a template language converter. You convert Pug templates to Jet templates.
|
||||||
|
|
||||||
|
The target template language, Jet, is defined as follows:
|
||||||
|
'
|
||||||
|
|
||||||
|
// Create a chat completion request
|
||||||
|
res := client.chat_completion(
|
||||||
|
msgs: openai.Messages{
|
||||||
|
messages: [
|
||||||
|
openai.Message{
|
||||||
|
role: .user
|
||||||
|
content: 'What are the key differences between Groq and other AI inference providers?'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)!
|
||||||
|
|
||||||
|
// Print the response
|
||||||
|
println('\nGroq AI Response:')
|
||||||
|
println('==================')
|
||||||
|
println(res.choices[0].message.content)
|
||||||
|
println('\nUsage Statistics:')
|
||||||
|
println('Prompt tokens: ${res.usage.prompt_tokens}')
|
||||||
|
println('Completion tokens: ${res.usage.completion_tokens}')
|
||||||
|
println('Total tokens: ${res.usage.total_tokens}')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test2(mut client openai.OpenAI) ! {
|
||||||
|
// Create a chat completion request
|
||||||
|
res := client.chat_completion(
|
||||||
|
model: 'deepseek-r1-distill-llama-70b'
|
||||||
|
msgs: openai.Messages{
|
||||||
|
messages: [
|
||||||
|
openai.Message{
|
||||||
|
role: .user
|
||||||
|
content: 'A story of 10 lines?'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)!
|
||||||
|
|
||||||
|
println('\nGroq AI Response:')
|
||||||
|
println('==================')
|
||||||
|
println(res.choices[0].message.content)
|
||||||
|
println('\nUsage Statistics:')
|
||||||
|
println('Prompt tokens: ${res.usage.prompt_tokens}')
|
||||||
|
println('Completion tokens: ${res.usage.completion_tokens}')
|
||||||
|
println('Total tokens: ${res.usage.total_tokens}')
|
||||||
|
}
|
||||||
|
|
||||||
|
println("
|
||||||
|
TO USE:
|
||||||
|
export AIKEY='gsk_...'
|
||||||
|
export AIURL='https://api.groq.com/openai/v1'
|
||||||
|
export AIMODEL='llama-3.3-70b-versatile'
|
||||||
|
")
|
||||||
|
|
||||||
|
mut client := openai.get(name: 'test')!
|
||||||
|
println(client)
|
||||||
|
|
||||||
|
// test1(mut client)!
|
||||||
|
test2(mut client)!
|
||||||
7
examples/aiexamples/jetconvertor.vsh
Executable file
7
examples/aiexamples/jetconvertor.vsh
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.mcp.aitools
|
||||||
|
|
||||||
|
// aitools.convert_pug("/root/code/github/freeflowuniverse/herolauncher/pkg/herolauncher/web/templates/admin")!
|
||||||
|
|
||||||
|
aitools.convert_pug('/root/code/github/freeflowuniverse/herolauncher/pkg/zaz/webui/templates')!
|
||||||
86
examples/aiexamples/jina.vsh
Executable file
86
examples/aiexamples/jina.vsh
Executable file
@@ -0,0 +1,86 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.clients.jina
|
||||||
|
|
||||||
|
mut jina_client := jina.get()!
|
||||||
|
health := jina_client.health()!
|
||||||
|
println('Server health: ${health}')
|
||||||
|
|
||||||
|
// Create embeddings
|
||||||
|
embeddings := jina_client.create_embeddings(
|
||||||
|
input: ['Hello', 'World']
|
||||||
|
model: .jina_embeddings_v3
|
||||||
|
task: 'separation'
|
||||||
|
) or { panic('Error while creating embeddings: ${err}') }
|
||||||
|
|
||||||
|
println('Created embeddings: ${embeddings}')
|
||||||
|
|
||||||
|
// Rerank
|
||||||
|
rerank_result := jina_client.rerank(
|
||||||
|
model: .reranker_v2_base_multilingual
|
||||||
|
query: 'skincare products'
|
||||||
|
documents: ['Product A', 'Product B', 'Product C']
|
||||||
|
top_n: 2
|
||||||
|
) or { panic('Error while reranking: ${err}') }
|
||||||
|
|
||||||
|
println('Rerank result: ${rerank_result}')
|
||||||
|
|
||||||
|
// Train
|
||||||
|
train_result := jina_client.train(
|
||||||
|
model: .jina_clip_v1
|
||||||
|
input: [
|
||||||
|
jina.TrainingExample{
|
||||||
|
text: 'Sample text'
|
||||||
|
label: 'positive'
|
||||||
|
},
|
||||||
|
jina.TrainingExample{
|
||||||
|
image: 'https://letsenhance.io/static/73136da51c245e80edc6ccfe44888a99/1015f/MainBefore.jpg'
|
||||||
|
label: 'negative'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
) or { panic('Error while training: ${err}') }
|
||||||
|
|
||||||
|
println('Train result: ${train_result}')
|
||||||
|
|
||||||
|
// Classify
|
||||||
|
classify_result := jina_client.classify(
|
||||||
|
model: .jina_clip_v1
|
||||||
|
input: [
|
||||||
|
jina.ClassificationInput{
|
||||||
|
text: 'A photo of a cat'
|
||||||
|
},
|
||||||
|
jina.ClassificationInput{
|
||||||
|
image: 'https://letsenhance.io/static/73136da51c245e80edc6ccfe44888a99/1015f/MainBefore.jpg'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
labels: ['cat', 'dog']
|
||||||
|
) or { panic('Error while classifying: ${err}') }
|
||||||
|
|
||||||
|
println('Classification result: ${classify_result}')
|
||||||
|
|
||||||
|
// List classifiers
|
||||||
|
classifiers := jina_client.list_classifiers() or { panic('Error fetching classifiers: ${err}') }
|
||||||
|
println('Classifiers: ${classifiers}')
|
||||||
|
|
||||||
|
// Delete classifier
|
||||||
|
delete_result := jina_client.delete_classifier(classifier_id: classifiers[0].classifier_id) or {
|
||||||
|
panic('Error deleting classifier: ${err}')
|
||||||
|
}
|
||||||
|
println('Delete result: ${delete_result}')
|
||||||
|
|
||||||
|
// Create multi vector
|
||||||
|
multi_vector := jina_client.create_multi_vector(
|
||||||
|
input: [
|
||||||
|
jina.MultiVectorTextDoc{
|
||||||
|
text: 'Hello world'
|
||||||
|
input_type: .document
|
||||||
|
},
|
||||||
|
jina.MultiVectorTextDoc{
|
||||||
|
text: "What's up?"
|
||||||
|
input_type: .query
|
||||||
|
},
|
||||||
|
]
|
||||||
|
embedding_type: ['float']
|
||||||
|
// dimensions: 96
|
||||||
|
)!
|
||||||
|
println('Multi vector: ${multi_vector}')
|
||||||
128
examples/aiexamples/qdrant.vsh
Executable file
128
examples/aiexamples/qdrant.vsh
Executable file
@@ -0,0 +1,128 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.clients.qdrant
|
||||||
|
import freeflowuniverse.herolib.installers.db.qdrant_installer
|
||||||
|
import freeflowuniverse.herolib.core.httpconnection
|
||||||
|
import rand
|
||||||
|
import os
|
||||||
|
|
||||||
|
println('Starting Qdrant example script')
|
||||||
|
|
||||||
|
// Print environment information
|
||||||
|
println('Current directory: ${os.getwd()}')
|
||||||
|
println('Home directory: ${os.home_dir()}')
|
||||||
|
|
||||||
|
mut i := qdrant_installer.get()!
|
||||||
|
i.install()!
|
||||||
|
|
||||||
|
// 1. Get the qdrant client
|
||||||
|
println('Getting Qdrant client...')
|
||||||
|
mut qdrant_client := qdrant.get()!
|
||||||
|
println('Qdrant client URL: ${qdrant_client.url}')
|
||||||
|
|
||||||
|
// Check if Qdrant server is running
|
||||||
|
println('Checking Qdrant server health...')
|
||||||
|
health := qdrant_client.health_check() or {
|
||||||
|
println('Error checking health: ${err}')
|
||||||
|
false
|
||||||
|
}
|
||||||
|
println('Qdrant server health: ${health}')
|
||||||
|
|
||||||
|
// Get service info
|
||||||
|
println('Getting Qdrant service info...')
|
||||||
|
service_info := qdrant_client.get_service_info() or {
|
||||||
|
println('Error getting service info: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
println('Qdrant service info: ${service_info}')
|
||||||
|
|
||||||
|
// 2. Generate collection name
|
||||||
|
collection_name := 'collection_' + rand.string(4)
|
||||||
|
println('Generated collection name: ${collection_name}')
|
||||||
|
|
||||||
|
// 3. Create a new collection
|
||||||
|
println('Creating collection...')
|
||||||
|
created_collection := qdrant_client.create_collection(
|
||||||
|
collection_name: collection_name
|
||||||
|
size: 15
|
||||||
|
distance: 'Cosine'
|
||||||
|
) or {
|
||||||
|
println('Error creating collection: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
println('Created Collection: ${created_collection}')
|
||||||
|
|
||||||
|
// 4. Get the created collection
|
||||||
|
println('Getting collection...')
|
||||||
|
get_collection := qdrant_client.get_collection(
|
||||||
|
collection_name: collection_name
|
||||||
|
) or {
|
||||||
|
println('Error getting collection: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
println('Get Collection: ${get_collection}')
|
||||||
|
|
||||||
|
// 5. List all collections
|
||||||
|
println('Listing collections...')
|
||||||
|
list_collection := qdrant_client.list_collections() or {
|
||||||
|
println('Error listing collections: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
println('List Collection: ${list_collection}')
|
||||||
|
|
||||||
|
// 6. Check collection existence
|
||||||
|
println('Checking collection existence...')
|
||||||
|
collection_existence := qdrant_client.is_collection_exists(
|
||||||
|
collection_name: collection_name
|
||||||
|
) or {
|
||||||
|
println('Error checking collection existence: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
println('Collection Existence: ${collection_existence}')
|
||||||
|
|
||||||
|
// 7. Retrieve points
|
||||||
|
println('Retrieving points...')
|
||||||
|
collection_points := qdrant_client.retrieve_points(
|
||||||
|
collection_name: collection_name
|
||||||
|
ids: [
|
||||||
|
0,
|
||||||
|
3,
|
||||||
|
100,
|
||||||
|
]
|
||||||
|
) or {
|
||||||
|
println('Error retrieving points: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
println('Collection Points: ${collection_points}')
|
||||||
|
|
||||||
|
// 8. Upsert points
|
||||||
|
println('Upserting points...')
|
||||||
|
upsert_points := qdrant_client.upsert_points(
|
||||||
|
collection_name: collection_name
|
||||||
|
points: [
|
||||||
|
qdrant.Point{
|
||||||
|
payload: {
|
||||||
|
'key': 'value'
|
||||||
|
}
|
||||||
|
vector: [1.0, 2.0, 3.0]
|
||||||
|
},
|
||||||
|
qdrant.Point{
|
||||||
|
payload: {
|
||||||
|
'key': 'value'
|
||||||
|
}
|
||||||
|
vector: [4.0, 5.0, 6.0]
|
||||||
|
},
|
||||||
|
qdrant.Point{
|
||||||
|
payload: {
|
||||||
|
'key': 'value'
|
||||||
|
}
|
||||||
|
vector: [7.0, 8.0, 9.0]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
) or {
|
||||||
|
println('Error upserting points: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
println('Upsert Points: ${upsert_points}')
|
||||||
|
|
||||||
|
println('Qdrant example script completed successfully')
|
||||||
3
examples/baobab/generator/basic/.gitignore
vendored
Normal file
3
examples/baobab/generator/basic/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
methods.v
|
||||||
|
pet_store_actor
|
||||||
|
docs
|
||||||
9
examples/baobab/generator/basic/README.md
Normal file
9
examples/baobab/generator/basic/README.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Actor Generation Examples
|
||||||
|
|
||||||
|
## `generate_methods.vsh`
|
||||||
|
|
||||||
|
This example generates actor method prototypes from an actor specification.
|
||||||
|
|
||||||
|
## `generate_actor_module.vsh`
|
||||||
|
|
||||||
|
This example generates an entire actor module from an actor specification with the support for the specified interfaces.
|
||||||
22
examples/baobab/generator/basic/generate_actor_module.vsh
Executable file
22
examples/baobab/generator/basic/generate_actor_module.vsh
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.baobab.generator
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.schemas.openrpc
|
||||||
|
import os
|
||||||
|
|
||||||
|
const example_dir = os.dir(@FILE)
|
||||||
|
const openrpc_spec_path = os.join_path(example_dir, 'openrpc.json')
|
||||||
|
|
||||||
|
// the actor specification obtained from the OpenRPC Specification
|
||||||
|
openrpc_spec := openrpc.new(path: openrpc_spec_path)!
|
||||||
|
actor_spec := specification.from_openrpc(openrpc_spec)!
|
||||||
|
|
||||||
|
actor_module := generator.generate_actor_module(actor_spec,
|
||||||
|
interfaces: [.openrpc]
|
||||||
|
)!
|
||||||
|
|
||||||
|
actor_module.write(example_dir,
|
||||||
|
format: true
|
||||||
|
overwrite: true
|
||||||
|
)!
|
||||||
19
examples/baobab/generator/basic/generate_methods.vsh
Executable file
19
examples/baobab/generator/basic/generate_methods.vsh
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.baobab.generator
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.schemas.openrpc
|
||||||
|
import os
|
||||||
|
|
||||||
|
const example_dir = os.dir(@FILE)
|
||||||
|
const openrpc_spec_path = os.join_path(example_dir, 'openrpc.json')
|
||||||
|
|
||||||
|
// the actor specification obtained from the OpenRPC Specification
|
||||||
|
openrpc_spec := openrpc.new(path: openrpc_spec_path)!
|
||||||
|
actor_spec := specification.from_openrpc(openrpc_spec)!
|
||||||
|
|
||||||
|
methods_file := generator.generate_methods_file(actor_spec)!
|
||||||
|
methods_file.write(example_dir,
|
||||||
|
format: true
|
||||||
|
overwrite: true
|
||||||
|
)!
|
||||||
19
examples/baobab/generator/basic/generate_openrpc_file.vsh
Executable file
19
examples/baobab/generator/basic/generate_openrpc_file.vsh
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.baobab.generator
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.schemas.openrpc
|
||||||
|
import os
|
||||||
|
|
||||||
|
const example_dir = os.dir(@FILE)
|
||||||
|
const openrpc_spec_path = os.join_path(example_dir, 'openrpc.json')
|
||||||
|
|
||||||
|
// the actor specification obtained from the OpenRPC Specification
|
||||||
|
openrpc_spec_ := openrpc.new(path: openrpc_spec_path)!
|
||||||
|
actor_spec := specification.from_openrpc(openrpc_spec_)!
|
||||||
|
openrpc_spec := actor_spec.to_openrpc()
|
||||||
|
|
||||||
|
openrpc_file := generator.generate_openrpc_file(openrpc_spec)!
|
||||||
|
openrpc_file.write(os.join_path(example_dir, 'docs'),
|
||||||
|
overwrite: true
|
||||||
|
)!
|
||||||
132
examples/baobab/generator/basic/openrpc.json
Normal file
132
examples/baobab/generator/basic/openrpc.json
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
{
|
||||||
|
"openrpc": "1.0.0",
|
||||||
|
"info": {
|
||||||
|
"title": "PetStore",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"methods": [
|
||||||
|
{
|
||||||
|
"name": "GetPets",
|
||||||
|
"description": "finds pets in the system that the user has access to by tags and within a limit",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "tags",
|
||||||
|
"description": "tags to filter by",
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "limit",
|
||||||
|
"description": "maximum number of results to return",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"result": {
|
||||||
|
"name": "pet_list",
|
||||||
|
"description": "all pets from the system, that mathes the tags",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#\/components\/schemas\/Pet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CreatePet",
|
||||||
|
"description": "creates a new pet in the store. Duplicates are allowed.",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "new_pet",
|
||||||
|
"description": "Pet to add to the store.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#\/components\/schemas\/NewPet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"result": {
|
||||||
|
"name": "pet",
|
||||||
|
"description": "the newly created pet",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#\/components\/schemas\/Pet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GetPetById",
|
||||||
|
"description": "gets a pet based on a single ID, if the user has access to the pet",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"description": "ID of pet to fetch",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"result": {
|
||||||
|
"name": "pet",
|
||||||
|
"description": "pet response",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#\/components\/schemas\/Pet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DeletePetById",
|
||||||
|
"description": "deletes a single pet based on the ID supplied",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"description": "ID of pet to delete",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"result": {
|
||||||
|
"name": "pet",
|
||||||
|
"description": "pet deleted",
|
||||||
|
"schema": {
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"NewPet": {
|
||||||
|
"title": "NewPet",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Pet": {
|
||||||
|
"title": "Pet",
|
||||||
|
"description": "a pet struct that represents a pet",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"description": "name of the pet",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"description": "a tag of the pet, helps finding pet",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"description": "unique indentifier",
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
examples/baobab/generator/geomind_poc/.gitignore
vendored
Normal file
3
examples/baobab/generator/geomind_poc/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
merchant
|
||||||
|
profiler
|
||||||
|
farmer
|
||||||
344
examples/baobab/generator/geomind_poc/farmer.json
Normal file
344
examples/baobab/generator/geomind_poc/farmer.json
Normal file
@@ -0,0 +1,344 @@
|
|||||||
|
{
|
||||||
|
"openapi": "3.0.1",
|
||||||
|
"info": {
|
||||||
|
"title": "Farmer",
|
||||||
|
"description": "API for managing farms and nodes, tracking rewards, capacity, and location.",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "http://localhost:8080",
|
||||||
|
"description": "Local development server"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"Farm": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Amsterdam Data Center"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Enterprise-grade data center with renewable energy focus"
|
||||||
|
},
|
||||||
|
"owner": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"owner"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Node": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "n47ac10b-58cc-4372-a567-0e02b2c3d479"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "High-performance GPU compute node with 4x NVIDIA A100"
|
||||||
|
},
|
||||||
|
"farm_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"$ref": "#/components/schemas/Location"
|
||||||
|
},
|
||||||
|
"capacity": {
|
||||||
|
"$ref": "#/components/schemas/Capacity"
|
||||||
|
},
|
||||||
|
"grid_version": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "3.16.2"
|
||||||
|
},
|
||||||
|
"reward": {
|
||||||
|
"$ref": "#/components/schemas/Reward"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"description",
|
||||||
|
"farm_id",
|
||||||
|
"location",
|
||||||
|
"capacity",
|
||||||
|
"reward"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Location": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"coordinates": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "52.3740, 4.8897"
|
||||||
|
},
|
||||||
|
"continent": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Europe"
|
||||||
|
},
|
||||||
|
"country": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Netherlands"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"coordinates",
|
||||||
|
"continent",
|
||||||
|
"country"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Capacity": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"cpu": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 128
|
||||||
|
},
|
||||||
|
"memory_gb": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 1024
|
||||||
|
},
|
||||||
|
"storage_tb": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"cpu",
|
||||||
|
"memory_gb",
|
||||||
|
"storage_tb"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Reward": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"reward_promised": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double",
|
||||||
|
"example": 25000.50
|
||||||
|
},
|
||||||
|
"reward_given": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double",
|
||||||
|
"example": 12500.25
|
||||||
|
},
|
||||||
|
"duration_months": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 36
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"reward_promised",
|
||||||
|
"reward_given",
|
||||||
|
"duration_months"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"NodeStats": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"node_id": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32",
|
||||||
|
"example": "42"
|
||||||
|
},
|
||||||
|
"uptime_hours": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 8760
|
||||||
|
},
|
||||||
|
"bandwidth_gb": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 25000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"node_id",
|
||||||
|
"uptime_hours",
|
||||||
|
"bandwidth_gb"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"/farms": {
|
||||||
|
"get": {
|
||||||
|
"summary": "List all farms",
|
||||||
|
"operationId": "getFarms",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "List of farms",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Farm"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": [
|
||||||
|
{
|
||||||
|
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
||||||
|
"name": "Amsterdam Data Center",
|
||||||
|
"description": "Enterprise-grade data center with renewable energy focus",
|
||||||
|
"owner": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "d47ac10b-58cc-4372-a567-0e02b2c3d480",
|
||||||
|
"name": "Dubai Compute Hub",
|
||||||
|
"description": "High-density compute farm with advanced cooling",
|
||||||
|
"owner": "0x842d35Cc6634C0532925a3b844Bc454e4438f55f"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/farms/{farmId}/nodes": {
|
||||||
|
"get": {
|
||||||
|
"summary": "List nodes in a farm",
|
||||||
|
"operationId": "getNodesByFarm",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "farmId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"example": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "List of nodes in the farm",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Node"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": [
|
||||||
|
{
|
||||||
|
"id": "n47ac10b-58cc-4372-a567-0e02b2c3d479",
|
||||||
|
"description": "High-performance GPU compute node with 4x NVIDIA A100",
|
||||||
|
"farm_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
||||||
|
"location": {
|
||||||
|
"coordinates": "52.3740, 4.8897",
|
||||||
|
"continent": "Europe",
|
||||||
|
"country": "Netherlands"
|
||||||
|
},
|
||||||
|
"capacity": {
|
||||||
|
"cpu": 128,
|
||||||
|
"memory_gb": 1024,
|
||||||
|
"storage_tb": 100
|
||||||
|
},
|
||||||
|
"grid_version": "3.16.2",
|
||||||
|
"reward": {
|
||||||
|
"reward_promised": 25000.50,
|
||||||
|
"reward_given": 12500.25,
|
||||||
|
"duration_months": 36
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Farm not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 404
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Farm with ID f47ac10b-58cc-4372-a567-0e02b2c3d479 not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/nodes/{nodeId}/stats": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get node statistics",
|
||||||
|
"operationId": "getNodeStats",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "nodeId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32"
|
||||||
|
},
|
||||||
|
"example": "42"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Node statistics",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/NodeStats"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"node_id": "42",
|
||||||
|
"uptime_hours": 8760,
|
||||||
|
"bandwidth_gb": 25000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Node not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 404
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Node with ID n47ac10b-58cc-4372-a567-0e02b2c3d479 not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
examples/baobab/generator/geomind_poc/generate
Executable file
BIN
examples/baobab/generator/geomind_poc/generate
Executable file
Binary file not shown.
23
examples/baobab/generator/geomind_poc/generate.vsh
Executable file
23
examples/baobab/generator/geomind_poc/generate.vsh
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.baobab.generator
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.schemas.openapi
|
||||||
|
import os
|
||||||
|
|
||||||
|
const example_dir = os.dir(@FILE)
|
||||||
|
const specs = ['merchant', 'profiler', 'farmer']
|
||||||
|
|
||||||
|
for spec in specs {
|
||||||
|
openapi_spec_path := os.join_path(example_dir, '${spec}.json')
|
||||||
|
openapi_spec := openapi.new(path: openapi_spec_path, process: true)!
|
||||||
|
actor_spec := specification.from_openapi(openapi_spec)!
|
||||||
|
actor_module := generator.generate_actor_folder(actor_spec,
|
||||||
|
interfaces: [.openapi, .http]
|
||||||
|
)!
|
||||||
|
actor_module.write(example_dir,
|
||||||
|
format: true
|
||||||
|
overwrite: true
|
||||||
|
compile: false
|
||||||
|
)!
|
||||||
|
}
|
||||||
997
examples/baobab/generator/geomind_poc/merchant.json
Normal file
997
examples/baobab/generator/geomind_poc/merchant.json
Normal file
@@ -0,0 +1,997 @@
|
|||||||
|
{
|
||||||
|
"openapi": "3.0.1",
|
||||||
|
"info": {
|
||||||
|
"title": "Merchant",
|
||||||
|
"description": "API for e-commerce operations including stores, products, and orders",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"servers": [{
|
||||||
|
"url": "http://localhost:8080",
|
||||||
|
"description": "Local development server"
|
||||||
|
},{
|
||||||
|
"url": "http://localhost:8080/openapi/example",
|
||||||
|
"description": "Local example server"
|
||||||
|
}],
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"Store": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174000"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Tech Gadgets Store"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Premium electronics and gadgets retailer"
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "contact@techgadgets.com"
|
||||||
|
},
|
||||||
|
"active": {
|
||||||
|
"type": "boolean",
|
||||||
|
"example": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"contact",
|
||||||
|
"active"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ProductComponentTemplate": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174001"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "4K Display Panel"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "55-inch 4K UHD Display Panel"
|
||||||
|
},
|
||||||
|
"specs": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"resolution": "3840x2160",
|
||||||
|
"refreshRate": "120Hz",
|
||||||
|
"panel_type": "OLED"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"price": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double",
|
||||||
|
"example": 599.99
|
||||||
|
},
|
||||||
|
"currency": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[A-Z]{3}$",
|
||||||
|
"example": "USD"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"price",
|
||||||
|
"currency"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ProductTemplate": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174002"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Smart TV 55-inch"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "55-inch Smart TV with 4K Display"
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/ProductComponentTemplate"
|
||||||
|
},
|
||||||
|
"example": [
|
||||||
|
{
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174001",
|
||||||
|
"name": "4K Display Panel",
|
||||||
|
"description": "55-inch 4K UHD Display Panel",
|
||||||
|
"specs": {
|
||||||
|
"resolution": "3840x2160",
|
||||||
|
"refreshRate": "120Hz"
|
||||||
|
},
|
||||||
|
"price": 599.99,
|
||||||
|
"currency": "USD"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"store_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174000"
|
||||||
|
},
|
||||||
|
"category": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Electronics"
|
||||||
|
},
|
||||||
|
"active": {
|
||||||
|
"type": "boolean",
|
||||||
|
"example": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"components",
|
||||||
|
"store_id",
|
||||||
|
"active"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Product": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174003"
|
||||||
|
},
|
||||||
|
"template_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174002"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Smart TV 55-inch"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "55-inch Smart TV with 4K Display"
|
||||||
|
},
|
||||||
|
"price": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double",
|
||||||
|
"example": 899.99
|
||||||
|
},
|
||||||
|
"currency": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[A-Z]{3}$",
|
||||||
|
"example": "USD"
|
||||||
|
},
|
||||||
|
"store_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174000"
|
||||||
|
},
|
||||||
|
"stock_quantity": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"example": 50
|
||||||
|
},
|
||||||
|
"available": {
|
||||||
|
"type": "boolean",
|
||||||
|
"example": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"template_id",
|
||||||
|
"name",
|
||||||
|
"price",
|
||||||
|
"currency",
|
||||||
|
"store_id",
|
||||||
|
"stock_quantity",
|
||||||
|
"available"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"OrderItem": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"product_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174003"
|
||||||
|
},
|
||||||
|
"quantity": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
"example": 2
|
||||||
|
},
|
||||||
|
"price": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double",
|
||||||
|
"example": 899.99
|
||||||
|
},
|
||||||
|
"currency": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[A-Z]{3}$",
|
||||||
|
"example": "USD"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"product_id",
|
||||||
|
"quantity",
|
||||||
|
"price",
|
||||||
|
"currency"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Order": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174004"
|
||||||
|
},
|
||||||
|
"customer_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174005"
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/OrderItem"
|
||||||
|
},
|
||||||
|
"example": [
|
||||||
|
{
|
||||||
|
"product_id": "123e4567-e89b-12d3-a456-426614174003",
|
||||||
|
"quantity": 2,
|
||||||
|
"price": 899.99,
|
||||||
|
"currency": "USD"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"total_amount": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double",
|
||||||
|
"example": 1799.98
|
||||||
|
},
|
||||||
|
"currency": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[A-Z]{3}$",
|
||||||
|
"example": "USD"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"pending",
|
||||||
|
"confirmed",
|
||||||
|
"shipped",
|
||||||
|
"delivered"
|
||||||
|
],
|
||||||
|
"example": "pending"
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time",
|
||||||
|
"example": "2024-02-10T10:30:00Z"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time",
|
||||||
|
"example": "2024-02-10T10:30:00Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"customer_id",
|
||||||
|
"items",
|
||||||
|
"total_amount",
|
||||||
|
"currency",
|
||||||
|
"status",
|
||||||
|
"created_at",
|
||||||
|
"updated_at"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Error": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 404
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Resource not found"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"code",
|
||||||
|
"message"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"/stores": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Create a new store",
|
||||||
|
"operationId": "createStore",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Tech Gadgets Store"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Premium electronics and gadgets retailer"
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "contact@techgadgets.com"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"contact"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"newStore": {
|
||||||
|
"summary": "Create a new electronics store",
|
||||||
|
"value": {
|
||||||
|
"name": "Tech Gadgets Store",
|
||||||
|
"description": "Premium electronics and gadgets retailer",
|
||||||
|
"contact": "contact@techgadgets.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Store created successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Store"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174000",
|
||||||
|
"name": "Tech Gadgets Store",
|
||||||
|
"description": "Premium electronics and gadgets retailer",
|
||||||
|
"contact": "contact@techgadgets.com",
|
||||||
|
"active": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Invalid input",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"code": 400,
|
||||||
|
"message": "Invalid store data provided"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/products/templates/components": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Create a new product component template",
|
||||||
|
"operationId": "createProductComponentTemplate",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"specs": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"price": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"currency": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"price",
|
||||||
|
"currency"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"displayPanel": {
|
||||||
|
"summary": "Create a display panel component",
|
||||||
|
"value": {
|
||||||
|
"name": "4K Display Panel",
|
||||||
|
"description": "55-inch 4K UHD Display Panel",
|
||||||
|
"specs": {
|
||||||
|
"resolution": "3840x2160",
|
||||||
|
"refreshRate": "120Hz",
|
||||||
|
"panel_type": "OLED"
|
||||||
|
},
|
||||||
|
"price": 599.99,
|
||||||
|
"currency": "USD"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Component template created successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ProductComponentTemplate"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174001",
|
||||||
|
"name": "4K Display Panel",
|
||||||
|
"description": "55-inch 4K UHD Display Panel",
|
||||||
|
"specs": {
|
||||||
|
"resolution": "3840x2160",
|
||||||
|
"refreshRate": "120Hz",
|
||||||
|
"panel_type": "OLED"
|
||||||
|
},
|
||||||
|
"price": 599.99,
|
||||||
|
"currency": "USD"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Invalid input",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"code": 400,
|
||||||
|
"message": "Invalid component template data"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/products/templates": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Create a new product template",
|
||||||
|
"operationId": "createProductTemplate",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"store_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"category": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"components",
|
||||||
|
"store_id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"smartTV": {
|
||||||
|
"summary": "Create a Smart TV template",
|
||||||
|
"value": {
|
||||||
|
"name": "Smart TV 55-inch",
|
||||||
|
"description": "55-inch Smart TV with 4K Display",
|
||||||
|
"components": [
|
||||||
|
"123e4567-e89b-12d3-a456-426614174001"
|
||||||
|
],
|
||||||
|
"store_id": "123e4567-e89b-12d3-a456-426614174000",
|
||||||
|
"category": "Electronics"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Product template created successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ProductTemplate"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174002",
|
||||||
|
"name": "Smart TV 55-inch",
|
||||||
|
"description": "55-inch Smart TV with 4K Display",
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174001",
|
||||||
|
"name": "4K Display Panel",
|
||||||
|
"description": "55-inch 4K UHD Display Panel",
|
||||||
|
"specs": {
|
||||||
|
"resolution": "3840x2160",
|
||||||
|
"refreshRate": "120Hz"
|
||||||
|
},
|
||||||
|
"price": 599.99,
|
||||||
|
"currency": "USD"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"store_id": "123e4567-e89b-12d3-a456-426614174000",
|
||||||
|
"category": "Electronics",
|
||||||
|
"active": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Store not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"code": 404,
|
||||||
|
"message": "Store not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/products": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Create a new product from template",
|
||||||
|
"operationId": "createProduct",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"template_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"store_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"stock_quantity": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"template_id",
|
||||||
|
"store_id",
|
||||||
|
"stock_quantity"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"newProduct": {
|
||||||
|
"summary": "Create a new Smart TV product",
|
||||||
|
"value": {
|
||||||
|
"template_id": "123e4567-e89b-12d3-a456-426614174002",
|
||||||
|
"store_id": "123e4567-e89b-12d3-a456-426614174000",
|
||||||
|
"stock_quantity": 50
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Product created successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Product"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174003",
|
||||||
|
"template_id": "123e4567-e89b-12d3-a456-426614174002",
|
||||||
|
"name": "Smart TV 55-inch",
|
||||||
|
"description": "55-inch Smart TV with 4K Display",
|
||||||
|
"price": 899.99,
|
||||||
|
"currency": "USD",
|
||||||
|
"store_id": "123e4567-e89b-12d3-a456-426614174000",
|
||||||
|
"stock_quantity": 50,
|
||||||
|
"available": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Template or store not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"code": 404,
|
||||||
|
"message": "Product template not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/orders": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Create a new order",
|
||||||
|
"operationId": "createOrder",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"customer_id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/OrderItem"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"customer_id",
|
||||||
|
"items"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"newOrder": {
|
||||||
|
"summary": "Create an order for two Smart TVs",
|
||||||
|
"value": {
|
||||||
|
"customer_id": "123e4567-e89b-12d3-a456-426614174005",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"product_id": "123e4567-e89b-12d3-a456-426614174003",
|
||||||
|
"quantity": 2,
|
||||||
|
"price": 899.99,
|
||||||
|
"currency": "USD"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Order created successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Order"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174004",
|
||||||
|
"customer_id": "123e4567-e89b-12d3-a456-426614174005",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"product_id": "123e4567-e89b-12d3-a456-426614174003",
|
||||||
|
"quantity": 2,
|
||||||
|
"price": 899.99,
|
||||||
|
"currency": "USD"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total_amount": 1799.98,
|
||||||
|
"currency": "USD",
|
||||||
|
"status": "pending",
|
||||||
|
"created_at": "2024-02-10T10:30:00Z",
|
||||||
|
"updated_at": "2024-02-10T10:30:00Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Invalid input or insufficient stock",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"code": 400,
|
||||||
|
"message": "Insufficient stock for product"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/orders/{orderId}/status": {
|
||||||
|
"put": {
|
||||||
|
"summary": "Update order status",
|
||||||
|
"operationId": "updateOrderStatus",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "orderId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174004"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"pending",
|
||||||
|
"confirmed",
|
||||||
|
"shipped",
|
||||||
|
"delivered"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"status"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"updateStatus": {
|
||||||
|
"summary": "Update order to shipped status",
|
||||||
|
"value": {
|
||||||
|
"status": "shipped"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Order status updated successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Order"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174004",
|
||||||
|
"customer_id": "123e4567-e89b-12d3-a456-426614174005",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"product_id": "123e4567-e89b-12d3-a456-426614174003",
|
||||||
|
"quantity": 2,
|
||||||
|
"price": 899.99,
|
||||||
|
"currency": "USD"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total_amount": 1799.98,
|
||||||
|
"currency": "USD",
|
||||||
|
"status": "shipped",
|
||||||
|
"created_at": "2024-02-10T10:30:00Z",
|
||||||
|
"updated_at": "2024-02-10T10:35:00Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Order not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"code": 404,
|
||||||
|
"message": "Order not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/stores/{storeId}/products": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get all products for a store",
|
||||||
|
"operationId": "getStoreProducts",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "storeId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174000"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "List of store's products",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Product"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": [
|
||||||
|
{
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174003",
|
||||||
|
"template_id": "123e4567-e89b-12d3-a456-426614174002",
|
||||||
|
"name": "Smart TV 55-inch",
|
||||||
|
"description": "55-inch Smart TV with 4K Display",
|
||||||
|
"price": 899.99,
|
||||||
|
"currency": "USD",
|
||||||
|
"store_id": "123e4567-e89b-12d3-a456-426614174000",
|
||||||
|
"stock_quantity": 48,
|
||||||
|
"available": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Store not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"code": 404,
|
||||||
|
"message": "Store not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/stores/{storeId}/orders": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get all orders for a store's products",
|
||||||
|
"operationId": "getStoreOrders",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "storeId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174000"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "List of orders containing store's products",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Order"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": [
|
||||||
|
{
|
||||||
|
"id": "123e4567-e89b-12d3-a456-426614174004",
|
||||||
|
"customer_id": "123e4567-e89b-12d3-a456-426614174005",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"product_id": "123e4567-e89b-12d3-a456-426614174003",
|
||||||
|
"quantity": 2,
|
||||||
|
"price": 899.99,
|
||||||
|
"currency": "USD"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total_amount": 1799.98,
|
||||||
|
"currency": "USD",
|
||||||
|
"status": "shipped",
|
||||||
|
"created_at": "2024-02-10T10:30:00Z",
|
||||||
|
"updated_at": "2024-02-10T10:35:00Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Store not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"code": 404,
|
||||||
|
"message": "Store not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
81
examples/baobab/generator/geomind_poc/model.v
Normal file
81
examples/baobab/generator/geomind_poc/model.v
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
module geomind_poc
|
||||||
|
|
||||||
|
pub struct Merchant {
|
||||||
|
pub:
|
||||||
|
id string
|
||||||
|
name string
|
||||||
|
description string
|
||||||
|
contact string
|
||||||
|
active bool
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ProductComponentTemplate {
|
||||||
|
pub:
|
||||||
|
id string
|
||||||
|
name string
|
||||||
|
description string
|
||||||
|
// technical specifications
|
||||||
|
specs map[string]string
|
||||||
|
// price per unit
|
||||||
|
price f64
|
||||||
|
// currency code (e.g., 'USD', 'EUR')
|
||||||
|
currency string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ProductTemplate {
|
||||||
|
pub:
|
||||||
|
id string
|
||||||
|
name string
|
||||||
|
description string
|
||||||
|
// components that make up this product template
|
||||||
|
components []ProductComponentTemplate
|
||||||
|
// merchant who created this template
|
||||||
|
merchant_id string
|
||||||
|
// category of the product (e.g., 'electronics', 'clothing')
|
||||||
|
category string
|
||||||
|
// whether this template is available for use
|
||||||
|
active bool
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Product {
|
||||||
|
pub:
|
||||||
|
id string
|
||||||
|
template_id string
|
||||||
|
// specific instance details that may differ from template
|
||||||
|
name string
|
||||||
|
description string
|
||||||
|
// actual price of this product instance
|
||||||
|
price f64
|
||||||
|
currency string
|
||||||
|
// merchant selling this product
|
||||||
|
merchant_id string
|
||||||
|
// current stock level
|
||||||
|
stock_quantity int
|
||||||
|
// whether this product is available for purchase
|
||||||
|
available bool
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OrderItem {
|
||||||
|
pub:
|
||||||
|
product_id string
|
||||||
|
quantity int
|
||||||
|
price f64
|
||||||
|
currency string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Order {
|
||||||
|
pub:
|
||||||
|
id string
|
||||||
|
// customer identifier
|
||||||
|
customer_id string
|
||||||
|
// items in the order
|
||||||
|
items []OrderItem
|
||||||
|
// total order amount
|
||||||
|
total_amount f64
|
||||||
|
currency string
|
||||||
|
// order status (e.g., 'pending', 'confirmed', 'shipped', 'delivered')
|
||||||
|
status string
|
||||||
|
// timestamps
|
||||||
|
created_at string
|
||||||
|
updated_at string
|
||||||
|
}
|
||||||
148
examples/baobab/generator/geomind_poc/play.v
Normal file
148
examples/baobab/generator/geomind_poc/play.v
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
module geomind_poc
|
||||||
|
|
||||||
|
import freeflowuniverse.crystallib.core.playbook { PlayBook }
|
||||||
|
|
||||||
|
// play_commerce processes heroscript actions for the commerce system
|
||||||
|
pub fn play_commerce(mut plbook PlayBook) ! {
|
||||||
|
commerce_actions := plbook.find(filter: 'commerce.')!
|
||||||
|
mut c := Commerce{}
|
||||||
|
|
||||||
|
for action in commerce_actions {
|
||||||
|
match action.name {
|
||||||
|
'merchant' {
|
||||||
|
mut p := action.params
|
||||||
|
merchant := c.create_merchant(
|
||||||
|
name: p.get('name')!
|
||||||
|
description: p.get_default('description', '')!
|
||||||
|
contact: p.get('contact')!
|
||||||
|
)!
|
||||||
|
println('Created merchant: ${merchant.name}')
|
||||||
|
}
|
||||||
|
'component' {
|
||||||
|
mut p := action.params
|
||||||
|
component := c.create_product_component_template(
|
||||||
|
name: p.get('name')!
|
||||||
|
description: p.get_default('description', '')!
|
||||||
|
specs: p.get_map()
|
||||||
|
price: p.get_float('price')!
|
||||||
|
currency: p.get('currency')!
|
||||||
|
)!
|
||||||
|
println('Created component: ${component.name}')
|
||||||
|
}
|
||||||
|
'template' {
|
||||||
|
mut p := action.params
|
||||||
|
// Get component IDs as a list
|
||||||
|
component_ids := p.get_list('components')!
|
||||||
|
// Convert component IDs to actual components
|
||||||
|
mut components := []ProductComponentTemplate{}
|
||||||
|
for id in component_ids {
|
||||||
|
// In a real implementation, you would fetch the component from storage
|
||||||
|
// For this example, we create a dummy component
|
||||||
|
component := ProductComponentTemplate{
|
||||||
|
id: id
|
||||||
|
name: 'Component'
|
||||||
|
description: ''
|
||||||
|
specs: map[string]string{}
|
||||||
|
price: 0
|
||||||
|
currency: 'USD'
|
||||||
|
}
|
||||||
|
components << component
|
||||||
|
}
|
||||||
|
|
||||||
|
template := c.create_product_template(
|
||||||
|
name: p.get('name')!
|
||||||
|
description: p.get_default('description', '')!
|
||||||
|
components: components
|
||||||
|
merchant_id: p.get('merchant_id')!
|
||||||
|
category: p.get_default('category', 'General')!
|
||||||
|
)!
|
||||||
|
println('Created template: ${template.name}')
|
||||||
|
}
|
||||||
|
'product' {
|
||||||
|
mut p := action.params
|
||||||
|
product := c.create_product(
|
||||||
|
template_id: p.get('template_id')!
|
||||||
|
merchant_id: p.get('merchant_id')!
|
||||||
|
stock_quantity: p.get_int('stock_quantity')!
|
||||||
|
)!
|
||||||
|
println('Created product: ${product.name} with stock: ${product.stock_quantity}')
|
||||||
|
}
|
||||||
|
'order' {
|
||||||
|
mut p := action.params
|
||||||
|
// Get order items as a list of maps
|
||||||
|
items_data := p.get_list('items')!
|
||||||
|
mut items := []OrderItem{}
|
||||||
|
for item_data in items_data {
|
||||||
|
// Parse item data (format: "product_id:quantity:price:currency")
|
||||||
|
parts := item_data.split(':')
|
||||||
|
if parts.len != 4 {
|
||||||
|
return error('Invalid order item format: ${item_data}')
|
||||||
|
}
|
||||||
|
item := OrderItem{
|
||||||
|
product_id: parts[0]
|
||||||
|
quantity: parts[1].int()
|
||||||
|
price: parts[2].f64()
|
||||||
|
currency: parts[3]
|
||||||
|
}
|
||||||
|
items << item
|
||||||
|
}
|
||||||
|
|
||||||
|
order := c.create_order(
|
||||||
|
customer_id: p.get('customer_id')!
|
||||||
|
items: items
|
||||||
|
)!
|
||||||
|
println('Created order: ${order.id} with ${order.items.len} items')
|
||||||
|
}
|
||||||
|
'update_order' {
|
||||||
|
mut p := action.params
|
||||||
|
order := c.update_order_status(
|
||||||
|
order_id: p.get('order_id')!
|
||||||
|
new_status: p.get('status')!
|
||||||
|
)!
|
||||||
|
println('Updated order ${order.id} status to: ${order.status}')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return error('Unknown commerce action: ${action.name}')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example heroscript usage:
|
||||||
|
/*
|
||||||
|
!!commerce.merchant
|
||||||
|
name: "Tech Gadgets Store"
|
||||||
|
description: "Premium electronics and gadgets retailer"
|
||||||
|
contact: "contact@techgadgets.com"
|
||||||
|
|
||||||
|
!!commerce.component
|
||||||
|
name: "4K Display Panel"
|
||||||
|
description: "55-inch 4K UHD Display Panel"
|
||||||
|
specs:
|
||||||
|
resolution: "3840x2160"
|
||||||
|
refreshRate: "120Hz"
|
||||||
|
panel_type: "OLED"
|
||||||
|
price: 599.99
|
||||||
|
currency: "USD"
|
||||||
|
|
||||||
|
!!commerce.template
|
||||||
|
name: "Smart TV 55-inch"
|
||||||
|
description: "55-inch Smart TV with 4K Display"
|
||||||
|
components: "123e4567-e89b-12d3-a456-426614174001"
|
||||||
|
merchant_id: "123e4567-e89b-12d3-a456-426614174000"
|
||||||
|
category: "Electronics"
|
||||||
|
|
||||||
|
!!commerce.product
|
||||||
|
template_id: "123e4567-e89b-12d3-a456-426614174002"
|
||||||
|
merchant_id: "123e4567-e89b-12d3-a456-426614174000"
|
||||||
|
stock_quantity: 50
|
||||||
|
|
||||||
|
!!commerce.order
|
||||||
|
customer_id: "123e4567-e89b-12d3-a456-426614174005"
|
||||||
|
items:
|
||||||
|
- "123e4567-e89b-12d3-a456-426614174003:2:899.99:USD"
|
||||||
|
|
||||||
|
!!commerce.update_order
|
||||||
|
order_id: "123e4567-e89b-12d3-a456-426614174004"
|
||||||
|
status: "shipped"
|
||||||
|
*/
|
||||||
286
examples/baobab/generator/geomind_poc/profiler.json
Normal file
286
examples/baobab/generator/geomind_poc/profiler.json
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
{
|
||||||
|
"openapi": "3.0.1",
|
||||||
|
"info": {
|
||||||
|
"title": "Profiler",
|
||||||
|
"description": "API for managing user profiles with name, public key, and KYC verification",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "http://localhost:8080",
|
||||||
|
"description": "Local development server"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"Profile": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"example": "123e4567-e89b-12d3-a456-426614174000"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Alice Doe"
|
||||||
|
},
|
||||||
|
"public_key": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "028a8f8b59f7283a47f9f6d4bc8176e847ad2b6c6d8bdfd041e5e7f3b4ac28c9fc"
|
||||||
|
},
|
||||||
|
"kyc_verified": {
|
||||||
|
"type": "boolean",
|
||||||
|
"example": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["id", "name", "public_key", "kyc_verified"]
|
||||||
|
},
|
||||||
|
"Error": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 400
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Invalid request"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["code", "message"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"/profiles": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Create a new profile",
|
||||||
|
"operationId": "createProfile",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Bob Smith"
|
||||||
|
},
|
||||||
|
"public_key": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "03a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["name", "public_key"]
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"newProfile": {
|
||||||
|
"summary": "Example of creating a new profile",
|
||||||
|
"value": {
|
||||||
|
"name": "Bob Smith",
|
||||||
|
"public_key": "03a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Profile created successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Profile"
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"successResponse": {
|
||||||
|
"summary": "Example of successful profile creation",
|
||||||
|
"value": {
|
||||||
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"name": "Bob Smith",
|
||||||
|
"public_key": "03a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
|
||||||
|
"kyc_verified": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Invalid input",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"invalidInput": {
|
||||||
|
"summary": "Example of invalid input error",
|
||||||
|
"value": {
|
||||||
|
"code": 400,
|
||||||
|
"message": "Invalid public key format"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/profiles/{profileId}": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get profile details",
|
||||||
|
"operationId": "getProfile",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "profileId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32"
|
||||||
|
},
|
||||||
|
"example": "42"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Profile retrieved successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Profile"
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"existingProfile": {
|
||||||
|
"summary": "Example of retrieved profile",
|
||||||
|
"value": {
|
||||||
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"name": "Bob Smith",
|
||||||
|
"public_key": "03a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
|
||||||
|
"kyc_verified": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Profile not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"notFound": {
|
||||||
|
"summary": "Example of profile not found error",
|
||||||
|
"value": {
|
||||||
|
"code": 404,
|
||||||
|
"message": "Profile with ID '550e8400-e29b-41d4-a716-446655440000' not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/profiles/{profileId}/kyc": {
|
||||||
|
"put": {
|
||||||
|
"summary": "Update KYC verification status",
|
||||||
|
"operationId": "updateKYCStatus",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "profileId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32"
|
||||||
|
},
|
||||||
|
"example": "42"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"kyc_verified": {
|
||||||
|
"type": "boolean",
|
||||||
|
"example": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["kyc_verified"]
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"verifyKYC": {
|
||||||
|
"summary": "Example of verifying KYC",
|
||||||
|
"value": {
|
||||||
|
"kyc_verified": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"unverifyKYC": {
|
||||||
|
"summary": "Example of unverifying KYC",
|
||||||
|
"value": {
|
||||||
|
"kyc_verified": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "KYC status updated successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Profile"
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"updatedProfile": {
|
||||||
|
"summary": "Example of profile with updated KYC status",
|
||||||
|
"value": {
|
||||||
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"name": "Bob Smith",
|
||||||
|
"public_key": "03a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
|
||||||
|
"kyc_verified": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Profile not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"notFound": {
|
||||||
|
"summary": "Example of profile not found error",
|
||||||
|
"value": {
|
||||||
|
"code": 404,
|
||||||
|
"message": "Profile with ID '550e8400-e29b-41d4-a716-446655440000' not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
191
examples/baobab/generator/geomind_poc/server.v
Normal file
191
examples/baobab/generator/geomind_poc/server.v
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
module geomind_poc
|
||||||
|
|
||||||
|
import crypto.rand
|
||||||
|
import time
|
||||||
|
|
||||||
|
// Commerce represents the main e-commerce server handling all operations
|
||||||
|
pub struct Commerce {
|
||||||
|
mut:
|
||||||
|
merchants map[string]Merchant
|
||||||
|
templates map[string]ProductTemplate
|
||||||
|
products map[string]Product
|
||||||
|
orders map[string]Order
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate_id creates a unique identifier
|
||||||
|
fn generate_id() string {
|
||||||
|
return rand.uuid_v4()
|
||||||
|
}
|
||||||
|
|
||||||
|
// create_merchant adds a new merchant to the system
|
||||||
|
pub fn (mut c Commerce) create_merchant(name string, description string, contact string) !Merchant {
|
||||||
|
merchant_id := generate_id()
|
||||||
|
merchant := Merchant{
|
||||||
|
id: merchant_id
|
||||||
|
name: name
|
||||||
|
description: description
|
||||||
|
contact: contact
|
||||||
|
active: true
|
||||||
|
}
|
||||||
|
c.merchants[merchant_id] = merchant
|
||||||
|
return merchant
|
||||||
|
}
|
||||||
|
|
||||||
|
// create_product_component_template creates a new component template
|
||||||
|
pub fn (mut c Commerce) create_product_component_template(name string, description string, specs map[string]string, price f64, currency string) !ProductComponentTemplate {
|
||||||
|
component := ProductComponentTemplate{
|
||||||
|
id: generate_id()
|
||||||
|
name: name
|
||||||
|
description: description
|
||||||
|
specs: specs
|
||||||
|
price: price
|
||||||
|
currency: currency
|
||||||
|
}
|
||||||
|
return component
|
||||||
|
}
|
||||||
|
|
||||||
|
// create_product_template creates a new product template
|
||||||
|
pub fn (mut c Commerce) create_product_template(name string, description string, components []ProductComponentTemplate, merchant_id string, category string) !ProductTemplate {
|
||||||
|
if merchant_id !in c.merchants {
|
||||||
|
return error('Merchant not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
template := ProductTemplate{
|
||||||
|
id: generate_id()
|
||||||
|
name: name
|
||||||
|
description: description
|
||||||
|
components: components
|
||||||
|
merchant_id: merchant_id
|
||||||
|
category: category
|
||||||
|
active: true
|
||||||
|
}
|
||||||
|
c.templates[template.id] = template
|
||||||
|
return template
|
||||||
|
}
|
||||||
|
|
||||||
|
// create_product creates a new product instance from a template
|
||||||
|
pub fn (mut c Commerce) create_product(template_id string, merchant_id string, stock_quantity int) !Product {
|
||||||
|
if template_id !in c.templates {
|
||||||
|
return error('Template not found')
|
||||||
|
}
|
||||||
|
if merchant_id !in c.merchants {
|
||||||
|
return error('Merchant not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
template := c.templates[template_id]
|
||||||
|
mut total_price := 0.0
|
||||||
|
for component in template.components {
|
||||||
|
total_price += component.price
|
||||||
|
}
|
||||||
|
|
||||||
|
product := Product{
|
||||||
|
id: generate_id()
|
||||||
|
template_id: template_id
|
||||||
|
name: template.name
|
||||||
|
description: template.description
|
||||||
|
price: total_price
|
||||||
|
currency: template.components[0].currency // assuming all components use same currency
|
||||||
|
merchant_id: merchant_id
|
||||||
|
stock_quantity: stock_quantity
|
||||||
|
available: true
|
||||||
|
}
|
||||||
|
c.products[product.id] = product
|
||||||
|
return product
|
||||||
|
}
|
||||||
|
|
||||||
|
// create_order creates a new order
|
||||||
|
pub fn (mut c Commerce) create_order(customer_id string, items []OrderItem) !Order {
|
||||||
|
mut total_amount := 0.0
|
||||||
|
mut currency := ''
|
||||||
|
|
||||||
|
for item in items {
|
||||||
|
if item.product_id !in c.products {
|
||||||
|
return error('Product not found: ${item.product_id}')
|
||||||
|
}
|
||||||
|
product := c.products[item.product_id]
|
||||||
|
if !product.available || product.stock_quantity < item.quantity {
|
||||||
|
return error('Product ${product.name} is not available in requested quantity')
|
||||||
|
}
|
||||||
|
total_amount += item.price * item.quantity
|
||||||
|
if currency == '' {
|
||||||
|
currency = item.currency
|
||||||
|
} else if currency != item.currency {
|
||||||
|
return error('Mixed currencies are not supported')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
order := Order{
|
||||||
|
id: generate_id()
|
||||||
|
customer_id: customer_id
|
||||||
|
items: items
|
||||||
|
total_amount: total_amount
|
||||||
|
currency: currency
|
||||||
|
status: 'pending'
|
||||||
|
created_at: time.now().str()
|
||||||
|
updated_at: time.now().str()
|
||||||
|
}
|
||||||
|
c.orders[order.id] = order
|
||||||
|
|
||||||
|
// Update stock quantities
|
||||||
|
for item in items {
|
||||||
|
mut product := c.products[item.product_id]
|
||||||
|
product.stock_quantity -= item.quantity
|
||||||
|
if product.stock_quantity == 0 {
|
||||||
|
product.available = false
|
||||||
|
}
|
||||||
|
c.products[item.product_id] = product
|
||||||
|
}
|
||||||
|
|
||||||
|
return order
|
||||||
|
}
|
||||||
|
|
||||||
|
// update_order_status updates the status of an order
|
||||||
|
pub fn (mut c Commerce) update_order_status(order_id string, new_status string) !Order {
|
||||||
|
if order_id !in c.orders {
|
||||||
|
return error('Order not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
mut order := c.orders[order_id]
|
||||||
|
order.status = new_status
|
||||||
|
order.updated_at = time.now().str()
|
||||||
|
c.orders[order_id] = order
|
||||||
|
return order
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_merchant_products returns all products for a given merchant
|
||||||
|
pub fn (c Commerce) get_merchant_products(merchant_id string) ![]Product {
|
||||||
|
if merchant_id !in c.merchants {
|
||||||
|
return error('Merchant not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
mut products := []Product{}
|
||||||
|
for product in c.products.values() {
|
||||||
|
if product.merchant_id == merchant_id {
|
||||||
|
products << product
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return products
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_merchant_orders returns all orders for products sold by a merchant
|
||||||
|
pub fn (c Commerce) get_merchant_orders(merchant_id string) ![]Order {
|
||||||
|
if merchant_id !in c.merchants {
|
||||||
|
return error('Merchant not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
mut orders := []Order{}
|
||||||
|
for order in c.orders.values() {
|
||||||
|
mut includes_merchant := false
|
||||||
|
for item in order.items {
|
||||||
|
product := c.products[item.product_id]
|
||||||
|
if product.merchant_id == merchant_id {
|
||||||
|
includes_merchant = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if includes_merchant {
|
||||||
|
orders << order
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return orders
|
||||||
|
}
|
||||||
57
examples/baobab/generator/geomind_poc/specs.md
Normal file
57
examples/baobab/generator/geomind_poc/specs.md
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
|
||||||
|
- profile management
|
||||||
|
- my name
|
||||||
|
- my pub key
|
||||||
|
- kyc
|
||||||
|
- ...
|
||||||
|
- product has components
|
||||||
|
- admin items
|
||||||
|
- supported_currencies
|
||||||
|
- countries
|
||||||
|
- continents
|
||||||
|
- farming
|
||||||
|
- farms
|
||||||
|
- default farm exists, users don't have to chose
|
||||||
|
- name
|
||||||
|
- description
|
||||||
|
- owner (pubkey)
|
||||||
|
- nodes
|
||||||
|
- reward (nr of INCA per month and time e.g. 24 months)
|
||||||
|
- reward_promised
|
||||||
|
- reward_given
|
||||||
|
- location
|
||||||
|
- coordinates
|
||||||
|
- continent
|
||||||
|
- country
|
||||||
|
- description
|
||||||
|
- farmid
|
||||||
|
- capacity (disks, mem, ...)
|
||||||
|
- gridversion (eg. 3.16)
|
||||||
|
- nodestats
|
||||||
|
- ...
|
||||||
|
- uptime
|
||||||
|
- bandwidth
|
||||||
|
- referral system
|
||||||
|
- coupons for discounts (one product can have multiple coupons and discounts)
|
||||||
|
- data gets imported with heroscript for what we sell
|
||||||
|
- minimal wallet function (BTC, CHF, MGLD, TFT, INCA)
|
||||||
|
- transactions, so they can see what they spend money on
|
||||||
|
- transfer/exchange
|
||||||
|
- basic communication (messages in/out)
|
||||||
|
- to allow us to communicate with user
|
||||||
|
- news
|
||||||
|
- basic news feed with topics, which we can set
|
||||||
|
- vdc
|
||||||
|
- name
|
||||||
|
- description (optional)
|
||||||
|
- spendinglimit
|
||||||
|
- currency per month, week or day e.g. 0.1 BTC/month
|
||||||
|
- each spending limit has name
|
||||||
|
- admins, list of pubkeys who have access to this and can add capacity to it, or delete, ...
|
||||||
|
- deployment
|
||||||
|
- deploymentid
|
||||||
|
- vdcid
|
||||||
|
- heroscript
|
||||||
|
- status
|
||||||
|
- links (name, link, description, category)
|
||||||
47
examples/baobab/generator/geomind_poc/test_commerce.vsh
Normal file
47
examples/baobab/generator/geomind_poc/test_commerce.vsh
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/env -S v
|
||||||
|
|
||||||
|
import freeflowuniverse.crystallib.core.playbook
|
||||||
|
import geomind_poc
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
test_script := "
|
||||||
|
!!commerce.merchant
|
||||||
|
name: 'Tech Gadgets Store'
|
||||||
|
description: 'Premium electronics and gadgets retailer'
|
||||||
|
contact: 'contact@techgadgets.com'
|
||||||
|
|
||||||
|
!!commerce.component
|
||||||
|
name: '4K Display Panel'
|
||||||
|
description: '55-inch 4K UHD Display Panel'
|
||||||
|
specs:
|
||||||
|
resolution: '3840x2160'
|
||||||
|
refreshRate: '120Hz'
|
||||||
|
panel_type: 'OLED'
|
||||||
|
price: 599.99
|
||||||
|
currency: 'USD'
|
||||||
|
|
||||||
|
!!commerce.template
|
||||||
|
name: 'Smart TV 55-inch'
|
||||||
|
description: '55-inch Smart TV with 4K Display'
|
||||||
|
components: '123e4567-e89b-12d3-a456-426614174001'
|
||||||
|
merchant_id: '123e4567-e89b-12d3-a456-426614174000'
|
||||||
|
category: 'Electronics'
|
||||||
|
|
||||||
|
!!commerce.product
|
||||||
|
template_id: '123e4567-e89b-12d3-a456-426614174002'
|
||||||
|
merchant_id: '123e4567-e89b-12d3-a456-426614174000'
|
||||||
|
stock_quantity: 50
|
||||||
|
|
||||||
|
!!commerce.order
|
||||||
|
customer_id: '123e4567-e89b-12d3-a456-426614174005'
|
||||||
|
items:
|
||||||
|
- '123e4567-e89b-12d3-a456-426614174003:2:899.99:USD'
|
||||||
|
|
||||||
|
!!commerce.update_order
|
||||||
|
order_id: '123e4567-e89b-12d3-a456-426614174004'
|
||||||
|
status: 'shipped'
|
||||||
|
"
|
||||||
|
|
||||||
|
mut plbook := playbook.new(text: test_script)!
|
||||||
|
geomind_poc.play_commerce(mut plbook)!
|
||||||
|
}
|
||||||
25
examples/baobab/generator/mcc_example.vsh
Executable file
25
examples/baobab/generator/mcc_example.vsh
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.baobab.generator
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.schemas.openapi
|
||||||
|
import os
|
||||||
|
|
||||||
|
const example_dir = os.join_path('${os.home_dir()}/code/github/freeflowuniverse/herolib/lib/circles/mcc',
|
||||||
|
'baobab')
|
||||||
|
const openapi_spec_path = os.join_path('${os.home_dir()}/code/github/freeflowuniverse/herolib/lib/circles/mcc',
|
||||||
|
'openapi.json')
|
||||||
|
|
||||||
|
// the actor specification obtained from the OpenRPC Specification
|
||||||
|
openapi_spec := openapi.new(path: openapi_spec_path)!
|
||||||
|
actor_spec := specification.from_openapi(openapi_spec)!
|
||||||
|
|
||||||
|
actor_module := generator.generate_actor_module(actor_spec,
|
||||||
|
interfaces: [.openapi, .http]
|
||||||
|
)!
|
||||||
|
|
||||||
|
actor_module.write(example_dir,
|
||||||
|
format: true
|
||||||
|
overwrite: true
|
||||||
|
compile: false
|
||||||
|
)!
|
||||||
4
examples/baobab/generator/openapi_e2e/.gitignore
vendored
Normal file
4
examples/baobab/generator/openapi_e2e/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
methods.v
|
||||||
|
meeting_scheduler_actor
|
||||||
|
generate_actor_module
|
||||||
|
src
|
||||||
27
examples/baobab/generator/openapi_e2e/generate_actor_module.vsh
Executable file
27
examples/baobab/generator/openapi_e2e/generate_actor_module.vsh
Executable file
@@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.baobab.generator
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.schemas.openapi
|
||||||
|
import os
|
||||||
|
|
||||||
|
const example_dir = os.dir(@FILE)
|
||||||
|
const openapi_spec_path = os.join_path(example_dir, 'openapi.json')
|
||||||
|
|
||||||
|
// the actor specification obtained from the OpenRPC Specification
|
||||||
|
openapi_spec := openapi.new(path: openapi_spec_path)!
|
||||||
|
actor_spec := specification.from_openapi(openapi_spec)!
|
||||||
|
|
||||||
|
println(actor_spec)
|
||||||
|
|
||||||
|
actor_module := generator.generate_actor_module(actor_spec,
|
||||||
|
interfaces: [.openapi, .http]
|
||||||
|
)!
|
||||||
|
|
||||||
|
actor_module.write(example_dir,
|
||||||
|
format: false
|
||||||
|
overwrite: true
|
||||||
|
compile: false
|
||||||
|
)!
|
||||||
|
|
||||||
|
// os.execvp('bash', ['${example_dir}/meeting_scheduler_actor/scripts/run.sh'])!
|
||||||
311
examples/baobab/generator/openapi_e2e/openapi.json
Normal file
311
examples/baobab/generator/openapi_e2e/openapi.json
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
{
|
||||||
|
"openapi": "3.0.0",
|
||||||
|
"info": {
|
||||||
|
"title": "Meeting Scheduler",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "An API for managing meetings, availability, and scheduling."
|
||||||
|
},
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "http://localhost:8080/openapi/v1",
|
||||||
|
"description": "Production server"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "http://localhost:8081/openapi/v1",
|
||||||
|
"description": "Example server"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"/users": {
|
||||||
|
"get": {
|
||||||
|
"summary": "List all users",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A list of users",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/User"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": [
|
||||||
|
{
|
||||||
|
"id": "1",
|
||||||
|
"name": "Alice",
|
||||||
|
"email": "alice@example.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2",
|
||||||
|
"name": "Bob",
|
||||||
|
"email": "bob@example.com"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/users/{userId}": {
|
||||||
|
"get": {
|
||||||
|
"operationId": "get_user",
|
||||||
|
"summary": "Get user by ID",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "userId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32"
|
||||||
|
},
|
||||||
|
"description": "The ID of the user",
|
||||||
|
"example": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "User details",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/User"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"id": "1",
|
||||||
|
"name": "Alice",
|
||||||
|
"email": "alice@example.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "User not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/events": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Create an event",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Event"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"title": "Team Meeting",
|
||||||
|
"description": "Weekly sync",
|
||||||
|
"startTime": "2023-10-10T10:00:00Z",
|
||||||
|
"endTime": "2023-10-10T11:00:00Z",
|
||||||
|
"userId": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Event created",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Event"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"id": "101",
|
||||||
|
"title": "Team Meeting",
|
||||||
|
"description": "Weekly sync",
|
||||||
|
"startTime": "2023-10-10T10:00:00Z",
|
||||||
|
"endTime": "2023-10-10T11:00:00Z",
|
||||||
|
"userId": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/availability": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get availability for a user",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "userId",
|
||||||
|
"in": "query",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "The ID of the user",
|
||||||
|
"example": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "date",
|
||||||
|
"in": "query",
|
||||||
|
"required": false,
|
||||||
|
"schema": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date"
|
||||||
|
},
|
||||||
|
"description": "The date to check availability (YYYY-MM-DD)",
|
||||||
|
"example": "2023-10-10"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Availability details",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/TimeSlot"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": [
|
||||||
|
{
|
||||||
|
"startTime": "10:00:00",
|
||||||
|
"endTime": "11:00:00",
|
||||||
|
"available": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"startTime": "11:00:00",
|
||||||
|
"endTime": "12:00:00",
|
||||||
|
"available": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/bookings": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Book a meeting",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Booking"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"userId": "1",
|
||||||
|
"eventId": "101",
|
||||||
|
"timeSlot": {
|
||||||
|
"startTime": "10:00:00",
|
||||||
|
"endTime": "11:00:00",
|
||||||
|
"available": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Booking created",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Booking"
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"id": "5001",
|
||||||
|
"userId": "1",
|
||||||
|
"eventId": "101",
|
||||||
|
"timeSlot": {
|
||||||
|
"startTime": "10:00:00",
|
||||||
|
"endTime": "11:00:00",
|
||||||
|
"available": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"User": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "email"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Event": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"startTime": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
|
"endTime": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
|
"userId": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"TimeSlot": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"startTime": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "time"
|
||||||
|
},
|
||||||
|
"endTime": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "time"
|
||||||
|
},
|
||||||
|
"available": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Booking": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"userId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"eventId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"timeSlot": {
|
||||||
|
"$ref": "#/components/schemas/TimeSlot"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
examples/baobab/specification/README.md
Normal file
3
examples/baobab/specification/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Actor Specification Examples
|
||||||
|
|
||||||
|
These examples show how `OpenRPC` and `OpenAPI` specifications can be translated back and forth into an `ActorSpecification`. This is an important step of actor generation as actor code is generated from actor specification.
|
||||||
346
examples/baobab/specification/openapi.json
Normal file
346
examples/baobab/specification/openapi.json
Normal file
@@ -0,0 +1,346 @@
|
|||||||
|
{
|
||||||
|
"openapi": "3.0.3",
|
||||||
|
"info": {
|
||||||
|
"title": "Pet Store API",
|
||||||
|
"description": "A sample API for a pet store",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "https://api.petstore.example.com/v1",
|
||||||
|
"description": "Production server"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://staging.petstore.example.com/v1",
|
||||||
|
"description": "Staging server"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"/pets": {
|
||||||
|
"get": {
|
||||||
|
"summary": "List all pets",
|
||||||
|
"operationId": "listPets",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "limit",
|
||||||
|
"in": "query",
|
||||||
|
"description": "Maximum number of pets to return",
|
||||||
|
"required": false,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A paginated list of pets",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Pets"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Invalid request"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"post": {
|
||||||
|
"summary": "Create a new pet",
|
||||||
|
"operationId": "createPet",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/NewPet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Pet created",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Pet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Invalid input"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/pets/{petId}": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get a pet by ID",
|
||||||
|
"operationId": "getPet",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "petId",
|
||||||
|
"in": "path",
|
||||||
|
"description": "ID of the pet to retrieve",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A pet",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Pet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Pet not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"delete": {
|
||||||
|
"summary": "Delete a pet by ID",
|
||||||
|
"operationId": "deletePet",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "petId",
|
||||||
|
"in": "path",
|
||||||
|
"description": "ID of the pet to delete",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"description": "Pet deleted"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Pet not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/orders": {
|
||||||
|
"get": {
|
||||||
|
"summary": "List all orders",
|
||||||
|
"operationId": "listOrders",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A list of orders",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Order"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/orders/{orderId}": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get an order by ID",
|
||||||
|
"operationId": "getOrder",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "orderId",
|
||||||
|
"in": "path",
|
||||||
|
"description": "ID of the order to retrieve",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "An order",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Order"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Order not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"delete": {
|
||||||
|
"summary": "Delete an order by ID",
|
||||||
|
"operationId": "deleteOrder",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "orderId",
|
||||||
|
"in": "path",
|
||||||
|
"description": "ID of the order to delete",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"description": "Order deleted"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Order not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/users": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Create a user",
|
||||||
|
"operationId": "createUser",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/NewUser"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "User created",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/User"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"Pet": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["id", "name"],
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NewPet": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["name"],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Pets": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Pet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Order": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["id", "petId", "quantity", "shipDate"],
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
|
"petId": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
|
"quantity": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"shipDate": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["placed", "approved", "delivered"]
|
||||||
|
},
|
||||||
|
"complete": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"User": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["id", "username"],
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"phone": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NewUser": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["username"],
|
||||||
|
"properties": {
|
||||||
|
"username": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"phone": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
examples/baobab/specification/openapi_to_specification.vsh
Executable file
13
examples/baobab/specification/openapi_to_specification.vsh
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env -S v -w -n -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.schemas.openapi
|
||||||
|
import os
|
||||||
|
|
||||||
|
const example_dir = os.dir(@FILE)
|
||||||
|
const openapi_spec_path = os.join_path(example_dir, 'openapi.json')
|
||||||
|
|
||||||
|
// the actor specification obtained from the OpenRPC Specification
|
||||||
|
openapi_spec := openapi.new(path: openapi_spec_path)!
|
||||||
|
actor_specification := specification.from_openapi(openapi_spec)!
|
||||||
|
println(actor_specification)
|
||||||
132
examples/baobab/specification/openrpc.json
Normal file
132
examples/baobab/specification/openrpc.json
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
{
|
||||||
|
"openrpc": "1.0.0",
|
||||||
|
"info": {
|
||||||
|
"title": "PetStore",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"methods": [
|
||||||
|
{
|
||||||
|
"name": "GetPets",
|
||||||
|
"description": "finds pets in the system that the user has access to by tags and within a limit",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "tags",
|
||||||
|
"description": "tags to filter by",
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "limit",
|
||||||
|
"description": "maximum number of results to return",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"result": {
|
||||||
|
"name": "pet_list",
|
||||||
|
"description": "all pets from the system, that mathes the tags",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#\/components\/schemas\/Pet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CreatePet",
|
||||||
|
"description": "creates a new pet in the store. Duplicates are allowed.",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "new_pet",
|
||||||
|
"description": "Pet to add to the store.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#\/components\/schemas\/NewPet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"result": {
|
||||||
|
"name": "pet",
|
||||||
|
"description": "the newly created pet",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#\/components\/schemas\/Pet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GetPetById",
|
||||||
|
"description": "gets a pet based on a single ID, if the user has access to the pet",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"description": "ID of pet to fetch",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"result": {
|
||||||
|
"name": "pet",
|
||||||
|
"description": "pet response",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#\/components\/schemas\/Pet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "DeletePetById",
|
||||||
|
"description": "deletes a single pet based on the ID supplied",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"description": "ID of pet to delete",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"result": {
|
||||||
|
"name": "pet",
|
||||||
|
"description": "pet deleted",
|
||||||
|
"schema": {
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"NewPet": {
|
||||||
|
"title": "NewPet",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Pet": {
|
||||||
|
"title": "Pet",
|
||||||
|
"description": "a pet struct that represents a pet",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"description": "name of the pet",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"description": "a tag of the pet, helps finding pet",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"description": "unique indentifier",
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
examples/baobab/specification/openrpc_to_specification.vsh
Executable file
13
examples/baobab/specification/openrpc_to_specification.vsh
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env -S v -w -n -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.schemas.openrpc
|
||||||
|
import os
|
||||||
|
|
||||||
|
const example_dir = os.dir(@FILE)
|
||||||
|
const openrpc_spec_path = os.join_path(example_dir, 'openrpc.json')
|
||||||
|
|
||||||
|
// the actor specification obtained from the OpenRPC Specification
|
||||||
|
openrpc_spec := openrpc.new(path: openrpc_spec_path)!
|
||||||
|
actor_specification := specification.from_openrpc(openrpc_spec)!
|
||||||
|
println(actor_specification)
|
||||||
107
examples/baobab/specification/specification_to_openapi.vsh
Executable file
107
examples/baobab/specification/specification_to_openapi.vsh
Executable file
@@ -0,0 +1,107 @@
|
|||||||
|
#!/usr/bin/env -S v -w -n -enable-globals run
|
||||||
|
|
||||||
|
import json
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.schemas.jsonschema
|
||||||
|
import freeflowuniverse.herolib.schemas.openrpc
|
||||||
|
import os
|
||||||
|
|
||||||
|
const actor_specification = specification.ActorSpecification{
|
||||||
|
name: 'PetStore'
|
||||||
|
interfaces: [.openrpc]
|
||||||
|
methods: [
|
||||||
|
specification.ActorMethod{
|
||||||
|
name: 'GetPets'
|
||||||
|
description: 'finds pets in the system that the user has access to by tags and within a limit'
|
||||||
|
parameters: [
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'tags'
|
||||||
|
description: 'tags to filter by'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'array'
|
||||||
|
items: jsonschema.Items(jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'string'
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'limit'
|
||||||
|
description: 'maximum number of results to return'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'integer'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
]
|
||||||
|
result: openrpc.ContentDescriptor{
|
||||||
|
name: 'pet_list'
|
||||||
|
description: 'all pets from the system, that matches the tags'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||||
|
ref: '#/components/schemas/Pet'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
specification.ActorMethod{
|
||||||
|
name: 'CreatePet'
|
||||||
|
description: 'creates a new pet in the store. Duplicates are allowed.'
|
||||||
|
parameters: [
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'new_pet'
|
||||||
|
description: 'Pet to add to the store.'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||||
|
ref: '#/components/schemas/NewPet'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
]
|
||||||
|
result: openrpc.ContentDescriptor{
|
||||||
|
name: 'pet'
|
||||||
|
description: 'the newly created pet'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||||
|
ref: '#/components/schemas/Pet'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
specification.ActorMethod{
|
||||||
|
name: 'GetPetById'
|
||||||
|
description: 'gets a pet based on a single ID, if the user has access to the pet'
|
||||||
|
parameters: [
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'id'
|
||||||
|
description: 'ID of pet to fetch'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'integer'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
]
|
||||||
|
result: openrpc.ContentDescriptor{
|
||||||
|
name: 'pet'
|
||||||
|
description: 'pet response'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||||
|
ref: '#/components/schemas/Pet'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
specification.ActorMethod{
|
||||||
|
name: 'DeletePetById'
|
||||||
|
description: 'deletes a single pet based on the ID supplied'
|
||||||
|
parameters: [
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'id'
|
||||||
|
description: 'ID of pet to delete'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'integer'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
]
|
||||||
|
result: openrpc.ContentDescriptor{
|
||||||
|
name: 'pet'
|
||||||
|
description: 'pet deleted'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'null'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
openapi_specification := actor_specification.to_openapi()
|
||||||
|
println(json.encode_pretty(openapi_specification))
|
||||||
109
examples/baobab/specification/specification_to_openrpc.vsh
Executable file
109
examples/baobab/specification/specification_to_openrpc.vsh
Executable file
@@ -0,0 +1,109 @@
|
|||||||
|
#!/usr/bin/env -S v -w -n -enable-globals run
|
||||||
|
|
||||||
|
import json
|
||||||
|
import freeflowuniverse.herolib.baobab.specification
|
||||||
|
import freeflowuniverse.herolib.core.code
|
||||||
|
import freeflowuniverse.herolib.schemas.jsonschema
|
||||||
|
import freeflowuniverse.herolib.schemas.openrpc
|
||||||
|
import os
|
||||||
|
|
||||||
|
const actor_specification = specification.ActorSpecification{
|
||||||
|
name: 'PetStore'
|
||||||
|
structure: code.Struct{}
|
||||||
|
interfaces: [.openrpc]
|
||||||
|
methods: [
|
||||||
|
specification.ActorMethod{
|
||||||
|
name: 'GetPets'
|
||||||
|
description: 'finds pets in the system that the user has access to by tags and within a limit'
|
||||||
|
parameters: [
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'tags'
|
||||||
|
description: 'tags to filter by'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'array'
|
||||||
|
items: jsonschema.Items(jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'string'
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'limit'
|
||||||
|
description: 'maximum number of results to return'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'integer'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
]
|
||||||
|
result: openrpc.ContentDescriptor{
|
||||||
|
name: 'pet_list'
|
||||||
|
description: 'all pets from the system, that matches the tags'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||||
|
ref: '#/components/schemas/Pet'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
specification.ActorMethod{
|
||||||
|
name: 'CreatePet'
|
||||||
|
description: 'creates a new pet in the store. Duplicates are allowed.'
|
||||||
|
parameters: [
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'new_pet'
|
||||||
|
description: 'Pet to add to the store.'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||||
|
ref: '#/components/schemas/NewPet'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
]
|
||||||
|
result: openrpc.ContentDescriptor{
|
||||||
|
name: 'pet'
|
||||||
|
description: 'the newly created pet'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||||
|
ref: '#/components/schemas/Pet'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
specification.ActorMethod{
|
||||||
|
name: 'GetPetById'
|
||||||
|
description: 'gets a pet based on a single ID, if the user has access to the pet'
|
||||||
|
parameters: [
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'id'
|
||||||
|
description: 'ID of pet to fetch'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'integer'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
]
|
||||||
|
result: openrpc.ContentDescriptor{
|
||||||
|
name: 'pet'
|
||||||
|
description: 'pet response'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||||
|
ref: '#/components/schemas/Pet'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
specification.ActorMethod{
|
||||||
|
name: 'DeletePetById'
|
||||||
|
description: 'deletes a single pet based on the ID supplied'
|
||||||
|
parameters: [
|
||||||
|
openrpc.ContentDescriptor{
|
||||||
|
name: 'id'
|
||||||
|
description: 'ID of pet to delete'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'integer'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
]
|
||||||
|
result: openrpc.ContentDescriptor{
|
||||||
|
name: 'pet'
|
||||||
|
description: 'pet deleted'
|
||||||
|
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||||
|
typ: 'null'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
openrpc_specification := actor_specification.to_openrpc()
|
||||||
|
println(json.encode_pretty(openrpc_specification))
|
||||||
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.threefold.info/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.threefold.info/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)
|
||||||
17
examples/biztools/bizmodel.vsh
Executable file
17
examples/biztools/bizmodel.vsh
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.biz.bizmodel
|
||||||
|
import os
|
||||||
|
|
||||||
|
const playbook_path = os.dir(@FILE) + '/playbook'
|
||||||
|
const build_path = os.join_path(os.dir(@FILE), '/docusaurus')
|
||||||
|
|
||||||
|
buildpath := '${os.home_dir()}/hero/var/mdbuild/bizmodel'
|
||||||
|
|
||||||
|
mut model := bizmodel.generate('test', playbook_path)!
|
||||||
|
|
||||||
|
println(model.sheet)
|
||||||
|
println(model.sheet.export()!)
|
||||||
|
|
||||||
|
model.sheet.export(path: '~/Downloads/test.csv')!
|
||||||
|
model.sheet.export(path: '~/code/github/freeflowuniverse/starlight_template/src/content/test.csv')!
|
||||||
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'
|
||||||
34
examples/biztools/bizmodel_docusaurus/bizmodel_docusaurus.vsh
Executable file
34
examples/biztools/bizmodel_docusaurus/bizmodel_docusaurus.vsh
Executable file
@@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
//#!/usr/bin/env -S v -cg -enable-globals run
|
||||||
|
import freeflowuniverse.herolib.biz.bizmodel
|
||||||
|
import freeflowuniverse.herolib.core.playbook
|
||||||
|
import freeflowuniverse.herolib.core.playcmds
|
||||||
|
import os
|
||||||
|
|
||||||
|
// TODO: need to fix wrong location
|
||||||
|
const playbook_path = os.dir(@FILE) + '/playbook'
|
||||||
|
const build_path = os.join_path(os.dir(@FILE), '/docusaurus')
|
||||||
|
|
||||||
|
buildpath := '${os.home_dir()}/hero/var/mdbuild/bizmodel'
|
||||||
|
|
||||||
|
mut model := bizmodel.getset('example')!
|
||||||
|
model.workdir = build_path
|
||||||
|
model.play(mut playbook.new(path: playbook_path)!)!
|
||||||
|
|
||||||
|
println(model.sheet)
|
||||||
|
println(model.sheet.export()!)
|
||||||
|
|
||||||
|
// model.sheet.export(path:"~/Downloads/test.csv")!
|
||||||
|
// model.sheet.export(path:"~/code/github/freeflowuniverse/starlight_template/src/content/test.csv")!
|
||||||
|
|
||||||
|
report := model.new_report(
|
||||||
|
name: 'example_report'
|
||||||
|
title: 'Example Business Model'
|
||||||
|
)!
|
||||||
|
|
||||||
|
report.export(
|
||||||
|
path: build_path
|
||||||
|
overwrite: true
|
||||||
|
format: .docusaurus
|
||||||
|
)!
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
output dir of example
|
||||||
22
examples/biztools/bizmodel_docusaurus/docusaurus/build.sh
Executable file
22
examples/biztools/bizmodel_docusaurus/docusaurus/build.sh
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
cd "${script_dir}"
|
||||||
|
|
||||||
|
echo "Docs directory: $script_dir"
|
||||||
|
|
||||||
|
cd "${HOME}/hero/var/docusaurus"
|
||||||
|
|
||||||
|
export PATH=/tmp/docusaurus_build/node_modules/.bin:${HOME}/.bun/bin/:$PATH
|
||||||
|
|
||||||
|
rm -rf /Users/despiegk/hero/var/docusaurus/build/
|
||||||
|
|
||||||
|
. ${HOME}/.zprofile
|
||||||
|
|
||||||
|
bun docusaurus build
|
||||||
|
|
||||||
|
mkdir -p /Users/despiegk/code/github/freeflowuniverse/herolib/examples/biztools/bizmodel/example/docusaurus
|
||||||
|
echo SYNC TO /Users/despiegk/code/github/freeflowuniverse/herolib/examples/biztools/bizmodel/example/docusaurus
|
||||||
|
rsync -rv --delete /Users/despiegk/hero/var/docusaurus/build/ /Users/despiegk/code/github/freeflowuniverse/herolib/examples/biztools/bizmodel/example/docusaurus/
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user