diff --git a/doc.vsh b/doc.vsh index 8142301d..e8e60dda 100755 --- a/doc.vsh +++ b/doc.vsh @@ -9,21 +9,26 @@ println('Formatting code...') if os.system('v fmt -w ${abs_dir_of_script}/examples') != 0 { eprintln('Warning: Failed to format examples') } -if os.system('v fmt -w ${abs_dir_of_script}/herolib') != 0 { + +if os.system('v fmt -w ${abs_dir_of_script}/lib') != 0 { eprintln('Warning: Failed to format herolib') } // Clean existing docs println('Cleaning existing documentation...') -os.rmdir_all('${abs_dir_of_script}/docs') or {} -herolib_path := os.join_path(abs_dir_of_script, 'herolib') +os.rmdir_all('_docs') or {} +os.rmdir_all('docs') or {} +os.rmdir_all('vdocs') or {} + +herolib_path := os.join_path(abs_dir_of_script, 'lib') os.chdir(herolib_path) or { panic('Failed to change directory to herolib: ${err}') } os.rmdir_all('_docs') or {} os.rmdir_all('docs') or {} +os.rmdir_all('vdocs') or {} // Generate HTML documentation println('Generating HTML documentation...') @@ -36,20 +41,20 @@ os.rename('_docs', '${abs_dir_of_script}/docs') or { panic('Failed to move documentation to parent directory: ${err}') } + +os.chdir(abs_dir_of_script) or { + panic('Failed to change directory to abs_dir_of_script: ${err}') +} + // Generate Markdown documentation println('Generating Markdown documentation...') os.rmdir_all('vdocs') or {} -os.mkdir_all('vdocs/v') or { - panic('Failed to create v docs directory: ${err}') -} -os.mkdir_all('vdocs/crystal') or { - panic('Failed to create crystal docs directory: ${err}') -} -if os.system('v doc -m -no-color -f md -o vdocs/v/') != 0 { - panic('Failed to generate V markdown documentation') -} -if os.system('v doc -m -no-color -f md -o vdocs/crystal/') != 0 { +// if os.system('v doc -m -no-color -f md -o ../vdocs/v/') != 0 { +// panic('Failed to generate V markdown documentation') +// } + +if os.system('v doc -m -no-color -f md -o vdocs/herolib/') != 0 { panic('Failed to generate Crystal markdown documentation') } diff --git a/examples/core/base/aconfigfile.txt b/examples/core/base/aconfigfile.txt new file mode 100644 index 00000000..76e518ac --- /dev/null +++ b/examples/core/base/aconfigfile.txt @@ -0,0 +1,7 @@ + +//This is a config file, ofcourse not correct +//the {CAPITALS} will be converted to the name of the argument + +keyname : ${myconfig.keyname} +keyid : '' +appkey : ${myconfig.appkey} \ No newline at end of file diff --git a/examples/core/base/config_basic.vsh b/examples/core/base/config_basic.vsh new file mode 100755 index 00000000..029fe113 --- /dev/null +++ b/examples/core/base/config_basic.vsh @@ -0,0 +1,27 @@ +#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run + +import freeflowuniverse.crystallib.core.base + +pub struct MyClient[T] { + base.BaseConfig[T] +} + +@[params] +pub struct MyConfig { +pub mut: + // the config items which are important to remember + keyname string + keyid string + appkey string @[secret] +} + +// EXAMPLE USAGE + +mut cl := new('testinstance', keyname: 'somekey', appkey: 'will be secret')! +println(cl.config_get()!) + +// now get the client, will give error if it doesn't exist +mut cl2 := get('testinstance')! +println(cl2.config_get()!) + +delete('testinstance')! diff --git a/examples/core/base/config_with_template_replacement.vsh b/examples/core/base/config_with_template_replacement.vsh new file mode 100755 index 00000000..3aa43f88 --- /dev/null +++ b/examples/core/base/config_with_template_replacement.vsh @@ -0,0 +1,54 @@ +#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run + +import freeflowuniverse.crystallib.core.pathlib +import freeflowuniverse.crystallib.core.base + +pub struct MyClient[T] { + base.BaseConfig[T] +} + +@[params] +pub struct MyConfig { +pub mut: + // the config items which are important to remember + keyname string + keyid string + appkey string @[secret] +} + +pub fn new(instance string, cfg MyConfig) !MyClient[MyConfig] { + mut self := MyClient[MyConfig]{ + type_name: 'myclient' + } + self.init(instance: instance, action: .new)! + self.config_set(cfg)! + return self +} + +pub fn get(instance string) !MyClient[MyConfig] { + mut self := MyClient[MyConfig]{ + type_name: 'myclient' + } + self.init(instance: instance, action: .get)! + return self +} + +pub fn delete(instance string) ! { + mut self := MyClient[MyConfig]{ + type_name: 'myclient' + } + self.init(instance: instance, action: .delete)! +} + +// EXAMPLE USAGE + +mut cl := new('testinstance', keyname: 'somekey', appkey: 'will be secret')! +myconfig := cl.config_get()! + +// it should show how the fields are normal, but at back there was encryption/decryption of the field marked secret +println(myconfig) + +config_content := $tmpl('aconfigfile.txt') + +mut myconfigfile := pathlib.get_file(path: '/tmp/myconfigfile.txt', create: false)! +myconfigfile.write(config_content)! diff --git a/examples/core/base/core_1.vsh b/examples/core/base/core_1.vsh new file mode 100755 index 00000000..eaafe2f9 --- /dev/null +++ b/examples/core/base/core_1.vsh @@ -0,0 +1,34 @@ +#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run + +import freeflowuniverse.crystallib.core.base +import freeflowuniverse.crystallib.develop.gittools + +pub struct MyClass { + base.Base +pub mut: + descr string +} + +// will fetch default context +mut c := base.context()! + +mut s := c.session_new()! +println(s) + +mut gs := gittools.configure(multibranch: true, root: '/tmp/code', name: 'test')! +// mut gs:=gittools.get(name:"test")! + +mut s2 := c.session_latest()! +println(s2) + +println(gs) + +mut mc := MyClass{ + type_name: 'mytype' + instance: 'first' +} + +mut mysession := mc.session()! + +println(mc) +println(mysession) diff --git a/examples/core/codeparser/parse_embedded/embedding.v b/examples/core/codeparser/parse_embedded/embedding.v new file mode 100644 index 00000000..07ca89da --- /dev/null +++ b/examples/core/codeparser/parse_embedded/embedding.v @@ -0,0 +1,13 @@ +module embedding + +pub struct Embedder { + Embedded +} + +pub struct Embedded { + id int + related_ids []int + name string + tags []string + date time.Time +} diff --git a/examples/core/codeparser/parse_embedded/example.vsh b/examples/core/codeparser/parse_embedded/example.vsh new file mode 100755 index 00000000..23c37787 --- /dev/null +++ b/examples/core/codeparser/parse_embedded/example.vsh @@ -0,0 +1,13 @@ +#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run + +import os +import freeflowuniverse.crystallib.core.codeparser +import freeflowuniverse.crystallib.core.codemodel { Struct } + +code_path := '${os.dir(@FILE)}/embedding.v' + +code := codeparser.parse_v(code_path)! +assert code.len == 2 +assert code[0] is Struct +embedder_struct := code[0] as Struct +println(embedder_struct.fields.map('${it.name}: ${it.typ.symbol}')) diff --git a/examples/core/db/db_do.v b/examples/core/db/db_do.v new file mode 100755 index 00000000..7786e938 --- /dev/null +++ b/examples/core/db/db_do.v @@ -0,0 +1,143 @@ +#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run + +import time +import freeflowuniverse.crystallib.core.smartid +import freeflowuniverse.crystallib.data.ourtime +import freeflowuniverse.crystallib.core.db + +pub struct MyStruct { + db.Base +pub mut: + color string + nr int +} + +fn create_struct() MyStruct { + mut m := MyStruct{ + name: 'aname' + description: 'a description\ncan be multiline\n1' + gid: smartid.gid(oid_u32: 99, cid_name: 'test') or { panic(err) } + color: 'red' + nr: 8 + } + + author_gid := smartid.gid(oid_u32: 333, cid_name: 'test') or { panic(err) } + + m.params_add('priority:urgent silver') or { panic(err) } + m.params_add('priority:low gold') or { panic(err) } + m.params_add('timing:now gold') or { panic(err) } + + m.remark_add( + author: author_gid + content: ' + lucky we did do this + can be multiline + ' + rtype: .audit + ) or { panic(err) } + + m.remark_add( + content: ' + another one + ' + rtype: .log + params: 'color:red urgent' + ) or { panic(err) } + + m.remark_add( + content: 'hiii' + rtype: .log + params: 'color:red urgent' + ) or { panic(err) } + + return m +} + +// example of how we should implement binary serialization +pub fn (o MyStruct) serialize_binary() ![]u8 { + mut b := o.bin_encoder()! + b.add_string(o.color) + b.add_int(o.nr) + return b.data +} + +pub fn load(data []u8) !MyStruct { + mut d, base := db.base_decoder(data)! + mut o := MyStruct{ + Base: base + } + o.color = d.get_string() + o.nr = d.get_int() + return o +} + +fn do1() ! { + m := create_struct() + + data := m.serialize_binary()! + m2 := load(data)! + + assert m.gid == m2.gid + + println(m2) + + // assert m.params.params.len == m2.params.params.len + // for id, _ in m.params.params { + // assert m.params.params[id] == m2.params.params[id] + // } + + // assert m.params.args.len == m2.params.args.len + // mut args_map := map[string]bool{} + // for id, _ in m.params.args { + // args_map[m.params.args[id]] = true + // } + // for a in m2.params.args { + // assert args_map[a] == true + // } + + // assert m.version_base == m2.version_base + // assert m.serialization_type == m2.serialization_type + // assert m.name == m2.name + // assert m.description == m2.description + + // assert m.remarks.remarks.len == m2.remarks.remarks.len + // for id, _ in m.remarks.remarks { + // assert m.remarks.remarks[id].content == m2.remarks.remarks[id].content + // assert m.remarks.remarks[id].time == m2.remarks.remarks[id].time + // assert m.remarks.remarks[id].rtype == m2.remarks.remarks[id].rtype + // a1 := m.remarks.remarks[id].author or { + // if _ := m2.remarks.remarks[id].author { + // panic('author is in original object, but not in deserialized object') + // } + // continue + // } + + // a2 := m2.remarks.remarks[id].author or { + // panic('author is in deserialized object, but not in original object') + // } + + // assert a1 == a2 + // } +} + +// fn test_find_remark() { +// m := create_struct() +// mut r := m.remarks.find_remark(time_to: ourtime.now())! +// assert r.len == 3 + +// r = m.remarks.find_remark(params_filter: 'color:red*')! +// assert r.len == 2 + +// r = m.remarks.find_remark( +// time_from: ourtime.OurTime{ +// unix: i64(time.now().unix_time()) - time.second +// } +// )! +// assert r.len == 3 + +// a := smartid.gid(oid_u32: 333, cid_name: 'test')! +// r = m.remarks.find_remark(author: a)! +// assert r.len == 1 +// } + +do1()! diff --git a/examples/core/dbfs/dbfs1.vsh b/examples/core/dbfs/dbfs1.vsh new file mode 100755 index 00000000..c6542a95 --- /dev/null +++ b/examples/core/dbfs/dbfs1.vsh @@ -0,0 +1,45 @@ +#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run + +import freeflowuniverse.crystallib.data.dbfs +import time +import os + +data_dir := '/tmp/db' +os.rmdir_all(data_dir) or {} +mut dbcollection := dbfs.get(contextid: 1, dbpath: data_dir, secret: '123456')! + +mut db := dbcollection.db_create(name: 'db_a', encrypted: true, withkeys: true)! + +id := db.set(key: 'a', value: 'bbbb')! +assert 'bbbb' == db.get(key: 'a')! + +id2 := db.set(key: 'a', value: 'bbbb2')! +assert 'bbbb2' == db.get(key: 'a')! +assert id == id2 +assert id == 1 + +id3 := db.set(key: 'b', value: 'bbbb3')! +assert 'bbbb3' == db.get(key: 'b')! +assert id3 == id2 + 1 + +assert db.exists(key: 'a')! +assert db.exists(key: 'b')! +assert db.exists(id: id2)! +assert db.exists(id: id3)! +id3_exsts := db.exists(id: id3 + 1)! +println(id3 + 1) +assert id3_exsts == false + +for i in 3 .. 100 { + id4 := db.set(key: 'a${i}', value: 'b${i}')! + println('${i} --> ${id4}') + assert i == id4 +} + +db.delete(key: 'a')! +assert db.exists(key: 'a')! == false +assert db.exists(id: id2)! == false + +db.delete(id: 50)! +assert db.exists(key: 'a50')! == false +assert db.exists(id: 50)! == false diff --git a/examples/core/generate.vsh b/examples/core/generate.vsh new file mode 100755 index 00000000..4b44acc0 --- /dev/null +++ b/examples/core/generate.vsh @@ -0,0 +1,5 @@ +#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run + +import freeflowuniverse.crystallib.core.generator.installer + +installer.scan('~/code/github/freeflowuniverse/crystallib/crystallib')! diff --git a/examples/core/openapi/gitea/gitea_client/client.v b/examples/core/openapi/gitea/gitea_client/client.v new file mode 100644 index 00000000..9c6bbe14 --- /dev/null +++ b/examples/core/openapi/gitea/gitea_client/client.v @@ -0,0 +1,4 @@ +module gitea_client + +struct GiteaClient { +} diff --git a/examples/core/openapi/gitea/gitea_client/factory.v b/examples/core/openapi/gitea/gitea_client/factory.v new file mode 100644 index 00000000..d082d8ec --- /dev/null +++ b/examples/core/openapi/gitea/gitea_client/factory.v @@ -0,0 +1,83 @@ +module dagu + +// import os +import freeflowuniverse.crystallib.clients.httpconnection +import os + +struct GiteaClient[T] { + base.Base[T] +mut: + connection &httpconnection.HTTPConnection +} + +struct Config { + play.ConfigBase[T] + url string +} + +// +pub fn get(args PlayArgs) GiteaClient[Config] { + mut client := GiteaClient[Config]{} + client.init(args)! + return client +} + +// +pub fn heroplay(args PlayBookAddArgs) ! { + // make session for configuring from heroscript + mut session := play.session_new(session_name: 'config')! + session.playbook_add(path: args.path, text: args.text, git_url: args.git_url)! + for mut action in session.plbook.find(filter: 'gitea_client.define')! { + mut p := action.params + instance := p.get_default('instance', 'default')! + mut cl := get(instance: instance)! + mut cfg := cl.config()! + mut config := p.decode[T]()! + cl.config_save()! + } +} + +// +pub fn (self GiteaClient[T]) config_interactive() ! { + mut myui := ui.new()! + console.clear() + println(' +## Configure B2 Client') + println('======================== + +') + + mut cfg := self.config()! + + self.instance = myui.ask_question( + question: 'name for B2 (backblaze) client' + default: self.instance + )! + + cfg.description = myui.ask_question( + question: 'description' + minlen: 0 + default: cfg.description + )! + cfg.keyid = myui.ask_question( + question: 'keyid e.g. 003e2a7be6357fb0000000001' + minlen: 5 + default: cfg.keyid + )! + + cfg.appkey = myui.ask_question( + question: 'appkey e.g. K008UsdrYOAou2ulBHA8p4KBe/dL2n4' + minlen: 5 + default: cfg.appkey + )! + + buckets := self.list_buckets()! + bucket_names := buckets.map(it.name) + + cfg.bucketname = myui.ask_dropdown( + question: 'choose default bucket name' + items: bucket_names + )! + + self.config_save()! +} diff --git a/examples/core/openapi/gitea/gitea_client/methods.v b/examples/core/openapi/gitea/gitea_client/methods.v new file mode 100644 index 00000000..bcdf618b --- /dev/null +++ b/examples/core/openapi/gitea/gitea_client/methods.v @@ -0,0 +1,69 @@ +module gitea_client + +import json +import net.http + +// Repository operations +pub fn (mut client GiteaClient) create_repo(name string, description string, private bool) !string { + data := { + 'name': name + 'description': description + 'private': private.str() + } + + resp := client.connection.post('/api/v1/user/repos', json.encode(data))! + return resp +} + +pub fn (mut client GiteaClient) get_repo(owner string, repo string) !string { + resp := client.connection.get('/api/v1/repos/${owner}/${repo}')! + return resp +} + +pub fn (mut client GiteaClient) list_repos() !string { + resp := client.connection.get('/api/v1/user/repos')! + return resp +} + +// User operations +pub fn (mut client GiteaClient) get_user() !string { + resp := client.connection.get('/api/v1/user')! + return resp +} + +pub fn (mut client GiteaClient) list_users() !string { + resp := client.connection.get('/api/v1/admin/users')! + return resp +} + +// Organization operations +pub fn (mut client GiteaClient) create_org(name string, description string) !string { + data := { + 'username': name + 'description': description + } + + resp := client.connection.post('/api/v1/orgs', json.encode(data))! + return resp +} + +pub fn (mut client GiteaClient) list_orgs() !string { + resp := client.connection.get('/api/v1/orgs')! + return resp +} + +// Issue operations +pub fn (mut client GiteaClient) create_issue(owner string, repo string, title string, body string) !string { + data := { + 'title': title + 'body': body + } + + resp := client.connection.post('/api/v1/repos/${owner}/${repo}/issues', json.encode(data))! + return resp +} + +pub fn (mut client GiteaClient) list_issues(owner string, repo string) !string { + resp := client.connection.get('/api/v1/repos/${owner}/${repo}/issues')! + return resp +} diff --git a/examples/core/openapi/gitea/gitea_client/model.v b/examples/core/openapi/gitea/gitea_client/model.v new file mode 100644 index 00000000..08eb1783 --- /dev/null +++ b/examples/core/openapi/gitea/gitea_client/model.v @@ -0,0 +1 @@ +module gitea_client diff --git a/examples/core/openapi/gitea/gitea_openapi.vsh b/examples/core/openapi/gitea/gitea_openapi.vsh new file mode 100644 index 00000000..ba59608d --- /dev/null +++ b/examples/core/openapi/gitea/gitea_openapi.vsh @@ -0,0 +1,14 @@ +#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run + +import os +import json +import freeflowuniverse.crystallib.core.openapi.gen + +const spec_path = '${os.dir(@FILE)}/openapi.json' + +mod := gen.generate_client_module( + api_name: 'Gitea' +)! +mod.write_v('${os.dir(@FILE)}/gitea_client', + overwrite: true +)! diff --git a/examples/core/openrpc/examples/openrpc_client/client.v b/examples/core/openrpc/examples/openrpc_client/client.v new file mode 100644 index 00000000..f7f15451 --- /dev/null +++ b/examples/core/openrpc/examples/openrpc_client/client.v @@ -0,0 +1,18 @@ +module openrpc_client + +import freeflowuniverse.crystallib.data.jsonrpc { JsonRpcRequest } +import net.websocket + +struct Client { +mut: + ws_client &websocket.Client +} + +pub fn new() Client { + address := 'localhost:8000' + ws_client := websocket.new_client(address)! +} + +fn (mut client Client) send_rpc(rpc JsonRpcRequest) ! { + client.ws_client.write_string(rpc.to_json()) +} diff --git a/examples/core/openrpc/examples/openrpc_client/methods.v b/examples/core/openrpc/examples/openrpc_client/methods.v new file mode 100644 index 00000000..6bcf952c --- /dev/null +++ b/examples/core/openrpc/examples/openrpc_client/methods.v @@ -0,0 +1,26 @@ +module openrpc_client + +pub fn (client Client) hello() { + println('hello') +} + +pub fn (client Client) ping() string { + return 'pong' +} + +@[params] +pub struct AnimalArgs { + name string + species string +} + +// create_animal adds an animal with the provided arguments to the database +pub fn (client Client) create_animal(args AnimalArgs) { + println('Creating animal `${args.name}`') +} + +// get_animal finds an animal in the database with the provided name +// returns the animal, an animal in the db with a matching name +pub fn (client Client) get_animal(name string) Animal { + return Animal{} +} diff --git a/examples/core/openrpc/examples/openrpc_client/model.v b/examples/core/openrpc/examples/openrpc_client/model.v new file mode 100644 index 00000000..45b5f04f --- /dev/null +++ b/examples/core/openrpc/examples/openrpc_client/model.v @@ -0,0 +1,7 @@ +module openrpc_client + +pub struct Animal { + name string + species string + created_at string +} diff --git a/examples/core/openrpc/examples/openrpc_docs/openrpc.json b/examples/core/openrpc/examples/openrpc_docs/openrpc.json new file mode 100644 index 00000000..610eec4d --- /dev/null +++ b/examples/core/openrpc/examples/openrpc_docs/openrpc.json @@ -0,0 +1,153 @@ +{ + "openrpc": "1.0.0-rc1", + "info": { + "version": "1.0.0", + "title": "Petstore Expanded", + "description": "A sample API that uses a petstore as an example to demonstrate features in the OpenRPC specification", + "termsOfService": "https://open-rpc.org", + "contact": { + "name": "OpenRPC Team", + "email": "doesntexist@open-rpc.org", + "url": "https://open-rpc.org" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "servers": [ + { + "url": "http://petstore.open-rpc.org" + } + ], + "methods": [ + { + "name": "get_pets", + "description": "Returns all pets from the system that the user has access to\nNam sed condimentum est. Maecenas tempor sagittis sapien, nec rhoncus sem sagittis sit amet. Aenean at gravida augue, ac iaculis sem. Curabitur odio lorem, ornare eget elementum nec, cursus id lectus. Duis mi turpis, pulvinar ac eros ac, tincidunt varius justo. In hac habitasse platea dictumst. Integer at adipiscing ante, a sagittis ligula. Aenean pharetra tempor ante molestie imperdiet. Vivamus id aliquam diam.", + "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", + "description": "pet response", + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + { + "name": "create_pet", + "description": "Creates a new pet in the store. Duplicates are allowed", + "params": [ + { + "name": "newPet", + "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": "get_pet_by_id", + "description": "Returns a user based on a single ID, if the user does not have access to the pet", + "params": [ + { + "name": "id", + "description": "ID of pet to fetch", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "result": { + "name": "pet", + "description": "pet response", + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + }, + { + "name": "delete_pet_by_id", + "description": "deletes a single pet based on the ID supplied", + "params": [ + { + "name": "id", + "description": "ID of pet to delete", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "result": { + "name": "pet", + "description": "pet deleted", + "schema": {} + } + } + ], + "components": { + "schemas": { + "Pet": { + "allOf": [ + { + "$ref": "#/components/schemas/NewPet" + }, + { + "required": [ + "id" + ], + "properties": { + "id": { + "type": "integer" + } + } + } + ] + }, + "NewPet": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + } + } + } \ No newline at end of file diff --git a/examples/core/openrpc/examples/petstore_client/README.md b/examples/core/openrpc/examples/petstore_client/README.md new file mode 100644 index 00000000..d6a4b692 --- /dev/null +++ b/examples/core/openrpc/examples/petstore_client/README.md @@ -0,0 +1,2 @@ +This is a mock client to the Pet Store JSON-RPC API, described by the PetStore OpenRPC Document. +The client has comments that are copied from the PetStore OpenRPC Document to demonstrate that document generation from the client results in a similar OpenRPC Document. \ No newline at end of file diff --git a/examples/core/openrpc/examples/petstore_client/client.v b/examples/core/openrpc/examples/petstore_client/client.v new file mode 100644 index 00000000..df91ad0f --- /dev/null +++ b/examples/core/openrpc/examples/petstore_client/client.v @@ -0,0 +1,19 @@ +module petstore_client + +import freeflowuniverse.crystallib.data.jsonrpc { JsonRpcRequest } +import net.websocket + +struct Client { +mut: + ws_client &websocket.Client +} + +pub fn new() !Client { + address := 'localhost:8000' + ws_client := websocket.new_client(address)! + return Client{ws_client} +} + +fn (mut client Client) send_rpc[T](rpc JsonRpcRequest[T]) ! { + client.ws_client.write_string(rpc.to_json()) +} diff --git a/examples/core/openrpc/examples/petstore_client/methods.v b/examples/core/openrpc/examples/petstore_client/methods.v new file mode 100644 index 00000000..d6dc8ee5 --- /dev/null +++ b/examples/core/openrpc/examples/petstore_client/methods.v @@ -0,0 +1,36 @@ +module petstore_client + +import freeflowuniverse.crystallib.data.jsonrpc + +// get_pets finds pets in the system that the user has access to by tags and within a limit +// - tags: tags to filter by +// - limit: maximum number of results to return +// returns pet_list, all pets from the system, that mathes the tags +pub fn (mut client Client) get_pets(tags []string, limit int) []Pet { + return []Pet{} +} + +@[params] +struct NewPet { + name string @[required] + tag string +} + +// create_pet creates a new pet in the store. Duplicates are allowed. +// - new_pet: Pet to add to the store. +// returns pet, the newly created pet +pub fn (mut client Client) create_pet(new_pet NewPet) Pet { + return Pet{} +} + +// get_pet_by_id gets a pet based on a single ID, if the user has access to the pet +// - id: ID of pet to fetch +// returns pet, pet response +pub fn (mut client Client) get_pet_by_id(id int) Pet { + return Pet{} +} + +// delete_pet_by_id deletes a single pet based on the ID supplied +// - id: ID of pet to delete +// returns pet, pet deleted +pub fn (mut client Client) delete_pet_by_id(id int) {} diff --git a/examples/core/openrpc/examples/petstore_client/model.v b/examples/core/openrpc/examples/petstore_client/model.v new file mode 100644 index 00000000..295fdd3a --- /dev/null +++ b/examples/core/openrpc/examples/petstore_client/model.v @@ -0,0 +1,8 @@ +module petstore_client + +// a pet struct that represents a pet +struct Pet { + name string // name of the pet + tag string // a tag of the pet, helps finding pet + id int // unique indentifier +} diff --git a/examples/core/openrpc/examples/petstore_client/openrpc.json b/examples/core/openrpc/examples/petstore_client/openrpc.json new file mode 100644 index 00000000..07d811a6 --- /dev/null +++ b/examples/core/openrpc/examples/petstore_client/openrpc.json @@ -0,0 +1,132 @@ +{ + "openrpc": "1.0.0", + "info": { + "title": "PetStore API", + "version": "1.0.0" + }, + "methods": [ + { + "name": "petstore_client.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": "petstore_client.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": "petstore_client.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": "petstore_client.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" + } + } + } + } + } +} \ No newline at end of file diff --git a/examples/core/pathlib/examples/list/path_list.vsh b/examples/core/pathlib/examples/list/path_list.vsh new file mode 100755 index 00000000..82379f7d --- /dev/null +++ b/examples/core/pathlib/examples/list/path_list.vsh @@ -0,0 +1,11 @@ +#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run + +import freeflowuniverse.crystallib.core.pathlib +import os + +const testpath3 = os.dir(@FILE) + '/../../..' + +mut p := pathlib.get_dir(path: testpath3)! +// IMPORTANT TO HAVE r'... the r in front +pl := p.list(regex: [r'.*\.v$'])! +println(pl) diff --git a/examples/core/pathlib/examples/md5/paths_md5.vsh b/examples/core/pathlib/examples/md5/paths_md5.vsh new file mode 100755 index 00000000..d7b0745c --- /dev/null +++ b/examples/core/pathlib/examples/md5/paths_md5.vsh @@ -0,0 +1,17 @@ +#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run + +import freeflowuniverse.crystallib.core.pathlib +import os + +const testpath4 = os.dir(@FILE) + '../../' + +mut p := pathlib.get_file(path: os.dir(@FILE) + '/paths_md5.vsh')! + +md5hash := p.md5hex()! +println('file md5 hash: ${md5hash}') + +file_size_bytes := p.size()! +println('size in bytes: ${file_size_bytes}') + +file_size_kbytes := p.size_kb()! +println('size in kb: ${file_size_kbytes}') diff --git a/examples/core/pathlib/examples/scanner/path_scanner.vsh b/examples/core/pathlib/examples/scanner/path_scanner.vsh new file mode 100755 index 00000000..adfbbbd6 --- /dev/null +++ b/examples/core/pathlib/examples/scanner/path_scanner.vsh @@ -0,0 +1,35 @@ +#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run + +import freeflowuniverse.crystallib.core.pathlib +import freeflowuniverse.crystallib.data.paramsparser +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 { + if path.is_dir() { + if path.path.ends_with('.dSYM') { + return false + } + return true + } + if path.path.ends_with('.vsh') { + return true + } + return false +} + +fn executor_1(mut patho pathlib.Path, mut params paramsparser.Params) !paramsparser.Params { + if patho.is_file() { + // println( " - exec: $patho.path" ) + params.add(patho.path)! + } + return params +} + +mut p := pathlib.get_dir(path: testpath3)! +mut params := paramsparser.Params{} +mut params2 := p.scan(mut params, [filter_1], [executor_1])! +println(params2) +assert params2.args.len == 4 diff --git a/examples/core/pathlib/examples/sha256/paths_sha256.vsh b/examples/core/pathlib/examples/sha256/paths_sha256.vsh new file mode 100755 index 00000000..90f0f988 --- /dev/null +++ b/examples/core/pathlib/examples/sha256/paths_sha256.vsh @@ -0,0 +1,10 @@ +#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run + +import freeflowuniverse.crystallib.core.pathlib +import os + +const testpath4 = os.dir(@FILE) + '/paths_sha256.vsh' + +mut p := pathlib.get_file(path: testpath4)! +s := p.sha256()! +println(s) diff --git a/examples/core/secrets_example.vsh b/examples/core/secrets_example.vsh new file mode 100755 index 00000000..1bf4fb38 --- /dev/null +++ b/examples/core/secrets_example.vsh @@ -0,0 +1,8 @@ +#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run + +import freeflowuniverse.crystallib.crypt.secrets + +secrets.delete_passwd()! +r := secrets.encrypt('aaa')! +println(r) +assert 'aaa' == secrets.decrypt(r)! diff --git a/lib/core/httpconnection/connection.v b/lib/core/httpconnection/connection.v index 2ca35d3d..724641cb 100644 --- a/lib/core/httpconnection/connection.v +++ b/lib/core/httpconnection/connection.v @@ -19,4 +19,3 @@ fn (mut h HTTPConnection) header(req Request) Header { return h.default_header.join(header) } - diff --git a/lib/core/httpconnection/factory.v b/lib/core/httpconnection/factory.v index 3b535565..9d227dbb 100644 --- a/lib/core/httpconnection/factory.v +++ b/lib/core/httpconnection/factory.v @@ -3,7 +3,6 @@ module httpconnection import net.http import freeflowuniverse.herolib.clients.redisclient { RedisURL } - @[params] pub struct HTTPConnectionArgs { pub: @@ -34,6 +33,4 @@ pub fn new(args HTTPConnectionArgs) !&HTTPConnection { base_url: args.url.trim('/') } return &conn - } - diff --git a/lib/core/installers/redis.v b/lib/core/installers/redis.v index 86aa87a2..caed8ab8 100644 --- a/lib/core/installers/redis.v +++ b/lib/core/installers/redis.v @@ -42,7 +42,7 @@ pub fn install(args_ InstallArgs) ! { if osal.is_linux() { osal.package_install('redis-server')! } else { - osal.package_install('redis')!/Users/despiegk1/code/github/freeflowuniverse/herolib/herolib/installers/db/redis/template + osal.package_install('redis')! / Users / despiegk1 / code / github / freeflowuniverse / herolib / herolib / installers / db / redis / template } } osal.execute_silent('mkdir -p ${args.datadir}')! diff --git a/lib/core/rootpath/rootpath.v b/lib/core/rootpath/rootpath.v index 2d02c05a..81cb0223 100644 --- a/lib/core/rootpath/rootpath.v +++ b/lib/core/rootpath/rootpath.v @@ -23,7 +23,6 @@ pub fn ensure_hero_dirs() string { return herodir() } - // root dir for our hero environment pub fn herodir() string { return shell_expansion('~/hero') @@ -53,7 +52,6 @@ pub fn path_ensure(s string) string { return path } - // get path underneath the hero root directory pub fn hero_path(s string) string { path := shell_expansion(s).trim_left(' /') @@ -61,7 +59,6 @@ pub fn hero_path(s string) string { return full_path } - // return path and ensure it exists and return the path pub fn hero_path_ensure(s string) string { path := hero_path(s) diff --git a/lib/installers/db/zdb/zdb_installer.v b/lib/installers/db/zdb/zdb_installer.v index 569c2523..a28afe7d 100644 --- a/lib/installers/db/zdb/zdb_installer.v +++ b/lib/installers/db/zdb/zdb_installer.v @@ -150,7 +150,7 @@ pub fn secret() !string { return secret } -pub fn client() !zdb.ZDB { +pub fn client() !ZDB { mut db := zdb.get('localhost:3355', secret()!, 'test')! return db } diff --git a/lib/installers/sysadmintools/zinit/zinit_actions.v b/lib/installers/sysadmintools/zinit/zinit_actions.v index 8bf346e0..d3574c3f 100644 --- a/lib/installers/sysadmintools/zinit/zinit_actions.v +++ b/lib/installers/sysadmintools/zinit/zinit_actions.v @@ -94,9 +94,9 @@ fn ulist_get() !ulist.UList { fn upload() ! { } -fn startupcmd() ![]zinit.ZProcessNewArgs { +fn startupcmd() ![]ZProcessNewArgs { mut res := []zinit.ZProcessNewArgs{} - res << zinit.ZProcessNewArgs{ + res << ZProcessNewArgs{ name: 'zinit' cmd: '/usr/local/bin/zinit init' startuptype: .systemd diff --git a/lib/installers/sysadmintools/zinit/zinit_factory_.v b/lib/installers/sysadmintools/zinit/zinit_factory_.v index 49e9cf6b..6f71996c 100644 --- a/lib/installers/sysadmintools/zinit/zinit_factory_.v +++ b/lib/installers/sysadmintools/zinit/zinit_factory_.v @@ -28,7 +28,7 @@ pub fn get(args_ ArgsGet) !&Zinit { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit diff --git a/lib/osal/package_test.v b/lib/osal/package_test.v index 6f313a82..bc03a606 100644 --- a/lib/osal/package_test.v +++ b/lib/osal/package_test.v @@ -18,22 +18,16 @@ fn test_package_management() { assert !cmd_exists('wget') // Update package list - package_refresh() or { - assert false, 'Failed to refresh package list: ${err}' - } + package_refresh() or { assert false, 'Failed to refresh package list: ${err}' } // Install wget - package_install('wget') or { - assert false, 'Failed to install wget: ${err}' - } + package_install('wget') or { assert false, 'Failed to install wget: ${err}' } // Verify wget is now installed assert cmd_exists('wget') // Clean up - remove wget - package_remove('wget') or { - assert false, 'Failed to remove wget: ${err}' - } + package_remove('wget') or { assert false, 'Failed to remove wget: ${err}' } // Verify wget is removed assert !cmd_exists('wget') diff --git a/lib/ui/telegram/client/client.v b/lib/ui/telegram/client/client.v index f64ed6a5..9ebc6c2c 100644 --- a/lib/ui/telegram/client/client.v +++ b/lib/ui/telegram/client/client.v @@ -8,7 +8,7 @@ import json // client for telegram bot struct TelegramClient { bot vgram.Bot - baobab client.Client // Baobab client + baobab Client // Baobab client waiting_qs map[string]RedisQueue // where string is user_id }