Compare commits
49 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e997946c56 | |||
|
|
dd4bb73a78 | ||
|
|
1005576814 | ||
|
|
10c15f6f8e | ||
|
|
af2f33d4f6 | ||
|
|
1db2c3ee54 | ||
|
|
7e8a4c5c45 | ||
|
|
f6fe3d4fda | ||
|
|
eeb2602bcf | ||
|
|
565eec0292 | ||
|
|
a98fad32d3 | ||
|
|
10f0c0bd31 | ||
|
|
01552145a8 | ||
|
|
09ed341b97 | ||
|
|
5cb30e6783 | ||
|
|
ee8fbbca09 | ||
|
|
b9b21ac44b | ||
|
|
d403f84b6c | ||
|
|
dfeeb8cd4c | ||
|
|
135866e5b0 | ||
|
|
eef88b5375 | ||
|
|
8b9717bb74 | ||
|
|
9a7a66192b | ||
|
|
df950143b4 | ||
|
|
038c563843 | ||
|
|
4733e05c58 | ||
|
|
c9496f0973 | ||
|
|
31dffa14ce | ||
|
|
7459501c8f | ||
|
|
bc9fd08f7e | ||
|
|
be1cee5d6a | ||
|
|
c91f9ba43c | ||
|
|
357000ef13 | ||
|
|
6ba89a8b9c | ||
|
|
d5af1d19b8 | ||
|
|
ce1ce722d5 | ||
|
|
fa192e10b8 | ||
|
|
7ae3296ef5 | ||
|
|
a6ba22b0b1 | ||
|
|
d49e94e412 | ||
|
|
ff8ee3693c | ||
|
|
d43d4d8a9f | ||
|
|
6f814b5d09 | ||
|
|
5d3df608e1 | ||
|
|
86af42bf4a | ||
|
|
5869998f6e | ||
|
|
cbdc0fd313 | ||
|
|
bada9508ef | ||
|
|
7bc4da97ab |
@@ -1,187 +0,0 @@
|
||||
## 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,3 +1 @@
|
||||
hero
|
||||
compile
|
||||
compile_upload
|
||||
|
||||
23
cli/hero.v
23
cli/hero.v
@@ -19,26 +19,6 @@ fn playcmds_do(path string) ! {
|
||||
}
|
||||
|
||||
fn do() ! {
|
||||
|
||||
if ! core.is_osx()! {
|
||||
if os.getenv('SUDO_COMMAND') != '' || os.getenv('SUDO_USER') != '' {
|
||||
println('Error: Please do not run this program with sudo!')
|
||||
exit(1) // Exit with error code
|
||||
}
|
||||
}
|
||||
|
||||
if os.getuid() == 0 {
|
||||
if core.is_osx()! {
|
||||
eprintln("please do not run hero as root in osx.")
|
||||
exit(1)
|
||||
}
|
||||
} else {
|
||||
if ! core.is_osx()! {
|
||||
eprintln("please do run hero as root, don't use sudo.")
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
if os.args.len == 2 {
|
||||
mypath := os.args[1]
|
||||
if mypath.to_lower().ends_with('.hero') {
|
||||
@@ -51,7 +31,7 @@ fn do() ! {
|
||||
mut cmd := Command{
|
||||
name: 'hero'
|
||||
description: 'Your HERO toolset.'
|
||||
version: '1.0.15'
|
||||
version: '1.0.11'
|
||||
}
|
||||
|
||||
// herocmds.cmd_run_add_flags(mut cmd)
|
||||
@@ -102,7 +82,6 @@ fn do() ! {
|
||||
// herocmds.cmd_juggler(mut cmd)
|
||||
herocmds.cmd_generator(mut cmd)
|
||||
herocmds.cmd_docusaurus(mut cmd)
|
||||
herocmds.cmd_starlight(mut cmd)
|
||||
// herocmds.cmd_docsorter(mut cmd)
|
||||
// cmd.add_command(publishing.cmd_publisher(pre_func))
|
||||
cmd.setup()
|
||||
|
||||
3
examples/baobab/generator/.gitignore
vendored
Normal file
3
examples/baobab/generator/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
methods.v
|
||||
pet_store_actor
|
||||
docs
|
||||
9
examples/baobab/generator/README.md
Normal file
9
examples/baobab/generator/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Actor Generation Examples
|
||||
|
||||
## `generate_methods.vsh`
|
||||
|
||||
This example generates actor method prototypes from an actor specification.
|
||||
|
||||
## `generate_actor_module.vsh`
|
||||
|
||||
This example generates an entire actor module from an actor specification with the support for the specified interfaces.
|
||||
23
examples/baobab/generator/generate_actor_module.vsh
Executable file
23
examples/baobab/generator/generate_actor_module.vsh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/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
|
||||
)!
|
||||
19
examples/baobab/generator/generate_methods.vsh
Executable file
19
examples/baobab/generator/generate_methods.vsh
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/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
|
||||
)!
|
||||
19
examples/baobab/generator/generate_openrpc_file.vsh
Executable file
19
examples/baobab/generator/generate_openrpc_file.vsh
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/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
|
||||
)!
|
||||
2
examples/baobab/generator/openapi_e2e/.gitignore
vendored
Normal file
2
examples/baobab/generator/openapi_e2e/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
methods.v
|
||||
meeting_scheduler_actor
|
||||
26
examples/baobab/generator/openapi_e2e/generate_actor_module.vsh
Executable file
26
examples/baobab/generator/openapi_e2e/generate_actor_module.vsh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/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'])!
|
||||
311
examples/baobab/generator/openapi_e2e/openapi.json
Normal file
311
examples/baobab/generator/openapi_e2e/openapi.json
Normal file
@@ -0,0 +1,311 @@
|
||||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"title": "Meeting Scheduler",
|
||||
"version": "1.0.0",
|
||||
"description": "An API for managing meetings, availability, and scheduling."
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://localhost:8080/openapi/v1",
|
||||
"description": "Production server"
|
||||
},
|
||||
{
|
||||
"url": "http://localhost:8081/openapi/v1",
|
||||
"description": "Example server"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/users": {
|
||||
"get": {
|
||||
"summary": "List all users",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A list of users",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/User"
|
||||
}
|
||||
},
|
||||
"example": [
|
||||
{
|
||||
"id": "1",
|
||||
"name": "Alice",
|
||||
"email": "alice@example.com"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"name": "Bob",
|
||||
"email": "bob@example.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/{userId}": {
|
||||
"get": {
|
||||
"operationId": "get_user",
|
||||
"summary": "Get user by ID",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "userId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "uint32"
|
||||
},
|
||||
"description": "The ID of the user",
|
||||
"example": 1
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "User details",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/User"
|
||||
},
|
||||
"example": {
|
||||
"id": "1",
|
||||
"name": "Alice",
|
||||
"email": "alice@example.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "User not found"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/events": {
|
||||
"post": {
|
||||
"summary": "Create an event",
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Event"
|
||||
},
|
||||
"example": {
|
||||
"title": "Team Meeting",
|
||||
"description": "Weekly sync",
|
||||
"startTime": "2023-10-10T10:00:00Z",
|
||||
"endTime": "2023-10-10T11:00:00Z",
|
||||
"userId": "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Event created",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Event"
|
||||
},
|
||||
"example": {
|
||||
"id": "101",
|
||||
"title": "Team Meeting",
|
||||
"description": "Weekly sync",
|
||||
"startTime": "2023-10-10T10:00:00Z",
|
||||
"endTime": "2023-10-10T11:00:00Z",
|
||||
"userId": "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/availability": {
|
||||
"get": {
|
||||
"summary": "Get availability for a user",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "userId",
|
||||
"in": "query",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "The ID of the user",
|
||||
"example": "1"
|
||||
},
|
||||
{
|
||||
"name": "date",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
},
|
||||
"description": "The date to check availability (YYYY-MM-DD)",
|
||||
"example": "2023-10-10"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Availability details",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/TimeSlot"
|
||||
}
|
||||
},
|
||||
"example": [
|
||||
{
|
||||
"startTime": "10:00:00",
|
||||
"endTime": "11:00:00",
|
||||
"available": true
|
||||
},
|
||||
{
|
||||
"startTime": "11:00:00",
|
||||
"endTime": "12:00:00",
|
||||
"available": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/bookings": {
|
||||
"post": {
|
||||
"summary": "Book a meeting",
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Booking"
|
||||
},
|
||||
"example": {
|
||||
"userId": "1",
|
||||
"eventId": "101",
|
||||
"timeSlot": {
|
||||
"startTime": "10:00:00",
|
||||
"endTime": "11:00:00",
|
||||
"available": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Booking created",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Booking"
|
||||
},
|
||||
"example": {
|
||||
"id": "5001",
|
||||
"userId": "1",
|
||||
"eventId": "101",
|
||||
"timeSlot": {
|
||||
"startTime": "10:00:00",
|
||||
"endTime": "11:00:00",
|
||||
"available": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"User": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"format": "email"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Event": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"startTime": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"endTime": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"userId": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"TimeSlot": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"startTime": {
|
||||
"type": "string",
|
||||
"format": "time"
|
||||
},
|
||||
"endTime": {
|
||||
"type": "string",
|
||||
"format": "time"
|
||||
},
|
||||
"available": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Booking": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"userId": {
|
||||
"type": "string"
|
||||
},
|
||||
"eventId": {
|
||||
"type": "string"
|
||||
},
|
||||
"timeSlot": {
|
||||
"$ref": "#/components/schemas/TimeSlot"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
132
examples/baobab/generator/openrpc.json
Normal file
132
examples/baobab/generator/openrpc.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"openrpc": "1.0.0",
|
||||
"info": {
|
||||
"title": "PetStore",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"methods": [
|
||||
{
|
||||
"name": "GetPets",
|
||||
"description": "finds pets in the system that the user has access to by tags and within a limit",
|
||||
"params": [
|
||||
{
|
||||
"name": "tags",
|
||||
"description": "tags to filter by",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"description": "maximum number of results to return",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "pet_list",
|
||||
"description": "all pets from the system, that mathes the tags",
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/Pet"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "CreatePet",
|
||||
"description": "creates a new pet in the store. Duplicates are allowed.",
|
||||
"params": [
|
||||
{
|
||||
"name": "new_pet",
|
||||
"description": "Pet to add to the store.",
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/NewPet"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "pet",
|
||||
"description": "the newly created pet",
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/Pet"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "GetPetById",
|
||||
"description": "gets a pet based on a single ID, if the user has access to the pet",
|
||||
"params": [
|
||||
{
|
||||
"name": "id",
|
||||
"description": "ID of pet to fetch",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "pet",
|
||||
"description": "pet response",
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/Pet"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "DeletePetById",
|
||||
"description": "deletes a single pet based on the ID supplied",
|
||||
"params": [
|
||||
{
|
||||
"name": "id",
|
||||
"description": "ID of pet to delete",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "pet",
|
||||
"description": "pet deleted",
|
||||
"schema": {
|
||||
"type": "null"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"components": {
|
||||
"schemas": {
|
||||
"NewPet": {
|
||||
"title": "NewPet",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"tag": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Pet": {
|
||||
"title": "Pet",
|
||||
"description": "a pet struct that represents a pet",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "name of the pet",
|
||||
"type": "string"
|
||||
},
|
||||
"tag": {
|
||||
"description": "a tag of the pet, helps finding pet",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"description": "unique indentifier",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
examples/baobab/specification/README.md
Normal file
3
examples/baobab/specification/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Actor Specification Examples
|
||||
|
||||
These examples show how `OpenRPC` and `OpenAPI` specifications can be translated back and forth into an `ActorSpecification`. This is an important step of actor generation as actor code is generated from actor specification.
|
||||
346
examples/baobab/specification/openapi.json
Normal file
346
examples/baobab/specification/openapi.json
Normal file
@@ -0,0 +1,346 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"info": {
|
||||
"title": "Pet Store API",
|
||||
"description": "A sample API for a pet store",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://api.petstore.example.com/v1",
|
||||
"description": "Production server"
|
||||
},
|
||||
{
|
||||
"url": "https://staging.petstore.example.com/v1",
|
||||
"description": "Staging server"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"get": {
|
||||
"summary": "List all pets",
|
||||
"operationId": "listPets",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
"description": "Maximum number of pets to return",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A paginated list of pets",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Pets"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid request"
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"summary": "Create a new pet",
|
||||
"operationId": "createPet",
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/NewPet"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Pet created",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid input"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/pets/{petId}": {
|
||||
"get": {
|
||||
"summary": "Get a pet by ID",
|
||||
"operationId": "getPet",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "petId",
|
||||
"in": "path",
|
||||
"description": "ID of the pet to retrieve",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A pet",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Pet not found"
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"summary": "Delete a pet by ID",
|
||||
"operationId": "deletePet",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "petId",
|
||||
"in": "path",
|
||||
"description": "ID of the pet to delete",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "Pet deleted"
|
||||
},
|
||||
"404": {
|
||||
"description": "Pet not found"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/orders": {
|
||||
"get": {
|
||||
"summary": "List all orders",
|
||||
"operationId": "listOrders",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A list of orders",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Order"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/orders/{orderId}": {
|
||||
"get": {
|
||||
"summary": "Get an order by ID",
|
||||
"operationId": "getOrder",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "orderId",
|
||||
"in": "path",
|
||||
"description": "ID of the order to retrieve",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "An order",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Order"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Order not found"
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"summary": "Delete an order by ID",
|
||||
"operationId": "deleteOrder",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "orderId",
|
||||
"in": "path",
|
||||
"description": "ID of the order to delete",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "Order deleted"
|
||||
},
|
||||
"404": {
|
||||
"description": "Order not found"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users": {
|
||||
"post": {
|
||||
"summary": "Create a user",
|
||||
"operationId": "createUser",
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/NewUser"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "User created",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/User"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Pet": {
|
||||
"type": "object",
|
||||
"required": ["id", "name"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"tag": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"NewPet": {
|
||||
"type": "object",
|
||||
"required": ["name"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"tag": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Pets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
}
|
||||
},
|
||||
"Order": {
|
||||
"type": "object",
|
||||
"required": ["id", "petId", "quantity", "shipDate"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"petId": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"quantity": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"shipDate": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["placed", "approved", "delivered"]
|
||||
},
|
||||
"complete": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"User": {
|
||||
"type": "object",
|
||||
"required": ["id", "username"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"NewUser": {
|
||||
"type": "object",
|
||||
"required": ["username"],
|
||||
"properties": {
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
examples/baobab/specification/openapi_to_specification.vsh
Executable file
13
examples/baobab/specification/openapi_to_specification.vsh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env -S v -w -n -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.baobab.specification
|
||||
import freeflowuniverse.herolib.schemas.openapi
|
||||
import os
|
||||
|
||||
const example_dir = os.dir(@FILE)
|
||||
const openapi_spec_path = os.join_path(example_dir, 'openapi.json')
|
||||
|
||||
// the actor specification obtained from the OpenRPC Specification
|
||||
openapi_spec := openapi.new(path: openapi_spec_path)!
|
||||
actor_specification := specification.from_openapi(openapi_spec)!
|
||||
println(actor_specification)
|
||||
132
examples/baobab/specification/openrpc.json
Normal file
132
examples/baobab/specification/openrpc.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"openrpc": "1.0.0",
|
||||
"info": {
|
||||
"title": "PetStore",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"methods": [
|
||||
{
|
||||
"name": "GetPets",
|
||||
"description": "finds pets in the system that the user has access to by tags and within a limit",
|
||||
"params": [
|
||||
{
|
||||
"name": "tags",
|
||||
"description": "tags to filter by",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"description": "maximum number of results to return",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "pet_list",
|
||||
"description": "all pets from the system, that mathes the tags",
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/Pet"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "CreatePet",
|
||||
"description": "creates a new pet in the store. Duplicates are allowed.",
|
||||
"params": [
|
||||
{
|
||||
"name": "new_pet",
|
||||
"description": "Pet to add to the store.",
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/NewPet"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "pet",
|
||||
"description": "the newly created pet",
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/Pet"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "GetPetById",
|
||||
"description": "gets a pet based on a single ID, if the user has access to the pet",
|
||||
"params": [
|
||||
{
|
||||
"name": "id",
|
||||
"description": "ID of pet to fetch",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "pet",
|
||||
"description": "pet response",
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/Pet"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "DeletePetById",
|
||||
"description": "deletes a single pet based on the ID supplied",
|
||||
"params": [
|
||||
{
|
||||
"name": "id",
|
||||
"description": "ID of pet to delete",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "pet",
|
||||
"description": "pet deleted",
|
||||
"schema": {
|
||||
"type": "null"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"components": {
|
||||
"schemas": {
|
||||
"NewPet": {
|
||||
"title": "NewPet",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"tag": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Pet": {
|
||||
"title": "Pet",
|
||||
"description": "a pet struct that represents a pet",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "name of the pet",
|
||||
"type": "string"
|
||||
},
|
||||
"tag": {
|
||||
"description": "a tag of the pet, helps finding pet",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"description": "unique indentifier",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
examples/baobab/specification/openrpc_to_specification.vsh
Executable file
13
examples/baobab/specification/openrpc_to_specification.vsh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env -S v -w -n -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.baobab.specification
|
||||
import freeflowuniverse.herolib.schemas.openrpc
|
||||
import os
|
||||
|
||||
const example_dir = os.dir(@FILE)
|
||||
const openrpc_spec_path = os.join_path(example_dir, 'openrpc.json')
|
||||
|
||||
// the actor specification obtained from the OpenRPC Specification
|
||||
openrpc_spec := openrpc.new(path: openrpc_spec_path)!
|
||||
actor_specification := specification.from_openrpc(openrpc_spec)!
|
||||
println(actor_specification)
|
||||
107
examples/baobab/specification/specification_to_openapi.vsh
Executable file
107
examples/baobab/specification/specification_to_openapi.vsh
Executable file
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env -S v -w -n -enable-globals run
|
||||
|
||||
import json
|
||||
import freeflowuniverse.herolib.baobab.specification
|
||||
import freeflowuniverse.herolib.schemas.jsonschema
|
||||
import freeflowuniverse.herolib.schemas.openrpc
|
||||
import os
|
||||
|
||||
const actor_specification = specification.ActorSpecification{
|
||||
name: 'PetStore'
|
||||
interfaces: [.openrpc]
|
||||
methods: [
|
||||
specification.ActorMethod{
|
||||
name: 'GetPets'
|
||||
description: 'finds pets in the system that the user has access to by tags and within a limit'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'tags'
|
||||
description: 'tags to filter by'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'array'
|
||||
items: jsonschema.Items(jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'string'
|
||||
}))
|
||||
})
|
||||
},
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'limit'
|
||||
description: 'maximum number of results to return'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
})
|
||||
}
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'pet_list'
|
||||
description: 'all pets from the system, that matches the tags'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
})
|
||||
}
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'CreatePet'
|
||||
description: 'creates a new pet in the store. Duplicates are allowed.'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'new_pet'
|
||||
description: 'Pet to add to the store.'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/NewPet'
|
||||
})
|
||||
}
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'pet'
|
||||
description: 'the newly created pet'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
})
|
||||
}
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'GetPetById'
|
||||
description: 'gets a pet based on a single ID, if the user has access to the pet'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'id'
|
||||
description: 'ID of pet to fetch'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
})
|
||||
}
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'pet'
|
||||
description: 'pet response'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
})
|
||||
}
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'DeletePetById'
|
||||
description: 'deletes a single pet based on the ID supplied'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'id'
|
||||
description: 'ID of pet to delete'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
})
|
||||
}
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'pet'
|
||||
description: 'pet deleted'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'null'
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
openapi_specification := actor_specification.to_openapi()
|
||||
println(json.encode_pretty(openapi_specification))
|
||||
109
examples/baobab/specification/specification_to_openrpc.vsh
Executable file
109
examples/baobab/specification/specification_to_openrpc.vsh
Executable file
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env -S v -w -n -enable-globals run
|
||||
|
||||
import json
|
||||
import freeflowuniverse.herolib.baobab.specification
|
||||
import freeflowuniverse.herolib.core.code
|
||||
import freeflowuniverse.herolib.schemas.jsonschema
|
||||
import freeflowuniverse.herolib.schemas.openrpc
|
||||
import os
|
||||
|
||||
const actor_specification = specification.ActorSpecification{
|
||||
name: 'PetStore'
|
||||
structure: code.Struct{}
|
||||
interfaces: [.openrpc]
|
||||
methods: [
|
||||
specification.ActorMethod{
|
||||
name: 'GetPets'
|
||||
description: 'finds pets in the system that the user has access to by tags and within a limit'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'tags'
|
||||
description: 'tags to filter by'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'array'
|
||||
items: jsonschema.Items(jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'string'
|
||||
}))
|
||||
})
|
||||
},
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'limit'
|
||||
description: 'maximum number of results to return'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
})
|
||||
}
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'pet_list'
|
||||
description: 'all pets from the system, that matches the tags'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
})
|
||||
}
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'CreatePet'
|
||||
description: 'creates a new pet in the store. Duplicates are allowed.'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'new_pet'
|
||||
description: 'Pet to add to the store.'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/NewPet'
|
||||
})
|
||||
}
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'pet'
|
||||
description: 'the newly created pet'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
})
|
||||
}
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'GetPetById'
|
||||
description: 'gets a pet based on a single ID, if the user has access to the pet'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'id'
|
||||
description: 'ID of pet to fetch'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
})
|
||||
}
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'pet'
|
||||
description: 'pet response'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
})
|
||||
}
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'DeletePetById'
|
||||
description: 'deletes a single pet based on the ID supplied'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'id'
|
||||
description: 'ID of pet to delete'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
})
|
||||
}
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'pet'
|
||||
description: 'pet deleted'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'null'
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
openrpc_specification := actor_specification.to_openrpc()
|
||||
println(json.encode_pretty(openrpc_specification))
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/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()!
|
||||
@@ -1,48 +0,0 @@
|
||||
#!/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')!
|
||||
@@ -1,12 +0,0 @@
|
||||
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)
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/usr/bin/env -S v -n -w -cg -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
//#!/usr/bin/env -S v -cg -enable-globals run
|
||||
import freeflowuniverse.herolib.biz.bizmodel
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import freeflowuniverse.herolib.core.playcmds
|
||||
import os
|
||||
|
||||
const playbook_path = os.dir(@FILE) + '/playbook'
|
||||
const build_path = os.join_path(os.dir(@FILE), '/docusaurus')
|
||||
|
||||
buildpath := '${os.home_dir()}/hero/var/mdbuild/bizmodel'
|
||||
|
||||
mut model := bizmodel.getset("example")!
|
||||
model.workdir = build_path
|
||||
model.play(mut playbook.new(path: playbook_path)!)!
|
||||
|
||||
println(model.sheet)
|
||||
println(model.sheet.export()!)
|
||||
|
||||
model.sheet.export(path:"~/Downloads/test.csv")!
|
||||
model.sheet.export(path:"~/code/github/freeflowuniverse/starlight_template/src/content/test.csv")!
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
bizmodel
|
||||
dest
|
||||
wiki
|
||||
build
|
||||
@@ -1 +0,0 @@
|
||||
ms1bmodel.png
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.8 MiB |
@@ -1,13 +0,0 @@
|
||||
## 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'
|
||||
@@ -1,13 +0,0 @@
|
||||
- [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)
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# Overview of the rows in the biz model sheet
|
||||
|
||||
|
||||
!!bizmodel.sheet_wiki sheetname:'bizmodel_test'
|
||||
@@ -1,37 +0,0 @@
|
||||
#!/usr/bin/env -S v -n -w -cg -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
//#!/usr/bin/env -S v -cg -enable-globals run
|
||||
import freeflowuniverse.herolib.biz.bizmodel
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import freeflowuniverse.herolib.core.playcmds
|
||||
import os
|
||||
|
||||
//TODO: need to fix wrong location
|
||||
const playbook_path = os.dir(@FILE) + '/playbook'
|
||||
const build_path = os.join_path(os.dir(@FILE), '/docusaurus')
|
||||
|
||||
buildpath := '${os.home_dir()}/hero/var/mdbuild/bizmodel'
|
||||
|
||||
mut model := bizmodel.getset("example")!
|
||||
model.workdir = build_path
|
||||
model.play(mut playbook.new(path: playbook_path)!)!
|
||||
|
||||
println(model.sheet)
|
||||
println(model.sheet.export()!)
|
||||
|
||||
// model.sheet.export(path:"~/Downloads/test.csv")!
|
||||
// model.sheet.export(path:"~/code/github/freeflowuniverse/starlight_template/src/content/test.csv")!
|
||||
|
||||
|
||||
|
||||
|
||||
report := model.new_report(
|
||||
name: 'example_report'
|
||||
title: 'Example Business Model'
|
||||
)!
|
||||
|
||||
report.export(
|
||||
path: build_path
|
||||
overwrite: true
|
||||
format: .docusaurus
|
||||
)!
|
||||
@@ -1 +0,0 @@
|
||||
output dir of example
|
||||
@@ -1,22 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "${script_dir}"
|
||||
|
||||
echo "Docs directory: $script_dir"
|
||||
|
||||
cd "${HOME}/hero/var/docusaurus"
|
||||
|
||||
export PATH=/tmp/docusaurus_build/node_modules/.bin:${HOME}/.bun/bin/:$PATH
|
||||
|
||||
rm -rf /Users/despiegk/hero/var/docusaurus/build/
|
||||
|
||||
. ${HOME}/.zprofile
|
||||
|
||||
bun docusaurus build
|
||||
|
||||
mkdir -p /Users/despiegk/code/github/freeflowuniverse/herolib/examples/biztools/bizmodel/example/docusaurus
|
||||
echo SYNC TO /Users/despiegk/code/github/freeflowuniverse/herolib/examples/biztools/bizmodel/example/docusaurus
|
||||
rsync -rv --delete /Users/despiegk/hero/var/docusaurus/build/ /Users/despiegk/code/github/freeflowuniverse/herolib/examples/biztools/bizmodel/example/docusaurus/
|
||||
@@ -1 +0,0 @@
|
||||
{"style":"dark","links":[]}
|
||||
@@ -1 +0,0 @@
|
||||
{"name":"","title":"Docusaurus","tagline":"","favicon":"img/favicon.png","url":"http://localhost","url_home":"docs/introduction","baseUrl":"/","image":"img/tf_graph.png","metadata":{"description":"Docusaurus","image":"Docusaurus","title":"Docusaurus"},"buildDest":[],"buildDestDev":[]}
|
||||
@@ -1 +0,0 @@
|
||||
{"title":"Business Model","items":[{"href":"https://threefold.info/kristof/","label":"ThreeFold Technology","position":"right"},{"href":"https://threefold.io","label":"Operational Plan","position":"left"}]}
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "${script_dir}"
|
||||
|
||||
echo "Docs directory: $script_dir"
|
||||
|
||||
cd "${HOME}/hero/var/docusaurus"
|
||||
|
||||
export PATH=/tmp/docusaurus_build/node_modules/.bin:${HOME}/.bun/bin/:$PATH
|
||||
|
||||
. ${HOME}/.zprofile
|
||||
|
||||
bun run start -p 3100
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
## 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 +0,0 @@
|
||||
name:bizmodel_example
|
||||
@@ -1,10 +0,0 @@
|
||||

|
||||
|
||||
# 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, ...
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
# 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'
|
||||
|
||||
|
||||
```
|
||||
@@ -1,39 +0,0 @@
|
||||
# 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'
|
||||
|
||||
|
||||
```
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# Debug
|
||||
|
||||
Some tools and info to help debug the bizmodel simulator.
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# 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
|
||||
|
||||
```
|
||||
@@ -1,29 +0,0 @@
|
||||
# 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'
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
# 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'
|
||||
```
|
||||
@@ -1,14 +0,0 @@
|
||||
# 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.
|
||||
|
||||
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
# HR Params
|
||||
|
||||
## Revenue Items (non recurring)
|
||||
|
||||
This company is a cloud company ...
|
||||
|
||||
- name, e.g. for a specific project
|
||||
- descr, description of the revenue line item
|
||||
- revenue_items: does one of revenue, is not exterpolated
|
||||
- revenue_growth: is a revenue stream which is being extrapolated
|
||||
- revenue_setup, revenue for 1 item '1000usd'
|
||||
- revenue_setup_delay
|
||||
- revenue_monthly, revenue per month for 1 item
|
||||
- revenue_monthly_delay, how many months before monthly revenue starts
|
||||
- maintenance_month_perc, how much percent of revenue_setup will come back over months
|
||||
- cogs_setup, cost of good for 1 item at setup
|
||||
- cogs_setup_delay, how many months before setup cogs starts, after sales
|
||||
- cogs_setup_perc: what is percentage of the cogs (can change over time) for setup e.g. 0:50%
|
||||
|
||||
- cogs_monthly, cost of goods for the monthly per 1 item
|
||||
- cogs_monthly_delay, how many months before monthly cogs starts, after sales
|
||||
- cogs_monthly_perc: what is percentage of the cogs (can change over time) for monthly e.g. 0:5%,12:10%
|
||||
|
||||
- nr_sold: how many do we sell per month (is in growth format e.g. 10:100,20:200, default is 1)
|
||||
- nr_months_recurring: how many months is recurring, if 0 then no recurring
|
||||
|
||||
```js
|
||||
!!bizmodel.revenue_define bizname:'test'
|
||||
descr:'OEM Deals'
|
||||
revenue_items:'10:1000000EUR,15:3333,20:1200000'
|
||||
cogs_setup_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
|
||||
```
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
#!/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) + '/../..'
|
||||
|
||||
// if we return True then it means the dir or file is processed
|
||||
fn filter_1(mut path pathlib.Path, mut params paramsparser.Params) !bool {
|
||||
fn filter_1(mut path pathlib.Path) !bool {
|
||||
if path.is_dir() {
|
||||
if path.path.ends_with('.dSYM') {
|
||||
return false
|
||||
|
||||
18
examples/develop/gittools/gittools_example.vsh
Executable file
18
examples/develop/gittools/gittools_example.vsh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/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)
|
||||
@@ -1,14 +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 := 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
|
||||
|
||||
import os
|
||||
import freeflowuniverse.herolib.hero.baobab.actor { IActor, RunParams }
|
||||
import freeflowuniverse.herolib.hero.baobab.stage {IActor, RunParams}
|
||||
import freeflowuniverse.herolib.web.openapi
|
||||
import time
|
||||
|
||||
@@ -10,11 +10,13 @@ const openapi_spec_json = os.read_file(openapi_spec_path) or { panic(err) }
|
||||
const openapi_specification = openapi.json_decode(openapi_spec_json)!
|
||||
|
||||
struct ExampleActor {
|
||||
actor.Actor
|
||||
stage.Actor
|
||||
}
|
||||
|
||||
fn new() !ExampleActor {
|
||||
return ExampleActor{actor.new('example')}
|
||||
return ExampleActor{
|
||||
stage.new_actor('example')
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run() ! {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
@@ -0,0 +1 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
@@ -70,87 +70,74 @@ fn (mut actor Actor) listen() ! {
|
||||
|
||||
// Handle method invocations
|
||||
fn (mut actor Actor) handle_method(cmd string, data string) !string {
|
||||
println('debugzo received rpc ${cmd}:${data}')
|
||||
param_anys := json2.raw_decode(data)!.arr()
|
||||
match cmd {
|
||||
'listPets' {
|
||||
pets := if param_anys.len == 0 {
|
||||
actor.data_store.list_pets()
|
||||
} else {
|
||||
params := json.decode(ListPetParams, param_anys[0].str())!
|
||||
actor.data_store.list_pets(params)
|
||||
}
|
||||
return json.encode(pets)
|
||||
}
|
||||
'createPet' {
|
||||
response := if param_anys.len == 0 {
|
||||
return error('at least data expected')
|
||||
} else if param_anys.len == 1 {
|
||||
payload := json.decode(NewPet, param_anys[0].str())!
|
||||
actor.data_store.create_pet(payload)
|
||||
} 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)
|
||||
return json.encode(response)
|
||||
}
|
||||
'getPet' {
|
||||
response := if param_anys.len == 0 {
|
||||
return error('at least data expected')
|
||||
} else if param_anys.len == 1 {
|
||||
payload := param_anys[0].int()
|
||||
actor.data_store.get_pet(payload)!
|
||||
} else {
|
||||
return error('expected 1 param, found too many')
|
||||
}
|
||||
|
||||
return json.encode(response)
|
||||
}
|
||||
'deletePet' {
|
||||
params := json.decode(map[string]int, data) or {
|
||||
return error('Invalid params: ${err}')
|
||||
}
|
||||
actor.data_store.delete_pet(params['petId']) or {
|
||||
return error('Pet not found: ${err}')
|
||||
}
|
||||
return json.encode({
|
||||
'message': 'Pet deleted'
|
||||
})
|
||||
}
|
||||
'listOrders' {
|
||||
orders := actor.data_store.list_orders()
|
||||
return json.encode(orders)
|
||||
}
|
||||
'getOrder' {
|
||||
params := json.decode(map[string]int, data) or {
|
||||
return error('Invalid params: ${err}')
|
||||
}
|
||||
order := actor.data_store.get_order(params['orderId']) or {
|
||||
return error('Order not found: ${err}')
|
||||
}
|
||||
return json.encode(order)
|
||||
}
|
||||
'deleteOrder' {
|
||||
params := json.decode(map[string]int, data) or {
|
||||
return error('Invalid params: ${err}')
|
||||
}
|
||||
actor.data_store.delete_order(params['orderId']) or {
|
||||
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}')
|
||||
}
|
||||
}
|
||||
param_anys := json2.raw_decode(data)!.arr()
|
||||
match cmd {
|
||||
'listPets' {
|
||||
pets := if param_anys.len == 0 {
|
||||
actor.data_store.list_pets()
|
||||
} else {
|
||||
params := json.decode(ListPetParams, param_anys[0].str())!
|
||||
actor.data_store.list_pets(params)
|
||||
}
|
||||
return json.encode(pets)
|
||||
}
|
||||
'createPet' {
|
||||
response := if param_anys.len == 0 {
|
||||
return error('at least data expected')
|
||||
} else if param_anys.len == 1 {
|
||||
payload := json.decode(NewPet, param_anys[0].str())!
|
||||
actor.data_store.create_pet(payload)
|
||||
} 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)
|
||||
return json.encode(response)
|
||||
}
|
||||
'getPet' {
|
||||
response := if param_anys.len == 0 {
|
||||
return error('at least data expected')
|
||||
} else if param_anys.len == 1 {
|
||||
payload := param_anys[0].int()
|
||||
actor.data_store.get_pet(payload)!
|
||||
} else {
|
||||
return error('expected 1 param, found too many')
|
||||
}
|
||||
|
||||
return json.encode(response)
|
||||
}
|
||||
'deletePet' {
|
||||
params := json.decode(map[string]int, data) or { return error('Invalid params: $err') }
|
||||
actor.data_store.delete_pet(params['petId']) or { return error('Pet not found: $err') }
|
||||
return json.encode({'message': 'Pet deleted'})
|
||||
}
|
||||
'listOrders' {
|
||||
orders := actor.data_store.list_orders()
|
||||
return json.encode(orders)
|
||||
}
|
||||
'getOrder' {
|
||||
params := json.decode(map[string]int, data) or { return error('Invalid params: $err') }
|
||||
order := actor.data_store.get_order(params['orderId']) or {
|
||||
return error('Order not found: $err')
|
||||
}
|
||||
return json.encode(order)
|
||||
}
|
||||
'deleteOrder' {
|
||||
params := json.decode(map[string]int, data) or { return error('Invalid params: $err') }
|
||||
actor.data_store.delete_order(params['orderId']) or {
|
||||
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]
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#!/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.virt.herocontainers
|
||||
import freeflowuniverse.herolib.installers.virt.herocontainers
|
||||
|
||||
mut actrunner_ := actrunner.get()!
|
||||
actrunner_.install()!
|
||||
actrunner.install()!
|
||||
// herocontainers.start()!
|
||||
@@ -1,8 +1,5 @@
|
||||
#!/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.osal
|
||||
|
||||
// coredns_installer.delete()!
|
||||
mut installer := coredns_installer.get()!
|
||||
installer.build()!
|
||||
coredns_installer.install()!
|
||||
|
||||
15
examples/installers/dagu.vsh
Executable file
15
examples/installers/dagu.vsh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/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)
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/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()!
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/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()!
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/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()!
|
||||
16
examples/installers/gitea.vsh
Executable file
16
examples/installers/gitea.vsh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/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()!
|
||||
@@ -4,4 +4,3 @@ import freeflowuniverse.herolib.installers.threefold.griddriver
|
||||
|
||||
mut griddriver_installer := griddriver.get()!
|
||||
griddriver_installer.install()!
|
||||
griddriver_installer.destroy()!
|
||||
@@ -1,8 +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 gitea := gitea_installer.get()!
|
||||
gitea.install()!
|
||||
gitea.start()!
|
||||
gitea.destroy()!
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/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()!
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/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()!
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/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()!
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/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()!
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/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()!
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/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()!
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/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()!
|
||||
5
examples/installers/mycelium.vsh
Executable file
5
examples/installers/mycelium.vsh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/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()!
|
||||
@@ -1,42 +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_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}')
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/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()!
|
||||
13
examples/installers/postgresql.vsh
Executable file
13
examples/installers/postgresql.vsh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/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,8 +0,0 @@
|
||||
#!/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()!
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/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()!
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/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()!
|
||||
@@ -1,9 +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_installer
|
||||
|
||||
mut ds := daguserver.get()!
|
||||
ds.install()!
|
||||
ds.start()!
|
||||
ds.destroy()!
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/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()!
|
||||
@@ -1,60 +0,0 @@
|
||||
#!/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')!
|
||||
@@ -1,24 +0,0 @@
|
||||
#!/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
Normal file
1
examples/schemas/openapi/codegen/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
client_typescript
|
||||
19
examples/schemas/openapi/codegen/calendar_ts_client.vsh
Executable file
19
examples/schemas/openapi/codegen/calendar_ts_client.vsh
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/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)!
|
||||
|
||||
|
||||
245
examples/schemas/openapi/codegen/meeting_api.json
Normal file
245
examples/schemas/openapi/codegen/meeting_api.json
Normal file
@@ -0,0 +1,245 @@
|
||||
{
|
||||
"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,4 +1 @@
|
||||
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)!
|
||||
|
||||
// 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
|
||||
// mut builder_hero := engine.builder_hero(reset:true)!
|
||||
|
||||
// mut builder_web := engine.builder_heroweb(reset:true)!
|
||||
|
||||
// builder_gorust.shell()!
|
||||
builder_gorust.shell()!
|
||||
|
||||
@@ -7,22 +7,14 @@ import freeflowuniverse.herolib.core.base
|
||||
import time
|
||||
import os
|
||||
|
||||
// herocompile means we do it for the host system
|
||||
mut pm := herocontainers.new(herocompile: false, install: false)!
|
||||
mut pm := herocontainers.new(herocompile: true, install: false)!
|
||||
|
||||
// pm.builder_base(reset:true)!
|
||||
|
||||
mut builder := pm.builder_get('base')!
|
||||
builder.shell()!
|
||||
|
||||
println(builder)
|
||||
|
||||
// builder.install_zinit()!
|
||||
mut mybuildcontainer := pm.builder_get('builder_heroweb')!
|
||||
|
||||
// bash & python can be executed directly in build container
|
||||
|
||||
// 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
|
||||
// mybuildcontainer.run(
|
||||
|
||||
43
examples/webtools/docusaurus/docusaurus_example.vsh
Executable file
43
examples/webtools/docusaurus/docusaurus_example.vsh
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cg -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.web.docusaurus
|
||||
// import freeflowuniverse.herolib.data.doctree
|
||||
|
||||
// Create a new docusaurus factory
|
||||
mut docs := docusaurus.new(
|
||||
// build_path: '/tmp/docusaurus_build'
|
||||
)!
|
||||
|
||||
// Create a new docusaurus site
|
||||
mut site := docs.dev(
|
||||
url:'https://git.ourworld.tf/despiegk/docs_kristof'
|
||||
)!
|
||||
|
||||
|
||||
//FOR FUTURE TO ADD CONTENT FROM DOCTREE
|
||||
|
||||
// Create a doctree for content
|
||||
// mut tree := doctree.new(name: 'content')!
|
||||
|
||||
// // Add some content from a git repository
|
||||
// tree.scan(
|
||||
// git_url: 'https://github.com/yourusername/your-docs-repo'
|
||||
// git_pull: true
|
||||
// )!
|
||||
|
||||
// // Export the content to the docusaurus site
|
||||
// tree.export(
|
||||
// destination: '${site.path_build.path}/docs'
|
||||
// reset: true
|
||||
// keep_structure: true
|
||||
// exclude_errors: false
|
||||
// )!
|
||||
|
||||
// Build the docusaurus site
|
||||
//site.build()!
|
||||
|
||||
// Generate the static site
|
||||
//site.generate()!
|
||||
|
||||
// Optionally open the site in a browser
|
||||
// site.open()!
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cg -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.web.starlight
|
||||
// import freeflowuniverse.herolib.data.doctree
|
||||
|
||||
// Create a new starlight factory
|
||||
mut docs := starlight.new(
|
||||
build_path: '/tmp/starlight_build'
|
||||
)!
|
||||
|
||||
// Create a new starlight site
|
||||
mut site := docs.get(
|
||||
url: 'https://git.ourworld.tf/tfgrid/docs_aibox'
|
||||
init:true //init means we put config files if not there
|
||||
)!
|
||||
|
||||
site.dev()!
|
||||
@@ -4,7 +4,7 @@ set -e
|
||||
|
||||
os_name="$(uname -s)"
|
||||
arch_name="$(uname -m)"
|
||||
version='1.0.15'
|
||||
version='1.0.11'
|
||||
|
||||
|
||||
# Base URL for GitHub releases
|
||||
|
||||
@@ -181,7 +181,7 @@ function os_update {
|
||||
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
|
||||
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 libssl-dev iproute2"
|
||||
package_install "rclone rsync mc redis-server screen net-tools git dnsutils htop ca-certificates screen lsb-release binutils pkg-config"
|
||||
|
||||
elif [[ "${OSNAME}" == "darwin"* ]]; then
|
||||
if command -v brew >/dev/null 2>&1; then
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
module actor
|
||||
|
||||
import json
|
||||
import freeflowuniverse.herolib.core.redisclient
|
||||
import freeflowuniverse.herolib.hero.baobab.action { ProcedureCall, ProcedureResponse }
|
||||
import freeflowuniverse.herolib.clients.redisclient
|
||||
import freeflowuniverse.herolib.baobab.action { ProcedureCall, ProcedureResponse }
|
||||
|
||||
// Processor struct for managing procedure calls
|
||||
pub struct Client {
|
||||
@@ -14,7 +14,7 @@ pub mut:
|
||||
@[params]
|
||||
pub struct Params {
|
||||
pub:
|
||||
timeout int // Timeout in seconds
|
||||
timeout int = 60 // Timeout in seconds
|
||||
}
|
||||
|
||||
pub struct ClientConfig {
|
||||
@@ -62,8 +62,6 @@ pub fn (mut p Client) call_to_action(action Procedure, params Params) !Procedure
|
||||
// }
|
||||
}
|
||||
|
||||
println('resp data ${response_data}')
|
||||
|
||||
return ProcedureResponse{
|
||||
result: response_data
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user