Compare commits
87 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 29c2fccbe5 | |||
| 975c07fc2e | |||
| ff45beac09 | |||
| 24eb709293 | |||
| 49e2146152 | |||
| cdaf64b3cf | |||
| 49af31776e | |||
| 0880823576 | |||
| 1fa1ecb8ec | |||
| d6108c9836 | |||
|
|
cc344fa60e | ||
|
|
5e468359a1 | ||
|
|
2317dd2d4c | ||
|
|
b92647c52e | ||
|
|
54024ee222 | ||
| 60d6474a42 | |||
| 8c52326550 | |||
| 52aba347a8 | |||
|
|
61a0fd2aa6 | ||
|
|
d604d739e3 | ||
|
|
a57f53fdb4 | ||
|
|
f276cdf697 | ||
|
|
7fb46a4c0b | ||
|
|
fc993a95d7 | ||
| c6ff7e7ba5 | |||
| 3f9a3fb1cd | |||
| 7ae4f7dbd0 | |||
| dbb44ec30a | |||
| 7f4fc42a7a | |||
| 01db4540b1 | |||
| 5c0c096a79 | |||
| c1719a057a | |||
| e969eacd06 | |||
| 8ed3439cdc | |||
|
|
5241dfddd4 | ||
|
|
6e0572b48a | ||
|
|
9a4a39b19a | ||
|
|
8abf113715 | ||
| 25c997fec5 | |||
|
|
1546bf7f87 | ||
|
|
02d4adcff0 | ||
|
|
147c889b53 | ||
|
|
f6e7644284 | ||
|
|
582da6d7f0 | ||
|
|
3a337b7b0a | ||
|
|
2953dd0172 | ||
|
|
08f0620305 | ||
|
|
ec22a8e0ec | ||
|
|
be4d2547e4 | ||
|
|
a7f8893399 | ||
|
|
d0b52f40b7 | ||
| 3117d288b1 | |||
|
|
6ecd190de8 | ||
|
|
dacd6d5afb | ||
| 299f6dea06 | |||
| ed025f9acb | |||
|
|
de0e66a94a | ||
|
|
e86504ecd5 | ||
|
|
1b192328b2 | ||
|
|
77a77ff87e | ||
|
|
439dff4a64 | ||
|
|
f8cb6f25f7 | ||
| c4ea066927 | |||
| 5f9c6ff2bb | |||
| 8965f7ae89 | |||
|
|
c157c86600 | ||
| 9a931b65e2 | |||
| 2c149507f6 | |||
|
|
34dea39c52 | ||
|
|
f1a4547961 | ||
|
|
8ae56a8df6 | ||
| cb0110ed20 | |||
| 2bbf814003 | |||
|
86e3fdb910
|
|||
| b731c4c388 | |||
| e929ce029d | |||
| 5160096a1a | |||
| f219a4041a | |||
| 674eae1c11 | |||
| f62369bd01 | |||
| 7a6660ebd8 | |||
| e20d1bdcc5 | |||
| 3e309b6379 | |||
| ae4e92e090 | |||
| 7b69719f0e | |||
| 1d631fec21 | |||
| 690b1b68c3 |
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
|
||||||
|
// }
|
||||||
|
```
|
||||||
2
cli/.gitignore
vendored
2
cli/.gitignore
vendored
@@ -1 +1,3 @@
|
|||||||
hero
|
hero
|
||||||
|
compile
|
||||||
|
compile_upload
|
||||||
|
|||||||
22
cli/hero.v
22
cli/hero.v
@@ -19,6 +19,26 @@ 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 +51,7 @@ fn do() ! {
|
|||||||
mut cmd := Command{
|
mut cmd := Command{
|
||||||
name: 'hero'
|
name: 'hero'
|
||||||
description: 'Your HERO toolset.'
|
description: 'Your HERO toolset.'
|
||||||
version: '1.0.11'
|
version: '1.0.14'
|
||||||
}
|
}
|
||||||
|
|
||||||
// herocmds.cmd_run_add_flags(mut cmd)
|
// herocmds.cmd_run_add_flags(mut cmd)
|
||||||
|
|||||||
3
examples/baobab/generator/.gitignore
vendored
3
examples/baobab/generator/.gitignore
vendored
@@ -1,3 +0,0 @@
|
|||||||
methods.v
|
|
||||||
pet_store_actor
|
|
||||||
docs
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#!/usr/bin/env -S v -w -n -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
|
|
||||||
)!
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#!/usr/bin/env -S v -w -n -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
|
|
||||||
)!
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#!/usr/bin/env -S v -w -n -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
|
|
||||||
)!
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
methods.v
|
|
||||||
meeting_scheduler_actor
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#!/usr/bin/env -S v -w -n -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)!
|
|
||||||
|
|
||||||
actor_module := generator.generate_actor_module(
|
|
||||||
actor_spec,
|
|
||||||
interfaces: [.openapi, .http]
|
|
||||||
)!
|
|
||||||
|
|
||||||
actor_module.write(example_dir,
|
|
||||||
format: true
|
|
||||||
overwrite: true
|
|
||||||
compile: true
|
|
||||||
)!
|
|
||||||
|
|
||||||
os.execvp('bash', ['${example_dir}/meeting_scheduler_actor/scripts/run.sh'])!
|
|
||||||
@@ -1,311 +0,0 @@
|
|||||||
{
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
{
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,346 +0,0 @@
|
|||||||
{
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/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)
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
{
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/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)
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
#!/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))
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
#!/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))
|
|
||||||
2
examples/biztools/bizmodel/example/.gitignore
vendored
Normal file
2
examples/biztools/bizmodel/example/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
bizmodel
|
||||||
|
dest
|
||||||
41
examples/biztools/bizmodel/example/bizmodel.vsh
Executable file
41
examples/biztools/bizmodel/example/bizmodel.vsh
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
//#!/usr/bin/env -S v -cg -enable-globals run
|
||||||
|
import freeflowuniverse.herolib.data.doctree
|
||||||
|
import freeflowuniverse.herolib.biz.bizmodel
|
||||||
|
import freeflowuniverse.herolib.core.playbook
|
||||||
|
import freeflowuniverse.herolib.core.playcmds
|
||||||
|
import freeflowuniverse.herolib.web.mdbook
|
||||||
|
import os
|
||||||
|
|
||||||
|
const wikipath = os.dir(@FILE) + '/wiki'
|
||||||
|
const summarypath = os.dir(@FILE) + '/wiki/summary.md'
|
||||||
|
|
||||||
|
buildpath := '${os.home_dir()}/hero/var/mdbuild/bizmodel'
|
||||||
|
|
||||||
|
mut m := bizmodel.getset('example')!
|
||||||
|
m.workdir = wikipath
|
||||||
|
m.play(mut playbook.new(path: wikipath)!)!
|
||||||
|
m.export_sheets()!
|
||||||
|
bizmodel.set(m)
|
||||||
|
|
||||||
|
// // execute the actions so we have the info populated
|
||||||
|
// // playcmds.run(mut plb,false)!
|
||||||
|
|
||||||
|
// // just run the doctree & mdbook and it should
|
||||||
|
// // load the doctree, these are all collections
|
||||||
|
// mut tree := doctree.new(name: 'bizmodel')!
|
||||||
|
// tree.scan(path: wikipath)!
|
||||||
|
// tree.export(dest: buildpath, reset: true)!
|
||||||
|
|
||||||
|
// // mut bm:=bizmodel.get("test")!
|
||||||
|
// // println(bm)
|
||||||
|
|
||||||
|
// mut mdbooks := mdbook.get()!
|
||||||
|
// mdbooks.generate(
|
||||||
|
// name: 'bizmodel'
|
||||||
|
// summary_path: summarypath
|
||||||
|
// doctree_path: buildpath
|
||||||
|
// title: 'bizmodel example'
|
||||||
|
// )!
|
||||||
|
// mdbook.book_open('bizmodel')!
|
||||||
10
examples/biztools/bizmodel/example/load.md
Normal file
10
examples/biztools/bizmodel/example/load.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
## Loader instructions
|
||||||
|
|
||||||
|
this will make sure we load the appropriate biz model
|
||||||
|
|
||||||
|
|
||||||
|
```js
|
||||||
|
!!bizmodel.load name:'default' url:'https://github.com/freeflowuniverse/herolib/tree/development/bizmodel/example/data'
|
||||||
|
```
|
||||||
|
|
||||||
1
examples/biztools/bizmodel/example/wiki/.collection
Normal file
1
examples/biztools/bizmodel/example/wiki/.collection
Normal file
@@ -0,0 +1 @@
|
|||||||
|
name:bizmodel_example
|
||||||
10
examples/biztools/bizmodel/example/wiki/bizmodel.md
Normal file
10
examples/biztools/bizmodel/example/wiki/bizmodel.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|

|
||||||
|
|
||||||
|
# bizmodel
|
||||||
|
|
||||||
|
OurWorld has developed a tool to generate and keep business models up to date.
|
||||||
|
|
||||||
|
Our aim is to make it easy for ourworld to track changes in planning over the multiple projects and even be able to aggregated them. Because the input for such a plan is text (as you can see in this ebook) its easy to see how the modelling and parameters change over time.
|
||||||
|
|
||||||
|
This is a very flexible tool which will be extended for budgetting, cashflow management, shareholder tables, ...
|
||||||
|
|
||||||
4
examples/biztools/bizmodel/example/wiki/debug.md
Normal file
4
examples/biztools/bizmodel/example/wiki/debug.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Debug
|
||||||
|
|
||||||
|
Some tools and info to help debug the bizmodel simulator.
|
||||||
|
|
||||||
8
examples/biztools/bizmodel/example/wiki/employees.md
Normal file
8
examples/biztools/bizmodel/example/wiki/employees.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Hr Overview
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
!!!bizmodel.employees_wiki bizname:'test'
|
||||||
|
|
||||||
|
|
||||||
|
> note: Nr People like 0:5,20:5 means, month 0 (start) is 5, month 20 its 5 people
|
||||||
5
examples/biztools/bizmodel/example/wiki/hr/cto.md
Normal file
5
examples/biztools/bizmodel/example/wiki/hr/cto.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# CTO
|
||||||
|
|
||||||
|
!!!bizmodel.employee_wiki bizname:'test' name:'despiegk'
|
||||||
|
|
||||||
|
!!wiki.include page:cto_description.md
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
## CTO Description
|
||||||
|
|
||||||
|
this is a page to test nested includes
|
||||||
1
examples/biztools/bizmodel/example/wiki/img/.done
Normal file
1
examples/biztools/bizmodel/example/wiki/img/.done
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ms1bmodel.png
|
||||||
BIN
examples/biztools/bizmodel/example/wiki/img/ms1bmodel.png
Normal file
BIN
examples/biztools/bizmodel/example/wiki/img/ms1bmodel.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
52
examples/biztools/bizmodel/example/wiki/overview.md
Normal file
52
examples/biztools/bizmodel/example/wiki/overview.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# This is our business model planner
|
||||||
|
|
||||||
|
## P&L Overview
|
||||||
|
|
||||||
|
|
||||||
|
<!-- period is in months, 3 means every quarter -->
|
||||||
|
|
||||||
|
|
||||||
|
!!bizmodel.graph_bar_row rowname:revenue_total unit:million title:'A Title' title_sub:'Sub' sheetname:'bizmodel_test'
|
||||||
|
|
||||||
|
Unit is in Million USD.
|
||||||
|
|
||||||
|
!!bizmodel.graph_bar_row rowname:revenue_total unit:million sheetname:'bizmodel_test'
|
||||||
|
|
||||||
|
!!bizmodel.graph_line_row rowname:revenue_total unit:million sheetname:'bizmodel_test'
|
||||||
|
|
||||||
|
!!bizmodel.graph_pie_row rowname:revenue_total unit:million size:'80%' sheetname:'bizmodel_test'
|
||||||
|
|
||||||
|
## FUNDING
|
||||||
|
|
||||||
|
!!bizmodel.sheet_wiki includefilter:'funding' sheetname:'bizmodel_test'
|
||||||
|
|
||||||
|
!!bizmodel.sheet_wiki title:'REVENUE' includefilter:rev sheetname:'bizmodel_test'
|
||||||
|
|
||||||
|
!!bizmodel.sheet_wiki title:'Revenue Total' includefilter:'revtotal' sheetname:'bizmodel_test'
|
||||||
|
|
||||||
|
!!bizmodel.sheet_wiki title:'REVENUE' includefilter:'revtotal2' sheetname:'bizmodel_test'
|
||||||
|
|
||||||
|
!!bizmodel.sheet_wiki title:'COGS' includefilter:'cogs' sheetname:'bizmodel_test'
|
||||||
|
|
||||||
|
!!bizmodel.sheet_wiki title:'Margin' includefilter:'margin' sheetname:'bizmodel_test'
|
||||||
|
|
||||||
|
!!bizmodel.sheet_wiki title:'HR Teams' includefilter:'hrnr' sheetname:'bizmodel_test'
|
||||||
|
|
||||||
|
!!bizmodel.sheet_wiki title:'HR Costs' includefilter:'hrcost' sheetname:'bizmodel_test'
|
||||||
|
|
||||||
|
!!bizmodel.sheet_wiki title:'COSTS' includefilter:'ocost' sheetname:'bizmodel_test'
|
||||||
|
|
||||||
|
!!bizmodel.sheet_wiki title:'HR Costs' includefilter:'hrcost' sheetname:'bizmodel_test'
|
||||||
|
|
||||||
|
!!bizmodel.sheet_wiki title:'P&L Overview' includefilter:'pl' sheetname:'bizmodel_test'
|
||||||
|
|
||||||
|
!!bizmodel.sheet_wiki title:'P&L Overview' includefilter:'pl' sheetname:'bizmodel_test'
|
||||||
|
|
||||||
|
## Some Details
|
||||||
|
|
||||||
|
> show how we can do per month
|
||||||
|
|
||||||
|
!!bizmodel.sheet_wiki includefilter:'pl' period_months:1 sheetname:'bizmodel_test'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# HR Params
|
||||||
|
|
||||||
|
## Engineering
|
||||||
|
|
||||||
|
Costs can be grouped in cost centers which can then be used to futher process e.g. transcactions between companies.
|
||||||
|
|
||||||
|
```js
|
||||||
|
|
||||||
|
!!bizmodel.costcenter_define bizname:'test'
|
||||||
|
name:'tfdmcc'
|
||||||
|
descr:'TFDMCC executes on near source agreement for TFTech'
|
||||||
|
min_month:'10000USD'
|
||||||
|
max_month:'100000USD'
|
||||||
|
end_date:'1/1/2026' //when does agreement stop
|
||||||
|
|
||||||
|
!!bizmodel.costcenter_define bizname:'test'
|
||||||
|
name:'cs_tftech'
|
||||||
|
descr:'Nearsource agreement for TFTech towards Codescalers'
|
||||||
|
min_month:'10000USD'
|
||||||
|
max_month:'100000USD'
|
||||||
|
end_date:'1/1/2026'
|
||||||
|
|
||||||
|
!!bizmodel.costcenter_define bizname:'test'
|
||||||
|
name:'cs_tfcloud'
|
||||||
|
descr:'Nearsource agreement for TFCloud towards Codescalers'
|
||||||
|
min_month:'10000USD'
|
||||||
|
max_month:'100000USD'
|
||||||
|
end_date:'1/1/2026'
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# Generic Overhead Costs
|
||||||
|
|
||||||
|
possible parameters
|
||||||
|
|
||||||
|
- name
|
||||||
|
- descr: description of the cost
|
||||||
|
- cost: is 'month:amount,month:amount, ...', no extrapolation
|
||||||
|
- cost_growth: is 'month:amount,month:amount, ..., or just a nr', will extrapolate
|
||||||
|
- type: travel, admin, legal, varia, office
|
||||||
|
- cost_percent_revenue e.g. 4%, will make sure the cost will be at least 4% of revenue
|
||||||
|
- indexation, e.g. 2%
|
||||||
|
|
||||||
|
Other financial flows can be mentioned here as well.
|
||||||
|
|
||||||
|
|
||||||
|
```js
|
||||||
|
!!bizmodel.cost_define bizname:'test'
|
||||||
|
name:'rental'
|
||||||
|
descr:'Office Rental in BE.'
|
||||||
|
cost:'5000'
|
||||||
|
indexation:'2%'
|
||||||
|
type:'office'
|
||||||
|
|
||||||
|
!!bizmodel.cost_define bizname:'test'
|
||||||
|
name:'oneoff'
|
||||||
|
descr:'Event in Z.'
|
||||||
|
cost_one:'3:50000'
|
||||||
|
type:'event'
|
||||||
|
|
||||||
|
!!bizmodel.cost_define bizname:'test'
|
||||||
|
name:'cloud'
|
||||||
|
descr:'Datacenter and Cloud Costs'
|
||||||
|
cost:'2000eur'
|
||||||
|
cost_percent_revenue:'2%'
|
||||||
|
type:'cloud'
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# Department Params
|
||||||
|
|
||||||
|
```js
|
||||||
|
|
||||||
|
!!bizmodel.department_define bizname:'test'
|
||||||
|
name:'ops'
|
||||||
|
title:'Operations'
|
||||||
|
order:5
|
||||||
|
|
||||||
|
!!bizmodel.department_define bizname:'test'
|
||||||
|
name:'coordination'
|
||||||
|
title:'Coordination'
|
||||||
|
order:1
|
||||||
|
|
||||||
|
!!bizmodel.department_define bizname:'test'
|
||||||
|
name:'engineering'
|
||||||
|
title:'Engineering'
|
||||||
|
order:4
|
||||||
|
|
||||||
|
```
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# Funding Params
|
||||||
|
|
||||||
|
possible parameters
|
||||||
|
|
||||||
|
- name, e.g. for a specific person
|
||||||
|
- descr: description of the funding
|
||||||
|
- investment is month:amount,month:amount, ...
|
||||||
|
- type: loan or capital
|
||||||
|
|
||||||
|
Other financial flows can be mentioned here as well.
|
||||||
|
|
||||||
|
|
||||||
|
```js
|
||||||
|
!!bizmodel.funding_define bizname:'test'
|
||||||
|
name:'our_investor'
|
||||||
|
descr:'A fantastic super investor.'
|
||||||
|
investment:'3:1000000EUR'
|
||||||
|
type:'capital'
|
||||||
|
|
||||||
|
!!bizmodel.funding_define bizname:'test'
|
||||||
|
name:'a_founder'
|
||||||
|
descr:'Together Are Strong'
|
||||||
|
investment:'2000000'
|
||||||
|
type:'loan'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
73
examples/biztools/bizmodel/example/wiki/params/hr_params.md
Normal file
73
examples/biztools/bizmodel/example/wiki/params/hr_params.md
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# HR Params
|
||||||
|
|
||||||
|
## Engineering
|
||||||
|
|
||||||
|
possible parameters
|
||||||
|
|
||||||
|
- descr, description of the function (e.g. master architect)
|
||||||
|
- cost, any currency eg. 1000usd
|
||||||
|
- in case cost changes over time e.g. 1:10000USD,20:20000USD,60:30000USD
|
||||||
|
- indexation, e.g. 2%
|
||||||
|
- department
|
||||||
|
- name, e.g. for a specific person
|
||||||
|
- nrpeople: how many people per month, growth over time notation e.g. 1:10,60:20 means 10 in month 1 growing to 20 month 60
|
||||||
|
- cost_percent_revenue e.g. 4%, will make sure the cost will be at least 4% of revenue
|
||||||
|
|
||||||
|
```js
|
||||||
|
|
||||||
|
!!bizmodel.employee_define bizname:'test'
|
||||||
|
sid:2
|
||||||
|
descr:'Senior Engineer'
|
||||||
|
cost:'1:12000,12:14000' //cost is always per person
|
||||||
|
department:'engineering'
|
||||||
|
nrpeople:'0:5,20:5'
|
||||||
|
|
||||||
|
!!bizmodel.employee_define bizname:'test'
|
||||||
|
name:'despiegk'
|
||||||
|
title: 'CTO and crazy inventor.'
|
||||||
|
sid:3
|
||||||
|
descr:'CTO'
|
||||||
|
cost:'12000EUR' //the salary is the cost independent of the fulltime status
|
||||||
|
indexation:'10%'
|
||||||
|
department:'coordination'
|
||||||
|
page:'cto.md'
|
||||||
|
fulltime: "50%" //100% means yes
|
||||||
|
|
||||||
|
!!bizmodel.employee_define bizname:'test'
|
||||||
|
descr:'Senior Architect'
|
||||||
|
cost:'10000USD' indexation:'5%'
|
||||||
|
department:'engineering'
|
||||||
|
nrpeople:'0:5,20:10'
|
||||||
|
|
||||||
|
!!bizmodel.employee_define bizname:'test'
|
||||||
|
descr:'Junior Engineer'
|
||||||
|
cost:'4000USD' indexation:'5%'
|
||||||
|
department:'engineering'
|
||||||
|
nrpeople:'0:5,20:10'
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Operations
|
||||||
|
|
||||||
|
```js
|
||||||
|
|
||||||
|
!!bizmodel.employee_define bizname:'test'
|
||||||
|
descr:'Ops Manager'
|
||||||
|
cost:'1:8000,12:14000'
|
||||||
|
department:'ops'
|
||||||
|
!!bizmodel.employee_define bizname:'test'
|
||||||
|
descr:'Support Junior'
|
||||||
|
cost:'2000EUR' indexation:'5%'
|
||||||
|
department:'ops'
|
||||||
|
nrpeople:'7:5,18:10'
|
||||||
|
cost_percent_revenue:'1%'
|
||||||
|
!!bizmodel.employee_define bizname:'test'
|
||||||
|
descr:'Support Senior'
|
||||||
|
cost:'5000EUR' indexation:'5%'
|
||||||
|
department:'ops'
|
||||||
|
nrpeople:'3:5,20:10'
|
||||||
|
cost_percent_revenue:'1%'
|
||||||
|
costcenter:'tfdmcc:25,cs_tfcloud:75'
|
||||||
|
generate_page:'../employees/support_senior.md'
|
||||||
|
```
|
||||||
14
examples/biztools/bizmodel/example/wiki/params/params.md
Normal file
14
examples/biztools/bizmodel/example/wiki/params/params.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# Bizmodel Params
|
||||||
|
|
||||||
|
In this section we can find all the parameters for the bizmodel.
|
||||||
|
|
||||||
|
## how to use and read
|
||||||
|
|
||||||
|
The params are defined in the different instruction files e.g. revenue_params.md
|
||||||
|
|
||||||
|
Often you will see something like `revenue_growth:'10:1000,20:1100'` this can be read as month 10 it 1000, month 20 its 1100.
|
||||||
|
|
||||||
|
The software will extrapolate.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
# HR Params
|
||||||
|
|
||||||
|
## Revenue Items (non recurring)
|
||||||
|
|
||||||
|
This company is a cloud company ...
|
||||||
|
|
||||||
|
```js
|
||||||
|
!!bizmodel.revenue_define bizname:'test'
|
||||||
|
descr:'OEM Deals'
|
||||||
|
revenue_time:'10:1000000EUR,15:3333,20:1200000'
|
||||||
|
cogs_perc: '1:5%,20:10%'
|
||||||
|
|
||||||
|
!!bizmodel.revenue_define bizname:'test'
|
||||||
|
descr:'License Deals'
|
||||||
|
revenue_growth:'10:1000,20:1100'
|
||||||
|
cogs_perc: '10%'
|
||||||
|
rev_delay_month: 1
|
||||||
|
|
||||||
|
!!bizmodel.revenue_define bizname:'test'
|
||||||
|
descr:'3NODE License Sales 1 Time'
|
||||||
|
//means revenue is 100 month 1, 200 month 60
|
||||||
|
revenue_item:'1:100,60:200'
|
||||||
|
revenue_nr:'10:1000,24:2000,60:40000'
|
||||||
|
cogs_perc: '10%'
|
||||||
|
rev_delay_month: 1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Revenue Items Recurring
|
||||||
|
|
||||||
|
possible parameters
|
||||||
|
|
||||||
|
- name, e.g. for a specific project
|
||||||
|
- descr, description of the revenue line item
|
||||||
|
- revenue_setup, revenue for 1 item '1000usd'
|
||||||
|
- revenue_monthly, revenue per month for 1 item
|
||||||
|
- revenue_setup_delay, how many months before revenue comes in after sales
|
||||||
|
- revenue_monthly_delay, how many months before monthly revenue starts
|
||||||
|
- cogs_setup, cost of good for 1 item at setup
|
||||||
|
- cogs_setup_perc: what is percentage of the cogs (can change over time) for setup e.g. 0:50%
|
||||||
|
- cogs_monthly, cost of goods for the monthly per 1 item
|
||||||
|
- cogs_monthly_perc: what is percentage of the cogs (can change over time) for monthly e.g. 0:5%,12:10%
|
||||||
|
- nr_sold: how many do we sell per month (is in growth format e.g. 10:100,20:200)
|
||||||
|
- nr_months: how many months is recurring
|
||||||
|
|
||||||
|
if currency not specified then is always in USD
|
||||||
|
|
||||||
|
```js
|
||||||
|
|
||||||
|
!!bizmodel.revenue_recurring_define bizname:'test'
|
||||||
|
name: '3node_lic'
|
||||||
|
descr:'3NODE License Sales Recurring Basic'
|
||||||
|
revenue_setup:'1:100,60:50'
|
||||||
|
// revenue_setup:'5'
|
||||||
|
revenue_monthly_delay:3
|
||||||
|
revenue_monthly:'1:1,60:1'
|
||||||
|
// cogs_setup:'1:0'
|
||||||
|
cogs_setup_perc:'50%'
|
||||||
|
revenue_setup_delay:1
|
||||||
|
cogs_monthly_perc:'50%'
|
||||||
|
nr_sold:'10:1000,24:2000,60:40000'
|
||||||
|
60 is the default
|
||||||
|
nr_months:60
|
||||||
|
```
|
||||||
|
|
||||||
13
examples/biztools/bizmodel/example/wiki/revenue.md
Normal file
13
examples/biztools/bizmodel/example/wiki/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/example/wiki/summary.md
Normal file
13
examples/biztools/bizmodel/example/wiki/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)
|
||||||
|
|
||||||
4
examples/biztools/bizmodel/example/wiki/worksheet.md
Normal file
4
examples/biztools/bizmodel/example/wiki/worksheet.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Overview of the rows in the biz model sheet
|
||||||
|
|
||||||
|
|
||||||
|
!!bizmodel.sheet_wiki sheetname:'bizmodel_test'
|
||||||
48
examples/biztools/bizmodel/tf9_biz.vsh
Executable file
48
examples/biztools/bizmodel/tf9_biz.vsh
Executable file
@@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/bin/env -S v -cg -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
// #!/usr/bin/env -S v -cg -enable-globals run
|
||||||
|
import freeflowuniverse.herolib.data.doctree
|
||||||
|
import freeflowuniverse.herolib.ui.console
|
||||||
|
import freeflowuniverse.herolib.biz.bizmodel
|
||||||
|
import freeflowuniverse.herolib.core.playbook
|
||||||
|
import freeflowuniverse.herolib.core.playcmds
|
||||||
|
import freeflowuniverse.herolib.web.mdbook
|
||||||
|
import freeflowuniverse.herolib.biz.spreadsheet
|
||||||
|
import os
|
||||||
|
|
||||||
|
const name = 'tf9_budget'
|
||||||
|
|
||||||
|
const wikipath = '${os.home_dir()}/code/git.ourworld.tf/ourworld_holding/info_ourworld/collections/${name}'
|
||||||
|
const summarypath = '${wikipath}/summary.md'
|
||||||
|
|
||||||
|
// mut sh := spreadsheet.sheet_new(name: 'test2') or { panic(err) }
|
||||||
|
// println(sh)
|
||||||
|
// sh.row_new(descr: 'this is a description', name: 'something', growth: '0:100aed,55:1000eur')!
|
||||||
|
// println(sh)
|
||||||
|
// println(sh.wiki()!)
|
||||||
|
|
||||||
|
// exit(0)
|
||||||
|
|
||||||
|
// execute the actions so we have the info populated
|
||||||
|
// mut plb:=playbook.new(path: wikipath)!
|
||||||
|
// playcmds.run(mut plb,false)!
|
||||||
|
|
||||||
|
buildpath := '${os.home_dir()}/hero/var/mdbuild/bizmodel'
|
||||||
|
|
||||||
|
// just run the doctree & mdbook and it should
|
||||||
|
// load the doctree, these are all collections
|
||||||
|
mut tree := doctree.new(name: name)!
|
||||||
|
tree.scan(path: wikipath)!
|
||||||
|
tree.export(dest: buildpath, reset: true)!
|
||||||
|
|
||||||
|
// mut bm:=bizmodel.get("test")!
|
||||||
|
// println(bm)
|
||||||
|
|
||||||
|
mut mdbooks := mdbook.get()!
|
||||||
|
mdbooks.generate(
|
||||||
|
name: 'bizmodel'
|
||||||
|
summary_path: summarypath
|
||||||
|
doctree_path: buildpath
|
||||||
|
title: 'bizmodel ${name}'
|
||||||
|
)!
|
||||||
|
mdbook.book_open('bizmodel')!
|
||||||
12
examples/biztools/bizmodel/todo.md
Normal file
12
examples/biztools/bizmodel/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)
|
||||||
11
examples/biztools/investor_tool.vsh
Executable file
11
examples/biztools/investor_tool.vsh
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.biz.investortool
|
||||||
|
import freeflowuniverse.herolib.core.playbook
|
||||||
|
import os
|
||||||
|
|
||||||
|
mut plbook := playbook.new(
|
||||||
|
path: '${os.home_dir()}/code/git.ourworld.tf/ourworld_holding/investorstool/output'
|
||||||
|
)!
|
||||||
|
mut it := investortool.play(mut plbook)!
|
||||||
|
it.check()!
|
||||||
108
examples/clients/mycelium.vsh
Executable file
108
examples/clients/mycelium.vsh
Executable file
@@ -0,0 +1,108 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.clients.mycelium
|
||||||
|
import freeflowuniverse.herolib.installers.net.mycelium as mycelium_installer
|
||||||
|
import freeflowuniverse.herolib.osal
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
import encoding.base64
|
||||||
|
|
||||||
|
const server1_port = 9001
|
||||||
|
const server2_port = 9002
|
||||||
|
|
||||||
|
fn terminate(port int) ! {
|
||||||
|
// Step 1: Run lsof to get process details
|
||||||
|
res := os.execute('lsof -i:${port}')
|
||||||
|
if res.exit_code != 0 {
|
||||||
|
return error('no service running at port ${port} due to: ${res.output}')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: Parse the output to extract the PID
|
||||||
|
lines := res.output.split('\n')
|
||||||
|
if lines.len < 2 {
|
||||||
|
return error('no process found running on port ${port}')
|
||||||
|
}
|
||||||
|
|
||||||
|
// The PID is the second column in the output
|
||||||
|
fields := lines[1].split(' ')
|
||||||
|
if fields.len < 2 {
|
||||||
|
return error('failed to parse lsof output')
|
||||||
|
}
|
||||||
|
pid := fields[1]
|
||||||
|
|
||||||
|
// Step 3: Kill the process using the PID
|
||||||
|
kill_res := os.execute('kill ${pid}')
|
||||||
|
if kill_res.exit_code != 0 {
|
||||||
|
return error('failed to kill process ${pid}: ${kill_res.output}')
|
||||||
|
}
|
||||||
|
|
||||||
|
println('Successfully terminated process ${pid} running on port ${port}')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if not installed install it.
|
||||||
|
mut installer := mycelium_installer.get()!
|
||||||
|
installer.install()!
|
||||||
|
|
||||||
|
mycelium.delete()!
|
||||||
|
|
||||||
|
spawn fn () {
|
||||||
|
os.execute('mkdir -p /tmp/mycelium_server1 && cd /tmp/mycelium_server1 && mycelium --peers tcp://188.40.132.242:9651 quic://[2a01:4f8:212:fa6::2]:9651 tcp://185.69.166.7:9651 quic://[2a02:1802:5e:0:ec4:7aff:fe51:e36b]:9651 tcp://65.21.231.58:9651 quic://[2a01:4f9:5a:1042::2]:9651 tcp://[2604:a00:50:17b:9e6b:ff:fe1f:e054]:9651 quic://5.78.122.16:9651 tcp://[2a01:4ff:2f0:3621::1]:9651 quic://142.93.217.194:9651 --tun-name tun2 --tcp-listen-port 9652 --quic-listen-port 9653 --api-addr 127.0.0.1:${server1_port}')
|
||||||
|
}()
|
||||||
|
|
||||||
|
spawn fn () {
|
||||||
|
os.execute('mkdir -p /tmp/mycelium_server2 && cd /tmp/mycelium_server2 && mycelium --peers tcp://188.40.132.242:9651 quic://[2a01:4f8:212:fa6::2]:9651 tcp://185.69.166.7:9651 quic://[2a02:1802:5e:0:ec4:7aff:fe51:e36b]:9651 tcp://65.21.231.58:9651 quic://[2a01:4f9:5a:1042::2]:9651 tcp://[2604:a00:50:17b:9e6b:ff:fe1f:e054]:9651 quic://5.78.122.16:9651 tcp://[2a01:4ff:2f0:3621::1]:9651 quic://142.93.217.194:9651 --tun-name tun3 --tcp-listen-port 9654 --quic-listen-port 9655 --api-addr 127.0.0.1:${server2_port}')
|
||||||
|
}()
|
||||||
|
|
||||||
|
defer {
|
||||||
|
terminate(server1_port) or {}
|
||||||
|
terminate(server2_port) or {}
|
||||||
|
}
|
||||||
|
|
||||||
|
time.sleep(2 * time.second)
|
||||||
|
|
||||||
|
mut client1 := mycelium.get()!
|
||||||
|
client1.server_url = 'http://localhost:${server1_port}'
|
||||||
|
client1.name = 'client1'
|
||||||
|
println(client1)
|
||||||
|
|
||||||
|
mut client2 := mycelium.get()!
|
||||||
|
client2.server_url = 'http://localhost:${server2_port}'
|
||||||
|
client2.name = 'client2'
|
||||||
|
println(client2)
|
||||||
|
|
||||||
|
inspect1 := mycelium.inspect(key_file_path: '/tmp/mycelium_server1/priv_key.bin')!
|
||||||
|
inspect2 := mycelium.inspect(key_file_path: '/tmp/mycelium_server2/priv_key.bin')!
|
||||||
|
|
||||||
|
println('Server 1 public key: ${inspect1.public_key}')
|
||||||
|
println('Server 2 public key: ${inspect2.public_key}')
|
||||||
|
|
||||||
|
// Send a message to a node by public key
|
||||||
|
// Parameters: public_key, payload, topic, wait_for_reply
|
||||||
|
msg := client1.send_msg(
|
||||||
|
public_key: inspect2.public_key // destination public key
|
||||||
|
payload: 'Sending a message from the client 1 to the client 2' // message payload
|
||||||
|
topic: 'testing' // optional topic
|
||||||
|
)!
|
||||||
|
|
||||||
|
println('Sent message ID: ${msg.id}')
|
||||||
|
println('send succeeded')
|
||||||
|
|
||||||
|
// Receive messages
|
||||||
|
// Parameters: wait_for_message, peek_only, topic_filter
|
||||||
|
received := client2.receive_msg(wait: true, peek: false, topic: 'testing')!
|
||||||
|
println('Received message from: ${received.src_pk}')
|
||||||
|
println('Message payload: ${base64.decode_str(received.payload)}')
|
||||||
|
|
||||||
|
// Reply to a message
|
||||||
|
// client1.reply_msg(
|
||||||
|
// id: received.id
|
||||||
|
// public_key: received.src_pk
|
||||||
|
// payload: 'Got your message!'
|
||||||
|
// topic: 'greetings'
|
||||||
|
// )!
|
||||||
|
|
||||||
|
// // // Check message status
|
||||||
|
// // status := client.get_msg_status(msg.id)!
|
||||||
|
// // println('Message status: ${status.state}')
|
||||||
|
// // println('Created at: ${status.created}')
|
||||||
|
// // println('Expires at: ${status.deadline}')
|
||||||
@@ -7,7 +7,7 @@ import os
|
|||||||
const testpath3 = os.dir(@FILE) + '/../..'
|
const testpath3 = os.dir(@FILE) + '/../..'
|
||||||
|
|
||||||
// if we return True then it means the dir or file is processed
|
// if we return True then it means the dir or file is processed
|
||||||
fn filter_1(mut path pathlib.Path) !bool {
|
fn filter_1(mut path pathlib.Path, mut params paramsparser.Params) !bool {
|
||||||
if path.is_dir() {
|
if path.is_dir() {
|
||||||
if path.path.ends_with('.dSYM') {
|
if path.path.ends_with('.dSYM') {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
|
||||||
|
|
||||||
import freeflowuniverse.herolib.develop.gittools
|
|
||||||
import freeflowuniverse.herolib.osal
|
|
||||||
import time
|
|
||||||
|
|
||||||
mut gs_default := gittools.new()!
|
|
||||||
|
|
||||||
println(gs_default)
|
|
||||||
|
|
||||||
// // Initializes the Git structure with the coderoot path.
|
|
||||||
// coderoot := '/tmp/code'
|
|
||||||
// mut gs_tmo := gittools.new(coderoot: coderoot)!
|
|
||||||
|
|
||||||
// // Retrieve the specified repository.
|
|
||||||
// mut repo := gs_default.get_repo(name: 'herolib')!
|
|
||||||
|
|
||||||
// println(repo)
|
|
||||||
14
examples/develop/gittools/gittools_path_get.vsh
Executable file
14
examples/develop/gittools/gittools_path_get.vsh
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.develop.gittools
|
||||||
|
import freeflowuniverse.herolib.osal
|
||||||
|
import time
|
||||||
|
|
||||||
|
mut gs := gittools.new()!
|
||||||
|
mydocs_path := gs.get_path(
|
||||||
|
pull: true
|
||||||
|
reset: false
|
||||||
|
url: 'https://git.ourworld.tf/tfgrid/info_docs_depin/src/branch/main/docs'
|
||||||
|
)!
|
||||||
|
|
||||||
|
println(mydocs_path)
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
module example_actor
|
module example_actor
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import freeflowuniverse.herolib.hero.baobab.stage {IActor, RunParams}
|
import freeflowuniverse.herolib.hero.baobab.actor { IActor, RunParams }
|
||||||
import freeflowuniverse.herolib.web.openapi
|
import freeflowuniverse.herolib.web.openapi
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@@ -10,13 +10,11 @@ const openapi_spec_json = os.read_file(openapi_spec_path) or { panic(err) }
|
|||||||
const openapi_specification = openapi.json_decode(openapi_spec_json)!
|
const openapi_specification = openapi.json_decode(openapi_spec_json)!
|
||||||
|
|
||||||
struct ExampleActor {
|
struct ExampleActor {
|
||||||
stage.Actor
|
actor.Actor
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new() !ExampleActor {
|
fn new() !ExampleActor {
|
||||||
return ExampleActor{
|
return ExampleActor{actor.new('example')}
|
||||||
stage.new_actor('example')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run() ! {
|
pub fn run() ! {
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
|
||||||
@@ -70,74 +70,87 @@ fn (mut actor Actor) listen() ! {
|
|||||||
|
|
||||||
// Handle method invocations
|
// Handle method invocations
|
||||||
fn (mut actor Actor) handle_method(cmd string, data string) !string {
|
fn (mut actor Actor) handle_method(cmd string, data string) !string {
|
||||||
param_anys := json2.raw_decode(data)!.arr()
|
println('debugzo received rpc ${cmd}:${data}')
|
||||||
match cmd {
|
param_anys := json2.raw_decode(data)!.arr()
|
||||||
'listPets' {
|
match cmd {
|
||||||
pets := if param_anys.len == 0 {
|
'listPets' {
|
||||||
actor.data_store.list_pets()
|
pets := if param_anys.len == 0 {
|
||||||
} else {
|
actor.data_store.list_pets()
|
||||||
params := json.decode(ListPetParams, param_anys[0].str())!
|
} else {
|
||||||
actor.data_store.list_pets(params)
|
params := json.decode(ListPetParams, param_anys[0].str())!
|
||||||
}
|
actor.data_store.list_pets(params)
|
||||||
return json.encode(pets)
|
}
|
||||||
}
|
return json.encode(pets)
|
||||||
'createPet' {
|
}
|
||||||
response := if param_anys.len == 0 {
|
'createPet' {
|
||||||
return error('at least data expected')
|
response := if param_anys.len == 0 {
|
||||||
} else if param_anys.len == 1 {
|
return error('at least data expected')
|
||||||
payload := json.decode(NewPet, param_anys[0].str())!
|
} else if param_anys.len == 1 {
|
||||||
actor.data_store.create_pet(payload)
|
payload := json.decode(NewPet, param_anys[0].str())!
|
||||||
} else {
|
actor.data_store.create_pet(payload)
|
||||||
return error('expected 1 param, found too many')
|
} else {
|
||||||
}
|
return error('expected 1 param, found too many')
|
||||||
// data := json.decode(NewPet, data) or { return error('Invalid pet data: $err') }
|
}
|
||||||
// created_pet := actor.data_store.create_pet(pet)
|
// data := json.decode(NewPet, data) or { return error('Invalid pet data: $err') }
|
||||||
return json.encode(response)
|
// created_pet := actor.data_store.create_pet(pet)
|
||||||
}
|
return json.encode(response)
|
||||||
'getPet' {
|
}
|
||||||
response := if param_anys.len == 0 {
|
'getPet' {
|
||||||
return error('at least data expected')
|
response := if param_anys.len == 0 {
|
||||||
} else if param_anys.len == 1 {
|
return error('at least data expected')
|
||||||
payload := param_anys[0].int()
|
} else if param_anys.len == 1 {
|
||||||
actor.data_store.get_pet(payload)!
|
payload := param_anys[0].int()
|
||||||
} else {
|
actor.data_store.get_pet(payload)!
|
||||||
return error('expected 1 param, found too many')
|
} else {
|
||||||
}
|
return error('expected 1 param, found too many')
|
||||||
|
}
|
||||||
|
|
||||||
return json.encode(response)
|
return json.encode(response)
|
||||||
}
|
}
|
||||||
'deletePet' {
|
'deletePet' {
|
||||||
params := json.decode(map[string]int, data) or { return error('Invalid params: $err') }
|
params := json.decode(map[string]int, data) or {
|
||||||
actor.data_store.delete_pet(params['petId']) or { return error('Pet not found: $err') }
|
return error('Invalid params: ${err}')
|
||||||
return json.encode({'message': 'Pet deleted'})
|
}
|
||||||
}
|
actor.data_store.delete_pet(params['petId']) or {
|
||||||
'listOrders' {
|
return error('Pet not found: ${err}')
|
||||||
orders := actor.data_store.list_orders()
|
}
|
||||||
return json.encode(orders)
|
return json.encode({
|
||||||
}
|
'message': 'Pet deleted'
|
||||||
'getOrder' {
|
})
|
||||||
params := json.decode(map[string]int, data) or { return error('Invalid params: $err') }
|
}
|
||||||
order := actor.data_store.get_order(params['orderId']) or {
|
'listOrders' {
|
||||||
return error('Order not found: $err')
|
orders := actor.data_store.list_orders()
|
||||||
}
|
return json.encode(orders)
|
||||||
return json.encode(order)
|
}
|
||||||
}
|
'getOrder' {
|
||||||
'deleteOrder' {
|
params := json.decode(map[string]int, data) or {
|
||||||
params := json.decode(map[string]int, data) or { return error('Invalid params: $err') }
|
return error('Invalid params: ${err}')
|
||||||
actor.data_store.delete_order(params['orderId']) or {
|
}
|
||||||
return error('Order not found: $err')
|
order := actor.data_store.get_order(params['orderId']) or {
|
||||||
}
|
return error('Order not found: ${err}')
|
||||||
return json.encode({'message': 'Order deleted'})
|
}
|
||||||
}
|
return json.encode(order)
|
||||||
'createUser' {
|
}
|
||||||
user := json.decode(NewUser, data) or { return error('Invalid user data: $err') }
|
'deleteOrder' {
|
||||||
created_user := actor.data_store.create_user(user)
|
params := json.decode(map[string]int, data) or {
|
||||||
return json.encode(created_user)
|
return error('Invalid params: ${err}')
|
||||||
}
|
}
|
||||||
else {
|
actor.data_store.delete_order(params['orderId']) or {
|
||||||
return error('Unknown method: $cmd')
|
return error('Order not found: ${err}')
|
||||||
}
|
}
|
||||||
}
|
return json.encode({
|
||||||
|
'message': 'Order deleted'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
'createUser' {
|
||||||
|
user := json.decode(NewUser, data) or { return error('Invalid user data: ${err}') }
|
||||||
|
created_user := actor.data_store.create_user(user)
|
||||||
|
return json.encode(created_user)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return error('Unknown method: ${cmd}')
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@[params]
|
@[params]
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
import freeflowuniverse.herolib.installers.infra.coredns as coredns_installer
|
import freeflowuniverse.herolib.installers.infra.coredns as coredns_installer
|
||||||
|
import freeflowuniverse.herolib.osal
|
||||||
|
|
||||||
coredns_installer.install()!
|
// coredns_installer.delete()!
|
||||||
|
mut installer := coredns_installer.get()!
|
||||||
|
installer.build()!
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
|
||||||
|
|
||||||
import freeflowuniverse.herolib.installers.sysadmintools.daguserver
|
|
||||||
import freeflowuniverse.herolib.installers.infra.zinit
|
|
||||||
|
|
||||||
// make sure zinit is there and running, will restart it if needed
|
|
||||||
mut z := zinit.get()!
|
|
||||||
z.destroy()!
|
|
||||||
z.start()!
|
|
||||||
|
|
||||||
// mut ds := daguserver.get()!
|
|
||||||
// ds.destroy()!
|
|
||||||
// ds.start()!
|
|
||||||
|
|
||||||
// println(ds)
|
|
||||||
8
examples/installers/db/meilisearch.vsh
Executable file
8
examples/installers/db/meilisearch.vsh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.db.meilisearch_installer
|
||||||
|
|
||||||
|
mut meilisearch := meilisearch_installer.get()!
|
||||||
|
meilisearch.install()!
|
||||||
|
meilisearch.start()!
|
||||||
|
meilisearch.destroy()!
|
||||||
9
examples/installers/db/postgresql.vsh
Executable file
9
examples/installers/db/postgresql.vsh
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.db.postgresql as postgresql_installer
|
||||||
|
|
||||||
|
mut db := postgresql_installer.get()!
|
||||||
|
|
||||||
|
db.install()!
|
||||||
|
db.start()!
|
||||||
|
db.destroy()!
|
||||||
9
examples/installers/db/zerodb.vsh
Executable file
9
examples/installers/db/zerodb.vsh
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.db.zerodb as zerodb_installer
|
||||||
|
|
||||||
|
mut db := zerodb_installer.get()!
|
||||||
|
|
||||||
|
db.install()!
|
||||||
|
db.start()!
|
||||||
|
db.destroy()!
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
|
||||||
|
|
||||||
import freeflowuniverse.herolib.installers.infra.gitea as gitea_installer
|
|
||||||
|
|
||||||
mut installer := gitea_installer.get(name: 'test')!
|
|
||||||
|
|
||||||
// if you want to configure using heroscript
|
|
||||||
gitea_installer.play(
|
|
||||||
heroscript: "
|
|
||||||
!!gitea.configure name:test
|
|
||||||
passwd:'something'
|
|
||||||
domain: 'docs.info.com'
|
|
||||||
"
|
|
||||||
)!
|
|
||||||
|
|
||||||
installer.start()!
|
|
||||||
8
examples/installers/infra/gitea.vsh
Executable file
8
examples/installers/infra/gitea.vsh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.infra.gitea as gitea_installer
|
||||||
|
|
||||||
|
mut gitea := gitea_installer.get()!
|
||||||
|
gitea.install()!
|
||||||
|
gitea.start()!
|
||||||
|
gitea.destroy()!
|
||||||
8
examples/installers/infra/livekit.vsh
Executable file
8
examples/installers/infra/livekit.vsh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.infra.livekit as livekit_installer
|
||||||
|
|
||||||
|
mut livekit := livekit_installer.get()!
|
||||||
|
livekit.install()!
|
||||||
|
livekit.start()!
|
||||||
|
livekit.destroy()!
|
||||||
8
examples/installers/infra/screen.vsh
Executable file
8
examples/installers/infra/screen.vsh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.infra.screen as screen_installer
|
||||||
|
|
||||||
|
mut screen := screen_installer.get()!
|
||||||
|
|
||||||
|
screen.install()!
|
||||||
|
screen.destroy()!
|
||||||
8
examples/installers/infra/zinit_installer.vsh
Executable file
8
examples/installers/infra/zinit_installer.vsh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.infra.zinit_installer
|
||||||
|
|
||||||
|
mut installer := zinit_installer.get()!
|
||||||
|
installer.install()!
|
||||||
|
installer.start()!
|
||||||
|
// installer.destroy()!
|
||||||
6
examples/installers/lang/golang.vsh
Executable file
6
examples/installers/lang/golang.vsh
Executable file
@@ -0,0 +1,6 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.lang.golang
|
||||||
|
|
||||||
|
mut golang_installer := golang.get()!
|
||||||
|
golang_installer.install()!
|
||||||
7
examples/installers/lang/nodejs.vsh
Executable file
7
examples/installers/lang/nodejs.vsh
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.lang.nodejs
|
||||||
|
|
||||||
|
mut nodejs_installer := nodejs.get()!
|
||||||
|
// nodejs_installer.install()!
|
||||||
|
nodejs_installer.destroy()!
|
||||||
7
examples/installers/lang/python.vsh
Executable file
7
examples/installers/lang/python.vsh
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.lang.python as python_module
|
||||||
|
|
||||||
|
mut python_installer := python_module.get()!
|
||||||
|
// python_installer.install()!
|
||||||
|
python_installer.destroy()!
|
||||||
7
examples/installers/lang/rust.vsh
Executable file
7
examples/installers/lang/rust.vsh
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.lang.rust as rust_module
|
||||||
|
|
||||||
|
mut rust_installer := rust_module.get()!
|
||||||
|
// rust_installer.install()!
|
||||||
|
rust_installer.destroy()!
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
|
||||||
|
|
||||||
import freeflowuniverse.herolib.installers.net.mycelium as mycelium_installer
|
|
||||||
|
|
||||||
mycelium_installer.start()!
|
|
||||||
42
examples/installers/net/mycelium.vsh
Executable file
42
examples/installers/net/mycelium.vsh
Executable file
@@ -0,0 +1,42 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.net.mycelium_installer
|
||||||
|
import freeflowuniverse.herolib.clients.mycelium
|
||||||
|
|
||||||
|
mut installer := mycelium_installer.get()!
|
||||||
|
installer.start()!
|
||||||
|
|
||||||
|
mut r := mycelium.inspect()!
|
||||||
|
println(r)
|
||||||
|
|
||||||
|
mut client := mycelium.get()!
|
||||||
|
|
||||||
|
// Send a message to a node by public key
|
||||||
|
// Parameters: public_key, payload, topic, wait_for_reply
|
||||||
|
msg := client.send_msg(
|
||||||
|
public_key: 'abc123...' // destination public key
|
||||||
|
payload: 'Hello World' // message payload
|
||||||
|
topic: 'greetings' // optional topic
|
||||||
|
wait: true // wait for reply
|
||||||
|
)!
|
||||||
|
println('Sent message ID: ${msg.id}')
|
||||||
|
|
||||||
|
// Receive messages
|
||||||
|
// Parameters: wait_for_message, peek_only, topic_filter
|
||||||
|
received := client.receive_msg(wait: true, peek: false, topic: 'greetings')!
|
||||||
|
println('Received message from: ${received.src_pk}')
|
||||||
|
println('Message payload: ${received.payload}')
|
||||||
|
|
||||||
|
// Reply to a message
|
||||||
|
client.reply_msg(
|
||||||
|
id: received.id // original message ID
|
||||||
|
public_key: received.src_pk // sender's public key
|
||||||
|
payload: 'Got your message!' // reply payload
|
||||||
|
topic: 'greetings' // topic
|
||||||
|
)!
|
||||||
|
|
||||||
|
// Check message status
|
||||||
|
status := client.get_msg_status(msg.id)!
|
||||||
|
println('Message status: ${status.state}')
|
||||||
|
println('Created at: ${status.created}')
|
||||||
|
println('Expires at: ${status.deadline}')
|
||||||
7
examples/installers/net/wireguard.vsh
Executable file
7
examples/installers/net/wireguard.vsh
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.net.wireguard_installer as wireguard
|
||||||
|
|
||||||
|
mut wireguard_installer := wireguard.get()!
|
||||||
|
wireguard_installer.install()!
|
||||||
|
wireguard_installer.destroy()!
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
|
||||||
|
|
||||||
import time
|
|
||||||
import freeflowuniverse.herolib.installers.db.postgresql
|
|
||||||
|
|
||||||
mut db := postgresql.get()!
|
|
||||||
|
|
||||||
// db.destroy()!
|
|
||||||
db.start()!
|
|
||||||
|
|
||||||
// db.db_create('my_new_db')!
|
|
||||||
// db.stop()!
|
|
||||||
// db.start()!
|
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
import freeflowuniverse.herolib.installers.sysadmintools.actrunner
|
import freeflowuniverse.herolib.installers.sysadmintools.actrunner
|
||||||
import freeflowuniverse.herolib.installers.virt.herocontainers
|
// import freeflowuniverse.herolib.installers.virt.herocontainers
|
||||||
|
|
||||||
actrunner.install()!
|
mut actrunner_ := actrunner.get()!
|
||||||
|
actrunner_.install()!
|
||||||
// herocontainers.start()!
|
// herocontainers.start()!
|
||||||
8
examples/installers/sysadmintools/garage_s3.vsh
Executable file
8
examples/installers/sysadmintools/garage_s3.vsh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.sysadmintools.garage_s3 as garage_s3_installer
|
||||||
|
|
||||||
|
mut garage_s3 := garage_s3_installer.get()!
|
||||||
|
garage_s3.install()!
|
||||||
|
garage_s3.start()!
|
||||||
|
garage_s3.destroy()!
|
||||||
7
examples/installers/sysadmintools/rclone.vsh
Executable file
7
examples/installers/sysadmintools/rclone.vsh
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.sysadmintools.rclone as rclone_installer
|
||||||
|
|
||||||
|
mut rclone := rclone_installer.get()!
|
||||||
|
rclone.install()!
|
||||||
|
rclone.destroy()!
|
||||||
@@ -4,3 +4,4 @@ import freeflowuniverse.herolib.installers.threefold.griddriver
|
|||||||
|
|
||||||
mut griddriver_installer := griddriver.get()!
|
mut griddriver_installer := griddriver.get()!
|
||||||
griddriver_installer.install()!
|
griddriver_installer.install()!
|
||||||
|
griddriver_installer.destroy()!
|
||||||
12
examples/installers/traefik.vsh
Executable file
12
examples/installers/traefik.vsh
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import os
|
||||||
|
import freeflowuniverse.herolib.installers.web.traefik as traefik_installer
|
||||||
|
|
||||||
|
traefik_installer.delete()!
|
||||||
|
mut installer := traefik_installer.get()!
|
||||||
|
|
||||||
|
installer.password = 'planet'
|
||||||
|
traefik_installer.set(installer)!
|
||||||
|
|
||||||
|
installer.start()!
|
||||||
9
examples/installers/virt/dagu.vsh
Executable file
9
examples/installers/virt/dagu.vsh
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.sysadmintools.daguserver
|
||||||
|
import freeflowuniverse.herolib.installers.infra.zinit_installer
|
||||||
|
|
||||||
|
mut ds := daguserver.get()!
|
||||||
|
ds.install()!
|
||||||
|
ds.start()!
|
||||||
|
ds.destroy()!
|
||||||
11
examples/installers/virt/pacman.vsh
Executable file
11
examples/installers/virt/pacman.vsh
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.virt.pacman as pacman_installer
|
||||||
|
|
||||||
|
mut pacman := pacman_installer.get()!
|
||||||
|
|
||||||
|
// To install
|
||||||
|
pacman.install()!
|
||||||
|
|
||||||
|
// To remove
|
||||||
|
pacman.destroy()!
|
||||||
60
examples/osal/coredns/example.vsh
Executable file
60
examples/osal/coredns/example.vsh
Executable file
@@ -0,0 +1,60 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.infra.coredns as coredns_installer
|
||||||
|
import freeflowuniverse.herolib.osal.coredns
|
||||||
|
import freeflowuniverse.herolib.core.playbook
|
||||||
|
|
||||||
|
// coredns_installer.delete()!
|
||||||
|
mut installer := coredns_installer.get()!
|
||||||
|
// coredns_installer.fix()!
|
||||||
|
installer.start()!
|
||||||
|
|
||||||
|
mut script := "
|
||||||
|
!!dns.a_record
|
||||||
|
sub_domain: 'host1'
|
||||||
|
ip: '1.2.3.4'
|
||||||
|
ttl: 300
|
||||||
|
|
||||||
|
!!dns.aaaa_record
|
||||||
|
sub_domain: 'host1'
|
||||||
|
ip: '2001:db8::1'
|
||||||
|
ttl: 300
|
||||||
|
|
||||||
|
!!dns.mx_record
|
||||||
|
sub_domain: '*'
|
||||||
|
host: 'mail.example.com'
|
||||||
|
preference: 10
|
||||||
|
ttl: 300
|
||||||
|
|
||||||
|
!!dns.txt_record
|
||||||
|
sub_domain: '*'
|
||||||
|
text: 'v=spf1 mx ~all'
|
||||||
|
ttl: 300
|
||||||
|
|
||||||
|
!!dns.srv_record
|
||||||
|
service: 'ssh'
|
||||||
|
protocol: 'tcp'
|
||||||
|
host: 'host1'
|
||||||
|
target: 'sip.example.com'
|
||||||
|
port: 5060
|
||||||
|
priority: 10
|
||||||
|
weight: 100
|
||||||
|
ttl: 300
|
||||||
|
|
||||||
|
!!dns.ns_record
|
||||||
|
host: 'ns1.example.com'
|
||||||
|
ttl: 300
|
||||||
|
|
||||||
|
!!dns.soa_record
|
||||||
|
mbox: 'hostmaster.example.com'
|
||||||
|
ns: 'ns1.example.com'
|
||||||
|
refresh: 44
|
||||||
|
retry: 55
|
||||||
|
expire: 66
|
||||||
|
minttl: 100
|
||||||
|
ttl: 300
|
||||||
|
"
|
||||||
|
|
||||||
|
mut plbook := playbook.new(text: script)!
|
||||||
|
mut set := coredns.play_dns(mut plbook)!
|
||||||
|
set.set(key_prefix: 'dns:', domain: 'heroexample.com')!
|
||||||
24
examples/osal/tun.vsh
Executable file
24
examples/osal/tun.vsh
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.osal.tun
|
||||||
|
|
||||||
|
// Check if TUN is available
|
||||||
|
if available := tun.available() {
|
||||||
|
if available {
|
||||||
|
println('TUN is available on this system')
|
||||||
|
|
||||||
|
// Get a free TUN interface name
|
||||||
|
if interface_name := tun.free() {
|
||||||
|
println('Found free TUN interface: ${interface_name}')
|
||||||
|
|
||||||
|
// Example: Now you could use this interface name
|
||||||
|
// to set up your tunnel
|
||||||
|
} else {
|
||||||
|
println('Error finding free interface: ${err}')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println('TUN is not available on this system')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println('Error checking TUN availability: ${err}')
|
||||||
|
}
|
||||||
1
examples/schemas/openapi/codegen/.gitignore
vendored
1
examples/schemas/openapi/codegen/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
client_typescript
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#!/usr/bin/env -S v -n -w -enable-globals run
|
|
||||||
|
|
||||||
// Calendar Typescript Client Generation Example
|
|
||||||
// This example demonstrates how to generate a typescript client
|
|
||||||
// from a given OpenAPI Specification using the `openapi/codegen` module.
|
|
||||||
|
|
||||||
import os
|
|
||||||
import freeflowuniverse.herolib.schemas.openapi
|
|
||||||
import freeflowuniverse.herolib.schemas.openapi.codegen
|
|
||||||
|
|
||||||
const dir = os.dir(@FILE)
|
|
||||||
const specification = openapi.new(path: '${dir}/meeting_api.json') or {
|
|
||||||
panic('this should never happen ${err}')
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate typescript client folder and write it in dir
|
|
||||||
codegen.ts_client_folder(specification)!.write(dir, overwrite: true)!
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,245 +0,0 @@
|
|||||||
{
|
|
||||||
"openapi": "3.0.0",
|
|
||||||
"info": {
|
|
||||||
"title": "Meeting Scheduler API",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "An API for managing meetings, availability, and scheduling."
|
|
||||||
},
|
|
||||||
"servers": [
|
|
||||||
{
|
|
||||||
"url": "https://api.meetingscheduler.com/v1",
|
|
||||||
"description": "Production server"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://sandbox.api.meetingscheduler.com/v1",
|
|
||||||
"description": "Sandbox 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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/users/{userId}": {
|
|
||||||
"get": {
|
|
||||||
"operationId": "get_user",
|
|
||||||
"summary": "Get user by ID",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "userId",
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"description": "The ID of the user"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "User details",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/User"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"404": {
|
|
||||||
"description": "User not found"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/events": {
|
|
||||||
"post": {
|
|
||||||
"summary": "Create an event",
|
|
||||||
"requestBody": {
|
|
||||||
"required": true,
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/Event"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"201": {
|
|
||||||
"description": "Event created",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/Event"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/availability": {
|
|
||||||
"get": {
|
|
||||||
"summary": "Get availability for a user",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "userId",
|
|
||||||
"in": "query",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"description": "The ID of the user"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "date",
|
|
||||||
"in": "query",
|
|
||||||
"required": false,
|
|
||||||
"schema": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "date"
|
|
||||||
},
|
|
||||||
"description": "The date to check availability (YYYY-MM-DD)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "Availability details",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/components/schemas/TimeSlot"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/bookings": {
|
|
||||||
"post": {
|
|
||||||
"summary": "Book a meeting",
|
|
||||||
"requestBody": {
|
|
||||||
"required": true,
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/Booking"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"201": {
|
|
||||||
"description": "Booking created",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/Booking"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"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/virt/podman_buildah/.gitignore
vendored
3
examples/virt/podman_buildah/.gitignore
vendored
@@ -1 +1,4 @@
|
|||||||
buildah_example
|
buildah_example
|
||||||
|
buildah_run_clean
|
||||||
|
buildah_run_mdbook
|
||||||
|
buildah_run
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ podman_installer0.install()!
|
|||||||
|
|
||||||
mut engine := herocontainers.new(install: true, herocompile: false)!
|
mut engine := herocontainers.new(install: true, herocompile: false)!
|
||||||
|
|
||||||
engine.reset_all()!
|
// engine.reset_all()!
|
||||||
|
|
||||||
mut builder_gorust := engine.builder_go_rust()!
|
// mut builder_gorust := engine.builder_go_rust()!
|
||||||
|
|
||||||
// will build nodejs, python build & herolib, hero
|
// will build nodejs, python build & herolib, hero
|
||||||
// mut builder_hero := engine.builder_hero(reset:true)!
|
// mut builder_hero := engine.builder_hero(reset:true)!
|
||||||
|
|
||||||
// mut builder_web := engine.builder_heroweb(reset:true)!
|
// mut builder_web := engine.builder_heroweb(reset:true)!
|
||||||
|
|
||||||
builder_gorust.shell()!
|
// builder_gorust.shell()!
|
||||||
|
|||||||
@@ -7,14 +7,22 @@ import freeflowuniverse.herolib.core.base
|
|||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
|
|
||||||
mut pm := herocontainers.new(herocompile: true, install: false)!
|
// herocompile means we do it for the host system
|
||||||
|
mut pm := herocontainers.new(herocompile: false, install: false)!
|
||||||
|
|
||||||
mut mybuildcontainer := pm.builder_get('builder_heroweb')!
|
// pm.builder_base(reset:true)!
|
||||||
|
|
||||||
|
mut builder := pm.builder_get('base')!
|
||||||
|
builder.shell()!
|
||||||
|
|
||||||
|
println(builder)
|
||||||
|
|
||||||
|
// builder.install_zinit()!
|
||||||
|
|
||||||
// bash & python can be executed directly in build container
|
// bash & python can be executed directly in build container
|
||||||
|
|
||||||
// any of the herocommands can be executed like this
|
// any of the herocommands can be executed like this
|
||||||
mybuildcontainer.run(cmd: 'installers -n heroweb', runtime: .herocmd)!
|
// mybuildcontainer.run(cmd: 'installers -n heroweb', runtime: .herocmd)!
|
||||||
|
|
||||||
// //following will execute heroscript in the buildcontainer
|
// //following will execute heroscript in the buildcontainer
|
||||||
// mybuildcontainer.run(
|
// mybuildcontainer.run(
|
||||||
|
|||||||
@@ -5,16 +5,15 @@ import freeflowuniverse.herolib.web.docusaurus
|
|||||||
|
|
||||||
// Create a new docusaurus factory
|
// Create a new docusaurus factory
|
||||||
mut docs := docusaurus.new(
|
mut docs := docusaurus.new(
|
||||||
// build_path: '/tmp/docusaurus_build'
|
build_path: '/tmp/docusaurus_build'
|
||||||
)!
|
)!
|
||||||
|
|
||||||
// Create a new docusaurus site
|
// Create a new docusaurus site
|
||||||
mut site := docs.dev(
|
mut site := docs.dev(
|
||||||
url:'https://git.ourworld.tf/despiegk/docs_kristof'
|
url: 'https://git.ourworld.tf/despiegk/docs_kristof'
|
||||||
)!
|
)!
|
||||||
|
|
||||||
|
// FOR FUTURE TO ADD CONTENT FROM DOCTREE
|
||||||
//FOR FUTURE TO ADD CONTENT FROM DOCTREE
|
|
||||||
|
|
||||||
// Create a doctree for content
|
// Create a doctree for content
|
||||||
// mut tree := doctree.new(name: 'content')!
|
// mut tree := doctree.new(name: 'content')!
|
||||||
@@ -34,10 +33,10 @@ mut site := docs.dev(
|
|||||||
// )!
|
// )!
|
||||||
|
|
||||||
// Build the docusaurus site
|
// Build the docusaurus site
|
||||||
//site.build()!
|
// site.build()!
|
||||||
|
|
||||||
// Generate the static site
|
// Generate the static site
|
||||||
//site.generate()!
|
// site.generate()!
|
||||||
|
|
||||||
// Optionally open the site in a browser
|
// Optionally open the site in a browser
|
||||||
// site.open()!
|
// site.open()!
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ set -e
|
|||||||
|
|
||||||
os_name="$(uname -s)"
|
os_name="$(uname -s)"
|
||||||
arch_name="$(uname -m)"
|
arch_name="$(uname -m)"
|
||||||
version='1.0.11'
|
version='1.0.14'
|
||||||
|
|
||||||
|
|
||||||
# Base URL for GitHub releases
|
# Base URL for GitHub releases
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ function os_update {
|
|||||||
fi
|
fi
|
||||||
#apt install apt-transport-https ca-certificates curl software-properties-common -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" --force-yes
|
#apt install apt-transport-https ca-certificates curl software-properties-common -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" --force-yes
|
||||||
package_install "apt-transport-https ca-certificates curl wget software-properties-common tmux"
|
package_install "apt-transport-https ca-certificates curl wget software-properties-common tmux"
|
||||||
package_install "rclone rsync mc redis-server screen net-tools git dnsutils htop ca-certificates screen lsb-release binutils pkg-config"
|
package_install "rclone rsync mc redis-server screen net-tools git dnsutils htop ca-certificates screen lsb-release binutils pkg-config libssl-dev iproute2"
|
||||||
|
|
||||||
elif [[ "${OSNAME}" == "darwin"* ]]; then
|
elif [[ "${OSNAME}" == "darwin"* ]]; then
|
||||||
if command -v brew >/dev/null 2>&1; then
|
if command -v brew >/dev/null 2>&1; then
|
||||||
|
|||||||
@@ -1,118 +0,0 @@
|
|||||||
module generator
|
|
||||||
|
|
||||||
import freeflowuniverse.herolib.core.code {Folder, File}
|
|
||||||
import freeflowuniverse.herolib.core.texttools
|
|
||||||
import freeflowuniverse.herolib.schemas.jsonschema.codegen { schema_to_struct }
|
|
||||||
import freeflowuniverse.herolib.schemas.openrpc.codegen as openrpc_codegen { content_descriptor_to_parameter }
|
|
||||||
import freeflowuniverse.herolib.baobab.specification {ActorSpecification, ActorMethod, BaseObject}
|
|
||||||
import net.http
|
|
||||||
|
|
||||||
// pub enum BaseObjectMethodType {
|
|
||||||
// new
|
|
||||||
// get
|
|
||||||
// set
|
|
||||||
// delete
|
|
||||||
// list
|
|
||||||
// other
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub struct BaseObjectMethod {
|
|
||||||
// pub:
|
|
||||||
// typ BaseObjectMethodType
|
|
||||||
// object string // the name of the base object
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn ts_client_get_fn(object string, params TSClientFunctionParams) string {
|
|
||||||
// name_snake := texttools.snake_case(object)
|
|
||||||
// name_pascal := texttools.name_fix_pascal(object)
|
|
||||||
// root := get_endpoint_root(params.endpoint)
|
|
||||||
|
|
||||||
// return "async get${name_pascal}(id: string): Promise<${name_pascal}> {\n return this.restClient.get<${name_pascal}>(`/${root}/${name_snake}/\${id}`);\n }"
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn ts_client_set_fn(object string, params TSClientFunctionParams) string {
|
|
||||||
// name_snake := texttools.snake_case(object)
|
|
||||||
// name_pascal := texttools.name_fix_pascal(object)
|
|
||||||
// root := get_endpoint_root(params.endpoint)
|
|
||||||
|
|
||||||
// return "async set${name_pascal}(id: string, ${name_snake}: Partial<${name_pascal}>): Promise<${name_pascal}> {\n return this.restClient.put<${name_pascal}>(`/${root}/${name_snake}/\${id}`, ${name_snake});\n }"
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn ts_client_delete_fn(object string, params TSClientFunctionParams) string {
|
|
||||||
// name_snake := texttools.snake_case(object)
|
|
||||||
// name_pascal := texttools.name_fix_pascal(object)
|
|
||||||
// root := get_endpoint_root(params.endpoint)
|
|
||||||
|
|
||||||
// return "async delete${name_pascal}(id: string): Promise<void> {\n return this.restClient.delete<void>(`/${root}/${name_snake}/\${id}`);\n }"
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn ts_client_list_fn(object string, params TSClientFunctionParams) string {
|
|
||||||
// name_snake := texttools.snake_case(object)
|
|
||||||
// name_pascal := texttools.name_fix_pascal(object)
|
|
||||||
// root := get_endpoint_root(params.endpoint)
|
|
||||||
|
|
||||||
// return "async list${name_pascal}(): Promise<${name_pascal}[]> {\n return this.restClient.get<${name_pascal}[]>(`/${root}/${name_snake}`);\n }"
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn get_endpoint_root(root string) string {
|
|
||||||
return if root == '' {
|
|
||||||
''
|
|
||||||
} else {
|
|
||||||
"/${root.trim('/')}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// // generates a Base Object's `create` method
|
|
||||||
// pub fn ts_client_new_fn(object string, params TSClientFunctionParams) string {
|
|
||||||
// name_snake := texttools.snake_case(object)
|
|
||||||
// name_pascal := texttools.name_fix_pascal(object)
|
|
||||||
// root := get_endpoint_root(params.endpoint)
|
|
||||||
|
|
||||||
// return "async create${name_snake}(object: Omit<${name_pascal}, 'id'>): Promise<${name_pascal}> {
|
|
||||||
// return this.restClient.post<${name_pascal}>('${root}/${name_snake}', board);
|
|
||||||
// }"
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn ts_client_get_fn(object string, params TSClientFunctionParams) string {
|
|
||||||
// name_snake := texttools.snake_case(object)
|
|
||||||
// name_pascal := texttools.name_fix_pascal(object)
|
|
||||||
// root := get_endpoint_root(params.endpoint)
|
|
||||||
|
|
||||||
// return "async get${name_pascal}(id: string): Promise<${name_pascal}> {\n return this.restClient.get<${name_pascal}>(`/${root}/${name_snake}/\${id}`);\n }"
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn ts_client_set_fn(object string, params TSClientFunctionParams) string {
|
|
||||||
// name_snake := texttools.snake_case(object)
|
|
||||||
// name_pascal := texttools.name_fix_pascal(object)
|
|
||||||
// root := get_endpoint_root(params.endpoint)
|
|
||||||
|
|
||||||
// return "async set${name_pascal}(id: string, ${name_snake}: Partial<${name_pascal}>): Promise<${name_pascal}> {\n return this.restClient.put<${name_pascal}>(`/${root}/${name_snake}/\${id}`, ${name_snake});\n }"
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn ts_client_delete_fn(object string, params TSClientFunctionParams) string {
|
|
||||||
// name_snake := texttools.snake_case(object)
|
|
||||||
// name_pascal := texttools.name_fix_pascal(object)
|
|
||||||
// root := get_endpoint_root(params.endpoint)
|
|
||||||
|
|
||||||
// return "async delete${name_pascal}(id: string): Promise<void> {\n return this.restClient.delete<void>(`/${root}/${name_snake}/\${id}`);\n }"
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn ts_client_list_fn(object string, params TSClientFunctionParams) string {
|
|
||||||
// name_snake := texttools.snake_case(object)
|
|
||||||
// name_pascal := texttools.name_fix_pascal(object)
|
|
||||||
// root := get_endpoint_root(params.endpoint)
|
|
||||||
|
|
||||||
// return "async list${name_pascal}(): Promise<${name_pascal}[]> {\n return this.restClient.get<${name_pascal}[]>(`/${root}/${name_snake}`);\n }"
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // generates a function prototype given an `ActorMethod`
|
|
||||||
// pub fn ts_client_fn_prototype(method ActorMethod) string {
|
|
||||||
// name := texttools.name_fix_pascal(method.name)
|
|
||||||
// params := method.parameters
|
|
||||||
// .map(content_descriptor_to_parameter(it) or {panic(err)})
|
|
||||||
// .map(it.typescript())
|
|
||||||
// .join(', ')
|
|
||||||
|
|
||||||
// return_type := content_descriptor_to_parameter(method.result) or {panic(err)}.typ.typescript()
|
|
||||||
// return 'async ${name}(${params}): Promise<${return_type}> {}'
|
|
||||||
// }
|
|
||||||
@@ -1,202 +0,0 @@
|
|||||||
module generator
|
|
||||||
|
|
||||||
import x.json2 as json
|
|
||||||
import arrays
|
|
||||||
import freeflowuniverse.herolib.core.code
|
|
||||||
import freeflowuniverse.herolib.baobab.specification
|
|
||||||
import freeflowuniverse.herolib.schemas.openrpc
|
|
||||||
import freeflowuniverse.herolib.schemas.jsonschema
|
|
||||||
|
|
||||||
const specification = specification.ActorSpecification{
|
|
||||||
name: 'Pet Store'
|
|
||||||
description: 'A sample API for a pet store'
|
|
||||||
structure: code.Struct{}
|
|
||||||
interfaces: [.openapi]
|
|
||||||
methods: [
|
|
||||||
specification.ActorMethod{
|
|
||||||
name: 'listPets'
|
|
||||||
summary: 'List all pets'
|
|
||||||
example: openrpc.ExamplePairing{
|
|
||||||
params: [
|
|
||||||
openrpc.ExampleRef(openrpc.Example{
|
|
||||||
name: 'Example limit'
|
|
||||||
description: 'Example Maximum number of pets to return'
|
|
||||||
value: 10
|
|
||||||
})
|
|
||||||
]
|
|
||||||
result: openrpc.ExampleRef(openrpc.Example{
|
|
||||||
name: 'Example response'
|
|
||||||
value: json.raw_decode('[
|
|
||||||
{"id": 1, "name": "Fluffy", "tag": "dog"},
|
|
||||||
{"id": 2, "name": "Whiskers", "tag": "cat"}
|
|
||||||
]')!
|
|
||||||
})
|
|
||||||
}
|
|
||||||
parameters: [
|
|
||||||
openrpc.ContentDescriptor{
|
|
||||||
name: 'limit'
|
|
||||||
summary: 'Maximum number of pets to return'
|
|
||||||
description: 'Maximum number of pets to return'
|
|
||||||
required: false
|
|
||||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
...jsonschema.schema_u32,
|
|
||||||
example: 10
|
|
||||||
})
|
|
||||||
}
|
|
||||||
]
|
|
||||||
result: openrpc.ContentDescriptor{
|
|
||||||
name: 'pets'
|
|
||||||
description: 'A paged array of pets'
|
|
||||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
typ: 'array'
|
|
||||||
items: jsonschema.Items(jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
id: 'pet'
|
|
||||||
title: 'Pet'
|
|
||||||
typ: 'object'
|
|
||||||
properties: {
|
|
||||||
'id': jsonschema.SchemaRef(jsonschema.Reference{
|
|
||||||
ref: '#/components/schemas/PetId'
|
|
||||||
}),
|
|
||||||
'name': jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
typ: 'string'
|
|
||||||
}),
|
|
||||||
'tag': jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
typ: 'string'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
required: ['id', 'name']
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
errors: [
|
|
||||||
openrpc.ErrorSpec{
|
|
||||||
code: 400
|
|
||||||
message: 'Invalid request'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
specification.ActorMethod{
|
|
||||||
name: 'createPet'
|
|
||||||
summary: 'Create a new pet'
|
|
||||||
example: openrpc.ExamplePairing{
|
|
||||||
result: openrpc.ExampleRef(openrpc.Example{
|
|
||||||
name: 'Example response'
|
|
||||||
value: '[]'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
result: openrpc.ContentDescriptor{
|
|
||||||
name: 'result'
|
|
||||||
description: 'The response of the operation.'
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
errors: [
|
|
||||||
openrpc.ErrorSpec{
|
|
||||||
code: 400
|
|
||||||
message: 'Invalid input'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
specification.ActorMethod{
|
|
||||||
name: 'getPet'
|
|
||||||
summary: 'Get a pet by ID'
|
|
||||||
example: openrpc.ExamplePairing{
|
|
||||||
params: [
|
|
||||||
openrpc.ExampleRef(openrpc.Example{
|
|
||||||
name: 'Example petId'
|
|
||||||
description: 'Example ID of the pet to retrieve'
|
|
||||||
value: 1
|
|
||||||
})
|
|
||||||
]
|
|
||||||
result: openrpc.ExampleRef(openrpc.Example{
|
|
||||||
name: 'Example response'
|
|
||||||
value: json.raw_decode('{"id": 1, "name": "Fluffy", "tag": "dog"}')!
|
|
||||||
})
|
|
||||||
}
|
|
||||||
parameters: [
|
|
||||||
openrpc.ContentDescriptor{
|
|
||||||
name: 'petId'
|
|
||||||
summary: 'ID of the pet to retrieve'
|
|
||||||
description: 'ID of the pet to retrieve'
|
|
||||||
required: true
|
|
||||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
...jsonschema.schema_u32,
|
|
||||||
format:'uint32'
|
|
||||||
example: 1
|
|
||||||
})
|
|
||||||
}
|
|
||||||
]
|
|
||||||
result: openrpc.ContentDescriptor{
|
|
||||||
name: 'result'
|
|
||||||
description: 'The response of the operation.'
|
|
||||||
required: true
|
|
||||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
|
||||||
ref: '#/components/schemas/Pet'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
errors: [
|
|
||||||
openrpc.ErrorSpec{
|
|
||||||
code: 404
|
|
||||||
message: 'Pet not found'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
specification.ActorMethod{
|
|
||||||
name: 'deletePet'
|
|
||||||
summary: 'Delete a pet by ID'
|
|
||||||
example: openrpc.ExamplePairing{
|
|
||||||
params: [
|
|
||||||
openrpc.ExampleRef(openrpc.Example{
|
|
||||||
name: 'Example petId'
|
|
||||||
description: 'Example ID of the pet to delete'
|
|
||||||
value: 1
|
|
||||||
})
|
|
||||||
]
|
|
||||||
}
|
|
||||||
parameters: [
|
|
||||||
openrpc.ContentDescriptor{
|
|
||||||
name: 'petId'
|
|
||||||
summary: 'ID of the pet to delete'
|
|
||||||
description: 'ID of the pet to delete'
|
|
||||||
required: true
|
|
||||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
...jsonschema.schema_u32,
|
|
||||||
example: 1
|
|
||||||
})
|
|
||||||
}
|
|
||||||
]
|
|
||||||
result: openrpc.ContentDescriptor{
|
|
||||||
name: 'result'
|
|
||||||
description: 'The response of the operation.'
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
errors: [
|
|
||||||
openrpc.ErrorSpec{
|
|
||||||
code: 404
|
|
||||||
message: 'Pet not found'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
objects: [
|
|
||||||
specification.BaseObject{
|
|
||||||
schema: jsonschema.Schema{
|
|
||||||
title: 'Pet'
|
|
||||||
typ: 'object'
|
|
||||||
properties: {
|
|
||||||
'id': jsonschema.schema_u32,
|
|
||||||
'name': jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
typ: 'string'
|
|
||||||
}),
|
|
||||||
'tag': jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
typ: 'string'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
required: ['id', 'name']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn test_typescript_client_folder() {
|
|
||||||
client := typescript_client_folder(specification)
|
|
||||||
}
|
|
||||||
@@ -1,192 +0,0 @@
|
|||||||
module generator
|
|
||||||
|
|
||||||
import freeflowuniverse.herolib.core.code { Result, Object, Param, Folder, IFile, VFile, CodeItem, File, Function, Import, Module, Struct, CustomCode }
|
|
||||||
import freeflowuniverse.herolib.core.texttools
|
|
||||||
import freeflowuniverse.herolib.schemas.openrpc {Example, ContentDescriptor}
|
|
||||||
import freeflowuniverse.herolib.schemas.jsonschema.codegen {schemaref_to_type}
|
|
||||||
import freeflowuniverse.herolib.baobab.specification {ActorMethod, ActorSpecification}
|
|
||||||
|
|
||||||
fn generate_handle_example_file(spec ActorSpecification) !VFile {
|
|
||||||
mut items := []CodeItem{}
|
|
||||||
items << CustomCode{generate_handle_example_function(spec)}
|
|
||||||
for method in spec.methods {
|
|
||||||
items << generate_example_method_handle(spec.name, method)!
|
|
||||||
}
|
|
||||||
return VFile {
|
|
||||||
name: 'act'
|
|
||||||
imports: [
|
|
||||||
Import{mod:'freeflowuniverse.herolib.baobab.stage' types:['Action']}
|
|
||||||
Import{mod:'x.json2 as json'}
|
|
||||||
]
|
|
||||||
items: items
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_handle_file(spec ActorSpecification) !VFile {
|
|
||||||
mut items := []CodeItem{}
|
|
||||||
items << CustomCode{generate_handle_function(spec)}
|
|
||||||
for method in spec.methods {
|
|
||||||
items << generate_method_handle(spec.name, method)!
|
|
||||||
}
|
|
||||||
return VFile {
|
|
||||||
name: 'act'
|
|
||||||
imports: [
|
|
||||||
Import{mod:'freeflowuniverse.herolib.baobab.stage' types:['Action']}
|
|
||||||
Import{mod:'x.json2 as json'}
|
|
||||||
]
|
|
||||||
items: items
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate_handle_function(spec ActorSpecification) string {
|
|
||||||
actor_name_pascal := texttools.snake_case_to_pascal(spec.name)
|
|
||||||
mut operation_handlers := []string{}
|
|
||||||
mut routes := []string{}
|
|
||||||
|
|
||||||
// Iterate over OpenAPI paths and operations
|
|
||||||
for method in spec.methods {
|
|
||||||
operation_id := method.name
|
|
||||||
params := method.parameters.map(it.name).join(', ')
|
|
||||||
|
|
||||||
// Generate route case
|
|
||||||
route := generate_route_case(operation_id, 'handle_${operation_id}')
|
|
||||||
routes << route
|
|
||||||
}
|
|
||||||
|
|
||||||
// Combine the generated handlers and main router into a single file
|
|
||||||
return [
|
|
||||||
'// AUTO-GENERATED FILE - DO NOT EDIT MANUALLY',
|
|
||||||
'',
|
|
||||||
'pub fn (mut actor ${actor_name_pascal}Actor) act(action Action) !Action {',
|
|
||||||
' return match action.name {',
|
|
||||||
routes.join('\n'),
|
|
||||||
' else {',
|
|
||||||
' return error("Unknown operation: \${action.name}")',
|
|
||||||
' }',
|
|
||||||
' }',
|
|
||||||
'}',
|
|
||||||
].join('\n')
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate_handle_example_function(spec ActorSpecification) string {
|
|
||||||
actor_name_pascal := texttools.snake_case_to_pascal(spec.name)
|
|
||||||
mut operation_handlers := []string{}
|
|
||||||
mut routes := []string{}
|
|
||||||
|
|
||||||
// Iterate over OpenAPI paths and operations
|
|
||||||
for method in spec.methods {
|
|
||||||
operation_id := method.name
|
|
||||||
params := method.parameters.map(it.name).join(', ')
|
|
||||||
|
|
||||||
// Generate route case
|
|
||||||
route := generate_route_case(operation_id, 'handle_${operation_id}_example')
|
|
||||||
routes << route
|
|
||||||
}
|
|
||||||
|
|
||||||
// Combine the generated handlers and main router into a single file
|
|
||||||
return [
|
|
||||||
'// AUTO-GENERATED FILE - DO NOT EDIT MANUALLY',
|
|
||||||
'',
|
|
||||||
'pub fn (mut actor ${actor_name_pascal}Actor) act(action Action) !Action {',
|
|
||||||
' return match action.name {',
|
|
||||||
routes.join('\n'),
|
|
||||||
' else {',
|
|
||||||
' return error("Unknown operation: \${action.name}")',
|
|
||||||
' }',
|
|
||||||
' }',
|
|
||||||
'}',
|
|
||||||
].join('\n')
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate_method_handle(actor_name string, method ActorMethod) !Function {
|
|
||||||
actor_name_pascal := texttools.snake_case_to_pascal(actor_name)
|
|
||||||
name_fixed := texttools.snake_case(method.name)
|
|
||||||
mut body := ''
|
|
||||||
if method.parameters.len == 1 {
|
|
||||||
param := method.parameters[0]
|
|
||||||
param_name := texttools.snake_case(param.name)
|
|
||||||
decode_stmt := generate_decode_stmt('action.params', param)!
|
|
||||||
body += '${param_name} := ${decode_stmt}\n'
|
|
||||||
}
|
|
||||||
if method.parameters.len > 1 {
|
|
||||||
body += 'params_arr := json.raw_decode(action.params)!.arr()\n'
|
|
||||||
for i, param in method.parameters {
|
|
||||||
param_name := texttools.snake_case(param.name)
|
|
||||||
decode_stmt := generate_decode_stmt('params_arr[${i}]', param)!
|
|
||||||
body += '${param_name} := ${decode_stmt}'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
call_stmt := generate_call_stmt(method)!
|
|
||||||
body += '${call_stmt}\n'
|
|
||||||
body += '${generate_return_stmt(method)!}\n'
|
|
||||||
return Function {
|
|
||||||
name: 'handle_${name_fixed}'
|
|
||||||
description: '// Handler for ${name_fixed}\n'
|
|
||||||
receiver: Param{name: 'actor', mutable: true, typ: Object{'${actor_name_pascal}Actor'}}
|
|
||||||
params: [Param{name: 'action', typ: Object{'Action'}}]
|
|
||||||
result: Param{typ: Result{Object{'Action'}}}
|
|
||||||
body: body
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn method_is_void(method ActorMethod) !bool {
|
|
||||||
return schemaref_to_type(method.result.schema).vgen().trim_space() == ''
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate_example_method_handle(actor_name string, method ActorMethod) !Function {
|
|
||||||
actor_name_pascal := texttools.snake_case_to_pascal(actor_name)
|
|
||||||
name_fixed := texttools.snake_case(method.name)
|
|
||||||
body := if !method_is_void(method)! {
|
|
||||||
if method.example.result is Example {
|
|
||||||
'return Action{...action, result: json.encode(\'${method.example.result.value}\')}'
|
|
||||||
} else {
|
|
||||||
"return action"
|
|
||||||
}
|
|
||||||
} else { "return action" }
|
|
||||||
return Function {
|
|
||||||
name: 'handle_${name_fixed}_example'
|
|
||||||
description: '// Handler for ${name_fixed}\n'
|
|
||||||
receiver: Param{name: 'actor', mutable: true, typ: Object{'${actor_name_pascal}Actor'}}
|
|
||||||
params: [Param{name: 'action', typ: Object{'Action'}}]
|
|
||||||
result: Param{typ: Result{Object{'Action'}}}
|
|
||||||
body: body
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_call_stmt(method ActorMethod) !string {
|
|
||||||
mut call_stmt := if schemaref_to_type(method.result.schema).vgen().trim_space() != '' {
|
|
||||||
'${texttools.snake_case(method.result.name)} := '
|
|
||||||
} else {''}
|
|
||||||
name_fixed := texttools.snake_case(method.name)
|
|
||||||
param_names := method.parameters.map(texttools.snake_case(it.name))
|
|
||||||
call_stmt += 'actor.${name_fixed}(${param_names.join(", ")})!'
|
|
||||||
return call_stmt
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_return_stmt(method ActorMethod) !string {
|
|
||||||
if schemaref_to_type(method.result.schema).vgen().trim_space() != '' {
|
|
||||||
return 'return Action{...action, result: json.encode(${texttools.snake_case(method.result.name)})}'
|
|
||||||
}
|
|
||||||
return "return action"
|
|
||||||
}
|
|
||||||
|
|
||||||
// generates decode statement for variable with given name
|
|
||||||
fn generate_decode_stmt(name string, param ContentDescriptor) !string {
|
|
||||||
param_type := schemaref_to_type(param.schema)
|
|
||||||
if param_type is Object {
|
|
||||||
return 'json.decode[${schemaref_to_type(param.schema).vgen()}](${name})!'
|
|
||||||
}
|
|
||||||
// else if param.schema.typ == 'array' {
|
|
||||||
// return 'json2.decode[${schemaref_to_type(param.schema)!.vgen()}](${name})'
|
|
||||||
// }
|
|
||||||
param_symbol := param_type.vgen()
|
|
||||||
return if param_symbol == 'string' {
|
|
||||||
'${name}.str()'
|
|
||||||
} else {'${name}.${param_type.vgen()}()'}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function to generate a case block for the main router
|
|
||||||
fn generate_route_case(case string, handler_name string) string {
|
|
||||||
name_fixed := texttools.snake_case(handler_name)
|
|
||||||
return "'${texttools.snake_case(case)}' {actor.${name_fixed}(action)}"
|
|
||||||
}
|
|
||||||
@@ -1,239 +0,0 @@
|
|||||||
module generator
|
|
||||||
|
|
||||||
import freeflowuniverse.herolib.core.code { Folder, IFolder, IFile, VFile, CodeItem, File, Function, Import, Module, Struct, CustomCode }
|
|
||||||
import freeflowuniverse.herolib.schemas.openapi
|
|
||||||
import freeflowuniverse.herolib.core.texttools
|
|
||||||
import freeflowuniverse.herolib.baobab.specification {ActorMethod, ActorSpecification, ActorInterface}
|
|
||||||
import json
|
|
||||||
|
|
||||||
@[params]
|
|
||||||
pub struct Params {
|
|
||||||
pub:
|
|
||||||
interfaces []ActorInterface // the interfaces to be supported
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate_actor_module(spec ActorSpecification, params Params) !Module {
|
|
||||||
mut files := []IFile{}
|
|
||||||
mut folders := []IFolder{}
|
|
||||||
|
|
||||||
files = [
|
|
||||||
generate_readme_file(spec)!,
|
|
||||||
generate_actor_file(spec)!,
|
|
||||||
generate_actor_test_file(spec)!,
|
|
||||||
generate_specs_file(spec.name, params.interfaces)!,
|
|
||||||
generate_handle_file(spec)!,
|
|
||||||
generate_methods_file(spec)!
|
|
||||||
generate_client_file(spec)!
|
|
||||||
generate_model_file(spec)!
|
|
||||||
]
|
|
||||||
|
|
||||||
mut docs_files := []IFile{}
|
|
||||||
|
|
||||||
// generate code files for supported interfaces
|
|
||||||
for iface in params.interfaces {
|
|
||||||
match iface {
|
|
||||||
.openrpc {
|
|
||||||
// convert actor spec to openrpc spec
|
|
||||||
openrpc_spec := spec.to_openrpc()
|
|
||||||
|
|
||||||
// generate openrpc code files
|
|
||||||
// files << generate_openrpc_client_file(openrpc_spec)!
|
|
||||||
// files << generate_openrpc_client_test_file(openrpc_spec)!
|
|
||||||
iface_file, iface_test_file := generate_openrpc_interface_files(params.interfaces)
|
|
||||||
files << iface_file
|
|
||||||
files << iface_test_file
|
|
||||||
|
|
||||||
// add openrpc.json to docs
|
|
||||||
// TODO
|
|
||||||
docs_files << generate_openrpc_file(openrpc_spec)!
|
|
||||||
}
|
|
||||||
.openapi {
|
|
||||||
// convert actor spec to openrpc spec
|
|
||||||
openapi_spec_raw := spec.to_openapi()
|
|
||||||
docs_files << generate_openapi_file(openapi_spec_raw)!
|
|
||||||
|
|
||||||
openapi_spec := openapi.process(openapi_spec_raw)!
|
|
||||||
// generate openrpc code files
|
|
||||||
iface_file, iface_test_file := generate_openapi_interface_files(params.interfaces)
|
|
||||||
files << iface_file
|
|
||||||
files << iface_test_file
|
|
||||||
|
|
||||||
// add openapi.json to docs
|
|
||||||
folders << generate_openapi_ts_client(openapi_spec)!
|
|
||||||
}
|
|
||||||
.http {
|
|
||||||
// interfaces that have http controllers
|
|
||||||
controllers := params.interfaces.filter(it == .openrpc || it == .openapi)
|
|
||||||
// generate openrpc code files
|
|
||||||
iface_file, iface_test_file := generate_http_interface_files(controllers)
|
|
||||||
files << iface_file
|
|
||||||
files << iface_test_file
|
|
||||||
}
|
|
||||||
.command {
|
|
||||||
files << generate_command_file(spec)!
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return error('unsupported interface ${iface}')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// folder with docs
|
|
||||||
folders << Folder {
|
|
||||||
name: 'docs'
|
|
||||||
files: docs_files
|
|
||||||
}
|
|
||||||
folders << generate_scripts_folder(spec.name, false)
|
|
||||||
folders << generate_examples_folder(spec, params)!
|
|
||||||
|
|
||||||
// create module with code files and docs folder
|
|
||||||
name_fixed := texttools.snake_case(spec.name)
|
|
||||||
return code.new_module(
|
|
||||||
name: '${name_fixed}_actor'
|
|
||||||
description: spec.description
|
|
||||||
files: files
|
|
||||||
folders: folders
|
|
||||||
in_src: true
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_readme_file(spec ActorSpecification) !File {
|
|
||||||
return File{
|
|
||||||
name: 'README'
|
|
||||||
extension: 'md'
|
|
||||||
content: '# ${spec.name}\n${spec.description}'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_actor_file(spec ActorSpecification) !VFile {
|
|
||||||
dollar := '$'
|
|
||||||
actor_name_snake := texttools.snake_case(spec.name)
|
|
||||||
actor_name_pascal := texttools.snake_case_to_pascal(spec.name)
|
|
||||||
actor_code := $tmpl('./templates/actor.v.template')
|
|
||||||
return VFile {
|
|
||||||
name: 'actor'
|
|
||||||
items: [CustomCode{actor_code}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_actor_example_file(spec ActorSpecification) !VFile {
|
|
||||||
dollar := '$'
|
|
||||||
actor_name_snake := texttools.snake_case(spec.name)
|
|
||||||
actor_name_pascal := texttools.snake_case_to_pascal(spec.name)
|
|
||||||
actor_code := $tmpl('./templates/actor_example.v.template')
|
|
||||||
return VFile {
|
|
||||||
name: 'actor_example'
|
|
||||||
items: [CustomCode{actor_code}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_actor_test_file(spec ActorSpecification) !VFile {
|
|
||||||
dollar := '$'
|
|
||||||
actor_name_snake := texttools.snake_case(spec.name)
|
|
||||||
actor_name_pascal := texttools.snake_case_to_pascal(spec.name)
|
|
||||||
actor_test_code := $tmpl('./templates/actor_test.v.template')
|
|
||||||
return VFile {
|
|
||||||
name: 'actor_test'
|
|
||||||
items: [CustomCode{actor_test_code}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_specs_file(name string, interfaces []ActorInterface) !VFile {
|
|
||||||
support_openrpc := ActorInterface.openrpc in interfaces
|
|
||||||
support_openapi := ActorInterface.openapi in interfaces
|
|
||||||
dollar := '$'
|
|
||||||
actor_name_snake := texttools.snake_case(name)
|
|
||||||
actor_name_pascal := texttools.snake_case_to_pascal(name)
|
|
||||||
actor_code := $tmpl('./templates/specifications.v.template')
|
|
||||||
return VFile {
|
|
||||||
name: 'specifications'
|
|
||||||
items: [CustomCode{actor_code}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate_examples_folder(spec ActorSpecification, params Params) !Folder {
|
|
||||||
return Folder {
|
|
||||||
name: 'examples'
|
|
||||||
modules: [generate_example_actor_module(spec, params)!]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate_example_actor_module(spec ActorSpecification, params Params) !Module {
|
|
||||||
mut files := []IFile{}
|
|
||||||
mut folders := []IFolder{}
|
|
||||||
|
|
||||||
files = [
|
|
||||||
generate_readme_file(spec)!,
|
|
||||||
generate_actor_example_file(spec)!,
|
|
||||||
generate_specs_file(spec.name, params.interfaces)!,
|
|
||||||
generate_handle_example_file(spec)!,
|
|
||||||
generate_example_client_file(spec)!
|
|
||||||
generate_model_file(spec)!
|
|
||||||
]
|
|
||||||
|
|
||||||
mut docs_files := []IFile{}
|
|
||||||
|
|
||||||
// generate code files for supported interfaces
|
|
||||||
for iface in params.interfaces {
|
|
||||||
match iface {
|
|
||||||
.openrpc {
|
|
||||||
// convert actor spec to openrpc spec
|
|
||||||
openrpc_spec := spec.to_openrpc()
|
|
||||||
|
|
||||||
// generate openrpc code files
|
|
||||||
// files << generate_openrpc_client_file(openrpc_spec)!
|
|
||||||
// files << generate_openrpc_client_test_file(openrpc_spec)!
|
|
||||||
iface_file, iface_test_file := generate_openrpc_interface_files(params.interfaces)
|
|
||||||
files << iface_file
|
|
||||||
files << iface_test_file
|
|
||||||
|
|
||||||
// add openrpc.json to docs
|
|
||||||
// TODO
|
|
||||||
docs_files << generate_openrpc_file(openrpc_spec)!
|
|
||||||
}
|
|
||||||
.openapi {
|
|
||||||
// convert actor spec to openrpc spec
|
|
||||||
openapi_spec := spec.to_openapi()
|
|
||||||
|
|
||||||
// generate openrpc code files
|
|
||||||
iface_file, iface_test_file := generate_openapi_interface_files(params.interfaces)
|
|
||||||
files << iface_file
|
|
||||||
files << iface_test_file
|
|
||||||
|
|
||||||
// add openapi.json to docs
|
|
||||||
docs_files << generate_openapi_file(openapi_spec)!
|
|
||||||
}
|
|
||||||
.http {
|
|
||||||
// interfaces that have http controllers
|
|
||||||
controllers := params.interfaces.filter(it == .openrpc || it == .openapi)
|
|
||||||
// generate openrpc code files
|
|
||||||
iface_file, iface_test_file := generate_http_interface_files(controllers)
|
|
||||||
files << iface_file
|
|
||||||
files << iface_test_file
|
|
||||||
}
|
|
||||||
.command {
|
|
||||||
files << generate_command_file(spec)!
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return error('unsupported interface ${iface}')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// folder with docs
|
|
||||||
folders << Folder {
|
|
||||||
name: 'docs'
|
|
||||||
files: docs_files
|
|
||||||
}
|
|
||||||
folders << generate_scripts_folder('example_${spec.name}', true)
|
|
||||||
|
|
||||||
// create module with code files and docs folder
|
|
||||||
name_fixed := texttools.snake_case(spec.name)
|
|
||||||
return code.new_module(
|
|
||||||
name: 'example_${name_fixed}_actor'
|
|
||||||
files: files
|
|
||||||
folders: folders
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,273 +0,0 @@
|
|||||||
module generator
|
|
||||||
|
|
||||||
import freeflowuniverse.herolib.core.code
|
|
||||||
import freeflowuniverse.herolib.baobab.specification
|
|
||||||
import freeflowuniverse.herolib.schemas.openrpc
|
|
||||||
import freeflowuniverse.herolib.schemas.jsonschema
|
|
||||||
import os
|
|
||||||
import x.json2 as json {Any}
|
|
||||||
|
|
||||||
const actor_spec = specification.ActorSpecification{
|
|
||||||
name: 'Pet Store'
|
|
||||||
description: 'A sample API for a pet store'
|
|
||||||
structure: code.Struct{}
|
|
||||||
interfaces: [.openapi]
|
|
||||||
methods: [
|
|
||||||
specification.ActorMethod{
|
|
||||||
name: 'listPets'
|
|
||||||
summary: 'List all pets'
|
|
||||||
example: openrpc.ExamplePairing{
|
|
||||||
params: [
|
|
||||||
openrpc.ExampleRef(openrpc.Example{
|
|
||||||
name: 'Example limit'
|
|
||||||
description: 'Example Maximum number of pets to return'
|
|
||||||
value: 10
|
|
||||||
})
|
|
||||||
]
|
|
||||||
result: openrpc.ExampleRef(openrpc.Example{
|
|
||||||
name: 'Example response'
|
|
||||||
value: json.raw_decode('[
|
|
||||||
{"id": 1, "name": "Fluffy", "tag": "dog"},
|
|
||||||
{"id": 2, "name": "Whiskers", "tag": "cat"}
|
|
||||||
]')!
|
|
||||||
})
|
|
||||||
}
|
|
||||||
parameters: [
|
|
||||||
openrpc.ContentDescriptor{
|
|
||||||
name: 'limit'
|
|
||||||
summary: 'Maximum number of pets to return'
|
|
||||||
description: 'Maximum number of pets to return'
|
|
||||||
required: false
|
|
||||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
...jsonschema.schema_u32,
|
|
||||||
example: 10
|
|
||||||
})
|
|
||||||
}
|
|
||||||
]
|
|
||||||
result: openrpc.ContentDescriptor{
|
|
||||||
name: 'pets'
|
|
||||||
description: 'A paged array of pets'
|
|
||||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
typ: 'array'
|
|
||||||
items: jsonschema.Items(jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
id: 'pet'
|
|
||||||
title: 'Pet'
|
|
||||||
typ: 'object'
|
|
||||||
properties: {
|
|
||||||
'id': jsonschema.SchemaRef(jsonschema.Reference{
|
|
||||||
ref: '#/components/schemas/PetId'
|
|
||||||
}),
|
|
||||||
'name': jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
typ: 'string'
|
|
||||||
}),
|
|
||||||
'tag': jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
typ: 'string'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
required: ['id', 'name']
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
errors: [
|
|
||||||
openrpc.ErrorSpec{
|
|
||||||
code: 400
|
|
||||||
message: 'Invalid request'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
specification.ActorMethod{
|
|
||||||
name: 'newPet'
|
|
||||||
summary: 'Create a new pet'
|
|
||||||
parameters: [
|
|
||||||
openrpc.ContentDescriptor{
|
|
||||||
name: 'result'
|
|
||||||
description: 'The response of the operation.'
|
|
||||||
required: true
|
|
||||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
id: 'pet'
|
|
||||||
title: 'Pet'
|
|
||||||
typ: 'object'
|
|
||||||
properties: {
|
|
||||||
'id': jsonschema.SchemaRef(jsonschema.Reference{
|
|
||||||
ref: '#/components/schemas/PetId'
|
|
||||||
}),
|
|
||||||
'name': jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
typ: 'string'
|
|
||||||
}),
|
|
||||||
'tag': jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
typ: 'string'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
required: ['id', 'name']
|
|
||||||
})
|
|
||||||
}
|
|
||||||
]
|
|
||||||
example: openrpc.ExamplePairing{
|
|
||||||
result: openrpc.ExampleRef(openrpc.Example{
|
|
||||||
name: 'Example response'
|
|
||||||
value: '[]'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
result: openrpc.ContentDescriptor{
|
|
||||||
name: 'petId'
|
|
||||||
summary: 'ID of the created pet'
|
|
||||||
description: 'ID of the created pet'
|
|
||||||
required: true
|
|
||||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
...jsonschema.schema_u32,
|
|
||||||
example: 1
|
|
||||||
})
|
|
||||||
}
|
|
||||||
errors: [
|
|
||||||
openrpc.ErrorSpec{
|
|
||||||
code: 400
|
|
||||||
message: 'Invalid input'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
specification.ActorMethod{
|
|
||||||
name: 'getPet'
|
|
||||||
summary: 'Get a pet by ID'
|
|
||||||
example: openrpc.ExamplePairing{
|
|
||||||
params: [
|
|
||||||
openrpc.ExampleRef(openrpc.Example{
|
|
||||||
name: 'Example petId'
|
|
||||||
description: 'Example ID of the pet to retrieve'
|
|
||||||
value: 1
|
|
||||||
})
|
|
||||||
]
|
|
||||||
result: openrpc.ExampleRef(openrpc.Example{
|
|
||||||
name: 'Example response'
|
|
||||||
value: json.raw_decode('{"id": 1, "name": "Fluffy", "tag": "dog"}')!
|
|
||||||
})
|
|
||||||
}
|
|
||||||
parameters: [
|
|
||||||
openrpc.ContentDescriptor{
|
|
||||||
name: 'petId'
|
|
||||||
summary: 'ID of the pet to retrieve'
|
|
||||||
description: 'ID of the pet to retrieve'
|
|
||||||
required: true
|
|
||||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
...jsonschema.schema_u32,
|
|
||||||
format:'uint32'
|
|
||||||
example: 1
|
|
||||||
})
|
|
||||||
}
|
|
||||||
]
|
|
||||||
result: openrpc.ContentDescriptor{
|
|
||||||
name: 'result'
|
|
||||||
description: 'The response of the operation.'
|
|
||||||
required: true
|
|
||||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
|
||||||
ref: '#/components/schemas/Pet'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
errors: [
|
|
||||||
openrpc.ErrorSpec{
|
|
||||||
code: 404
|
|
||||||
message: 'Pet not found'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
specification.ActorMethod{
|
|
||||||
name: 'deletePet'
|
|
||||||
summary: 'Delete a pet by ID'
|
|
||||||
example: openrpc.ExamplePairing{
|
|
||||||
params: [
|
|
||||||
openrpc.ExampleRef(openrpc.Example{
|
|
||||||
name: 'Example petId'
|
|
||||||
description: 'Example ID of the pet to delete'
|
|
||||||
value: 1
|
|
||||||
})
|
|
||||||
]
|
|
||||||
}
|
|
||||||
parameters: [
|
|
||||||
openrpc.ContentDescriptor{
|
|
||||||
name: 'petId'
|
|
||||||
summary: 'ID of the pet to delete'
|
|
||||||
description: 'ID of the pet to delete'
|
|
||||||
required: true
|
|
||||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
...jsonschema.schema_u32,
|
|
||||||
example: 1
|
|
||||||
})
|
|
||||||
}
|
|
||||||
]
|
|
||||||
result: openrpc.ContentDescriptor{
|
|
||||||
name: 'result'
|
|
||||||
description: 'The response of the operation.'
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
errors: [
|
|
||||||
openrpc.ErrorSpec{
|
|
||||||
code: 404
|
|
||||||
message: 'Pet not found'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
objects: [
|
|
||||||
specification.BaseObject{
|
|
||||||
schema: jsonschema.Schema{
|
|
||||||
title: 'Pet'
|
|
||||||
typ: 'object'
|
|
||||||
properties: {
|
|
||||||
'id': jsonschema.schema_u32,
|
|
||||||
'name': jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
typ: 'string'
|
|
||||||
}),
|
|
||||||
'tag': jsonschema.SchemaRef(jsonschema.Schema{
|
|
||||||
typ: 'string'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
required: ['id', 'name']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
const destination = '${os.dir(@FILE)}/testdata'
|
|
||||||
|
|
||||||
fn test_generate_plain_actor_module() {
|
|
||||||
// plain actor module without interfaces
|
|
||||||
actor_module := generate_actor_module(actor_spec)!
|
|
||||||
actor_module.write(destination,
|
|
||||||
format: true
|
|
||||||
overwrite: true
|
|
||||||
test: true
|
|
||||||
)!
|
|
||||||
}
|
|
||||||
|
|
||||||
fn test_generate_actor_module_with_openrpc_interface() {
|
|
||||||
// plain actor module without interfaces
|
|
||||||
actor_module := generate_actor_module(actor_spec, interfaces: [.openrpc])!
|
|
||||||
actor_module.write(destination,
|
|
||||||
format: true
|
|
||||||
overwrite: true
|
|
||||||
test: true
|
|
||||||
)!
|
|
||||||
}
|
|
||||||
|
|
||||||
fn test_generate_actor_module_with_openapi_interface() {
|
|
||||||
// plain actor module without interfaces
|
|
||||||
actor_module := generate_actor_module(actor_spec,
|
|
||||||
interfaces: [.openapi]
|
|
||||||
)!
|
|
||||||
actor_module.write(destination,
|
|
||||||
format: true
|
|
||||||
overwrite: true
|
|
||||||
test: true
|
|
||||||
)!
|
|
||||||
}
|
|
||||||
|
|
||||||
fn test_generate_actor_module_with_all_interfaces() {
|
|
||||||
// plain actor module without interfaces
|
|
||||||
actor_module := generate_actor_module(actor_spec,
|
|
||||||
interfaces: [.openapi, .openrpc, .http]
|
|
||||||
)!
|
|
||||||
actor_module.write(destination,
|
|
||||||
format: true
|
|
||||||
overwrite: true
|
|
||||||
test: true
|
|
||||||
)!
|
|
||||||
}
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
module generator
|
|
||||||
|
|
||||||
import freeflowuniverse.herolib.core.code { Param, Folder, IFile, VFile, CodeItem, File, Function, Import, Module, Struct, CustomCode, Result }
|
|
||||||
import freeflowuniverse.herolib.core.texttools
|
|
||||||
import freeflowuniverse.herolib.schemas.jsonschema.codegen as jsonschema_codegen {schemaref_to_type}
|
|
||||||
import freeflowuniverse.herolib.schemas.openrpc.codegen {content_descriptor_to_parameter}
|
|
||||||
import freeflowuniverse.herolib.baobab.specification {ActorMethod, ActorSpecification}
|
|
||||||
|
|
||||||
pub fn generate_client_file(spec ActorSpecification) !VFile {
|
|
||||||
actor_name_snake := texttools.snake_case(spec.name)
|
|
||||||
actor_name_pascal := texttools.snake_case_to_pascal(spec.name)
|
|
||||||
|
|
||||||
mut items := []CodeItem{}
|
|
||||||
|
|
||||||
items << CustomCode {'
|
|
||||||
pub struct Client {
|
|
||||||
stage.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_client() !Client {
|
|
||||||
mut redis := redisclient.new(\'localhost:6379\')!
|
|
||||||
mut rpc_q := redis.rpc_get(\'actor_\${name}\')
|
|
||||||
return Client{
|
|
||||||
rpc: rpc_q
|
|
||||||
}
|
|
||||||
}'}
|
|
||||||
|
|
||||||
for method in spec.methods {
|
|
||||||
items << generate_client_method(method)!
|
|
||||||
}
|
|
||||||
|
|
||||||
return VFile {
|
|
||||||
imports: [
|
|
||||||
Import{
|
|
||||||
mod: 'freeflowuniverse.herolib.baobab.stage'
|
|
||||||
},
|
|
||||||
Import{
|
|
||||||
mod: 'freeflowuniverse.herolib.core.redisclient'
|
|
||||||
},
|
|
||||||
Import{
|
|
||||||
mod: 'x.json2 as json'
|
|
||||||
types: ['Any']
|
|
||||||
}
|
|
||||||
]
|
|
||||||
name: 'client'
|
|
||||||
items: items
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate_example_client_file(spec ActorSpecification) !VFile {
|
|
||||||
actor_name_snake := texttools.snake_case(spec.name)
|
|
||||||
actor_name_pascal := texttools.snake_case_to_pascal(spec.name)
|
|
||||||
|
|
||||||
mut items := []CodeItem{}
|
|
||||||
|
|
||||||
items << CustomCode {'
|
|
||||||
pub struct Client {
|
|
||||||
stage.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_client() !Client {
|
|
||||||
mut redis := redisclient.new(\'localhost:6379\')!
|
|
||||||
mut rpc_q := redis.rpc_get(\'actor_example_\${name}\')
|
|
||||||
return Client{
|
|
||||||
rpc: rpc_q
|
|
||||||
}
|
|
||||||
}'}
|
|
||||||
|
|
||||||
for method in spec.methods {
|
|
||||||
items << generate_client_method(method)!
|
|
||||||
}
|
|
||||||
|
|
||||||
return VFile {
|
|
||||||
imports: [
|
|
||||||
Import{
|
|
||||||
mod: 'freeflowuniverse.herolib.baobab.stage'
|
|
||||||
},
|
|
||||||
Import{
|
|
||||||
mod: 'freeflowuniverse.herolib.core.redisclient'
|
|
||||||
},
|
|
||||||
Import{
|
|
||||||
mod: 'x.json2 as json'
|
|
||||||
types: ['Any']
|
|
||||||
}
|
|
||||||
]
|
|
||||||
name: 'client'
|
|
||||||
items: items
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub fn generate_client_method(method ActorMethod) !Function {
|
|
||||||
name_fixed := texttools.snake_case(method.name)
|
|
||||||
|
|
||||||
call_params := if method.parameters.len > 0 {
|
|
||||||
method.parameters.map(texttools.snake_case(it.name)).map('Any(${it})').join(', ')
|
|
||||||
} else {''}
|
|
||||||
|
|
||||||
params_stmt := if method.parameters.len == 0 {
|
|
||||||
''
|
|
||||||
} else if method.parameters.len == 1 {
|
|
||||||
'params := json.encode(${texttools.snake_case(method.parameters[0].name)})'
|
|
||||||
} else {
|
|
||||||
'mut params_arr := []Any{}
|
|
||||||
params_arr = [${call_params}]
|
|
||||||
params := json.encode(params_arr.str())
|
|
||||||
'
|
|
||||||
}
|
|
||||||
|
|
||||||
mut client_call_stmt := "action := client.call_to_action(
|
|
||||||
name: '${name_fixed}'"
|
|
||||||
|
|
||||||
if params_stmt != '' {
|
|
||||||
client_call_stmt += 'params: params'
|
|
||||||
}
|
|
||||||
client_call_stmt += ')!'
|
|
||||||
|
|
||||||
result_type := schemaref_to_type(method.result.schema).vgen().trim_space()
|
|
||||||
result_stmt := if result_type == '' {
|
|
||||||
''
|
|
||||||
} else {
|
|
||||||
"return json.decode[${result_type}](action.result)!"
|
|
||||||
}
|
|
||||||
result_param := content_descriptor_to_parameter(method.result)!
|
|
||||||
return Function {
|
|
||||||
receiver: code.new_param(v: 'mut client Client')!
|
|
||||||
result: Param{...result_param, typ: Result{result_param.typ}}
|
|
||||||
name: name_fixed
|
|
||||||
body: '${params_stmt}\n${client_call_stmt}\n${result_stmt}'
|
|
||||||
summary: method.summary
|
|
||||||
description: method.description
|
|
||||||
params: method.parameters.map(content_descriptor_to_parameter(it)!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user