From 77b8cb222e2a81d52a7f4d2a1564c7e7847019b6 Mon Sep 17 00:00:00 2001 From: Dario Pranjic Date: Tue, 7 Apr 2026 22:15:21 +0200 Subject: [PATCH 01/43] Add class registering way --- ts/examples/simple-example-ts/index.ts | 48 ++- .../simple-example-ts/package-lock.json | 19 +- ts/package-lock.json | 217 ++++++++------ ts/package.json | 5 +- ts/src/action_sdk.ts | 277 +++++++++++------- ts/src/types.ts | 111 +++++-- 6 files changed, 421 insertions(+), 256 deletions(-) diff --git a/ts/examples/simple-example-ts/index.ts b/ts/examples/simple-example-ts/index.ts index f1a9ede..dfbaaa3 100644 --- a/ts/examples/simple-example-ts/index.ts +++ b/ts/examples/simple-example-ts/index.ts @@ -1,8 +1,8 @@ import { createSdk, HerculesActionProjectConfiguration, - HerculesFunctionContext, - RuntimeErrorException + HerculesFunctionContext, Identifier, LinkedDataTypeIdentifiers, + RuntimeErrorException, RuntimeParameter, Signature } from "@code0-tech/hercules"; const sdk = createSdk({ @@ -22,33 +22,29 @@ sdk.registerDataTypes({ type: "any", }) -sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions({ - definition: { - signature: "(number: number) => number", - parameters: [ - { - runtimeName: "number", - defaultValue: 20, - } - ], - runtimeName: "fib", - }, - //This param is optional and can be omitted - handler: (context: HerculesFunctionContext, number: bigint): bigint => { - console.log(context) - console.log("Project id:", context.projectId); - console.log("Execution id:", context.executionId); - console.log("Matched configs:", context.matchedConfig); // matched configs for the current execution - - function fibonacci(num: bigint): bigint { - if (num <= 1) return num; - return fibonacci(num - 1n) + fibonacci(num - 2n); - } +@Identifier("fib") +@Signature("(number: number) => number") +@RuntimeParameter({ + runtimeName: "number", + defaultValue: 20 +}) +class FibonacciFunction { + run(context: HerculesFunctionContext, number: number): number { + console.log(context) + console.log("Project id:", context.projectId); + console.log("Execution id:", context.executionId); + console.log("Matched configs:", context.matchedConfig); // matched configs for the current execution - return fibonacci(number) + function fibonacci(num: number): number { + if (num <= 1) return num; + return fibonacci(num - 1) + fibonacci(num - 2); } + + return fibonacci(number) } -) +} + +sdk.registerRuntimeFunctionDefinitionClass(FibonacciFunction) sdk.registerFlowTypes( { diff --git a/ts/examples/simple-example-ts/package-lock.json b/ts/examples/simple-example-ts/package-lock.json index b9a1c24..ef97b74 100644 --- a/ts/examples/simple-example-ts/package-lock.json +++ b/ts/examples/simple-example-ts/package-lock.json @@ -15,23 +15,24 @@ "node_modules/@code0-tech/hercules": { "version": "0.0.0", "resolved": "file:../../code0-tech-hercules-0.0.0.tgz", - "integrity": "sha512-0J+8A+AN0rmy8YTXBAGPBgHYUARwf60k63kiWVHA2dob9xJfX7PyyncnRfPdRG0DtENLVN26qmtTmCRo4mM0kQ==", + "integrity": "sha512-KgSdzgsOzIyHCMebtf0B/HUgSJNgYe7yuj8tpuqdJIP1UzhVU/2Tptwv6z9RZK/iv+EG4yq0gntZWXnHwZAS0w==", "license": "ISC", "dependencies": { - "@code0-tech/tucana": "0.0.67", + "@code0-tech/tucana": "0.0.68", "@grpc/grpc-js": "^1.14.3", "@protobuf-ts/grpc-backend": "^2.11.1", "@protobuf-ts/grpc-transport": "^2.11.1", "@protobuf-ts/runtime": "^2.11.1", "@protobuf-ts/runtime-rpc": "^2.11.1", "pino": "^10.3.1", - "pino-pretty": "^13.1.3" + "pino-pretty": "^13.1.3", + "reflect-metadata": "^0.2.2" } }, "node_modules/@code0-tech/tucana": { - "version": "0.0.67", - "resolved": "https://registry.npmjs.org/@code0-tech/tucana/-/tucana-0.0.67.tgz", - "integrity": "sha512-3V1h3LB+iWeXnt80nsIQo+TeMgVTgbDxvDsAArbffHyU37ii1tsAAV6Ty7wAdkrCSsObyFRpdiIZgzgYVVKfzw==", + "version": "0.0.68", + "resolved": "https://registry.npmjs.org/@code0-tech/tucana/-/tucana-0.0.68.tgz", + "integrity": "sha512-kbjLiKjJyZLnPmNi5JabWRNZcWZyXnfnld8jCFrUkvKbGj77CAwggR0uH8SqaxwWNWqQZlavYzCZWO/ob3+uKA==", "license": "Apache-2.0" }, "node_modules/@grpc/grpc-js": { @@ -509,6 +510,12 @@ "node": ">= 12.13.0" } }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "license": "Apache-2.0" + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", diff --git a/ts/package-lock.json b/ts/package-lock.json index 5f6a676..c69bfdb 100644 --- a/ts/package-lock.json +++ b/ts/package-lock.json @@ -9,14 +9,15 @@ "version": "0.0.0", "license": "ISC", "dependencies": { - "@code0-tech/tucana": "0.0.67", + "@code0-tech/tucana": "0.0.68", "@grpc/grpc-js": "^1.14.3", "@protobuf-ts/grpc-backend": "^2.11.1", "@protobuf-ts/grpc-transport": "^2.11.1", "@protobuf-ts/runtime": "^2.11.1", "@protobuf-ts/runtime-rpc": "^2.11.1", "pino": "^10.3.1", - "pino-pretty": "^13.1.3" + "pino-pretty": "^13.1.3", + "reflect-metadata": "^0.2.2" }, "devDependencies": { "@types/node": "^25.0.10", @@ -78,9 +79,9 @@ } }, "node_modules/@code0-tech/tucana": { - "version": "0.0.67", - "resolved": "https://registry.npmjs.org/@code0-tech/tucana/-/tucana-0.0.67.tgz", - "integrity": "sha512-3V1h3LB+iWeXnt80nsIQo+TeMgVTgbDxvDsAArbffHyU37ii1tsAAV6Ty7wAdkrCSsObyFRpdiIZgzgYVVKfzw==", + "version": "0.0.68", + "resolved": "https://registry.npmjs.org/@code0-tech/tucana/-/tucana-0.0.68.tgz", + "integrity": "sha512-kbjLiKjJyZLnPmNi5JabWRNZcWZyXnfnld8jCFrUkvKbGj77CAwggR0uH8SqaxwWNWqQZlavYzCZWO/ob3+uKA==", "license": "Apache-2.0" }, "node_modules/@emnapi/core": { @@ -640,9 +641,9 @@ } }, "node_modules/@microsoft/api-extractor": { - "version": "7.58.0", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.58.0.tgz", - "integrity": "sha512-XcHlDylX5GblbGbs1eBoexjVyvdJMioTPuBCgCorE2rqijzTYxi6eudXyez3xACRxtH9aDtahoL9fYM4XTvQmg==", + "version": "7.58.1", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.58.1.tgz", + "integrity": "sha512-kF3GFME4lN22O5zbnXk2RP4y/4PDQdps0xKiYTipMYprkwCmmpsWLZt/N2Fkbil540cSLfJX0BW7LkHzgMVUYg==", "dev": true, "license": "MIT", "dependencies": { @@ -654,7 +655,7 @@ "@rushstack/terminal": "0.22.4", "@rushstack/ts-command-line": "5.3.4", "diff": "~8.0.2", - "lodash": "~4.17.23", + "lodash": "~4.18.1", "minimatch": "10.2.3", "resolve": "~1.22.1", "semver": "~7.5.4", @@ -708,26 +709,28 @@ } }, "node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz", - "integrity": "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.2.tgz", + "integrity": "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" }, "funding": { "type": "github", "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" } }, "node_modules/@oxc-project/types": { - "version": "0.122.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.122.0.tgz", - "integrity": "sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==", + "version": "0.123.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.123.0.tgz", + "integrity": "sha512-YtECP/y8Mj1lSHiUWGSRzy/C6teUKlS87dEfuVKT09LgQbUsBW1rNg+MiJ4buGu3yuADV60gbIvo9/HplA56Ew==", "dev": true, "license": "MIT", "funding": { @@ -846,9 +849,9 @@ "license": "BSD-3-Clause" }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.12.tgz", - "integrity": "sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.13.tgz", + "integrity": "sha512-5ZiiecKH2DXAVJTNN13gNMUcCDg4Jy8ZjbXEsPnqa248wgOVeYRX0iqXXD5Jz4bI9BFHgKsI2qmyJynstbmr+g==", "cpu": [ "arm64" ], @@ -863,9 +866,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.12.tgz", - "integrity": "sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.13.tgz", + "integrity": "sha512-tz/v/8G77seu8zAB3A5sK3UFoOl06zcshEzhUO62sAEtrEuW/H1CcyoupOrD+NbQJytYgA4CppXPzlrmp4JZKA==", "cpu": [ "arm64" ], @@ -880,9 +883,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.12.tgz", - "integrity": "sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.13.tgz", + "integrity": "sha512-8DakphqOz8JrMYWTJmWA+vDJxut6LijZ8Xcdc4flOlAhU7PNVwo2MaWBF9iXjJAPo5rC/IxEFZDhJ3GC7NHvug==", "cpu": [ "x64" ], @@ -897,9 +900,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.12.tgz", - "integrity": "sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.13.tgz", + "integrity": "sha512-4wBQFfjDuXYN/SVI8inBF3Aa+isq40rc6VMFbk5jcpolUBTe5cYnMsHZ51nFWsx3PVyyNN3vgoESki0Hmr/4BA==", "cpu": [ "x64" ], @@ -914,9 +917,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.12.tgz", - "integrity": "sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.13.tgz", + "integrity": "sha512-JW/e4yPIXLms+jmnbwwy5LA/LxVwZUWLN8xug+V200wzaVi5TEGIWQlh8o91gWYFxW609euI98OCCemmWGuPrw==", "cpu": [ "arm" ], @@ -931,13 +934,16 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.12.tgz", - "integrity": "sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.13.tgz", + "integrity": "sha512-ZfKWpXiUymDnavepCaM6KG/uGydJ4l2nBmMxg60Ci4CbeefpqjPWpfaZM7PThOhk2dssqBAcwLc6rAyr0uTdXg==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -948,13 +954,16 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.12.tgz", - "integrity": "sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.13.tgz", + "integrity": "sha512-bmRg3O6Z0gq9yodKKWCIpnlH051sEfdVwt+6m5UDffAQMUUqU0xjnQqqAUm+Gu7ofAAly9DqiQDtKu2nPDEABA==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -965,13 +974,16 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.12.tgz", - "integrity": "sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.13.tgz", + "integrity": "sha512-8Wtnbw4k7pMYN9B/mOEAsQ8HOiq7AZ31Ig4M9BKn2So4xRaFEhtCSa4ZJaOutOWq50zpgR4N5+L/opnlaCx8wQ==", "cpu": [ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -982,13 +994,16 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.12.tgz", - "integrity": "sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.13.tgz", + "integrity": "sha512-D/0Nlo8mQuxSMohNJUF2lDXWRsFDsHldfRRgD9bRgktj+EndGPj4DOV37LqDKPYS+osdyhZEH7fTakTAEcW7qg==", "cpu": [ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -999,13 +1014,16 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.12.tgz", - "integrity": "sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.13.tgz", + "integrity": "sha512-eRrPvat2YaVQcwwKi/JzOP6MKf1WRnOCr+VaI3cTWz3ZoLcP/654z90lVCJ4dAuMEpPdke0n+qyAqXDZdIC4rA==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1016,13 +1034,16 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.12.tgz", - "integrity": "sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.13.tgz", + "integrity": "sha512-PsdONiFRp8hR8KgVjTWjZ9s7uA3uueWL0t74/cKHfM4dR5zXYv4AjB8BvA+QDToqxAFg4ZkcVEqeu5F7inoz5w==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1033,9 +1054,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.12.tgz", - "integrity": "sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.13.tgz", + "integrity": "sha512-hCNXgC5dI3TVOLrPT++PKFNZ+1EtS0mLQwfXXXSUD/+rGlB65gZDwN/IDuxLpQP4x8RYYHqGomlUXzpO8aVI2w==", "cpu": [ "arm64" ], @@ -1050,9 +1071,9 @@ } }, "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.12.tgz", - "integrity": "sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.13.tgz", + "integrity": "sha512-viLS5C5et8NFtLWw9Sw3M/w4vvnVkbWkO7wSNh3C+7G1+uCkGpr6PcjNDSFcNtmXY/4trjPBqUfcOL+P3sWy/g==", "cpu": [ "wasm32" ], @@ -1060,16 +1081,18 @@ "license": "MIT", "optional": true, "dependencies": { - "@napi-rs/wasm-runtime": "^1.1.1" + "@emnapi/core": "1.9.1", + "@emnapi/runtime": "1.9.1", + "@napi-rs/wasm-runtime": "^1.1.2" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.12.tgz", - "integrity": "sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.13.tgz", + "integrity": "sha512-Fqa3Tlt1xL4wzmAYxGNFV36Hb+VfPc9PYU+E25DAnswXv3ODDu/yyWjQDbXMo5AGWkQVjLgQExuVu8I/UaZhPQ==", "cpu": [ "arm64" ], @@ -1084,9 +1107,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.12.tgz", - "integrity": "sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.13.tgz", + "integrity": "sha512-/pLI5kPkGEi44TDlnbio3St/5gUFeN51YWNAk/Gnv6mEQBOahRBh52qVFVBpmrnU01n2yysvBML9Ynu7K4kGAQ==", "cpu": [ "x64" ], @@ -1101,9 +1124,9 @@ } }, "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.12.tgz", - "integrity": "sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.13.tgz", + "integrity": "sha512-3ngTAv6F/Py35BsYbeeLeecvhMKdsKm4AoOETVhAA+Qc8nrA2I0kF7oa93mE9qnIurngOSpMnQ0x2nQY2FPviA==", "dev": true, "license": "MIT" }, @@ -2899,9 +2922,9 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "dev": true, "license": "MIT" }, @@ -3366,6 +3389,12 @@ "node": ">= 12.13.0" } }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "license": "Apache-2.0" + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -3417,14 +3446,14 @@ } }, "node_modules/rolldown": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.12.tgz", - "integrity": "sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.13.tgz", + "integrity": "sha512-bvVj8YJmf0rq4pSFmH7laLa6pYrhghv3PRzrCdRAr23g66zOKVJ4wkvFtgohtPLWmthgg8/rkaqRHrpUEh0Zbw==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.122.0", - "@rolldown/pluginutils": "1.0.0-rc.12" + "@oxc-project/types": "=0.123.0", + "@rolldown/pluginutils": "1.0.0-rc.13" }, "bin": { "rolldown": "bin/cli.mjs" @@ -3433,21 +3462,21 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.0-rc.12", - "@rolldown/binding-darwin-arm64": "1.0.0-rc.12", - "@rolldown/binding-darwin-x64": "1.0.0-rc.12", - "@rolldown/binding-freebsd-x64": "1.0.0-rc.12", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.12", - "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.12", - "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.12", - "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.12", - "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.12", - "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.12", - "@rolldown/binding-linux-x64-musl": "1.0.0-rc.12", - "@rolldown/binding-openharmony-arm64": "1.0.0-rc.12", - "@rolldown/binding-wasm32-wasi": "1.0.0-rc.12", - "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.12", - "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.12" + "@rolldown/binding-android-arm64": "1.0.0-rc.13", + "@rolldown/binding-darwin-arm64": "1.0.0-rc.13", + "@rolldown/binding-darwin-x64": "1.0.0-rc.13", + "@rolldown/binding-freebsd-x64": "1.0.0-rc.13", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.13", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.13", + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.13", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.13", + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.13", + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.13", + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.13", + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.13", + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.13", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.13", + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.13" } }, "node_modules/rollup": { @@ -3895,16 +3924,16 @@ } }, "node_modules/vite": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.3.tgz", - "integrity": "sha512-B9ifbFudT1TFhfltfaIPgjo9Z3mDynBTJSUYxTjOQruf/zHH+ezCQKcoqO+h7a9Pw9Nm/OtlXAiGT1axBgwqrQ==", + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.7.tgz", + "integrity": "sha512-P1PbweD+2/udplnThz3btF4cf6AgPky7kk23RtHUkJIU5BIxwPprhRGmOAHs6FTI7UiGbTNrgNP6jSYD6JaRnw==", "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.8", - "rolldown": "1.0.0-rc.12", + "rolldown": "1.0.0-rc.13", "tinyglobby": "^0.2.15" }, "bin": { @@ -3922,7 +3951,7 @@ "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", - "esbuild": "^0.27.0", + "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", diff --git a/ts/package.json b/ts/package.json index 251652a..699e1f3 100644 --- a/ts/package.json +++ b/ts/package.json @@ -30,14 +30,15 @@ "license": "ISC", "type": "module", "dependencies": { - "@code0-tech/tucana": "0.0.67", + "@code0-tech/tucana": "0.0.68", "@grpc/grpc-js": "^1.14.3", "@protobuf-ts/grpc-backend": "^2.11.1", "@protobuf-ts/grpc-transport": "^2.11.1", "@protobuf-ts/runtime": "^2.11.1", "@protobuf-ts/runtime-rpc": "^2.11.1", "pino": "^10.3.1", - "pino-pretty": "^13.1.3" + "pino-pretty": "^13.1.3", + "reflect-metadata": "^0.2.2" }, "devDependencies": { "@types/node": "^25.0.10", diff --git a/ts/src/action_sdk.ts b/ts/src/action_sdk.ts index f8c1137..fdf2559 100644 --- a/ts/src/action_sdk.ts +++ b/ts/src/action_sdk.ts @@ -4,7 +4,9 @@ import {RpcOptions} from "@protobuf-ts/runtime-rpc"; import { ActionSdk, HerculesActionConfigurationDefinition, HerculesActionProjectConfiguration, HerculesFunctionContext, SdkState, RuntimeErrorException, - HerculesRegisterRuntimeFunctionParameter, HerculesRegisterFunctionDefinition + HerculesFunctionDefinition, RuntimeFunctionDefinitionClass, + FunctionDefinitionConstructor, RegisteredRuntimeFunction, HerculesFunctionDefinitionParameter, + HerculesRuntimeFunctionDefinitionParameter, HerculesRuntimeFunctionDefinition, RegisteredFunction } from "./types.js"; import { ActionTransferServiceClient, @@ -18,10 +20,11 @@ import { } from "@code0-tech/tucana/aquila"; import { ActionConfigurations, - FlowTypeSetting, + FlowTypeSetting, RuntimeParameterDefinition, } from "@code0-tech/tucana/shared"; import {constructValue, toAllowedValue} from "@code0-tech/tucana/helpers"; import {logger} from "./logger"; +import 'reflect-metadata'; const createSdk = (config: ActionSdk["config"], configDefinitions?: HerculesActionConfigurationDefinition[]): ActionSdk => { const transport = new GrpcTransport( @@ -54,74 +57,148 @@ const createSdk = (config: ActionSdk["config"], configDefinitions?: HerculesActi fullyConnected: false } - const registerFunctionDefinitions = async (...functionDefinitions: Array) => { - for (const functionDefinition of functionDefinitions) { - state.functions.push({ - identifier: functionDefinition.runtimeName, - definition: { - displayMessage: functionDefinition.displayMessage || [], - name: functionDefinition.name || [], - documentation: functionDefinition.documentation || [], - description: functionDefinition.description || [], - deprecationMessage: functionDefinition.deprecationMessage || [], - displayIcon: functionDefinition.displayIcon || "", - alias: functionDefinition.alias || [], - linkedDataTypeIdentifiers: functionDefinition.linkedDataTypes || [], - definitionSource: "action", - version: functionDefinition.version || config.version, - runtimeName: functionDefinition.runtimeName, - parameterDefinitions: (functionDefinition.parameters || []).map(param => ({ - runtimeName: param.runtimeName, + const buildRuntimeFunctionDefinition = (klass: RuntimeFunctionDefinitionClass): RegisteredRuntimeFunction => { + const identifier: string = Reflect.getMetadata('hercules:identifier', klass) + const runtimeParameters: HerculesRuntimeFunctionDefinitionParameter[] = Reflect.getMetadata('hercules:runtime_parameters', klass) + const names: HerculesRuntimeFunctionDefinition["name"] = Reflect.getMetadata('hercules:name', klass) || [] + const displayMessage: HerculesRuntimeFunctionDefinition["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass) || [] + const description: HerculesRuntimeFunctionDefinition["description"] = Reflect.getMetadata('hercules:description', klass) || [] + const deprecationMessage: HerculesRuntimeFunctionDefinition["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass) || [] + const alias: HerculesRuntimeFunctionDefinition["alias"] = Reflect.getMetadata('hercules:alias', klass) || [] + const documentation: HerculesRuntimeFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass) || [] + const signature: HerculesRuntimeFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass) + const linkedDataTypeIdentifiers: HerculesRuntimeFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) || [] + const version: HerculesRuntimeFunctionDefinition["version"] = Reflect.getMetadata('hercules:version', klass) || config.version + const displayIcon: HerculesRuntimeFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass) || "" + const throwsError: HerculesRuntimeFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass) || false + const runFunction = new klass().run + + if (!identifier) { + throw new Error(`Runtime function class ${klass.name} is missing an identifier. Please add @Identifier("your_identifier") decorator to the class.`) + } + if (!signature) { + throw new Error(`Runtime function class ${klass.name} is missing a signature. Please add @Signature("(param1: TYPE_1): RETURN_TYPE") decorator to the class.`) + } + + return { + identifier: identifier as string, + definition: { + alias: alias || [], + name: names || [], + description: description || [], + version: version || config.version, + runtimeName: identifier, + deprecationMessage: deprecationMessage || [], + displayIcon: displayIcon || "", + displayMessage: displayMessage || [], + documentation: documentation || [], + linkedDataTypeIdentifiers: linkedDataTypeIdentifiers || [], + runtimeParameterDefinitions: runtimeParameters.map(param => { + return { + ...param, name: param.name || [], description: param.description || [], documentation: param.documentation || [], - defaultValue: constructValue(param.defaultValue || null), hidden: param.hidden || false, - optional: param.hidden || false, - runtimeDefinitionName: param.runtimeDefinitionName || param.runtimeName - })), - signature: functionDefinition.signature, - throwsError: functionDefinition.throwsError || false, - runtimeDefinitionName: functionDefinition.runtimeDefinitionName + optional: param.optional || false, + defaultValue: param.defaultValue ? constructValue(param.defaultValue) : undefined, + } as RuntimeParameterDefinition + }), + signature: signature, + throwsError: throwsError || false, + definitionSource: "action" + }, + handler: runFunction + } as RegisteredRuntimeFunction + } + + return { + registerFunctionDefinitionClass(klass: FunctionDefinitionConstructor): Promise { + const parentClass = Object.getPrototypeOf(klass) + const runtimeFunction = buildRuntimeFunctionDefinition(parentClass); + const runtimeDefinition = runtimeFunction.definition + + const functionParameters: HerculesFunctionDefinitionParameter[] = Reflect.getMetadata('hercules:function_parameters', klass) + const names: HerculesFunctionDefinition["name"] = Reflect.getMetadata('hercules:name', klass) + const displayMessage: HerculesFunctionDefinition["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass) + const description: HerculesFunctionDefinition["description"] = Reflect.getMetadata('hercules:description', klass) + const deprecationMessage: HerculesFunctionDefinition["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass) + const alias: HerculesFunctionDefinition["alias"] = Reflect.getMetadata('hercules:alias', klass) + const documentation: HerculesFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass) + const signature: HerculesFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass) + const linkedDataTypeIdentifiers: HerculesFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) + const version: HerculesFunctionDefinition["version"] = Reflect.getMetadata('hercules:version', klass) + const displayIcon: HerculesFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass) + const throwsError: HerculesFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass) + + runtimeDefinition.runtimeParameterDefinitions.forEach(runtimeDefinition => { + if (functionParameters.find((param: HerculesFunctionDefinitionParameter) => param.runtimeName === runtimeDefinition.runtimeName)) { + return; } - }); - } - return Promise.resolve() - }; - const registerRuntimeFunctionDefinitions = async (...runtimeFunctionDefinitions: HerculesRegisterRuntimeFunctionParameter[]) => { - for (const registeredFunction of runtimeFunctionDefinitions) { - const handler = registeredFunction.handler; - const functionDefinition = registeredFunction.definition; - state.runtimeFunctions.push({ - identifier: functionDefinition.runtimeName, + functionParameters.push({ + ...runtimeDefinition, + runtimeDefinitionName: runtimeDefinition.runtimeName + }) + }) + + state.functions.push({ + identifier: runtimeFunction.identifier, definition: { - displayMessage: functionDefinition.displayMessage || [], - name: functionDefinition.name || [], - documentation: functionDefinition.documentation || [], - description: functionDefinition.description || [], - deprecationMessage: functionDefinition.deprecationMessage || [], - displayIcon: functionDefinition.displayIcon || "", - alias: functionDefinition.alias || [], - linkedDataTypeIdentifiers: functionDefinition.linkedDataTypes || [], + runtimeDefinitionName: runtimeDefinition.runtimeName, + runtimeName: runtimeDefinition.runtimeName || runtimeDefinition.runtimeName, + signature: signature || runtimeDefinition.signature, + throwsError: throwsError || runtimeDefinition.throwsError, + alias: alias || runtimeDefinition.alias, + version: version || runtimeDefinition.version, + description: description || runtimeDefinition.description, + name: names || runtimeDefinition.name, + documentation: documentation || runtimeDefinition.documentation, + deprecationMessage: deprecationMessage || runtimeDefinition.deprecationMessage, + displayMessage: displayMessage || runtimeDefinition.displayMessage, + displayIcon: displayIcon || runtimeDefinition.displayIcon, definitionSource: "action", - version: functionDefinition.version || config.version, - runtimeName: functionDefinition.runtimeName, - runtimeParameterDefinitions: (functionDefinition.parameters || []).map(param => ({ - runtimeName: param.runtimeName, - name: param.name || [], - description: param.description || [], - documentation: param.documentation || [], - defaultValue: constructValue(param.defaultValue || null), - })), - signature: functionDefinition.signature, - throwsError: functionDefinition.throwsError || false, + linkedDataTypeIdentifiers: linkedDataTypeIdentifiers || runtimeDefinition.linkedDataTypeIdentifiers, + parameterDefinitions: functionParameters.map(value => { + return { + ...value, + runtimeDefinitionName: value.runtimeDefinitionName || value.runtimeName, + name: value.name || [], + description: value.description || [], + documentation: value.documentation || [], + hidden: value.hidden || false, + optional: value.optional || false, + defaultValue: value.defaultValue ? constructValue(value.defaultValue || null) : undefined, + } + }) }, - handler: handler, - }); - } - return Promise.resolve() - }; - return { + } as RegisteredFunction) + + return Promise.resolve(); + }, registerRuntimeFunctionDefinitionClass(klass: RuntimeFunctionDefinitionClass): Promise { + const omitFunctionDefinition = Reflect.getMetadata('hercules:omit_function_definition', klass) || false + + const runtimeFunction = buildRuntimeFunctionDefinition(klass); + const definition = runtimeFunction.definition + + state.runtimeFunctions.push(runtimeFunction as RegisteredRuntimeFunction) + if (!omitFunctionDefinition) { + state.functions.push({ + identifier: definition.runtimeName, + definition: { + ...definition, + runtimeDefinitionName: definition.runtimeName, + parameterDefinitions: definition.runtimeParameterDefinitions.map(param => { + return { + ...param, + runtimeDefinitionName: param.runtimeName + } + }) + } + } as RegisteredFunction) + } + + return Promise.resolve(); + }, fullyConnected(): boolean { return state.fullyConnected; }, @@ -209,29 +286,6 @@ const createSdk = (config: ActionSdk["config"], configDefinitions?: HerculesActi }) return Promise.resolve() }, - registerRuntimeFunctionDefinitionsAndFunctionDefinitions: async (...runtimeFunctionDefinitions) => { - await Promise.all(runtimeFunctionDefinitions.map(async (register) => { - await Promise.all([ - registerRuntimeFunctionDefinitions( - register - ), - registerFunctionDefinitions( - { - ...register.definition, - runtimeDefinitionName: register.definition.runtimeName, - parameters: register.definition.parameters?.map(param => { - return { - ...param, - runtimeDefinitionName: param.runtimeName, - } - }) - } - ) - ]) - })); - }, - registerRuntimeFunctionDefinitions: registerRuntimeFunctionDefinitions, - registerFunctionDefinitions: registerFunctionDefinitions, dispatchEvent: async (eventType, projectId, payload) => { if (!state.stream) { return Promise.reject("SDK is not connected. Call connect() before dispatching events."); @@ -309,27 +363,40 @@ async function connect(state: SdkState, config: ActionSdk["config"], options?: R logger.debug("Successfully sent logon request") - const runtimeFunctionDefinitionClient = new RuntimeFunctionDefinitionServiceClient(state.transport) - await runtimeFunctionDefinitionClient.update( - RuntimeFunctionDefinitionUpdateRequest.create( - { - runtimeFunctions: [ - ...state.runtimeFunctions.map(func => ({ - ...func.definition, - })) - ] - } - ), builtOptions - ).then(value => { - if (!value.response.success) { - logger.error({ - err: value.response, - request: value.request, - config, - }) - return Promise.reject(value.response); + const request = RuntimeFunctionDefinitionUpdateRequest.create( + { + runtimeFunctions: [ + ...state.runtimeFunctions.map(func => ({ + ...func.definition, + })) + ] } - }) + ); + try { + const runtimeFunctionDefinitionClient = new RuntimeFunctionDefinitionServiceClient(state.transport) + await runtimeFunctionDefinitionClient.update( + request, builtOptions + ).then(value => { + if (!value.response.success) { + logger.error({ + err: value.response, + request: value.request, + config, + }) + return Promise.reject(value.response); + } + }) + } catch (error) { + logger.debug({ + ...request.runtimeFunctions[0].runtimeParameterDefinitions[0].defaultValue + }) + logger.error({ + err: error, + request: request, + config, + }, "Error while updating runtime function definitions") + return Promise.reject(error); + } logger.debug("Successfully updated runtime function definitions") const FunctionDefinitionClient = new FunctionDefinitionServiceClient(state.transport) diff --git a/ts/src/types.ts b/ts/src/types.ts index 7215e86..9ed34a9 100644 --- a/ts/src/types.ts +++ b/ts/src/types.ts @@ -10,6 +10,7 @@ import { } from "@code0-tech/tucana/shared"; import {PlainValue} from "@code0-tech/tucana/helpers"; import {ActionTransferServiceClient, TransferRequest, TransferResponse} from "@code0-tech/tucana/aquila"; +import 'reflect-metadata'; export interface HerculesFunctionContext { @@ -55,18 +56,19 @@ export interface HerculesFlowType { displayIcon?: string, } +export interface HerculesRuntimeFunctionDefinitionParameter { + runtimeName: string, + defaultValue?: PlainValue, + name?: Translation[], + description?: Translation[], + documentation?: Translation[], + hidden?: boolean, + optional?: boolean +} export interface HerculesRuntimeFunctionDefinition { runtimeName: string, - parameters?: { - runtimeName: string, - defaultValue?: PlainValue, - name?: Translation[], - description?: Translation[], - documentation?: Translation[], - hidden?: boolean, - optional?: boolean - }[], + parameters?: HerculesRuntimeFunctionDefinitionParameter[], signature: string, throwsError?: boolean, name?: Translation[], @@ -80,19 +82,21 @@ export interface HerculesRuntimeFunctionDefinition { displayIcon?: string, } -export interface HerculesRegisterFunctionDefinition { +export interface HerculesFunctionDefinitionParameter { + runtimeName: string, + defaultValue?: PlainValue, + name?: Translation[], + description?: Translation[], + documentation?: Translation[], + hidden?: boolean, + optional?: boolean, + runtimeDefinitionName?: string +} + +export interface HerculesFunctionDefinition { runtimeDefinitionName: string, runtimeName: string, - parameters?: { - runtimeName: string, - defaultValue?: PlainValue, - name?: Translation[], - description?: Translation[], - documentation?: Translation[], - hidden?: boolean, - optional?: boolean, - runtimeDefinitionName?: string - }[], + parameters?: HerculesFunctionDefinitionParameter[], signature: string, throwsError?: boolean, name?: Translation[], @@ -145,9 +149,8 @@ export interface ActionSdk { registerConfigDefinitions: (...actionConfigurations: Array) => Promise, registerDataTypes: (...dataType: Array) => Promise, registerFlowTypes: (...flowTypes: Array) => Promise, - registerRuntimeFunctionDefinitionsAndFunctionDefinitions: (...runtimeFunctionDefinitions: Array) => Promise, - registerFunctionDefinitions: (...functionDefinitions: Array) => Promise, - registerRuntimeFunctionDefinitions: (...runtimeFunctionDefinitions: Array) => Promise, + registerRuntimeFunctionDefinitionClass: (klass: RuntimeFunctionDefinitionClass) => Promise, + registerFunctionDefinitionClass: (klass: FunctionDefinitionConstructor) => Promise, dispatchEvent: (eventType: string, projectId: number | bigint, payload: PlainValue) => Promise, } @@ -163,6 +166,68 @@ export class RuntimeErrorException extends Error { } } + +export type FunctionDefinitionConstructor = new () => T; + +export type RuntimeFunctionDefinitionRunnable = { + run: (...args: any[]) => Promise | PlainValue; +}; + +export type RuntimeFunctionDefinitionClass = + new () => T; + + +export const Identifier = (id: string): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:identifier', id, target); + +export const OmitFunctionDefinition = (): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:omit_function_definition', true, target) + +export const RuntimeParameter = (parameter: HerculesRuntimeFunctionDefinitionParameter): ClassDecorator => + (target) => { + const parameters = Reflect.getMetadata('hercules:runtime_parameters', target) || []; + parameters.push(parameter); + + Reflect.defineMetadata('hercules:runtime_parameters', parameters, target) + } + +export const FunctionParameter = (parameter: HerculesFunctionDefinitionParameter): ClassDecorator => + (target) => { + const parameters = Reflect.getMetadata('hercules:function_parameters', target) || []; + parameters.push(parameter); + + Reflect.defineMetadata('hercules:function_parameters', parameters, target) + } + +export const Name = (...translation: Translation[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:name', translation, target) + +export const DisplayMessage = (...translation: Translation[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:display_message', translation, target) +export const Description = (...translation: Translation[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:description', translation, target) +export const DeprecationMessage = (...translation: Translation[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:deprecation_message', translation, target) +export const Alias = (...translation: Translation[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:alias', translation, target) +export const Documentation = (...translation: Translation[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:documentation', translation, target) + +export const Signature = (signature: string): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:signature', signature, target) + +export const LinkedDataTypeIdentifiers = (...linkedDataTypeIdentifiers: string[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:linked_data_type_identifiers', linkedDataTypeIdentifiers, target) + +export const Version = (version: string): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:version', version, target) + +export const ThrowsError = (throwsError: boolean = true): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:throws_error', throwsError, target) + +export const DisplayIcon = (displayIcon: string): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:display_icon', displayIcon, target) + export interface RegisteredFunction { identifier: string, definition: FunctionDefinition From 508fd709441d291c56859a2c4b751fbf6c3dc620 Mon Sep 17 00:00:00 2001 From: Dario Pranjic <96529060+Knerio@users.noreply.github.com> Date: Thu, 9 Apr 2026 20:30:33 +0200 Subject: [PATCH 02/43] Fix signature Co-authored-by: Nico Sammito Signed-off-by: Dario Pranjic <96529060+Knerio@users.noreply.github.com> --- ts/examples/simple-example-ts/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/examples/simple-example-ts/index.ts b/ts/examples/simple-example-ts/index.ts index dfbaaa3..824d3c3 100644 --- a/ts/examples/simple-example-ts/index.ts +++ b/ts/examples/simple-example-ts/index.ts @@ -23,7 +23,7 @@ sdk.registerDataTypes({ }) @Identifier("fib") -@Signature("(number: number) => number") +@Signature("(number: number): number") @RuntimeParameter({ runtimeName: "number", defaultValue: 20 From 52d7868f2b6e9e3e841206cec3788cf89e0a39a9 Mon Sep 17 00:00:00 2001 From: Dario Pranjic Date: Thu, 9 Apr 2026 20:57:42 +0200 Subject: [PATCH 03/43] Change tooling to vite build --- .../simple-example-ts/package-lock.json | 6 +++--- ts/examples/simple-example-ts/package.json | 4 ++-- ts/examples/simple-example-ts/tsconfig.json | 5 ++++- ts/examples/simple-example-ts/vite.config.ts | 18 ++++++++++++++++++ ts/tsconfig.json | 3 ++- 5 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 ts/examples/simple-example-ts/vite.config.ts diff --git a/ts/examples/simple-example-ts/package-lock.json b/ts/examples/simple-example-ts/package-lock.json index ef97b74..52fa24c 100644 --- a/ts/examples/simple-example-ts/package-lock.json +++ b/ts/examples/simple-example-ts/package-lock.json @@ -188,9 +188,9 @@ "license": "BSD-3-Clause" }, "node_modules/@types/node": { - "version": "25.5.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz", - "integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==", + "version": "25.5.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.2.tgz", + "integrity": "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==", "license": "MIT", "dependencies": { "undici-types": "~7.18.0" diff --git a/ts/examples/simple-example-ts/package.json b/ts/examples/simple-example-ts/package.json index 80046ca..dd44023 100644 --- a/ts/examples/simple-example-ts/package.json +++ b/ts/examples/simple-example-ts/package.json @@ -7,8 +7,8 @@ "type": "module", "main": "index.js", "scripts": { - "build": "tsc -p tsconfig.json", - "dev": "cd ../.. && npm install && npm run build && npm pack && cd examples/simple-example-ts && npm install ../../code0-tech-hercules-0.0.0.tgz && npx tsx index.ts" + "build": "vite build .", + "start": "cd ../.. && npm install && npm run build && npm pack && cd examples/simple-example-ts && npm install && npm run build && node dist/index.js" }, "dependencies": { "@code0-tech/hercules": "file:../../code0-tech-hercules-0.0.0.tgz" diff --git a/ts/examples/simple-example-ts/tsconfig.json b/ts/examples/simple-example-ts/tsconfig.json index 7193a07..64bfbd7 100644 --- a/ts/examples/simple-example-ts/tsconfig.json +++ b/ts/examples/simple-example-ts/tsconfig.json @@ -11,7 +11,10 @@ "baseUrl": ".", "paths": { "@code0-tech/hercules": ["../../ts"] - } + }, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "types": ["vite/client"] }, "include": [ "index.ts" diff --git a/ts/examples/simple-example-ts/vite.config.ts b/ts/examples/simple-example-ts/vite.config.ts new file mode 100644 index 0000000..001ed7e --- /dev/null +++ b/ts/examples/simple-example-ts/vite.config.ts @@ -0,0 +1,18 @@ +import { defineConfig } from 'vite'; +import { resolve } from 'path'; + +export default defineConfig({ + build: { + target: "node18", + ssr: resolve(__dirname, 'index.ts'), // ✅ correct SSR entry + rollupOptions: { + external: (id) => + [ + 'fs', + 'path', + 'typescript', + '@code0-tech/hercules' + ].includes(id) || id.startsWith('node:') + } + } +}); \ No newline at end of file diff --git a/ts/tsconfig.json b/ts/tsconfig.json index afd60b6..a48423f 100644 --- a/ts/tsconfig.json +++ b/ts/tsconfig.json @@ -6,7 +6,8 @@ "target": "es2020", "lib": ["es2020", "dom"], "strict": true, - "skipLibCheck": true + "skipLibCheck": true, + "types": ["vite/client"] }, "include": ["src/**/*"] } \ No newline at end of file From 1e7396228f37b304820477463fc2278f83489c00 Mon Sep 17 00:00:00 2001 From: Dario Pranjic Date: Thu, 9 Apr 2026 21:38:50 +0200 Subject: [PATCH 04/43] Refactor Hercules interfaces to use HerculesTranslation for localization --- ts/src/types.ts | 79 +++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/ts/src/types.ts b/ts/src/types.ts index 9ed34a9..7e11f86 100644 --- a/ts/src/types.ts +++ b/ts/src/types.ts @@ -5,13 +5,16 @@ import { DefinitionDataType, DefinitionDataTypeRule, FlowType, FlowTypeSetting_UniquenessScope, FunctionDefinition, - RuntimeFunctionDefinition, - Translation + RuntimeFunctionDefinition } from "@code0-tech/tucana/shared"; import {PlainValue} from "@code0-tech/tucana/helpers"; import {ActionTransferServiceClient, TransferRequest, TransferResponse} from "@code0-tech/tucana/aquila"; import 'reflect-metadata'; +export interface HerculesTranslation { + code: "en-US" | "de-DE" | string, + content: string +} export interface HerculesFunctionContext { projectId: number | bigint, @@ -21,9 +24,9 @@ export interface HerculesFunctionContext { export interface HerculesDataType { identifier: string, - name?: Translation[], - displayMessage?: Translation[], - alias?: Translation[], + name?: HerculesTranslation[], + displayMessage?: HerculesTranslation[], + alias?: HerculesTranslation[], rules?: DefinitionDataTypeRule[], genericKeys?: string[], type: string, @@ -37,8 +40,8 @@ export interface HerculesFlowTypeSetting { unique?: FlowTypeSetting_UniquenessScope, linkedDataTypeIdentifiers?: string[], defaultValue?: PlainValue, - name?: Translation[], - description?: Translation[], + name?: HerculesTranslation[], + description?: HerculesTranslation[], } export interface HerculesFlowType { @@ -47,11 +50,11 @@ export interface HerculesFlowType { signature: string, linkedDataTypes?: string[], editable: boolean, - name?: Translation[], - description?: Translation[], - documentation?: Translation[], - displayMessage?: Translation[], - alias?: Translation[], + name?: HerculesTranslation[], + description?: HerculesTranslation[], + documentation?: HerculesTranslation[], + displayMessage?: HerculesTranslation[], + alias?: HerculesTranslation[], version?: string, displayIcon?: string, } @@ -59,9 +62,9 @@ export interface HerculesFlowType { export interface HerculesRuntimeFunctionDefinitionParameter { runtimeName: string, defaultValue?: PlainValue, - name?: Translation[], - description?: Translation[], - documentation?: Translation[], + name?: HerculesTranslation[], + description?: HerculesTranslation[], + documentation?: HerculesTranslation[], hidden?: boolean, optional?: boolean } @@ -71,12 +74,12 @@ export interface HerculesRuntimeFunctionDefinition { parameters?: HerculesRuntimeFunctionDefinitionParameter[], signature: string, throwsError?: boolean, - name?: Translation[], - description?: Translation[], - documentation?: Translation[], - deprecationMessage?: Translation[], - displayMessage?: Translation[], - alias?: Translation[], + name?: HerculesTranslation[], + description?: HerculesTranslation[], + documentation?: HerculesTranslation[], + deprecationMessage?: HerculesTranslation[], + displayMessage?: HerculesTranslation[], + alias?: HerculesTranslation[], linkedDataTypes?: string[], version?: string, displayIcon?: string, @@ -85,9 +88,9 @@ export interface HerculesRuntimeFunctionDefinition { export interface HerculesFunctionDefinitionParameter { runtimeName: string, defaultValue?: PlainValue, - name?: Translation[], - description?: Translation[], - documentation?: Translation[], + name?: HerculesTranslation[], + description?: HerculesTranslation[], + documentation?: HerculesTranslation[], hidden?: boolean, optional?: boolean, runtimeDefinitionName?: string @@ -99,12 +102,12 @@ export interface HerculesFunctionDefinition { parameters?: HerculesFunctionDefinitionParameter[], signature: string, throwsError?: boolean, - name?: Translation[], - description?: Translation[], - documentation?: Translation[], - deprecationMessage?: Translation[], - displayMessage?: Translation[], - alias?: Translation[], + name?: HerculesTranslation[], + description?: HerculesTranslation[], + documentation?: HerculesTranslation[], + deprecationMessage?: HerculesTranslation[], + displayMessage?: HerculesTranslation[], + alias?: HerculesTranslation[], linkedDataTypes?: string[], version?: string, displayIcon?: string, @@ -120,8 +123,8 @@ export interface HerculesActionProjectConfiguration { } export interface HerculesActionConfigurationDefinition { - name?: Translation[], - description?: Translation[], + name?: HerculesTranslation[], + description?: HerculesTranslation[], type: string, linkedDataTypes?: string[], defaultValue?: PlainValue, @@ -199,18 +202,18 @@ export const FunctionParameter = (parameter: HerculesFunctionDefinitionParameter Reflect.defineMetadata('hercules:function_parameters', parameters, target) } -export const Name = (...translation: Translation[]): ClassDecorator => +export const Name = (...translation: HerculesTranslation[]): ClassDecorator => (target) => Reflect.defineMetadata('hercules:name', translation, target) -export const DisplayMessage = (...translation: Translation[]): ClassDecorator => +export const DisplayMessage = (...translation: HerculesTranslation[]): ClassDecorator => (target) => Reflect.defineMetadata('hercules:display_message', translation, target) -export const Description = (...translation: Translation[]): ClassDecorator => +export const Description = (...translation: HerculesTranslation[]): ClassDecorator => (target) => Reflect.defineMetadata('hercules:description', translation, target) -export const DeprecationMessage = (...translation: Translation[]): ClassDecorator => +export const DeprecationMessage = (...translation: HerculesTranslation[]): ClassDecorator => (target) => Reflect.defineMetadata('hercules:deprecation_message', translation, target) -export const Alias = (...translation: Translation[]): ClassDecorator => +export const Alias = (...translation: HerculesTranslation[]): ClassDecorator => (target) => Reflect.defineMetadata('hercules:alias', translation, target) -export const Documentation = (...translation: Translation[]): ClassDecorator => +export const Documentation = (...translation: HerculesTranslation[]): ClassDecorator => (target) => Reflect.defineMetadata('hercules:documentation', translation, target) export const Signature = (signature: string): ClassDecorator => From 667265f01b11d2e399a4f5c272be06269a9d98b6 Mon Sep 17 00:00:00 2001 From: Dario Pranjic Date: Thu, 9 Apr 2026 22:23:22 +0200 Subject: [PATCH 05/43] Refactor some code to make the structure clearer --- ts/.gitignore | 3 +- ts/src/action_sdk.ts | 539 +----------------- .../registerRuntimeFunctionDefinitionClass.ts | 35 ++ ts/src/sdk/builder/builder.ts | 66 +++ .../registerFunctionDefinitionClass.ts | 78 +++ ts/src/sdk/connection/connection.ts | 92 +++ ts/src/sdk/connection/dataType.ts | 29 + ts/src/sdk/connection/flowTypes.ts | 34 ++ ts/src/sdk/connection/functionDefinition.ts | 37 ++ ts/src/sdk/connection/logon.ts | 32 ++ .../connection/runtimeFunctionDefinition.ts | 45 ++ ts/src/sdk/execution.ts | 195 +++++++ 12 files changed, 657 insertions(+), 528 deletions(-) create mode 100644 ts/src/builder/registerRuntimeFunctionDefinitionClass.ts create mode 100644 ts/src/sdk/builder/builder.ts create mode 100644 ts/src/sdk/builder/registerFunctionDefinitionClass.ts create mode 100644 ts/src/sdk/connection/connection.ts create mode 100644 ts/src/sdk/connection/dataType.ts create mode 100644 ts/src/sdk/connection/flowTypes.ts create mode 100644 ts/src/sdk/connection/functionDefinition.ts create mode 100644 ts/src/sdk/connection/logon.ts create mode 100644 ts/src/sdk/connection/runtimeFunctionDefinition.ts create mode 100644 ts/src/sdk/execution.ts diff --git a/ts/.gitignore b/ts/.gitignore index 3c10377..48269aa 100644 --- a/ts/.gitignore +++ b/ts/.gitignore @@ -1,3 +1,4 @@ node_modules dist -code0-tech-hercules-*.tgz \ No newline at end of file +code0-tech-hercules-*.tgz +.env \ No newline at end of file diff --git a/ts/src/action_sdk.ts b/ts/src/action_sdk.ts index fdf2559..6b2ec4f 100644 --- a/ts/src/action_sdk.ts +++ b/ts/src/action_sdk.ts @@ -1,30 +1,14 @@ import {GrpcTransport} from "@protobuf-ts/grpc-transport"; import {ChannelCredentials} from "@grpc/grpc-js"; -import {RpcOptions} from "@protobuf-ts/runtime-rpc"; -import { - ActionSdk, HerculesActionConfigurationDefinition, - HerculesActionProjectConfiguration, HerculesFunctionContext, SdkState, RuntimeErrorException, - HerculesFunctionDefinition, RuntimeFunctionDefinitionClass, - FunctionDefinitionConstructor, RegisteredRuntimeFunction, HerculesFunctionDefinitionParameter, - HerculesRuntimeFunctionDefinitionParameter, HerculesRuntimeFunctionDefinition, RegisteredFunction -} from "./types.js"; -import { - ActionTransferServiceClient, - DataTypeServiceClient, - DataTypeUpdateRequest, ExecutionRequest, - FlowTypeServiceClient, - FlowTypeUpdateRequest, - FunctionDefinitionServiceClient, - FunctionDefinitionUpdateRequest, RuntimeFunctionDefinitionServiceClient, RuntimeFunctionDefinitionUpdateRequest, - TransferRequest, TransferResponse -} from "@code0-tech/tucana/aquila"; -import { - ActionConfigurations, - FlowTypeSetting, RuntimeParameterDefinition, -} from "@code0-tech/tucana/shared"; +import type {ActionSdk, HerculesActionConfigurationDefinition, SdkState} from "./types.js"; +import {ActionTransferServiceClient, TransferRequest} from "@code0-tech/tucana/aquila"; +import {FlowTypeSetting,} from "@code0-tech/tucana/shared"; import {constructValue, toAllowedValue} from "@code0-tech/tucana/helpers"; -import {logger} from "./logger"; import 'reflect-metadata'; +import {connect as connectHelper} from "./sdk/connection/connection"; +import {registerFunctionDefinitionClass} from "./sdk/builder/registerFunctionDefinitionClass"; +import {registerRuntimeFunctionDefinitionClass} from "./builder/registerRuntimeFunctionDefinitionClass"; + const createSdk = (config: ActionSdk["config"], configDefinitions?: HerculesActionConfigurationDefinition[]): ActionSdk => { const transport = new GrpcTransport( @@ -57,148 +41,9 @@ const createSdk = (config: ActionSdk["config"], configDefinitions?: HerculesActi fullyConnected: false } - const buildRuntimeFunctionDefinition = (klass: RuntimeFunctionDefinitionClass): RegisteredRuntimeFunction => { - const identifier: string = Reflect.getMetadata('hercules:identifier', klass) - const runtimeParameters: HerculesRuntimeFunctionDefinitionParameter[] = Reflect.getMetadata('hercules:runtime_parameters', klass) - const names: HerculesRuntimeFunctionDefinition["name"] = Reflect.getMetadata('hercules:name', klass) || [] - const displayMessage: HerculesRuntimeFunctionDefinition["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass) || [] - const description: HerculesRuntimeFunctionDefinition["description"] = Reflect.getMetadata('hercules:description', klass) || [] - const deprecationMessage: HerculesRuntimeFunctionDefinition["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass) || [] - const alias: HerculesRuntimeFunctionDefinition["alias"] = Reflect.getMetadata('hercules:alias', klass) || [] - const documentation: HerculesRuntimeFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass) || [] - const signature: HerculesRuntimeFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass) - const linkedDataTypeIdentifiers: HerculesRuntimeFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) || [] - const version: HerculesRuntimeFunctionDefinition["version"] = Reflect.getMetadata('hercules:version', klass) || config.version - const displayIcon: HerculesRuntimeFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass) || "" - const throwsError: HerculesRuntimeFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass) || false - const runFunction = new klass().run - - if (!identifier) { - throw new Error(`Runtime function class ${klass.name} is missing an identifier. Please add @Identifier("your_identifier") decorator to the class.`) - } - if (!signature) { - throw new Error(`Runtime function class ${klass.name} is missing a signature. Please add @Signature("(param1: TYPE_1): RETURN_TYPE") decorator to the class.`) - } - - return { - identifier: identifier as string, - definition: { - alias: alias || [], - name: names || [], - description: description || [], - version: version || config.version, - runtimeName: identifier, - deprecationMessage: deprecationMessage || [], - displayIcon: displayIcon || "", - displayMessage: displayMessage || [], - documentation: documentation || [], - linkedDataTypeIdentifiers: linkedDataTypeIdentifiers || [], - runtimeParameterDefinitions: runtimeParameters.map(param => { - return { - ...param, - name: param.name || [], - description: param.description || [], - documentation: param.documentation || [], - hidden: param.hidden || false, - optional: param.optional || false, - defaultValue: param.defaultValue ? constructValue(param.defaultValue) : undefined, - } as RuntimeParameterDefinition - }), - signature: signature, - throwsError: throwsError || false, - definitionSource: "action" - }, - handler: runFunction - } as RegisteredRuntimeFunction - } - return { - registerFunctionDefinitionClass(klass: FunctionDefinitionConstructor): Promise { - const parentClass = Object.getPrototypeOf(klass) - const runtimeFunction = buildRuntimeFunctionDefinition(parentClass); - const runtimeDefinition = runtimeFunction.definition - - const functionParameters: HerculesFunctionDefinitionParameter[] = Reflect.getMetadata('hercules:function_parameters', klass) - const names: HerculesFunctionDefinition["name"] = Reflect.getMetadata('hercules:name', klass) - const displayMessage: HerculesFunctionDefinition["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass) - const description: HerculesFunctionDefinition["description"] = Reflect.getMetadata('hercules:description', klass) - const deprecationMessage: HerculesFunctionDefinition["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass) - const alias: HerculesFunctionDefinition["alias"] = Reflect.getMetadata('hercules:alias', klass) - const documentation: HerculesFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass) - const signature: HerculesFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass) - const linkedDataTypeIdentifiers: HerculesFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) - const version: HerculesFunctionDefinition["version"] = Reflect.getMetadata('hercules:version', klass) - const displayIcon: HerculesFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass) - const throwsError: HerculesFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass) - - runtimeDefinition.runtimeParameterDefinitions.forEach(runtimeDefinition => { - if (functionParameters.find((param: HerculesFunctionDefinitionParameter) => param.runtimeName === runtimeDefinition.runtimeName)) { - return; - } - functionParameters.push({ - ...runtimeDefinition, - runtimeDefinitionName: runtimeDefinition.runtimeName - }) - }) - - state.functions.push({ - identifier: runtimeFunction.identifier, - definition: { - runtimeDefinitionName: runtimeDefinition.runtimeName, - runtimeName: runtimeDefinition.runtimeName || runtimeDefinition.runtimeName, - signature: signature || runtimeDefinition.signature, - throwsError: throwsError || runtimeDefinition.throwsError, - alias: alias || runtimeDefinition.alias, - version: version || runtimeDefinition.version, - description: description || runtimeDefinition.description, - name: names || runtimeDefinition.name, - documentation: documentation || runtimeDefinition.documentation, - deprecationMessage: deprecationMessage || runtimeDefinition.deprecationMessage, - displayMessage: displayMessage || runtimeDefinition.displayMessage, - displayIcon: displayIcon || runtimeDefinition.displayIcon, - definitionSource: "action", - linkedDataTypeIdentifiers: linkedDataTypeIdentifiers || runtimeDefinition.linkedDataTypeIdentifiers, - parameterDefinitions: functionParameters.map(value => { - return { - ...value, - runtimeDefinitionName: value.runtimeDefinitionName || value.runtimeName, - name: value.name || [], - description: value.description || [], - documentation: value.documentation || [], - hidden: value.hidden || false, - optional: value.optional || false, - defaultValue: value.defaultValue ? constructValue(value.defaultValue || null) : undefined, - } - }) - }, - } as RegisteredFunction) - - return Promise.resolve(); - }, registerRuntimeFunctionDefinitionClass(klass: RuntimeFunctionDefinitionClass): Promise { - const omitFunctionDefinition = Reflect.getMetadata('hercules:omit_function_definition', klass) || false - - const runtimeFunction = buildRuntimeFunctionDefinition(klass); - const definition = runtimeFunction.definition - - state.runtimeFunctions.push(runtimeFunction as RegisteredRuntimeFunction) - if (!omitFunctionDefinition) { - state.functions.push({ - identifier: definition.runtimeName, - definition: { - ...definition, - runtimeDefinitionName: definition.runtimeName, - parameterDefinitions: definition.runtimeParameterDefinitions.map(param => { - return { - ...param, - runtimeDefinitionName: param.runtimeName - } - }) - } - } as RegisteredFunction) - } - - return Promise.resolve(); - }, + registerFunctionDefinitionClass: registerFunctionDefinitionClass(config, state), + registerRuntimeFunctionDefinitionClass: registerRuntimeFunctionDefinitionClass(config, state), fullyConnected(): boolean { return state.fullyConnected; }, @@ -207,7 +52,7 @@ const createSdk = (config: ActionSdk["config"], configDefinitions?: HerculesActi state.stream?.responses.onError(handler) }, connect: options => { - return connect(state, config, options); + return connectHelper(state, config, options); }, getProjectActionConfigurations: () => { return state.projectConfigurations.map(value => { @@ -267,7 +112,7 @@ const createSdk = (config: ActionSdk["config"], configDefinitions?: HerculesActi name: flowType.name || [], alias: flowType.alias || [], description: flowType.description || [], - displayIcon: flowType.displayIcon || "", + displayIcon: flowType.displayIcon || "tabler:note", displayMessage: flowType.displayMessage || [], documentation: flowType.documentation || [], definitionSource: "action", @@ -314,367 +159,7 @@ const createSdk = (config: ActionSdk["config"], configDefinitions?: HerculesActi } } -async function connect(state: SdkState, config: ActionSdk["config"], options?: RpcOptions): Promise { - const builtOptions: RpcOptions = { - meta: { - "Authorization": config.authToken, - }, - ...options - } - state.stream = state.client.transfer(builtOptions); - - const dataTypeClient = new DataTypeServiceClient(state.transport) - await dataTypeClient.update(DataTypeUpdateRequest.create({ - dataTypes: [ - ...state.dataTypes - ] - }), builtOptions).then(value => { - if (!value.response.success) { - return Promise.reject(value.response); - } - }).catch(reason => { - logger.error({ - err: reason, - config, - }, "Error while updating data types") - return Promise.reject(reason); - }) - logger.debug("Sent data types request") - - await state.stream.requests.send( - TransferRequest.create({ - data: { - oneofKind: "logon", - logon: { - actionIdentifier: config.actionId, - version: config.version, - actionConfigurations: state.configurationDefinitions - } - } - } - ), - ).catch(reason => { - logger.error({ - err: reason, - config, - }, "Failed to send logon request") - return Promise.reject(reason); - }) - - logger.debug("Successfully sent logon request") - - const request = RuntimeFunctionDefinitionUpdateRequest.create( - { - runtimeFunctions: [ - ...state.runtimeFunctions.map(func => ({ - ...func.definition, - })) - ] - } - ); - try { - const runtimeFunctionDefinitionClient = new RuntimeFunctionDefinitionServiceClient(state.transport) - await runtimeFunctionDefinitionClient.update( - request, builtOptions - ).then(value => { - if (!value.response.success) { - logger.error({ - err: value.response, - request: value.request, - config, - }) - return Promise.reject(value.response); - } - }) - } catch (error) { - logger.debug({ - ...request.runtimeFunctions[0].runtimeParameterDefinitions[0].defaultValue - }) - logger.error({ - err: error, - request: request, - config, - }, "Error while updating runtime function definitions") - return Promise.reject(error); - } - logger.debug("Successfully updated runtime function definitions") - - const FunctionDefinitionClient = new FunctionDefinitionServiceClient(state.transport) - try { - const finishedCall = await FunctionDefinitionClient.update( - FunctionDefinitionUpdateRequest.create( - { - functions: [ - ...state.functions.map(func => ({ - ...func.definition, - })) - ] - } - ), builtOptions - ); - - if (!finishedCall.response.success) { - logger.error({ - err: finishedCall.response, - request: finishedCall.request, - config, - }, "Error while updating function definitions") - return Promise.reject(finishedCall.response); - } - } catch (error) { - logger.error({ - err: error, - config, - }, "Error while updating function definitions") - return Promise.reject(error); - } - logger.debug("Updated function definitions") - - const flowTypeClient = new FlowTypeServiceClient(state.transport) - await flowTypeClient.update(FlowTypeUpdateRequest.create({ - flowTypes: [ - ...state.flowTypes - ] - }), builtOptions).then(value => { - if (!value.response.success) { - logger.error({ - err: value.response, - request: value.request, - config, - }) - return Promise.reject(value.response); - } - }) - logger.info("Connected successfully to aquila") - - - return new Promise(async (resolve, reject) => { - try { - for await (let message of state?.stream?.responses || []) { - logger.debug({ - message: message, - config, - }, "Received message from stream") - switch (message?.data.oneofKind) { - case "actionConfigurations": { - logger.info("Received action configurations") - - const configs = message.data.actionConfigurations as ActionConfigurations; - state.projectConfigurations = configs.actionConfigurations - resolve(state.projectConfigurations.map(value => { - return { - projectId: value.projectId, - configValues: value.actionConfigurations.map(value => { - return { - identifier: value.identifier, - value: toAllowedValue(value.value || constructValue(null)), - } - }), - findConfig: identifier => { - const config = value.actionConfigurations.find(config => config.identifier === identifier); - return config ? toAllowedValue(config.value || constructValue(null)) : undefined; - } - } - })); - state.fullyConnected = true - break; - } - case "execution": { - logger.info({ - executionD: message.data.execution.executionIdentifier, - config, - }, "Handling execution request") - - logger.debug({ - message: message, - config, - }, "Handling execution request") - handleExecutionRequest(state, message) - break; - } - } - } - } catch (reason) { - logger.error({ - err: reason, - config - }, "Error occurred in stream") - reject(reason); - } - }) -} - -function handleExecutionRequest(state: SdkState, message: TransferResponse) { - if (!message.data || message.data.oneofKind !== "execution") { - return - } - const execution = message.data.execution as ExecutionRequest; - const func = state.runtimeFunctions.find(value => value.identifier == execution.functionIdentifier); - - if (!func) { - logger.warn({ - message - }, "Received execution request but no matching function found") - return; - } - - const params = Object.entries(execution.parameters!.fields!).map(([key, value]) => { - const param = func.definition.runtimeParameterDefinitions - .find(p => p.runtimeName === key); - - const parameterValue = param ? toAllowedValue(value) : undefined; - if (!parameterValue) return parameterValue - return parameterValue; - }); - - logger.debug({ - message, - BuiltParameter: params - }) - - let conf = state.projectConfigurations.find(config => { - //TODO - return true - }) - - if (!conf) { - logger.error({ - message, - execution - }, "No configuration found") - conf = { - projectId: 0n, - actionConfigurations: [] - } - } - logger.debug({ - message, - conf - }) - - const context: HerculesFunctionContext = { - projectId: execution.projectId, - executionId: execution.executionIdentifier, - matchedConfig: { - projectId: conf.projectId, - configValues: conf.actionConfigurations.map(value => { - return { - identifier: value.identifier, - value: toAllowedValue(value.value || constructValue(null)), - } - }), - findConfig: identifier => { - const config = conf.actionConfigurations.find(config => config.identifier === identifier); - return config ? toAllowedValue(config.value || constructValue(null)) : undefined; - } - } - } - - if (func.handler.length == params.length + 1) { - // handler has context parameter - params.unshift(context) - } else if (func.handler.length > params.length + 1) { - logger.error({ - params, - func, - }, "Handler has more parameters than provided arguments") - return; - } - - const result = new Promise((resolve, reject) => { - try { - resolve(func.handler(...params)) - } catch (e) { - reject(e) - } - }) - result.then((value: any) => { - const request = TransferRequest.create({ - data: { - oneofKind: "result", - result: { - executionIdentifier: execution.executionIdentifier, - result: { - oneofKind: "success", - success: constructValue(value) - }, - } - } - }); - logger.debug({ - request: request - }, "Responding with execution result") - - state.stream!.requests.send(request).catch(reason => { - logger.error({ - err: reason, - request: request, - message, - execution - }, "Responding with execution result lead to error") - }); - }).catch(reason => { - logger.warn({ - err: reason - }, "Executed function lead to error") - let request - if (reason instanceof RuntimeErrorException) { - request = TransferRequest.create({ - data: { - oneofKind: "result", - result: { - executionIdentifier: execution.executionIdentifier, - result: { - oneofKind: "error", - error: { - code: reason.code, - description: reason.description - } - }, - } - } - }); - } else { - request = TransferRequest.create({ - data: { - oneofKind: "result", - result: { - executionIdentifier: execution.executionIdentifier, - result: { - oneofKind: "error", - error: { - code: "UNKNOWN_ERROR", - description: reason.toString() - } - }, - } - } - }); - logger.warn({ - err: reason, - func, - execution - }, "Error occured while executing function, but not an RuntimeErrorException") - } - - logger.debug({ - request: request - }, "Responding with execution error") - - state.stream!.requests.send( - request - ).catch(reason => { - logger.error({ - err: reason, - request: request, - execution, - message - }, "Failed to send execution result error") - }); - }) -} - export { createSdk, - connect + connectHelper as connect } \ No newline at end of file diff --git a/ts/src/builder/registerRuntimeFunctionDefinitionClass.ts b/ts/src/builder/registerRuntimeFunctionDefinitionClass.ts new file mode 100644 index 0000000..50951a1 --- /dev/null +++ b/ts/src/builder/registerRuntimeFunctionDefinitionClass.ts @@ -0,0 +1,35 @@ +import type {RegisteredFunction, RegisteredRuntimeFunction, RuntimeFunctionDefinitionClass, SdkState} from "../types"; +import {buildRuntimeFunctionDefinition} from "../sdk/builder/builder"; + +export function registerRuntimeFunctionDefinitionClass(config: { + authToken: string; + aquilaUrl: string; + actionId: string; + version: string +}, state: SdkState) { + return (klass: RuntimeFunctionDefinitionClass): Promise => { + const omitFunctionDefinition = Reflect.getMetadata('hercules:omit_function_definition', klass) || false + + const runtimeFunction = buildRuntimeFunctionDefinition(klass, config); + const definition = runtimeFunction.definition + + state.runtimeFunctions.push(runtimeFunction as RegisteredRuntimeFunction) + if (!omitFunctionDefinition) { + state.functions.push({ + identifier: definition.runtimeName, + definition: { + ...definition, + runtimeDefinitionName: definition.runtimeName, + parameterDefinitions: definition.runtimeParameterDefinitions.map(param => { + return { + ...param, + runtimeDefinitionName: param.runtimeName + } + }) + } + } as RegisteredFunction) + } + + return Promise.resolve(); + }; +} \ No newline at end of file diff --git a/ts/src/sdk/builder/builder.ts b/ts/src/sdk/builder/builder.ts new file mode 100644 index 0000000..5b68e79 --- /dev/null +++ b/ts/src/sdk/builder/builder.ts @@ -0,0 +1,66 @@ +import 'reflect-metadata'; +import {constructValue} from "@code0-tech/tucana/helpers"; +import { + RuntimeFunctionDefinitionClass, + RegisteredRuntimeFunction, + HerculesRuntimeFunctionDefinitionParameter, + HerculesRuntimeFunctionDefinition, + ActionSdk, +} from "../../types"; +import {RuntimeParameterDefinition} from "@code0-tech/tucana/shared"; + +export function buildRuntimeFunctionDefinition(klass: RuntimeFunctionDefinitionClass, config: ActionSdk["config"]): RegisteredRuntimeFunction { + const identifier: string = Reflect.getMetadata('hercules:identifier', klass) + const runtimeParameters: HerculesRuntimeFunctionDefinitionParameter[] = Reflect.getMetadata('hercules:runtime_parameters', klass) + const names: HerculesRuntimeFunctionDefinition["name"] = Reflect.getMetadata('hercules:name', klass) || [] + const displayMessage: HerculesRuntimeFunctionDefinition["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass) || [] + const description: HerculesRuntimeFunctionDefinition["description"] = Reflect.getMetadata('hercules:description', klass) || [] + const deprecationMessage: HerculesRuntimeFunctionDefinition["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass) || [] + const alias: HerculesRuntimeFunctionDefinition["alias"] = Reflect.getMetadata('hercules:alias', klass) || [] + const documentation: HerculesRuntimeFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass) || [] + const signature: HerculesRuntimeFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass) + const linkedDataTypeIdentifiers: HerculesRuntimeFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) || [] + const version: HerculesRuntimeFunctionDefinition["version"] = Reflect.getMetadata('hercules:version', klass) || config.version + const displayIcon: HerculesRuntimeFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass) || "" + const throwsError: HerculesRuntimeFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass) || false + const runFunction = new klass().run + + if (!identifier) { + throw new Error(`Runtime function class ${klass.name} is missing an identifier. Please add @Identifier("your_identifier") decorator to the class.`) + } + if (!signature) { + throw new Error(`Runtime function class ${klass.name} is missing a signature. Please add @Signature("(param1: TYPE_1): RETURN_TYPE") decorator to the class.`) + } + + return { + identifier: identifier as string, + definition: { + alias: alias || [], + name: names || [], + description: description || [], + version: version || config.version, + runtimeName: identifier, + deprecationMessage: deprecationMessage || [], + displayIcon: displayIcon || "tabler:note", + displayMessage: displayMessage || [], + documentation: documentation || [], + linkedDataTypeIdentifiers: linkedDataTypeIdentifiers || [], + runtimeParameterDefinitions: runtimeParameters.map(param => { + return { + ...param, + name: param.name || [], + description: param.description || [], + documentation: param.documentation || [], + hidden: param.hidden || false, + optional: param.optional || false, + defaultValue: param.defaultValue ? constructValue(param.defaultValue) : undefined, + } as RuntimeParameterDefinition + }), + signature: signature, + throwsError: throwsError || false, + definitionSource: "action" + }, + handler: runFunction + } as RegisteredRuntimeFunction +} + diff --git a/ts/src/sdk/builder/registerFunctionDefinitionClass.ts b/ts/src/sdk/builder/registerFunctionDefinitionClass.ts new file mode 100644 index 0000000..1383c15 --- /dev/null +++ b/ts/src/sdk/builder/registerFunctionDefinitionClass.ts @@ -0,0 +1,78 @@ +import type { + FunctionDefinitionConstructor, + HerculesFunctionDefinition, + HerculesFunctionDefinitionParameter, RegisteredFunction, + SdkState +} from "../../types"; +import {buildRuntimeFunctionDefinition} from "./builder"; +import {constructValue} from "@code0-tech/tucana/helpers"; + +export function registerFunctionDefinitionClass(config: { + authToken: string; + aquilaUrl: string; + actionId: string; + version: string +}, state: SdkState) { + return (klass: FunctionDefinitionConstructor): Promise => { + const parentClass = Object.getPrototypeOf(klass) + const runtimeFunction = buildRuntimeFunctionDefinition(parentClass, config); + const runtimeDefinition = runtimeFunction.definition + + const functionParameters: HerculesFunctionDefinitionParameter[] = Reflect.getMetadata('hercules:function_parameters', klass) + const names: HerculesFunctionDefinition["name"] = Reflect.getMetadata('hercules:name', klass) + const displayMessage: HerculesFunctionDefinition["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass) + const description: HerculesFunctionDefinition["description"] = Reflect.getMetadata('hercules:description', klass) + const deprecationMessage: HerculesFunctionDefinition["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass) + const alias: HerculesFunctionDefinition["alias"] = Reflect.getMetadata('hercules:alias', klass) + const documentation: HerculesFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass) + const signature: HerculesFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass) + const linkedDataTypeIdentifiers: HerculesFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) + const version: HerculesFunctionDefinition["version"] = Reflect.getMetadata('hercules:version', klass) + const displayIcon: HerculesFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass) + const throwsError: HerculesFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass) + + runtimeDefinition.runtimeParameterDefinitions.forEach(runtimeDefinition => { + if (functionParameters.find((param: HerculesFunctionDefinitionParameter) => param.runtimeName === runtimeDefinition.runtimeName)) { + return; + } + functionParameters.push({ + ...runtimeDefinition, + runtimeDefinitionName: runtimeDefinition.runtimeName + }) + }) + + state.functions.push({ + identifier: runtimeFunction.identifier, + definition: { + runtimeDefinitionName: runtimeDefinition.runtimeName, + runtimeName: runtimeDefinition.runtimeName || runtimeDefinition.runtimeName, + signature: signature || runtimeDefinition.signature, + throwsError: throwsError || runtimeDefinition.throwsError, + alias: alias || runtimeDefinition.alias, + version: version || runtimeDefinition.version, + description: description || runtimeDefinition.description, + name: names || runtimeDefinition.name, + documentation: documentation || runtimeDefinition.documentation, + deprecationMessage: deprecationMessage || runtimeDefinition.deprecationMessage, + displayMessage: displayMessage || runtimeDefinition.displayMessage, + displayIcon: displayIcon || runtimeDefinition.displayIcon, + definitionSource: "action", + linkedDataTypeIdentifiers: linkedDataTypeIdentifiers || runtimeDefinition.linkedDataTypeIdentifiers, + parameterDefinitions: functionParameters.map(value => { + return { + ...value, + runtimeDefinitionName: value.runtimeDefinitionName || value.runtimeName, + name: value.name || [], + description: value.description || [], + documentation: value.documentation || [], + hidden: value.hidden || false, + optional: value.optional || false, + defaultValue: value.defaultValue ? constructValue(value.defaultValue || null) : undefined, + } + }) + }, + } as RegisteredFunction) + + return Promise.resolve(); + }; +} diff --git a/ts/src/sdk/connection/connection.ts b/ts/src/sdk/connection/connection.ts new file mode 100644 index 0000000..05963bc --- /dev/null +++ b/ts/src/sdk/connection/connection.ts @@ -0,0 +1,92 @@ +import type {RpcOptions} from "@protobuf-ts/runtime-rpc"; +import {logger} from "../../logger"; +import {constructValue, toAllowedValue} from "@code0-tech/tucana/helpers"; +import type { + ActionSdk, + SdkState, + HerculesActionProjectConfiguration +} from "../../types"; +import {handleExecutionRequest} from "../execution"; +import {handleLogon} from "./logon"; +import {handleRuntimeFunctionDefinitions} from "./runtimeFunctionDefinition"; +import {handleDataTypes} from "./dataType"; +import {handleFunctionDefinitions} from "./functionDefinition"; +import {handleFlowTypes} from "./flowTypes"; + + +export async function connect(state: SdkState, config: ActionSdk["config"], options?: RpcOptions): Promise { + logger.debug("Trying to connect to aquila") + const builtOptions: RpcOptions = { + meta: { + "Authorization": config.authToken, + }, + ...options + } + state.stream = state.client.transfer(builtOptions); + + await handleDataTypes(state, builtOptions, config); + await handleLogon(state, config); + await handleRuntimeFunctionDefinitions(state, builtOptions, config) + await handleFunctionDefinitions(state, builtOptions, config) + await handleFlowTypes(state, builtOptions, config) + + logger.info("Connected successfully to aquila") + + + return new Promise(async (resolve, reject) => { + try { + for await (let message of state?.stream?.responses || []) { + logger.debug({ + message: message, + config, + }, "Received message from stream") + switch (message?.data.oneofKind) { + case "actionConfigurations": { + logger.info("Received action configurations") + + const configs = message.data.actionConfigurations as any; + state.projectConfigurations = configs.actionConfigurations + resolve(state.projectConfigurations.map(value => { + return { + projectId: value.projectId, + configValues: value.actionConfigurations.map(value => { + return { + identifier: value.identifier, + value: toAllowedValue(value.value || constructValue(null)), + } + }), + findConfig: identifier => { + const config = value.actionConfigurations.find(config => config.identifier === identifier); + return config ? toAllowedValue(config.value || constructValue(null)) : undefined; + } + } + })); + state.fullyConnected = true + break; + } + + case "execution": { + logger.info({ + executionD: message.data.execution.executionIdentifier, + config, + }, "Handling execution request") + + logger.debug({ + message: message, + config, + }, "Handling execution request") + handleExecutionRequest(state, message) + break; + } + } + } + } catch (reason) { + logger.error({ + err: reason, + config + }, "Error occurred in stream") + reject(reason); + } + }) +} + diff --git a/ts/src/sdk/connection/dataType.ts b/ts/src/sdk/connection/dataType.ts new file mode 100644 index 0000000..bcb241a --- /dev/null +++ b/ts/src/sdk/connection/dataType.ts @@ -0,0 +1,29 @@ +import {DataTypeServiceClient, DataTypeUpdateRequest} from "@code0-tech/tucana/aquila"; +import {logger} from "../../logger"; +import {SdkState} from "../../types"; +import {RpcOptions} from "@protobuf-ts/runtime-rpc"; + +export async function handleDataTypes(state: SdkState, builtOptions: RpcOptions, config: { + authToken: string; + aquilaUrl: string; + actionId: string; + version: string +}) { + const dataTypeClient = new DataTypeServiceClient(state.transport) + await dataTypeClient.update(DataTypeUpdateRequest.create({ + dataTypes: [ + ...state.dataTypes + ] + }), builtOptions).then(value => { + if (!value.response.success) { + return Promise.reject(value.response); + } + }).catch(reason => { + logger.error({ + err: reason, + config, + }, "Error while updating data types") + return Promise.reject(reason); + }) + logger.debug("Sent data types request") +} diff --git a/ts/src/sdk/connection/flowTypes.ts b/ts/src/sdk/connection/flowTypes.ts new file mode 100644 index 0000000..3a2cdba --- /dev/null +++ b/ts/src/sdk/connection/flowTypes.ts @@ -0,0 +1,34 @@ +import {ActionSdk, SdkState} from "../../types"; +import {FlowTypeServiceClient, FlowTypeUpdateRequest} from "@code0-tech/tucana/aquila"; +import {RpcOptions} from "@protobuf-ts/runtime-rpc"; +import {logger} from "../../logger"; + +export async function handleFlowTypes(state: SdkState, builtOptions: RpcOptions | undefined, config: ActionSdk["config"]) { + const flowTypeClient = new FlowTypeServiceClient(state.transport) + const request = { + flowTypes: [ + ...state.flowTypes + ] + }; + try { + + await flowTypeClient.update(FlowTypeUpdateRequest.create(request), builtOptions).then(value => { + if (!value.response.success) { + logger.error({ + err: value.response, + request: value.request, + config, + }) + return Promise.reject(value.response); + } + }) + + } catch (error) { + logger.error({ + err: error, + request, + config, + }, "Error while updating flow types") + return Promise.reject(error); + } +} diff --git a/ts/src/sdk/connection/functionDefinition.ts b/ts/src/sdk/connection/functionDefinition.ts new file mode 100644 index 0000000..01065fe --- /dev/null +++ b/ts/src/sdk/connection/functionDefinition.ts @@ -0,0 +1,37 @@ +import type {ActionSdk, SdkState} from "../../types"; +import type {RpcOptions} from "@protobuf-ts/runtime-rpc"; +import {FunctionDefinitionServiceClient, FunctionDefinitionUpdateRequest} from "@code0-tech/tucana/aquila"; +import {logger} from "../../logger"; + +export async function handleFunctionDefinitions(state: SdkState, builtOptions: RpcOptions | undefined, config: ActionSdk["config"]) { + const FunctionDefinitionClient = new FunctionDefinitionServiceClient(state.transport) + try { + const finishedCall = await FunctionDefinitionClient.update( + FunctionDefinitionUpdateRequest.create( + { + functions: [ + ...state.functions.map(func => ({ + ...func.definition, + })) + ] + } + ), builtOptions + ); + + if (!finishedCall.response.success) { + logger.error({ + err: finishedCall.response, + request: finishedCall.request, + config, + }, "Error while updating function definitions") + return Promise.reject(finishedCall.response); + } + } catch (error) { + logger.error({ + err: error, + config, + }, "Error while updating function definitions") + return Promise.reject(error); + } + logger.debug("Updated function definitions") +} diff --git a/ts/src/sdk/connection/logon.ts b/ts/src/sdk/connection/logon.ts new file mode 100644 index 0000000..a5c576a --- /dev/null +++ b/ts/src/sdk/connection/logon.ts @@ -0,0 +1,32 @@ +import type {SdkState} from "../../types"; +import {TransferRequest} from "@code0-tech/tucana/aquila"; +import {logger} from "../../logger"; + +export async function handleLogon(state: SdkState, config: { + authToken: string; + aquilaUrl: string; + actionId: string; + version: string +}) { + await state.stream!.requests.send( + TransferRequest.create({ + data: { + oneofKind: "logon", + logon: { + actionIdentifier: config.actionId, + version: config.version, + actionConfigurations: state.configurationDefinitions + } + } + } + ), + ).catch(reason => { + logger.error({ + err: reason, + config, + }, "Failed to send logon request") + return Promise.reject(reason); + }) + + logger.debug("Successfully sent logon request") +} diff --git a/ts/src/sdk/connection/runtimeFunctionDefinition.ts b/ts/src/sdk/connection/runtimeFunctionDefinition.ts new file mode 100644 index 0000000..5f5354b --- /dev/null +++ b/ts/src/sdk/connection/runtimeFunctionDefinition.ts @@ -0,0 +1,45 @@ +import type {ActionSdk, SdkState} from "../../types"; +import type {RpcOptions} from "@protobuf-ts/runtime-rpc"; +import { + RuntimeFunctionDefinitionServiceClient, + RuntimeFunctionDefinitionUpdateRequest +} from "@code0-tech/tucana/aquila"; +import {logger} from "../../logger"; + +export async function handleRuntimeFunctionDefinitions(state: SdkState, builtOptions: RpcOptions | undefined, config: ActionSdk["config"]) { + const request = RuntimeFunctionDefinitionUpdateRequest.create( + { + runtimeFunctions: [ + ...state.runtimeFunctions.map(func => ({ + ...func.definition, + })) + ] + } + ); + try { + const runtimeFunctionDefinitionClient = new RuntimeFunctionDefinitionServiceClient(state.transport) + await runtimeFunctionDefinitionClient.update( + request, builtOptions + ).then(value => { + if (!value.response.success) { + logger.error({ + err: value.response, + request: value.request, + config, + }) + return Promise.reject(value.response); + } + }) + } catch (error) { + logger.debug({ + ...request.runtimeFunctions[0].runtimeParameterDefinitions[0].defaultValue + }) + logger.error({ + err: error, + request: request, + config, + }, "Error while updating runtime function definitions") + return Promise.reject(error); + } + logger.debug("Successfully updated runtime function definitions") +} diff --git a/ts/src/sdk/execution.ts b/ts/src/sdk/execution.ts new file mode 100644 index 0000000..c371829 --- /dev/null +++ b/ts/src/sdk/execution.ts @@ -0,0 +1,195 @@ +import {logger} from "../logger"; +import {constructValue, PlainValue, toAllowedValue} from "@code0-tech/tucana/helpers"; +import { + SdkState, + HerculesFunctionContext, + RuntimeErrorException, RegisteredRuntimeFunction +} from "../types.js"; +import {TransferRequest, ExecutionRequest, TransferResponse} from "@code0-tech/tucana/aquila"; +import {ActionProjectConfiguration} from "@code0-tech/tucana/shared"; + +function buildParams(execution: ExecutionRequest, func: RegisteredRuntimeFunction, message: TransferResponse) { + const params = Object.entries(execution.parameters!.fields!).map(([key, value]) => { + const param = func.definition.runtimeParameterDefinitions + .find(p => p.runtimeName === key); + + const parameterValue = param ? toAllowedValue(value) : undefined; + if (!parameterValue) return parameterValue + return parameterValue; + }); + + logger.debug({ + message, + BuiltParameter: params + }) + return params +} + +function buildContext(message: TransferResponse, execution: ExecutionRequest, state: SdkState): { + func: RegisteredRuntimeFunction, + context: HerculesFunctionContext, + conf: ActionProjectConfiguration, + params: (PlainValue | undefined)[] +} { + const func = state.runtimeFunctions.find(value => value.identifier == execution.functionIdentifier); + + if (!func) { + logger.error({ + message, + state + }, "Received execution request but no matching function found") + throw new Error("Received execution request for function " + execution.functionIdentifier + " but no matching function found") + } + + const params = buildParams(execution, func, message); + + let conf = state.projectConfigurations.find(config => { + //TODO + return true + }) + + if (!conf) { + logger.error({ + message, + execution + }, "No configuration found") + conf = { + projectId: 0n, + actionConfigurations: [] + } + } + const context: HerculesFunctionContext = { + projectId: execution.projectId, + executionId: execution.executionIdentifier, + matchedConfig: { + projectId: conf.projectId, + configValues: conf.actionConfigurations.map(value => { + return { + identifier: value.identifier, + value: toAllowedValue(value.value || constructValue(null)), + } + }), + findConfig: identifier => { + const config = conf.actionConfigurations.find(config => config.identifier === identifier); + return config ? toAllowedValue(config.value || constructValue(null)) : undefined; + } + } + } + return { + func, + context, + conf, + params + }; +} + +export function handleExecutionRequest(state: SdkState, message: TransferResponse) { + if (!message.data || message.data.oneofKind !== "execution") { + return + } + const execution = message.data.execution as ExecutionRequest; + + + const {func, context, conf, params} = buildContext(message, execution, state); + logger.debug({ + message, + conf, + context + }) + + const funcHandler = (func as any).handler + + if (funcHandler.length == params.length + 1) { + // handler has context parameter + params.unshift(context) + } else if (funcHandler.length > params.length + 1) { + logger.error({ + params, + func, + }, "Handler has more parameters than provided arguments") + return; + } + + const result = new Promise((resolve, reject) => { + try { + resolve(funcHandler(...params)) + } catch (e) { + reject(e) + } + }) + result.then((value: any) => { + const request = TransferRequest.create({ + data: { + oneofKind: "result", + result: { + executionIdentifier: execution.executionIdentifier, + result: { + oneofKind: "success", + success: constructValue(value) + }, + } + } + }); + logger.debug({ + request: request + }, "Responding with execution result") + + state.stream!.requests.send(request).catch(reason => { + logger.error({ + err: reason, + request: request, + message, + execution + }, "Responding with execution result lead to error") + }); + + }).catch(reason => { + logger.warn({ + err: reason + }, "Executed function lead to error") + let errorData + if (reason instanceof RuntimeErrorException) { + errorData = { + code: reason.code, + description: reason.description + } + } else { + errorData = { + code: "UNKNOWN_ERROR", + description: reason.toString() + } + + logger.warn({ + err: reason, + func, + execution + }, "Error occured while executing function, but not an RuntimeErrorException") + } + + + logger.debug({errorData}, "Responding with execution error") + + const request = TransferRequest.create({ + data: { + oneofKind: "result", + result: { + executionIdentifier: execution.executionIdentifier, + result: { + oneofKind: "error", + error: errorData + }, + } + } + }); + + state.stream!.requests.send(request).catch(reason => { + logger.error({ + err: reason, + request: request, + execution, + message + }, "Failed to send execution result error") + }); + }) +} + From 8719635db1578dfb1c3ac29bb2092b4bc73fa6e3 Mon Sep 17 00:00:00 2001 From: Dario Pranjic Date: Sat, 11 Apr 2026 17:33:33 +0200 Subject: [PATCH 06/43] Apply some ideas of code review --- ts/examples/simple-example-ts/example.env | 4 + ts/examples/simple-example-ts/index.ts | 79 ------------------- .../simple-example-ts/package-lock.json | 2 +- .../simple-example-ts/src/exampleDataType.ts | 6 ++ .../simple-example-ts/src/exampleEventType.ts | 7 ++ .../src/fibonacciFunction.ts | 23 ++++++ ts/examples/simple-example-ts/src/index.ts | 44 +++++++++++ ts/examples/simple-example-ts/tsconfig.json | 2 +- ts/examples/simple-example-ts/vite.config.ts | 2 +- ts/src/action_sdk.ts | 14 ++-- ts/src/sdk/builder/builder.ts | 3 +- .../registerFunctionDefinitionClass.ts | 3 +- ts/src/sdk/connection/connection.ts | 2 +- ts/src/sdk/execution.ts | 14 +--- ts/src/types.ts | 18 ++--- 15 files changed, 105 insertions(+), 118 deletions(-) create mode 100644 ts/examples/simple-example-ts/example.env delete mode 100644 ts/examples/simple-example-ts/index.ts create mode 100644 ts/examples/simple-example-ts/src/exampleDataType.ts create mode 100644 ts/examples/simple-example-ts/src/exampleEventType.ts create mode 100644 ts/examples/simple-example-ts/src/fibonacciFunction.ts create mode 100644 ts/examples/simple-example-ts/src/index.ts diff --git a/ts/examples/simple-example-ts/example.env b/ts/examples/simple-example-ts/example.env new file mode 100644 index 0000000..8f27264 --- /dev/null +++ b/ts/examples/simple-example-ts/example.env @@ -0,0 +1,4 @@ +AUTH_TOKEN=your_auth_token_here +AQUILA_URL=https://127.0.0.1:8000 +ACTION_ID=your_action_id_here +VERSION=0.0.0 \ No newline at end of file diff --git a/ts/examples/simple-example-ts/index.ts b/ts/examples/simple-example-ts/index.ts deleted file mode 100644 index 824d3c3..0000000 --- a/ts/examples/simple-example-ts/index.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { - createSdk, - HerculesActionProjectConfiguration, - HerculesFunctionContext, Identifier, LinkedDataTypeIdentifiers, - RuntimeErrorException, RuntimeParameter, Signature -} from "@code0-tech/hercules"; - -const sdk = createSdk({ - authToken: "token", - aquilaUrl: "127.0.0.1:8081", - actionId: "example", - version: "0.0.0", -}, [ - { - type: "string[]", - identifier: "config_discord_bot_token", - } -]) - -sdk.registerDataTypes({ - identifier: "SOME_DATATYPE", - type: "any", -}) - -@Identifier("fib") -@Signature("(number: number): number") -@RuntimeParameter({ - runtimeName: "number", - defaultValue: 20 -}) -class FibonacciFunction { - run(context: HerculesFunctionContext, number: number): number { - console.log(context) - console.log("Project id:", context.projectId); - console.log("Execution id:", context.executionId); - console.log("Matched configs:", context.matchedConfig); // matched configs for the current execution - - function fibonacci(num: number): number { - if (num <= 1) return num; - return fibonacci(num - 1) + fibonacci(num - 2); - } - - return fibonacci(number) - } -} - -sdk.registerRuntimeFunctionDefinitionClass(FibonacciFunction) - -sdk.registerFlowTypes( - { - signature: "(): string", - editable: false, - identifier: "test_flow", - } -) - - -connectToSdk(); - -function connectToSdk() { - sdk.connect().then((configs: HerculesActionProjectConfiguration[]) => { - console.log("SDK connected successfully"); - - sdk.dispatchEvent("test_flow", configs[0].projectId, "Hello, World! Configs loaded: " + configs.length).then(() => { - console.log("Event dispatched successfully"); - }) - }).catch(() => { - // will be handled by logger internally - process.exit(1) - }) - - sdk.onError((error) => { - console.error("SDK Error occurred:", error.message); - console.log("Attempting to reconnect in 5s..."); - setTimeout(() => { - connectToSdk(); - }, 5000) - }) -} diff --git a/ts/examples/simple-example-ts/package-lock.json b/ts/examples/simple-example-ts/package-lock.json index 52fa24c..ca17b67 100644 --- a/ts/examples/simple-example-ts/package-lock.json +++ b/ts/examples/simple-example-ts/package-lock.json @@ -15,7 +15,7 @@ "node_modules/@code0-tech/hercules": { "version": "0.0.0", "resolved": "file:../../code0-tech-hercules-0.0.0.tgz", - "integrity": "sha512-KgSdzgsOzIyHCMebtf0B/HUgSJNgYe7yuj8tpuqdJIP1UzhVU/2Tptwv6z9RZK/iv+EG4yq0gntZWXnHwZAS0w==", + "integrity": "sha512-WNWRc5+auZ15MBHcilAA+HPpASKW0CaTTe1QAYCUlcC1a+t9a8/yBEWQr4Ol8FA72yrR3+1/5r4C0YPm5cDVcQ==", "license": "ISC", "dependencies": { "@code0-tech/tucana": "0.0.68", diff --git a/ts/examples/simple-example-ts/src/exampleDataType.ts b/ts/examples/simple-example-ts/src/exampleDataType.ts new file mode 100644 index 0000000..c9ad177 --- /dev/null +++ b/ts/examples/simple-example-ts/src/exampleDataType.ts @@ -0,0 +1,6 @@ +import {HerculesDataType} from "@code0-tech/hercules"; + +export const someDataType: HerculesDataType = { + identifier: "SOME_DATATYPE", + type: "any", +} \ No newline at end of file diff --git a/ts/examples/simple-example-ts/src/exampleEventType.ts b/ts/examples/simple-example-ts/src/exampleEventType.ts new file mode 100644 index 0000000..9069207 --- /dev/null +++ b/ts/examples/simple-example-ts/src/exampleEventType.ts @@ -0,0 +1,7 @@ +import {HerculesEventType} from "@code0-tech/hercules" + +export const someEventType: HerculesEventType = { + signature: "(): string", + editable: false, + identifier: "test_flow", +} diff --git a/ts/examples/simple-example-ts/src/fibonacciFunction.ts b/ts/examples/simple-example-ts/src/fibonacciFunction.ts new file mode 100644 index 0000000..34a7a69 --- /dev/null +++ b/ts/examples/simple-example-ts/src/fibonacciFunction.ts @@ -0,0 +1,23 @@ +import {HerculesFunctionContext, Identifier, RuntimeParameter, Signature} from "@code0-tech/hercules"; + +@Identifier("fib") +@Signature("(number: number): number") +@RuntimeParameter({ + runtimeName: "number", + defaultValue: 20 +}) +export class FibonacciFunction { + run(context: HerculesFunctionContext, number: number): number { + console.log(context) + console.log("Project id:", context.projectId); + console.log("Execution id:", context.executionId); + console.log("Matched configs:", context.matchedConfig); // matched configs for the current execution + + function fibonacci(num: number): number { + if (num <= 1) return num; + return fibonacci(num - 1) + fibonacci(num - 2); + } + + return fibonacci(number) + } +} \ No newline at end of file diff --git a/ts/examples/simple-example-ts/src/index.ts b/ts/examples/simple-example-ts/src/index.ts new file mode 100644 index 0000000..5d5ce03 --- /dev/null +++ b/ts/examples/simple-example-ts/src/index.ts @@ -0,0 +1,44 @@ +import {createSdk, HerculesActionProjectConfiguration} from "@code0-tech/hercules"; +import {FibonacciFunction} from "./fibonacciFunction"; +import {someEventType} from "./exampleEventType"; +import {someDataType} from "./exampleDataType"; + +const sdk = createSdk({ + authToken: process.env.AUTH_TOKEN || "token", + aquilaUrl: process.env.AQUILA_URL || "127.0.0.1:8081", + actionId: process.env.ACTION_ID || "example", + version: process.env.VERSION || "0.0.0", +}, [ + { + type: "string[]", + identifier: "EXAMPLE_CONFIG_IDENTIFIER", + } +]) + +sdk.registerDataTypes(someDataType) +sdk.registerRuntimeFunctionDefinitionClass(FibonacciFunction) +sdk.registerEventTypes(someEventType) + + +connectToSdk(); + +function connectToSdk() { + sdk.connect().then((configs: HerculesActionProjectConfiguration[]) => { + console.log("SDK connected successfully"); + + sdk.dispatchEvent("test_flow", configs[0].projectId, "Hello, World! Configs loaded: " + configs.length).then(() => { + console.log("Event dispatched successfully"); + }) + }).catch(() => { + // will be handled by logger internally + process.exit(1) + }) + + sdk.onError((error) => { + console.error("SDK Error occurred:", error.message); + console.log("Attempting to reconnect in 5s..."); + setTimeout(() => { + connectToSdk(); + }, 5000) + }) +} diff --git a/ts/examples/simple-example-ts/tsconfig.json b/ts/examples/simple-example-ts/tsconfig.json index 64bfbd7..d2af2bc 100644 --- a/ts/examples/simple-example-ts/tsconfig.json +++ b/ts/examples/simple-example-ts/tsconfig.json @@ -17,6 +17,6 @@ "types": ["vite/client"] }, "include": [ - "index.ts" + "src/index.ts" ] } \ No newline at end of file diff --git a/ts/examples/simple-example-ts/vite.config.ts b/ts/examples/simple-example-ts/vite.config.ts index 001ed7e..303b4a4 100644 --- a/ts/examples/simple-example-ts/vite.config.ts +++ b/ts/examples/simple-example-ts/vite.config.ts @@ -4,7 +4,7 @@ import { resolve } from 'path'; export default defineConfig({ build: { target: "node18", - ssr: resolve(__dirname, 'index.ts'), // ✅ correct SSR entry + ssr: resolve(__dirname, 'src/index.ts'), rollupOptions: { external: (id) => [ diff --git a/ts/src/action_sdk.ts b/ts/src/action_sdk.ts index 6b2ec4f..1bffdd2 100644 --- a/ts/src/action_sdk.ts +++ b/ts/src/action_sdk.ts @@ -5,7 +5,7 @@ import {ActionTransferServiceClient, TransferRequest} from "@code0-tech/tucana/a import {FlowTypeSetting,} from "@code0-tech/tucana/shared"; import {constructValue, toAllowedValue} from "@code0-tech/tucana/helpers"; import 'reflect-metadata'; -import {connect as connectHelper} from "./sdk/connection/connection"; +import {connect} from "./sdk/connection/connection"; import {registerFunctionDefinitionClass} from "./sdk/builder/registerFunctionDefinitionClass"; import {registerRuntimeFunctionDefinitionClass} from "./builder/registerRuntimeFunctionDefinitionClass"; @@ -52,7 +52,7 @@ const createSdk = (config: ActionSdk["config"], configDefinitions?: HerculesActi state.stream?.responses.onError(handler) }, connect: options => { - return connectHelper(state, config, options); + return connect(state, config, options); }, getProjectActionConfigurations: () => { return state.projectConfigurations.map(value => { @@ -97,14 +97,14 @@ const createSdk = (config: ActionSdk["config"], configDefinitions?: HerculesActi linkedDataTypeIdentifiers: dataType.linkedDataTypes || [], displayMessage: dataType.displayMessage || [], definitionSource: "action", - version: dataType.version || config.version, + version: config.version, }); }) return Promise.resolve() }, - registerFlowTypes: async (...flowTypes) => { + registerEventTypes: async (...flowTypes) => { flowTypes.forEach(flowType => { state.flowTypes.push({ signature: flowType.signature, @@ -116,7 +116,7 @@ const createSdk = (config: ActionSdk["config"], configDefinitions?: HerculesActi displayMessage: flowType.displayMessage || [], documentation: flowType.documentation || [], definitionSource: "action", - version: flowType.version || config.version, + version: config.version, linkedDataTypeIdentifiers: flowType.linkedDataTypes || [], settings: (flowType.settings || []).map(setting => ({ name: setting.name || [], @@ -146,7 +146,7 @@ const createSdk = (config: ActionSdk["config"], configDefinitions?: HerculesActi event: { projectId: projectIdBigInt, eventType: eventType, - payload: constructValue(payload) || constructValue(null), + payload: constructValue(payload || null), } } }) @@ -161,5 +161,5 @@ const createSdk = (config: ActionSdk["config"], configDefinitions?: HerculesActi export { createSdk, - connectHelper as connect + connect } \ No newline at end of file diff --git a/ts/src/sdk/builder/builder.ts b/ts/src/sdk/builder/builder.ts index 5b68e79..5f38180 100644 --- a/ts/src/sdk/builder/builder.ts +++ b/ts/src/sdk/builder/builder.ts @@ -20,7 +20,6 @@ export function buildRuntimeFunctionDefinition(klass: RuntimeFunctionDefinitionC const documentation: HerculesRuntimeFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass) || [] const signature: HerculesRuntimeFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass) const linkedDataTypeIdentifiers: HerculesRuntimeFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) || [] - const version: HerculesRuntimeFunctionDefinition["version"] = Reflect.getMetadata('hercules:version', klass) || config.version const displayIcon: HerculesRuntimeFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass) || "" const throwsError: HerculesRuntimeFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass) || false const runFunction = new klass().run @@ -38,7 +37,7 @@ export function buildRuntimeFunctionDefinition(klass: RuntimeFunctionDefinitionC alias: alias || [], name: names || [], description: description || [], - version: version || config.version, + version: config.version, runtimeName: identifier, deprecationMessage: deprecationMessage || [], displayIcon: displayIcon || "tabler:note", diff --git a/ts/src/sdk/builder/registerFunctionDefinitionClass.ts b/ts/src/sdk/builder/registerFunctionDefinitionClass.ts index 1383c15..765ec9f 100644 --- a/ts/src/sdk/builder/registerFunctionDefinitionClass.ts +++ b/ts/src/sdk/builder/registerFunctionDefinitionClass.ts @@ -27,7 +27,6 @@ export function registerFunctionDefinitionClass(config: { const documentation: HerculesFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass) const signature: HerculesFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass) const linkedDataTypeIdentifiers: HerculesFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) - const version: HerculesFunctionDefinition["version"] = Reflect.getMetadata('hercules:version', klass) const displayIcon: HerculesFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass) const throwsError: HerculesFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass) @@ -49,7 +48,7 @@ export function registerFunctionDefinitionClass(config: { signature: signature || runtimeDefinition.signature, throwsError: throwsError || runtimeDefinition.throwsError, alias: alias || runtimeDefinition.alias, - version: version || runtimeDefinition.version, + version: config.version, description: description || runtimeDefinition.description, name: names || runtimeDefinition.name, documentation: documentation || runtimeDefinition.documentation, diff --git a/ts/src/sdk/connection/connection.ts b/ts/src/sdk/connection/connection.ts index 05963bc..ec92230 100644 --- a/ts/src/sdk/connection/connection.ts +++ b/ts/src/sdk/connection/connection.ts @@ -35,7 +35,7 @@ export async function connect(state: SdkState, config: ActionSdk["config"], opti return new Promise(async (resolve, reject) => { try { - for await (let message of state?.stream?.responses || []) { + for await (const message of state?.stream?.responses || []) { logger.debug({ message: message, config, diff --git a/ts/src/sdk/execution.ts b/ts/src/sdk/execution.ts index c371829..183f0d2 100644 --- a/ts/src/sdk/execution.ts +++ b/ts/src/sdk/execution.ts @@ -44,8 +44,7 @@ function buildContext(message: TransferResponse, execution: ExecutionRequest, st const params = buildParams(execution, func, message); let conf = state.projectConfigurations.find(config => { - //TODO - return true + return config.projectId === execution.projectId }) if (!conf) { @@ -97,7 +96,7 @@ export function handleExecutionRequest(state: SdkState, message: TransferRespons context }) - const funcHandler = (func as any).handler + const funcHandler = func.handler if (funcHandler.length == params.length + 1) { // handler has context parameter @@ -110,14 +109,7 @@ export function handleExecutionRequest(state: SdkState, message: TransferRespons return; } - const result = new Promise((resolve, reject) => { - try { - resolve(funcHandler(...params)) - } catch (e) { - reject(e) - } - }) - result.then((value: any) => { + Promise.resolve(funcHandler(...params)) .then((value: any) => { const request = TransferRequest.create({ data: { oneofKind: "result", diff --git a/ts/src/types.ts b/ts/src/types.ts index 7e11f86..76bd448 100644 --- a/ts/src/types.ts +++ b/ts/src/types.ts @@ -30,12 +30,10 @@ export interface HerculesDataType { rules?: DefinitionDataTypeRule[], genericKeys?: string[], type: string, - linkedDataTypes?: string[], - // Will default to sdk version - version?: string + linkedDataTypes?: string[] } -export interface HerculesFlowTypeSetting { +export interface HerculesEventTypeSetting { identifier: string, unique?: FlowTypeSetting_UniquenessScope, linkedDataTypeIdentifiers?: string[], @@ -44,9 +42,9 @@ export interface HerculesFlowTypeSetting { description?: HerculesTranslation[], } -export interface HerculesFlowType { +export interface HerculesEventType { identifier: string, - settings?: HerculesFlowTypeSetting[], + settings?: HerculesEventTypeSetting[], signature: string, linkedDataTypes?: string[], editable: boolean, @@ -55,7 +53,6 @@ export interface HerculesFlowType { documentation?: HerculesTranslation[], displayMessage?: HerculesTranslation[], alias?: HerculesTranslation[], - version?: string, displayIcon?: string, } @@ -81,7 +78,6 @@ export interface HerculesRuntimeFunctionDefinition { displayMessage?: HerculesTranslation[], alias?: HerculesTranslation[], linkedDataTypes?: string[], - version?: string, displayIcon?: string, } @@ -109,7 +105,6 @@ export interface HerculesFunctionDefinition { displayMessage?: HerculesTranslation[], alias?: HerculesTranslation[], linkedDataTypes?: string[], - version?: string, displayIcon?: string, } @@ -151,7 +146,7 @@ export interface ActionSdk { registerConfigDefinitions: (...actionConfigurations: Array) => Promise, registerDataTypes: (...dataType: Array) => Promise, - registerFlowTypes: (...flowTypes: Array) => Promise, + registerEventTypes: (...flowTypes: Array) => Promise, registerRuntimeFunctionDefinitionClass: (klass: RuntimeFunctionDefinitionClass) => Promise, registerFunctionDefinitionClass: (klass: FunctionDefinitionConstructor) => Promise, dispatchEvent: (eventType: string, projectId: number | bigint, payload: PlainValue) => Promise, @@ -222,9 +217,6 @@ export const Signature = (signature: string): ClassDecorator => export const LinkedDataTypeIdentifiers = (...linkedDataTypeIdentifiers: string[]): ClassDecorator => (target) => Reflect.defineMetadata('hercules:linked_data_type_identifiers', linkedDataTypeIdentifiers, target) -export const Version = (version: string): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:version', version, target) - export const ThrowsError = (throwsError: boolean = true): ClassDecorator => (target) => Reflect.defineMetadata('hercules:throws_error', throwsError, target) From c161e781a215751d7ed914905046aa419e943fb8 Mon Sep 17 00:00:00 2001 From: Dario Pranjic Date: Sun, 12 Apr 2026 13:05:17 +0200 Subject: [PATCH 07/43] Reorder function calls in connection.ts and update README for clarity --- README.md | 9 ++++----- ts/src/sdk/connection/connection.ts | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c39e6fa..1590bb5 100644 --- a/README.md +++ b/README.md @@ -16,18 +16,16 @@ sequenceDiagram Hercules->>Aquila: Register datatypes
because maybe they are needed in the config definitions Aquila-->>Hercules: Validation result - - Hercules->>Stream: Open bi-directional stream - Hercules->>Stream: ActionLogon request - - Hercules->>Aquila: Register function definitions Aquila-->>Hercules: Validation result Hercules->>Aquila: Register flow types Aquila-->>Hercules: Validation result + Hercules->>Stream: Open bi-directional stream + Hercules->>Stream: ActionLogon request + Stream-->>Hercules: Receive action configurations ``` @@ -62,3 +60,4 @@ To use a simple test server use the following command: ./bin/test_server.rb ``` This will start a test server on `localhost:50051` that you can connect to with the action sdk. +Watch out this test server isnt really working its just an way to test the connection. diff --git a/ts/src/sdk/connection/connection.ts b/ts/src/sdk/connection/connection.ts index ec92230..0bdc740 100644 --- a/ts/src/sdk/connection/connection.ts +++ b/ts/src/sdk/connection/connection.ts @@ -25,10 +25,10 @@ export async function connect(state: SdkState, config: ActionSdk["config"], opti state.stream = state.client.transfer(builtOptions); await handleDataTypes(state, builtOptions, config); - await handleLogon(state, config); await handleRuntimeFunctionDefinitions(state, builtOptions, config) await handleFunctionDefinitions(state, builtOptions, config) await handleFlowTypes(state, builtOptions, config) + await handleLogon(state, config); logger.info("Connected successfully to aquila") From 1396dff1996c2415af0ca0a8b57f632574c2c0e0 Mon Sep 17 00:00:00 2001 From: Dario Pranjic Date: Sun, 12 Apr 2026 14:10:42 +0200 Subject: [PATCH 08/43] Change auth header to lowercase --- ts/src/sdk/connection/connection.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/src/sdk/connection/connection.ts b/ts/src/sdk/connection/connection.ts index 0bdc740..c220e67 100644 --- a/ts/src/sdk/connection/connection.ts +++ b/ts/src/sdk/connection/connection.ts @@ -18,7 +18,7 @@ export async function connect(state: SdkState, config: ActionSdk["config"], opti logger.debug("Trying to connect to aquila") const builtOptions: RpcOptions = { meta: { - "Authorization": config.authToken, + "authorization": config.authToken, }, ...options } From 274b32a3c4c84a2a3e850ff9ba429f21d78df4e4 Mon Sep 17 00:00:00 2001 From: Dario Pranjic Date: Sun, 7 Jun 2026 19:50:44 +0200 Subject: [PATCH 09/43] Start to update to event emitter --- ts/src/action_sdk.ts | 2 +- .../connectionHandler.ts} | 64 +++++--- ts/src/handler/dataTypeHandler.ts | 25 +++ ts/src/index.ts | 143 +++++++++++++++++- ts/src/logger.ts | 12 -- ts/src/sdk/connection/dataType.ts | 29 ---- .../connection/runtimeFunctionDefinition.ts | 5 +- ts/src/types.ts | 1 + 8 files changed, 213 insertions(+), 68 deletions(-) rename ts/src/{sdk/connection/connection.ts => handler/connectionHandler.ts} (57%) create mode 100644 ts/src/handler/dataTypeHandler.ts delete mode 100644 ts/src/logger.ts delete mode 100644 ts/src/sdk/connection/dataType.ts diff --git a/ts/src/action_sdk.ts b/ts/src/action_sdk.ts index 1bffdd2..b2d2d6a 100644 --- a/ts/src/action_sdk.ts +++ b/ts/src/action_sdk.ts @@ -5,7 +5,7 @@ import {ActionTransferServiceClient, TransferRequest} from "@code0-tech/tucana/a import {FlowTypeSetting,} from "@code0-tech/tucana/shared"; import {constructValue, toAllowedValue} from "@code0-tech/tucana/helpers"; import 'reflect-metadata'; -import {connect} from "./sdk/connection/connection"; +import {connect} from "./handler/connection"; import {registerFunctionDefinitionClass} from "./sdk/builder/registerFunctionDefinitionClass"; import {registerRuntimeFunctionDefinitionClass} from "./builder/registerRuntimeFunctionDefinitionClass"; diff --git a/ts/src/sdk/connection/connection.ts b/ts/src/handler/connectionHandler.ts similarity index 57% rename from ts/src/sdk/connection/connection.ts rename to ts/src/handler/connectionHandler.ts index c220e67..467c704 100644 --- a/ts/src/sdk/connection/connection.ts +++ b/ts/src/handler/connectionHandler.ts @@ -1,45 +1,65 @@ import type {RpcOptions} from "@protobuf-ts/runtime-rpc"; -import {logger} from "../../logger"; import {constructValue, toAllowedValue} from "@code0-tech/tucana/helpers"; -import type { - ActionSdk, - SdkState, - HerculesActionProjectConfiguration -} from "../../types"; -import {handleExecutionRequest} from "../execution"; -import {handleLogon} from "./logon"; -import {handleRuntimeFunctionDefinitions} from "./runtimeFunctionDefinition"; -import {handleDataTypes} from "./dataType"; -import {handleFunctionDefinitions} from "./functionDefinition"; -import {handleFlowTypes} from "./flowTypes"; +import {handleExecutionRequest} from "../sdk/execution"; +import {handleLogon} from "../sdk/connection/logon"; +import {handleRuntimeFunctionDefinitions} from "../sdk/connection/runtimeFunctionDefinition"; +import {handleFunctionDefinitions} from "../sdk/connection/functionDefinition"; +import {handleFlowTypes} from "../sdk/connection/flowTypes"; +import {CodeZeroAction, CodeZeroEvent} from "../index"; +import {ActionTransferServiceClient} from "@code0-tech/tucana/aquila"; +import {GrpcTransport} from "@protobuf-ts/grpc-transport"; +import {ChannelCredentials} from "@grpc/grpc-js"; +import {handleDataTypes} from "./dataTypeHandler"; -export async function connect(state: SdkState, config: ActionSdk["config"], options?: RpcOptions): Promise { - logger.debug("Trying to connect to aquila") +export async function connect(action: CodeZeroAction, aquilaUrl: string, authToken: string, options?: RpcOptions): Promise { + console.debug("Trying to connect to aquila") + action.transport = new GrpcTransport({ + host: aquilaUrl, + channelCredentials: ChannelCredentials.createInsecure() + }) + const actionTransferServiceClient = new ActionTransferServiceClient(action.transport!) const builtOptions: RpcOptions = { meta: { - "authorization": config.authToken, + "authorization": authToken, }, ...options } - state.stream = state.client.transfer(builtOptions); + action.stream = actionTransferServiceClient.transfer(builtOptions) - await handleDataTypes(state, builtOptions, config); + await handleDataTypes(action, builtOptions); await handleRuntimeFunctionDefinitions(state, builtOptions, config) await handleFunctionDefinitions(state, builtOptions, config) await handleFlowTypes(state, builtOptions, config) await handleLogon(state, config); - logger.info("Connected successfully to aquila") + console.info("Connected successfully to aquila") + + for await (const message of action.stream!.responses) { + action.emit(CodeZeroEvent.streamMessageReceived, message) + console.debug({ + message: message, + }, "Received message from stream") + switch (message.data.oneofKind) { + case "actionConfigurations": { + console.info("Received action configurations") + action.emit(CodeZeroEvent.actionConfigurationsReceived, message.data.actionConfigurations) + break + } + case "execution": { + action.emit(CodeZeroEvent.executionRequestReceived, message.data.execution) + break + } + default: { + action.emit(CodeZeroEvent.error, new Error("Received unknown message type from stream")) + } + } + } return new Promise(async (resolve, reject) => { try { for await (const message of state?.stream?.responses || []) { - logger.debug({ - message: message, - config, - }, "Received message from stream") switch (message?.data.oneofKind) { case "actionConfigurations": { logger.info("Received action configurations") diff --git a/ts/src/handler/dataTypeHandler.ts b/ts/src/handler/dataTypeHandler.ts new file mode 100644 index 0000000..0747f43 --- /dev/null +++ b/ts/src/handler/dataTypeHandler.ts @@ -0,0 +1,25 @@ +import {DataTypeServiceClient, DataTypeUpdateRequest} from "@code0-tech/tucana/aquila"; +import {RpcOptions} from "@protobuf-ts/runtime-rpc"; +import {CodeZeroAction, CodeZeroEvent} from "../index"; + +export async function handleDataTypes(action: CodeZeroAction, grpcOptions: RpcOptions) { + const dataTypeClient = new DataTypeServiceClient(action.transport!) + try { + console.debug("Sent data types request") + const call = await dataTypeClient.update(DataTypeUpdateRequest.create({ + dataTypes: [ + ...action.dataTypes + ] + }), grpcOptions) + if (!call.response.success) { + action.emit(CodeZeroEvent.dataTypesUpdateFailed, new Error("Failed to update data types")) + return Promise.reject(call.response); + } + action.emit(CodeZeroEvent.dataTypesUpdated, call.response) + } catch (error) { + console.error({ + err: error, + }, "Error while updating data types") + return Promise.reject(error); + } +} diff --git a/ts/src/index.ts b/ts/src/index.ts index 169c718..cfdf224 100644 --- a/ts/src/index.ts +++ b/ts/src/index.ts @@ -1,2 +1,143 @@ +import {EventEmitter} from "node:events"; +import {RegisteredFunction, RegisteredRuntimeFunction} from "./types"; +import { + ActionConfigurationDefinition, + ActionProjectConfiguration, + DefinitionDataType, + FlowType +} from "@code0-tech/tucana/shared"; +import {GrpcOptions, GrpcTransport} from "@protobuf-ts/grpc-transport"; +import { + ActionTransferServiceClient, + DataTypeUpdateResponse, + TransferRequest, + TransferResponse +} from "@code0-tech/tucana/aquila"; +import {DuplexStreamingCall} from "@protobuf-ts/runtime-rpc"; +import {ChannelCredentials} from "@grpc/grpc-js"; + export * from "./action_sdk.js" -export * from "./types.js" \ No newline at end of file +export * from "./types.js" + +export enum CodeZeroEvent { + error = "error", + connected = "connected", + streamMessageReceived = "streamMessageReceived", + actionConfigurationsReceived = "actionConfigurationsReceived", + executionRequestReceived = "executionRequestReceived", + + streamMessageSent = "streamMessageSent", + dataTypesUpdated = "dataTypesUpdated", + dataTypesUpdateFailed = "dataTypesUpdateFailed", +} + +export interface CodeZeroEventMap { + [CodeZeroEvent.error]: [Error] + [CodeZeroEvent.connected]: [CodeZeroAction] + [CodeZeroEvent.streamMessageReceived]: [TransferResponse] + [CodeZeroEvent.dataTypesUpdated]: [DataTypeUpdateResponse] + [CodeZeroEvent.dataTypesUpdateFailed]: [Error] + [CodeZeroEvent.streamMessageSent]: [TransferRequest] + [flowType: string]: any[] +} + +export class CodeZeroAction extends EventEmitter { + private _version: string + private _functions: RegisteredFunction[] = []; + private _runtimeFunctions: RegisteredRuntimeFunction[] = []; + private _dataTypes: DefinitionDataType[] = []; + private _eventTypes: FlowType[] = []; + private _configurationDefinitions: ActionConfigurationDefinition[] = []; + private _projectConfigurations: ActionProjectConfiguration[] = []; + + private _transport?: GrpcTransport + private _actionTransferServiceClient?: ActionTransferServiceClient + private _stream?: DuplexStreamingCall + + + constructor(version: string) { + super() + this._version = version + } + + + set functions(value: RegisteredFunction[]) { + this._functions = value; + } + + set runtimeFunctions(value: RegisteredRuntimeFunction[]) { + this._runtimeFunctions = value; + } + + set dataTypes(value: DefinitionDataType[]) { + this._dataTypes = value; + } + + set eventTypes(value: FlowType[]) { + this._eventTypes = value; + } + + set configurationDefinitions(value: ActionConfigurationDefinition[]) { + this._configurationDefinitions = value; + } + + set projectConfigurations(value: ActionProjectConfiguration[]) { + this._projectConfigurations = value; + } + + get version(): string { + return this._version; + } + + get functions(): RegisteredFunction[] { + return this._functions; + } + + get runtimeFunctions(): RegisteredRuntimeFunction[] { + return this._runtimeFunctions; + } + + get dataTypes(): DefinitionDataType[] { + return this._dataTypes; + } + + get eventTypes(): FlowType[] { + return this._eventTypes; + } + + get configurationDefinitions(): ActionConfigurationDefinition[] { + return this._configurationDefinitions; + } + + get projectConfigurations(): ActionProjectConfiguration[] { + return this._projectConfigurations; + } + + get transport(): GrpcTransport | undefined { + return this._transport; + } + + get actionTransferServiceClient(): ActionTransferServiceClient | undefined { + return this._actionTransferServiceClient; + } + + get stream(): DuplexStreamingCall | undefined { + return this._stream; + } + + set transport(value: GrpcTransport) { + this._transport = value; + } + + set actionTransferServiceClient(value: ActionTransferServiceClient) { + this._actionTransferServiceClient = value; + } + + set stream(value: DuplexStreamingCall) { + this._stream = value; + } + + connect(authToken: string, aquilaUrl: string, identifier: string, grpcOptions?: GrpcOptions) { + + } +} diff --git a/ts/src/logger.ts b/ts/src/logger.ts deleted file mode 100644 index a196c63..0000000 --- a/ts/src/logger.ts +++ /dev/null @@ -1,12 +0,0 @@ -import pino from 'pino'; - -export const logger = pino({ - redact: ["config.authToken"], - level: process.env.LOG_LEVEL || "debug", - transport: { - target: 'pino-pretty', - options: { - colorize: true - } - } -}); \ No newline at end of file diff --git a/ts/src/sdk/connection/dataType.ts b/ts/src/sdk/connection/dataType.ts deleted file mode 100644 index bcb241a..0000000 --- a/ts/src/sdk/connection/dataType.ts +++ /dev/null @@ -1,29 +0,0 @@ -import {DataTypeServiceClient, DataTypeUpdateRequest} from "@code0-tech/tucana/aquila"; -import {logger} from "../../logger"; -import {SdkState} from "../../types"; -import {RpcOptions} from "@protobuf-ts/runtime-rpc"; - -export async function handleDataTypes(state: SdkState, builtOptions: RpcOptions, config: { - authToken: string; - aquilaUrl: string; - actionId: string; - version: string -}) { - const dataTypeClient = new DataTypeServiceClient(state.transport) - await dataTypeClient.update(DataTypeUpdateRequest.create({ - dataTypes: [ - ...state.dataTypes - ] - }), builtOptions).then(value => { - if (!value.response.success) { - return Promise.reject(value.response); - } - }).catch(reason => { - logger.error({ - err: reason, - config, - }, "Error while updating data types") - return Promise.reject(reason); - }) - logger.debug("Sent data types request") -} diff --git a/ts/src/sdk/connection/runtimeFunctionDefinition.ts b/ts/src/sdk/connection/runtimeFunctionDefinition.ts index 5f5354b..2a389c6 100644 --- a/ts/src/sdk/connection/runtimeFunctionDefinition.ts +++ b/ts/src/sdk/connection/runtimeFunctionDefinition.ts @@ -4,7 +4,6 @@ import { RuntimeFunctionDefinitionServiceClient, RuntimeFunctionDefinitionUpdateRequest } from "@code0-tech/tucana/aquila"; -import {logger} from "../../logger"; export async function handleRuntimeFunctionDefinitions(state: SdkState, builtOptions: RpcOptions | undefined, config: ActionSdk["config"]) { const request = RuntimeFunctionDefinitionUpdateRequest.create( @@ -22,7 +21,7 @@ export async function handleRuntimeFunctionDefinitions(state: SdkState, builtOpt request, builtOptions ).then(value => { if (!value.response.success) { - logger.error({ + console.error({ err: value.response, request: value.request, config, @@ -31,7 +30,7 @@ export async function handleRuntimeFunctionDefinitions(state: SdkState, builtOpt } }) } catch (error) { - logger.debug({ + console.debug({ ...request.runtimeFunctions[0].runtimeParameterDefinitions[0].defaultValue }) logger.error({ diff --git a/ts/src/types.ts b/ts/src/types.ts index 76bd448..3e5310b 100644 --- a/ts/src/types.ts +++ b/ts/src/types.ts @@ -10,6 +10,7 @@ import { import {PlainValue} from "@code0-tech/tucana/helpers"; import {ActionTransferServiceClient, TransferRequest, TransferResponse} from "@code0-tech/tucana/aquila"; import 'reflect-metadata'; +import {EventEmitter} from "node:events"; export interface HerculesTranslation { code: "en-US" | "de-DE" | string, From 08f25245f269f8077a5d520c1656a698cd7e0dec Mon Sep 17 00:00:00 2001 From: Dario Pranjic Date: Sun, 7 Jun 2026 21:23:08 +0200 Subject: [PATCH 10/43] Update emitter pattern --- .../src/fibonacciFunction.ts | 13 +- ts/package-lock.json | 10 +- ts/package.json | 2 +- ts/src/index.ts | 284 +++++++++++------- ts/src/sdk/builder/builder.ts | 50 --- .../registerFunctionDefinitionClass.ts | 59 ---- .../definitions/functions/functions.mapper.ts | 121 ++++++++ ts/src/sdk/definitions/functions/functions.ts | 95 ++++++ ts/src/sdk/definitions/meta.ts | 24 ++ ts/src/types.ts | 213 ++++--------- 10 files changed, 484 insertions(+), 387 deletions(-) create mode 100644 ts/src/sdk/definitions/functions/functions.mapper.ts create mode 100644 ts/src/sdk/definitions/functions/functions.ts create mode 100644 ts/src/sdk/definitions/meta.ts diff --git a/ts/examples/simple-example-ts/src/fibonacciFunction.ts b/ts/examples/simple-example-ts/src/fibonacciFunction.ts index 34a7a69..0f35fc8 100644 --- a/ts/examples/simple-example-ts/src/fibonacciFunction.ts +++ b/ts/examples/simple-example-ts/src/fibonacciFunction.ts @@ -1,4 +1,11 @@ -import {HerculesFunctionContext, Identifier, RuntimeParameter, Signature} from "@code0-tech/hercules"; +import { + DisplayMessage, + HerculesFunctionContext, + Identifier, + OmitFunctionDefinition, + RuntimeParameter, + Signature +} from "@code0-tech/hercules"; @Identifier("fib") @Signature("(number: number): number") @@ -6,6 +13,10 @@ import {HerculesFunctionContext, Identifier, RuntimeParameter, Signature} from " runtimeName: "number", defaultValue: 20 }) +@DisplayMessage({ + code: "de-DE", + content: "" +}) export class FibonacciFunction { run(context: HerculesFunctionContext, number: number): number { console.log(context) diff --git a/ts/package-lock.json b/ts/package-lock.json index c69bfdb..a1d0e73 100644 --- a/ts/package-lock.json +++ b/ts/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.0", "license": "ISC", "dependencies": { - "@code0-tech/tucana": "0.0.68", + "@code0-tech/tucana": "0.0.74", "@grpc/grpc-js": "^1.14.3", "@protobuf-ts/grpc-backend": "^2.11.1", "@protobuf-ts/grpc-transport": "^2.11.1", @@ -79,10 +79,10 @@ } }, "node_modules/@code0-tech/tucana": { - "version": "0.0.68", - "resolved": "https://registry.npmjs.org/@code0-tech/tucana/-/tucana-0.0.68.tgz", - "integrity": "sha512-kbjLiKjJyZLnPmNi5JabWRNZcWZyXnfnld8jCFrUkvKbGj77CAwggR0uH8SqaxwWNWqQZlavYzCZWO/ob3+uKA==", - "license": "Apache-2.0" + "version": "0.0.74", + "resolved": "https://registry.npmjs.org/@code0-tech/tucana/-/tucana-0.0.74.tgz", + "integrity": "sha512-AgCl812Sn/MyY1+cRG0pdN0Uj7z93hDa4E9bclaf9hS5wc1PrlQSutDgePvJFR/VBWoeYQczne7MNP7RDu9NRg==", + "license": "MIT" }, "node_modules/@emnapi/core": { "version": "1.9.1", diff --git a/ts/package.json b/ts/package.json index 699e1f3..e4a5c5f 100644 --- a/ts/package.json +++ b/ts/package.json @@ -30,7 +30,7 @@ "license": "ISC", "type": "module", "dependencies": { - "@code0-tech/tucana": "0.0.68", + "@code0-tech/tucana": "0.0.74", "@grpc/grpc-js": "^1.14.3", "@protobuf-ts/grpc-backend": "^2.11.1", "@protobuf-ts/grpc-transport": "^2.11.1", diff --git a/ts/src/index.ts b/ts/src/index.ts index cfdf224..4219ff3 100644 --- a/ts/src/index.ts +++ b/ts/src/index.ts @@ -1,20 +1,41 @@ import {EventEmitter} from "node:events"; -import {RegisteredFunction, RegisteredRuntimeFunction} from "./types"; import { - ActionConfigurationDefinition, - ActionProjectConfiguration, - DefinitionDataType, - FlowType + DefinitionDataType, Error, + FlowType, ModuleConfigurationDefinition, ModuleProjectConfigurations, RuntimeFunctionDefinition } from "@code0-tech/tucana/shared"; import {GrpcOptions, GrpcTransport} from "@protobuf-ts/grpc-transport"; import { - ActionTransferServiceClient, - DataTypeUpdateResponse, - TransferRequest, - TransferResponse + ActionTransferRequest, ActionTransferResponse, + ActionTransferServiceClient, DataTypeServiceClient, DataTypeUpdateRequest, ModuleServiceClient, ModuleUpdateRequest, } from "@code0-tech/tucana/aquila"; -import {DuplexStreamingCall} from "@protobuf-ts/runtime-rpc"; +import {DuplexStreamingCall, type RpcOptions} from "@protobuf-ts/runtime-rpc"; +import { + FunctionDefinitionClass, + HerculesFunctionDefinition, HerculesRuntimeFunctionDefinition, + RuntimeFunctionDefinitionClass, RuntimeFunctionDefinitionRunnable +} from "./sdk/definitions/functions/functions"; +import {functionMap, runtimeFunctionMap} from "./sdk/definitions/functions/functions.mapper"; +import {buildRuntimeFunctionDefinition} from "./sdk/builder/builder"; +import type { + HerculesActionConfigurationDefinition, + HerculesTranslation, + RegisteredFunction, + RegisteredRuntimeFunction +} from "./types"; import {ChannelCredentials} from "@grpc/grpc-js"; +import {handleDataTypes} from "./handler/dataTypeHandler"; +import {handleRuntimeFunctionDefinitions} from "./sdk/connection/runtimeFunctionDefinition"; +import {handleFunctionDefinitions} from "./sdk/connection/functionDefinition"; +import {handleFlowTypes} from "./sdk/connection/flowTypes"; +import {handleLogon} from "./sdk/connection/logon"; +import {name} from "pino-pretty"; +import * as console from "node:console"; +import * as console from "node:console"; +import {call} from "pino"; +import * as console from "node:console"; +import * as console from "node:console"; +import * as console from "node:console"; +import * as console from "node:console"; export * from "./action_sdk.js" export * from "./types.js" @@ -23,121 +44,166 @@ export enum CodeZeroEvent { error = "error", connected = "connected", streamMessageReceived = "streamMessageReceived", - actionConfigurationsReceived = "actionConfigurationsReceived", executionRequestReceived = "executionRequestReceived", - streamMessageSent = "streamMessageSent", - dataTypesUpdated = "dataTypesUpdated", - dataTypesUpdateFailed = "dataTypesUpdateFailed", + + moduleUpdated = "moduleUpdated", + moduleUpdateFailed = "moduleUpdateFailed", } export interface CodeZeroEventMap { [CodeZeroEvent.error]: [Error] [CodeZeroEvent.connected]: [CodeZeroAction] - [CodeZeroEvent.streamMessageReceived]: [TransferResponse] - [CodeZeroEvent.dataTypesUpdated]: [DataTypeUpdateResponse] - [CodeZeroEvent.dataTypesUpdateFailed]: [Error] - [CodeZeroEvent.streamMessageSent]: [TransferRequest] + [CodeZeroEvent.streamMessageReceived]: [ActionTransferResponse] + [CodeZeroEvent.streamMessageSent]: [ActionTransferRequest] + [CodeZeroEvent.moduleUpdated]: [ModuleUpdateRequest] + [CodeZeroEvent.moduleUpdateFailed]: [Error] + [flowType: string]: any[] } export class CodeZeroAction extends EventEmitter { - private _version: string - private _functions: RegisteredFunction[] = []; - private _runtimeFunctions: RegisteredRuntimeFunction[] = []; + private _functions: HerculesFunctionDefinition[] = []; + private _runtimeFunctions: HerculesRuntimeFunctionDefinition[] = []; private _dataTypes: DefinitionDataType[] = []; private _eventTypes: FlowType[] = []; - private _configurationDefinitions: ActionConfigurationDefinition[] = []; - private _projectConfigurations: ActionProjectConfiguration[] = []; - + private _projectConfigurations: ModuleProjectConfigurations[] = []; private _transport?: GrpcTransport private _actionTransferServiceClient?: ActionTransferServiceClient - private _stream?: DuplexStreamingCall - - constructor(version: string) { - super() - this._version = version - } - - - set functions(value: RegisteredFunction[]) { - this._functions = value; - } - - set runtimeFunctions(value: RegisteredRuntimeFunction[]) { - this._runtimeFunctions = value; - } - - set dataTypes(value: DefinitionDataType[]) { - this._dataTypes = value; - } - - set eventTypes(value: FlowType[]) { - this._eventTypes = value; - } - - set configurationDefinitions(value: ActionConfigurationDefinition[]) { - this._configurationDefinitions = value; - } - - set projectConfigurations(value: ActionProjectConfiguration[]) { - this._projectConfigurations = value; - } - - get version(): string { - return this._version; - } - - get functions(): RegisteredFunction[] { - return this._functions; - } - - get runtimeFunctions(): RegisteredRuntimeFunction[] { - return this._runtimeFunctions; - } - - get dataTypes(): DefinitionDataType[] { - return this._dataTypes; - } - - get eventTypes(): FlowType[] { - return this._eventTypes; - } - - get configurationDefinitions(): ActionConfigurationDefinition[] { - return this._configurationDefinitions; - } - - get projectConfigurations(): ActionProjectConfiguration[] { - return this._projectConfigurations; - } - - get transport(): GrpcTransport | undefined { - return this._transport; - } - - get actionTransferServiceClient(): ActionTransferServiceClient | undefined { - return this._actionTransferServiceClient; - } - - get stream(): DuplexStreamingCall | undefined { - return this._stream; - } - - set transport(value: GrpcTransport) { - this._transport = value; - } - - set actionTransferServiceClient(value: ActionTransferServiceClient) { - this._actionTransferServiceClient = value; - } - - set stream(value: DuplexStreamingCall) { - this._stream = value; - } - - connect(authToken: string, aquilaUrl: string, identifier: string, grpcOptions?: GrpcOptions) { + private _stream?: DuplexStreamingCall + private _identifier: string; + private _version: string + private _aquilaUrl?: string + private _author: string + private _icon: string; + private _name: HerculesTranslation[]; + private _documentation: string; + private _configurationDefinitions: HerculesActionConfigurationDefinition[]; + + + constructor(identifier: string, version: string, aquilaUrl: string, author: string, icon: string, documentation: string, name: HerculesTranslation[], configurationDefinitions: HerculesActionConfigurationDefinition[]) { + super(); + this._identifier = identifier; + this._version = version; + this._aquilaUrl = aquilaUrl; + this._author = author; + this._icon = icon; + this._name = name; + this._documentation = documentation; + } + + registerFunction(klass: FunctionDefinitionClass) { + const functionDefinition = functionMap(klass); + + this._functions.push(functionDefinition) + } + + registerRuntimeFunction(klass: RuntimeFunctionDefinitionClass) { + const omitFunctionDefinition = Reflect.getMetadata('hercules:omit_function_definition', klass) || false + + const runtimeFunction = runtimeFunctionMap(klass); + + this._runtimeFunctions.push(runtimeFunction) + if (!omitFunctionDefinition) { + this._functions.push({ + ...runtimeFunction, + runtimeDefinitionName: runtimeFunction.runtimeName, + parameters: runtimeFunction.parameters?.map(param => { + return { + ...param, + runtimeDefinitionName: param.runtimeName + } + }) || [] + }) + } + } + + connect(authToken: string, aquilaUrl: string, author: string, grpcOptions?: GrpcOptions) { + console.debug("Trying to connect to aquila") + this._transport = new GrpcTransport({ + host: aquilaUrl, + channelCredentials: ChannelCredentials.createInsecure() + }) + const actionTransferServiceClient = new ActionTransferServiceClient(this._transport!) + const builtOptions: RpcOptions = { + meta: { + "authorization": authToken, + }, + ...grpcOptions + } + this._stream = actionTransferServiceClient.transfer(builtOptions) + + + const moduleClient = new ModuleServiceClient(this._transport!) + try { + console.debug("Sent data types request") + const call = moduleClient.update(ModuleUpdateRequest.create({ + modules: [ + { + author: this._author, + version: this._version, + name: this._name, + icon: this._icon, + documentation: this._documentation, + identifier: this._identifier, + configurations: this._configurationDefinitions.map(definition => { + return { + identifier: definition.identifier, + name: definition.name, + type: definition.type, + hidden: definition.hidden || false, + defaultValue: definition.defaultValue, + description: definition.description, + optional: definition.optional || false, + linkedDataTypeIdentifiers: definition.linkedDataTypes + } as ModuleConfigurationDefinition + }) + + } + ] + }), grpcOptions) + if (!call.response.success) { + action.emit(CodeZeroEvent.dataTypesUpdateFailed, new Error("Failed to update data types")) + return Promise.reject(call.response); + } + action.emit(CodeZeroEvent.dataTypesUpdated, call.response) + } catch (error) { + console.error({ + err: error, + }, "Error while updating data types") + return Promise.reject(error); + } + + // await handleDataTypes(action, builtOptions); + // await handleRuntimeFunctionDefinitions(state, builtOptions, config) + // await handleFunctionDefinitions(state, builtOptions, config) + // await handleFlowTypes(state, builtOptions, config) + // await handleLogon(state, config); + + console.info("Connected successfully to aquila") + + + for await (const message of action.stream!.responses) { + action.emit(CodeZeroEvent.streamMessageReceived, message) + console.debug({ + message: message, + }, "Received message from stream") + switch (message.data.oneofKind) { + case "actionConfigurations": { + console.info("Received action configurations") + action.emit(CodeZeroEvent.actionConfigurationsReceived, message.data.actionConfigurations) + break + } + case "execution": { + action.emit(CodeZeroEvent.executionRequestReceived, message.data.execution) + break + } + default: { + action.emit(CodeZeroEvent.error, new Error("Received unknown message type from stream")) + } + } + } } } diff --git a/ts/src/sdk/builder/builder.ts b/ts/src/sdk/builder/builder.ts index 5f38180..2ec64e0 100644 --- a/ts/src/sdk/builder/builder.ts +++ b/ts/src/sdk/builder/builder.ts @@ -10,56 +10,6 @@ import { import {RuntimeParameterDefinition} from "@code0-tech/tucana/shared"; export function buildRuntimeFunctionDefinition(klass: RuntimeFunctionDefinitionClass, config: ActionSdk["config"]): RegisteredRuntimeFunction { - const identifier: string = Reflect.getMetadata('hercules:identifier', klass) - const runtimeParameters: HerculesRuntimeFunctionDefinitionParameter[] = Reflect.getMetadata('hercules:runtime_parameters', klass) - const names: HerculesRuntimeFunctionDefinition["name"] = Reflect.getMetadata('hercules:name', klass) || [] - const displayMessage: HerculesRuntimeFunctionDefinition["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass) || [] - const description: HerculesRuntimeFunctionDefinition["description"] = Reflect.getMetadata('hercules:description', klass) || [] - const deprecationMessage: HerculesRuntimeFunctionDefinition["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass) || [] - const alias: HerculesRuntimeFunctionDefinition["alias"] = Reflect.getMetadata('hercules:alias', klass) || [] - const documentation: HerculesRuntimeFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass) || [] - const signature: HerculesRuntimeFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass) - const linkedDataTypeIdentifiers: HerculesRuntimeFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) || [] - const displayIcon: HerculesRuntimeFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass) || "" - const throwsError: HerculesRuntimeFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass) || false - const runFunction = new klass().run - if (!identifier) { - throw new Error(`Runtime function class ${klass.name} is missing an identifier. Please add @Identifier("your_identifier") decorator to the class.`) - } - if (!signature) { - throw new Error(`Runtime function class ${klass.name} is missing a signature. Please add @Signature("(param1: TYPE_1): RETURN_TYPE") decorator to the class.`) - } - - return { - identifier: identifier as string, - definition: { - alias: alias || [], - name: names || [], - description: description || [], - version: config.version, - runtimeName: identifier, - deprecationMessage: deprecationMessage || [], - displayIcon: displayIcon || "tabler:note", - displayMessage: displayMessage || [], - documentation: documentation || [], - linkedDataTypeIdentifiers: linkedDataTypeIdentifiers || [], - runtimeParameterDefinitions: runtimeParameters.map(param => { - return { - ...param, - name: param.name || [], - description: param.description || [], - documentation: param.documentation || [], - hidden: param.hidden || false, - optional: param.optional || false, - defaultValue: param.defaultValue ? constructValue(param.defaultValue) : undefined, - } as RuntimeParameterDefinition - }), - signature: signature, - throwsError: throwsError || false, - definitionSource: "action" - }, - handler: runFunction - } as RegisteredRuntimeFunction } diff --git a/ts/src/sdk/builder/registerFunctionDefinitionClass.ts b/ts/src/sdk/builder/registerFunctionDefinitionClass.ts index 765ec9f..7363003 100644 --- a/ts/src/sdk/builder/registerFunctionDefinitionClass.ts +++ b/ts/src/sdk/builder/registerFunctionDefinitionClass.ts @@ -14,64 +14,5 @@ export function registerFunctionDefinitionClass(config: { version: string }, state: SdkState) { return (klass: FunctionDefinitionConstructor): Promise => { - const parentClass = Object.getPrototypeOf(klass) - const runtimeFunction = buildRuntimeFunctionDefinition(parentClass, config); - const runtimeDefinition = runtimeFunction.definition - const functionParameters: HerculesFunctionDefinitionParameter[] = Reflect.getMetadata('hercules:function_parameters', klass) - const names: HerculesFunctionDefinition["name"] = Reflect.getMetadata('hercules:name', klass) - const displayMessage: HerculesFunctionDefinition["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass) - const description: HerculesFunctionDefinition["description"] = Reflect.getMetadata('hercules:description', klass) - const deprecationMessage: HerculesFunctionDefinition["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass) - const alias: HerculesFunctionDefinition["alias"] = Reflect.getMetadata('hercules:alias', klass) - const documentation: HerculesFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass) - const signature: HerculesFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass) - const linkedDataTypeIdentifiers: HerculesFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) - const displayIcon: HerculesFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass) - const throwsError: HerculesFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass) - - runtimeDefinition.runtimeParameterDefinitions.forEach(runtimeDefinition => { - if (functionParameters.find((param: HerculesFunctionDefinitionParameter) => param.runtimeName === runtimeDefinition.runtimeName)) { - return; - } - functionParameters.push({ - ...runtimeDefinition, - runtimeDefinitionName: runtimeDefinition.runtimeName - }) - }) - - state.functions.push({ - identifier: runtimeFunction.identifier, - definition: { - runtimeDefinitionName: runtimeDefinition.runtimeName, - runtimeName: runtimeDefinition.runtimeName || runtimeDefinition.runtimeName, - signature: signature || runtimeDefinition.signature, - throwsError: throwsError || runtimeDefinition.throwsError, - alias: alias || runtimeDefinition.alias, - version: config.version, - description: description || runtimeDefinition.description, - name: names || runtimeDefinition.name, - documentation: documentation || runtimeDefinition.documentation, - deprecationMessage: deprecationMessage || runtimeDefinition.deprecationMessage, - displayMessage: displayMessage || runtimeDefinition.displayMessage, - displayIcon: displayIcon || runtimeDefinition.displayIcon, - definitionSource: "action", - linkedDataTypeIdentifiers: linkedDataTypeIdentifiers || runtimeDefinition.linkedDataTypeIdentifiers, - parameterDefinitions: functionParameters.map(value => { - return { - ...value, - runtimeDefinitionName: value.runtimeDefinitionName || value.runtimeName, - name: value.name || [], - description: value.description || [], - documentation: value.documentation || [], - hidden: value.hidden || false, - optional: value.optional || false, - defaultValue: value.defaultValue ? constructValue(value.defaultValue || null) : undefined, - } - }) - }, - } as RegisteredFunction) - - return Promise.resolve(); - }; } diff --git a/ts/src/sdk/definitions/functions/functions.mapper.ts b/ts/src/sdk/definitions/functions/functions.mapper.ts new file mode 100644 index 0000000..33f02ae --- /dev/null +++ b/ts/src/sdk/definitions/functions/functions.mapper.ts @@ -0,0 +1,121 @@ +import { + FunctionDefinitionClass, HerculesFunctionDefinition, HerculesFunctionDefinitionParameter, + HerculesRuntimeFunctionDefinition, HerculesRuntimeFunctionDefinitionParameter, RuntimeFunctionDefinitionClass +} from "./functions"; +import {constructValue} from "@code0-tech/tucana/helpers"; + +export const functionMap = (klass: FunctionDefinitionClass): HerculesFunctionDefinition => { + const parentClass = Object.getPrototypeOf(klass) + const runtimeFunction = runtimeFunctionMap(parentClass); + + const identifier: string = Reflect.getMetadata('hercules:identifier', klass) + const functionParameters: HerculesFunctionDefinitionParameter[] = Reflect.getMetadata('hercules:function_parameters', klass) + const names: HerculesFunctionDefinition["name"] = Reflect.getMetadata('hercules:name', klass) + const displayMessage: HerculesFunctionDefinition["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass) + const description: HerculesFunctionDefinition["description"] = Reflect.getMetadata('hercules:description', klass) + const deprecationMessage: HerculesFunctionDefinition["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass) + const alias: HerculesFunctionDefinition["alias"] = Reflect.getMetadata('hercules:alias', klass) + const documentation: HerculesFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass) + const signature: HerculesFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass) + const linkedDataTypeIdentifiers: HerculesFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) + const displayIcon: HerculesFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass) + const throwsError: HerculesFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass) + + if (functionParameters.length > (runtimeFunction?.parameters?.length ?? 0)) { + throw new Error(`Function definition class ${klass.name} has more function parameters than its runtime function.`) + } + + functionParameters.map(functionParameter => functionParameter.runtimeName).forEach(value => { + if (!runtimeFunction?.parameters?.map(value => value.runtimeName).includes(value)) { + throw new Error(`Function definition class ${klass.name} has a function parameter with runtime name ${value} that does not exist in its runtime function.`) + } + }) + + + runtimeFunction?.parameters?.forEach(runtimeDefinition => { + if (functionParameters.find((param: HerculesFunctionDefinitionParameter) => param.runtimeName === runtimeDefinition.runtimeName)) { + return; + } + functionParameters.push({ + ...runtimeDefinition, + runtimeDefinitionName: runtimeDefinition.runtimeName + }) + }) + + + return { + runtimeDefinitionName: runtimeFunction.runtimeName, + runtimeName: identifier || runtimeFunction.runtimeName, + signature: signature || runtimeFunction.signature, + throwsError: throwsError || runtimeFunction.throwsError, + alias: alias || runtimeFunction.alias, + description: description || runtimeFunction.description, + name: names || runtimeFunction.name, + documentation: documentation || runtimeFunction.documentation, + deprecationMessage: deprecationMessage || runtimeFunction.deprecationMessage, + displayMessage: displayMessage || runtimeFunction.displayMessage, + displayIcon: displayIcon || runtimeFunction.displayIcon, + linkedDataTypes: linkedDataTypeIdentifiers || runtimeFunction.linkedDataTypes, + parameters: functionParameters.map(value => { + return { + ...value, + runtimeDefinitionName: value.runtimeDefinitionName || value.runtimeName, + name: value.name || [], + description: value.description || [], + documentation: value.documentation || [], + hidden: value.hidden || false, + optional: value.optional || false, + defaultValue: value.defaultValue ? constructValue(value.defaultValue || null) : undefined, + } + }) + } +} +export const runtimeFunctionMap = (klass: RuntimeFunctionDefinitionClass): HerculesRuntimeFunctionDefinition => { + const identifier: string = Reflect.getMetadata('hercules:identifier', klass) + const runtimeParameters: HerculesRuntimeFunctionDefinitionParameter[] = Reflect.getMetadata('hercules:runtime_parameters', klass) + const names: HerculesRuntimeFunctionDefinition["name"] = Reflect.getMetadata('hercules:name', klass) || [] + const displayMessage: HerculesRuntimeFunctionDefinition["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass) || [] + const description: HerculesRuntimeFunctionDefinition["description"] = Reflect.getMetadata('hercules:description', klass) || [] + const deprecationMessage: HerculesRuntimeFunctionDefinition["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass) || [] + const alias: HerculesRuntimeFunctionDefinition["alias"] = Reflect.getMetadata('hercules:alias', klass) || [] + const documentation: HerculesRuntimeFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass) || [] + const signature: HerculesRuntimeFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass) + const linkedDataTypeIdentifiers: HerculesRuntimeFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) || [] + const displayIcon: HerculesRuntimeFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass) || "" + const throwsError: HerculesRuntimeFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass) || false + const runFunction = new klass().run + + if (!identifier) { + throw new Error(`Runtime function class ${klass.name} is missing an identifier. Please add @Identifier("your_identifier") decorator to the class.`) + } + if (!signature) { + throw new Error(`Runtime function class ${klass.name} is missing a signature. Please add @Signature("(param1: TYPE_1): RETURN_TYPE") decorator to the class.`) + } + + return { + alias: alias || [], + name: names || [], + description: description || [], + runtimeName: identifier, + deprecationMessage: deprecationMessage || [], + displayIcon: displayIcon || "tabler:note", + displayMessage: displayMessage || [], + documentation: documentation || [], + linkedDataTypes: linkedDataTypeIdentifiers || [], + parameters: runtimeParameters.map(param => { + return { + ...param, + name: param.name || [], + description: param.description || [], + documentation: param.documentation || [], + hidden: param.hidden || false, + optional: param.optional || false, + defaultValue: param.defaultValue ? constructValue(param.defaultValue) : undefined, + } + }), + signature: signature, + throwsError: throwsError || false, + handler: runFunction + } + +} diff --git a/ts/src/sdk/definitions/functions/functions.ts b/ts/src/sdk/definitions/functions/functions.ts new file mode 100644 index 0000000..118ebab --- /dev/null +++ b/ts/src/sdk/definitions/functions/functions.ts @@ -0,0 +1,95 @@ +import {PlainValue} from "@code0-tech/tucana/helpers"; +import { + HerculesTranslation, +} from "../../../types"; + + +export interface HerculesRuntimeFunctionDefinitionParameter { + runtimeName: string, + defaultValue?: PlainValue, + name?: HerculesTranslation[], + description?: HerculesTranslation[], + documentation?: HerculesTranslation[], + hidden?: boolean, + optional?: boolean +} + +export interface HerculesRuntimeFunctionDefinition { + runtimeName: string, + parameters?: HerculesRuntimeFunctionDefinitionParameter[], + signature: string, + throwsError?: boolean, + name?: HerculesTranslation[], + description?: HerculesTranslation[], + documentation?: HerculesTranslation[], + deprecationMessage?: HerculesTranslation[], + displayMessage?: HerculesTranslation[], + alias?: HerculesTranslation[], + linkedDataTypes?: string[], + displayIcon?: string, + handler: (...args: any[]) => Promise | PlainValue, +} + +export interface HerculesFunctionDefinitionParameter { + runtimeName: string, + defaultValue?: PlainValue, + name?: HerculesTranslation[], + description?: HerculesTranslation[], + documentation?: HerculesTranslation[], + hidden?: boolean, + optional?: boolean, + runtimeDefinitionName?: string +} + +export interface HerculesFunctionDefinition { + runtimeDefinitionName: string, + runtimeName: string, + parameters?: HerculesFunctionDefinitionParameter[], + signature: string, + throwsError?: boolean, + name?: HerculesTranslation[], + description?: HerculesTranslation[], + documentation?: HerculesTranslation[], + deprecationMessage?: HerculesTranslation[], + displayMessage?: HerculesTranslation[], + alias?: HerculesTranslation[], + linkedDataTypes?: string[], + displayIcon?: string, +} + + +export type FunctionDefinitionClass = new () => T; + +export type RuntimeFunctionDefinitionRunnable = { + run: (...args: any[]) => Promise | PlainValue; +}; + +export type RuntimeFunctionDefinitionClass = + new () => T; + +export const OmitFunctionDefinition = (): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:omit_function_definition', true, target) + +export const RuntimeParameter = (parameter: HerculesRuntimeFunctionDefinitionParameter): ClassDecorator => + (target) => { + const parameters = Reflect.getMetadata('hercules:runtime_parameters', target) || []; + parameters.push(parameter); + + Reflect.defineMetadata('hercules:runtime_parameters', parameters, target) + } + +export const FunctionParameter = (parameter: HerculesFunctionDefinitionParameter): ClassDecorator => + (target) => { + const parameters = Reflect.getMetadata('hercules:function_parameters', target) || []; + parameters.push(parameter); + + Reflect.defineMetadata('hercules:function_parameters', parameters, target) + } + +export const ThrowsError = (throwsError: boolean = true): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:throws_error', throwsError, target) + + + +export const LinkedDataTypeIdentifiers = (...linkedDataTypeIdentifiers: string[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:linked_data_type_identifiers', linkedDataTypeIdentifiers, target) diff --git a/ts/src/sdk/definitions/meta.ts b/ts/src/sdk/definitions/meta.ts new file mode 100644 index 0000000..e152a00 --- /dev/null +++ b/ts/src/sdk/definitions/meta.ts @@ -0,0 +1,24 @@ +import {HerculesTranslation} from "../../types"; + +export const Name = (...translation: HerculesTranslation[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:name', translation, target) +export const DisplayMessage = (...translation: HerculesTranslation[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:display_message', translation, target) +export const Description = (...translation: HerculesTranslation[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:description', translation, target) +export const DeprecationMessage = (...translation: HerculesTranslation[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:deprecation_message', translation, target) +export const Alias = (...translation: HerculesTranslation[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:alias', translation, target) + +export const Documentation = (...translation: HerculesTranslation[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:documentation', translation, target) + +export const Signature = (signature: string): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:signature', signature, target) + +export const DisplayIcon = (displayIcon: string): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:display_icon', displayIcon, target) + +export const Identifier = (id: string): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:identifier', id, target); diff --git a/ts/src/types.ts b/ts/src/types.ts index 3e5310b..e391114 100644 --- a/ts/src/types.ts +++ b/ts/src/types.ts @@ -1,16 +1,14 @@ import {GrpcOptions, GrpcTransport} from "@protobuf-ts/grpc-transport"; import {DuplexStreamingCall} from "@protobuf-ts/runtime-rpc"; import { - ActionConfigurationDefinition, ActionProjectConfiguration, DefinitionDataType, DefinitionDataTypeRule, FlowType, FlowTypeSetting_UniquenessScope, FunctionDefinition, RuntimeFunctionDefinition } from "@code0-tech/tucana/shared"; import {PlainValue} from "@code0-tech/tucana/helpers"; -import {ActionTransferServiceClient, TransferRequest, TransferResponse} from "@code0-tech/tucana/aquila"; import 'reflect-metadata'; -import {EventEmitter} from "node:events"; +import {FunctionDefinitionClass, RuntimeFunctionDefinitionClass} from "./sdk/definitions/functions/functions"; export interface HerculesTranslation { code: "en-US" | "de-DE" | string, @@ -57,58 +55,6 @@ export interface HerculesEventType { displayIcon?: string, } -export interface HerculesRuntimeFunctionDefinitionParameter { - runtimeName: string, - defaultValue?: PlainValue, - name?: HerculesTranslation[], - description?: HerculesTranslation[], - documentation?: HerculesTranslation[], - hidden?: boolean, - optional?: boolean -} - -export interface HerculesRuntimeFunctionDefinition { - runtimeName: string, - parameters?: HerculesRuntimeFunctionDefinitionParameter[], - signature: string, - throwsError?: boolean, - name?: HerculesTranslation[], - description?: HerculesTranslation[], - documentation?: HerculesTranslation[], - deprecationMessage?: HerculesTranslation[], - displayMessage?: HerculesTranslation[], - alias?: HerculesTranslation[], - linkedDataTypes?: string[], - displayIcon?: string, -} - -export interface HerculesFunctionDefinitionParameter { - runtimeName: string, - defaultValue?: PlainValue, - name?: HerculesTranslation[], - description?: HerculesTranslation[], - documentation?: HerculesTranslation[], - hidden?: boolean, - optional?: boolean, - runtimeDefinitionName?: string -} - -export interface HerculesFunctionDefinition { - runtimeDefinitionName: string, - runtimeName: string, - parameters?: HerculesFunctionDefinitionParameter[], - signature: string, - throwsError?: boolean, - name?: HerculesTranslation[], - description?: HerculesTranslation[], - documentation?: HerculesTranslation[], - deprecationMessage?: HerculesTranslation[], - displayMessage?: HerculesTranslation[], - alias?: HerculesTranslation[], - linkedDataTypes?: string[], - displayIcon?: string, -} - export interface HerculesActionProjectConfiguration { projectId: number | bigint, configValues: { @@ -122,36 +68,38 @@ export interface HerculesActionConfigurationDefinition { name?: HerculesTranslation[], description?: HerculesTranslation[], type: string, + hidden: boolean, + optional: boolean, linkedDataTypes?: string[], defaultValue?: PlainValue, identifier: string, } -export type HerculesRegisterRuntimeFunctionParameter = { - definition: HerculesRuntimeFunctionDefinition, - handler: (...args: any[]) => Promise | PlainValue, -} - -export interface ActionSdk { - config: { - authToken: string, - aquilaUrl: string, - actionId: string, - version: string, - }, - fullyConnected: () => boolean, // indicates whether the SDK is fully connected and ready to send/receive messages. Becomes true after connect() resolves successfully - connect: (options?: GrpcOptions) => Promise, // after registering the functions and events - onError: (handler: (error: Error) => void) => void, - - getProjectActionConfigurations(): HerculesActionProjectConfiguration[], - - registerConfigDefinitions: (...actionConfigurations: Array) => Promise, - registerDataTypes: (...dataType: Array) => Promise, - registerEventTypes: (...flowTypes: Array) => Promise, - registerRuntimeFunctionDefinitionClass: (klass: RuntimeFunctionDefinitionClass) => Promise, - registerFunctionDefinitionClass: (klass: FunctionDefinitionConstructor) => Promise, - dispatchEvent: (eventType: string, projectId: number | bigint, payload: PlainValue) => Promise, -} +// export type HerculesRegisterRuntimeFunctionParameter = { +// definition: HerculesRuntimeFunctionDefinition, +// handler: (...args: any[]) => Promise | PlainValue, +// } + +// export interface ActionSdk { +// config: { +// authToken: string, +// aquilaUrl: string, +// actionId: string, +// version: string, +// }, +// fullyConnected: () => boolean, // indicates whether the SDK is fully connected and ready to send/receive messages. Becomes true after connect() resolves successfully +// connect: (options?: GrpcOptions) => Promise, // after registering the functions and events +// onError: (handler: (error: Error) => void) => void, +// +// getProjectActionConfigurations(): HerculesActionProjectConfiguration[], +// +// registerConfigDefinitions: (...actionConfigurations: Array) => Promise, +// registerDataTypes: (...dataType: Array) => Promise, +// registerEventTypes: (...flowTypes: Array) => Promise, +// registerRuntimeFunctionDefinitionClass: (klass: RuntimeFunctionDefinitionClass) => Promise, +// registerFunctionDefinitionClass: (klass: FunctionDefinitionClass) => Promise, +// dispatchEvent: (eventType: string, projectId: number | bigint, payload: PlainValue) => Promise, +// } export class RuntimeErrorException extends Error { code: string @@ -165,85 +113,26 @@ export class RuntimeErrorException extends Error { } } - -export type FunctionDefinitionConstructor = new () => T; - -export type RuntimeFunctionDefinitionRunnable = { - run: (...args: any[]) => Promise | PlainValue; -}; - -export type RuntimeFunctionDefinitionClass = - new () => T; - - -export const Identifier = (id: string): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:identifier', id, target); - -export const OmitFunctionDefinition = (): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:omit_function_definition', true, target) - -export const RuntimeParameter = (parameter: HerculesRuntimeFunctionDefinitionParameter): ClassDecorator => - (target) => { - const parameters = Reflect.getMetadata('hercules:runtime_parameters', target) || []; - parameters.push(parameter); - - Reflect.defineMetadata('hercules:runtime_parameters', parameters, target) - } - -export const FunctionParameter = (parameter: HerculesFunctionDefinitionParameter): ClassDecorator => - (target) => { - const parameters = Reflect.getMetadata('hercules:function_parameters', target) || []; - parameters.push(parameter); - - Reflect.defineMetadata('hercules:function_parameters', parameters, target) - } - -export const Name = (...translation: HerculesTranslation[]): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:name', translation, target) - -export const DisplayMessage = (...translation: HerculesTranslation[]): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:display_message', translation, target) -export const Description = (...translation: HerculesTranslation[]): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:description', translation, target) -export const DeprecationMessage = (...translation: HerculesTranslation[]): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:deprecation_message', translation, target) -export const Alias = (...translation: HerculesTranslation[]): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:alias', translation, target) -export const Documentation = (...translation: HerculesTranslation[]): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:documentation', translation, target) - -export const Signature = (signature: string): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:signature', signature, target) - -export const LinkedDataTypeIdentifiers = (...linkedDataTypeIdentifiers: string[]): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:linked_data_type_identifiers', linkedDataTypeIdentifiers, target) - -export const ThrowsError = (throwsError: boolean = true): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:throws_error', throwsError, target) - -export const DisplayIcon = (displayIcon: string): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:display_icon', displayIcon, target) - -export interface RegisteredFunction { - identifier: string, - definition: FunctionDefinition -} - -export interface RegisteredRuntimeFunction { - identifier: string, - definition: RuntimeFunctionDefinition, - handler: (...args: any[]) => Promise | PlainValue, -} - -export interface SdkState { - functions: RegisteredFunction[], - runtimeFunctions: RegisteredRuntimeFunction[], - dataTypes: DefinitionDataType[], - flowTypes: FlowType[], - configurationDefinitions: ActionConfigurationDefinition[], - projectConfigurations: ActionProjectConfiguration[], - transport: GrpcTransport, - client: ActionTransferServiceClient, - stream: DuplexStreamingCall | undefined, - fullyConnected: boolean, -} \ No newline at end of file +// +// export interface RegisteredFunction { +// identifier: string, +// definition: FunctionDefinition +// } +// +// export interface RegisteredRuntimeFunction { +// identifier: string, +// definition: RuntimeFunctionDefinition, +// } +// +// export interface SdkState { +// functions: RegisteredFunction[], +// runtimeFunctions: RegisteredRuntimeFunction[], +// dataTypes: DefinitionDataType[], +// flowTypes: FlowType[], +// configurationDefinitions: ActionConfigurationDefinition[], +// projectConfigurations: ActionProjectConfiguration[], +// transport: GrpcTransport, +// client: ActionTransferServiceClient, +// stream: DuplexStreamingCall | undefined, +// fullyConnected: boolean, +// } \ No newline at end of file From dc303653d63268b36356c253d58e60a7bd330258 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 00:46:16 +0200 Subject: [PATCH 11/43] feat: .gitignore --- ts/.gitignore | 37 +++++++++++++++++++++--- ts/examples/simple-example-ts/.gitignore | 5 ++++ 2 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 ts/examples/simple-example-ts/.gitignore diff --git a/ts/.gitignore b/ts/.gitignore index 48269aa..9acd6ff 100644 --- a/ts/.gitignore +++ b/ts/.gitignore @@ -1,4 +1,33 @@ -node_modules -dist -code0-tech-hercules-*.tgz -.env \ No newline at end of file +# Dependencies +node_modules/ + +# Build output +dist/ + +# Packed tarballs +*.tgz + +# Environment +.env +.env.* +!.env.example + +# Logs +*.log +logs/ + +# OS +.DS_Store +Thumbs.db + +# IDE +.idea/ +.vscode/ +*.suo +*.ntvs* +*.njsproj +*.sln +CLAUDE.md + +# Test coverage +coverage/ diff --git a/ts/examples/simple-example-ts/.gitignore b/ts/examples/simple-example-ts/.gitignore new file mode 100644 index 0000000..c744b43 --- /dev/null +++ b/ts/examples/simple-example-ts/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +dist/ +.env +.env.* +!.env.example From 6f53c053f52504e7cc90ae657fb8c3f162ffff34 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 00:46:45 +0200 Subject: [PATCH 12/43] feat: remove old files --- bin/.rubocop.yml | 26 --- bin/Gemfile | 8 - bin/Gemfile.lock | 35 ---- bin/test_server.rb | 186 ----------------- .../simple-example-ts/src/exampleDataType.ts | 6 - .../simple-example-ts/src/exampleEventType.ts | 7 - .../src/fibonacciFunction.ts | 34 ---- ts/src/action_sdk.ts | 165 ---------------- .../registerRuntimeFunctionDefinitionClass.ts | 35 ---- ts/src/handler/connectionHandler.ts | 112 ----------- ts/src/handler/dataTypeHandler.ts | 25 --- ts/src/sdk/builder/builder.ts | 15 -- .../registerFunctionDefinitionClass.ts | 18 -- ts/src/sdk/connection/flowTypes.ts | 34 ---- ts/src/sdk/connection/functionDefinition.ts | 37 ---- ts/src/sdk/connection/logon.ts | 32 --- .../connection/runtimeFunctionDefinition.ts | 44 ----- .../definitions/functions/functions.mapper.ts | 121 ------------ ts/src/sdk/definitions/functions/functions.ts | 95 --------- ts/src/sdk/execution.ts | 187 ------------------ 20 files changed, 1222 deletions(-) delete mode 100644 bin/.rubocop.yml delete mode 100644 bin/Gemfile delete mode 100644 bin/Gemfile.lock delete mode 100755 bin/test_server.rb delete mode 100644 ts/examples/simple-example-ts/src/exampleDataType.ts delete mode 100644 ts/examples/simple-example-ts/src/exampleEventType.ts delete mode 100644 ts/examples/simple-example-ts/src/fibonacciFunction.ts delete mode 100644 ts/src/action_sdk.ts delete mode 100644 ts/src/builder/registerRuntimeFunctionDefinitionClass.ts delete mode 100644 ts/src/handler/connectionHandler.ts delete mode 100644 ts/src/handler/dataTypeHandler.ts delete mode 100644 ts/src/sdk/builder/builder.ts delete mode 100644 ts/src/sdk/builder/registerFunctionDefinitionClass.ts delete mode 100644 ts/src/sdk/connection/flowTypes.ts delete mode 100644 ts/src/sdk/connection/functionDefinition.ts delete mode 100644 ts/src/sdk/connection/logon.ts delete mode 100644 ts/src/sdk/connection/runtimeFunctionDefinition.ts delete mode 100644 ts/src/sdk/definitions/functions/functions.mapper.ts delete mode 100644 ts/src/sdk/definitions/functions/functions.ts delete mode 100644 ts/src/sdk/execution.ts diff --git a/bin/.rubocop.yml b/bin/.rubocop.yml deleted file mode 100644 index 69e4753..0000000 --- a/bin/.rubocop.yml +++ /dev/null @@ -1,26 +0,0 @@ -AllCops: - NewCops: enable - -Lint/AmbiguousBlockAssociation: - AllowedMethods: [change] - -Metrics: - Enabled: false - -Naming/BlockForwarding: - Enabled: false - -Naming/MethodParameterName: - Enabled: false - -Style/ArgumentsForwarding: - Enabled: false - -Style/Documentation: - Enabled: false - -Style/HashSyntax: - EnforcedShorthandSyntax: never - -Style/TrailingCommaInHashLiteral: - EnforcedStyleForMultiline: comma diff --git a/bin/Gemfile b/bin/Gemfile deleted file mode 100644 index 23c96af..0000000 --- a/bin/Gemfile +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true - -source 'https://rubygems.org' - -ruby '3.4.7' - -gem 'grpc', '~> 1.67' -gem 'tucana', '0.0.57' diff --git a/bin/Gemfile.lock b/bin/Gemfile.lock deleted file mode 100644 index a0fe082..0000000 --- a/bin/Gemfile.lock +++ /dev/null @@ -1,35 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - bigdecimal (4.0.1) - google-protobuf (4.34.0) - bigdecimal - rake (~> 13.3) - google-protobuf (4.34.0-x86_64-linux-gnu) - bigdecimal - rake (~> 13.3) - googleapis-common-protos-types (1.22.0) - google-protobuf (~> 4.26) - grpc (1.78.1) - google-protobuf (>= 3.25, < 5.0) - googleapis-common-protos-types (~> 1.0) - grpc (1.78.1-x86_64-linux-gnu) - google-protobuf (>= 3.25, < 5.0) - googleapis-common-protos-types (~> 1.0) - rake (13.3.1) - tucana (0.0.57) - grpc (~> 1.64) - -PLATFORMS - ruby - x86_64-linux - -DEPENDENCIES - grpc (~> 1.67) - tucana (= 0.0.57) - -RUBY VERSION - ruby 3.4.7p58 - -BUNDLED WITH - 2.7.2 diff --git a/bin/test_server.rb b/bin/test_server.rb deleted file mode 100755 index cd4d80e..0000000 --- a/bin/test_server.rb +++ /dev/null @@ -1,186 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true - -require 'grpc' -require 'tucana' - -Tucana.load_protocol(:aquila) - -class State - attr_reader :data_types, :runtime_functions, :flow_types, :action_config_definitions - - def initialize - @data_types = [] - @runtime_functions = [] - @flow_types = [] - @action_config_definitions = [] - end - - def add_flow_types(flow_types) - @flow_types += flow_types - end - - def add_data_types(dts) - @data_types += dts - end - - def add_runtime_functions(functions) - @runtime_functions += functions - end - - def add_action_config_definition(config) - @action_config_definitions << config - end -end - -class FlowTypeTransferService < Tucana::Aquila::FlowTypeService::Service - def initialize(state) - @state = state - end - - def update(req, call) - puts "Got Auth token: #{call.metadata['authorization']}" - @state.add_flow_types(req.flow_types) - - puts "Flowtypes received: #{req.flow_types.map(&:identifier).join(', ')}" - - Tucana::Aquila::RuntimeFunctionDefinitionUpdateResponse.new(success: true) - end -end - -class RuntimeFunctionDefinitionTransferService < Tucana::Aquila::RuntimeFunctionDefinitionService::Service - def initialize(state) - @state = state - end - - def update(req, call) - puts "Got Auth token: #{call.metadata['authorization']}" - @state.add_runtime_functions(req.runtime_functions) - - puts "RuntimeFunctionDefinitions received: #{req.runtime_functions.map(&:runtime_name).join(', ')}" - - Tucana::Aquila::RuntimeFunctionDefinitionUpdateResponse.new(success: true) - end -end - -class DataTypeTransferService < Tucana::Aquila::DataTypeService::Service - def initialize(state) - @state = state - end - - def update(req, call) - puts "Got Auth token: #{call.metadata['authorization']}" - @state.add_data_types(req.data_types) - puts "Data types received: #{req.data_types.map(&:identifier).join(', ')}" - Tucana::Aquila::DataTypeUpdateResponse.new(success: true) - end -end - -class ActionTransferService < Tucana::Aquila::ActionTransferService::Service - def initialize(state) - @state = state - @sent_configs = [] - end - - def construct_parameters(func) - struct = Tucana::Shared::Struct.new - - func.runtime_parameter_definitions.each do |param_def| - struct.fields[param_def.runtime_name] = param_def.default_value - end - - struct - end - - def transfer(requests, call) - token = call.metadata['authorization'] - puts "Got Auth token: #{token}" - Enumerator.new do |yielder| - Thread.new do - loop do - sleep 5 - @state.action_config_definitions.each do |config| - next if @sent_configs.include?(config[:identifier]) - - puts "Received action config definition: #{config[:action_identifier]} (v#{config[:version]})" - count = Random.rand(1..5) - puts "Creating #{count} mock project config" - proj_conf = [] - - count.times do |i| - proj_conf << Tucana::Shared::ActionProjectConfiguration.new( - project_id: Random.rand(1..1000), - action_configurations: [ - Tucana::Shared::ActionConfiguration.new( - identifier: config[:identifier], - value: Tucana::Shared::Value.from_ruby("test value for project: #{i}") - ) - ] - ) - end - - yielder << Tucana::Aquila::TransferResponse.new( - { - action_configurations: - Tucana::Shared::ActionConfigurations.new(action_configurations: proj_conf), - } - ) - @sent_configs << config[:identifier] - end - @state.runtime_functions.each do |func| - puts "Sending execute request for: #{func.runtime_name}" - exec_identifier = "exec_#{func.runtime_name}_#{Time.now.to_i}" - puts "Execution identifier: #{exec_identifier}" - yielder << Tucana::Aquila::TransferResponse.new( - { - execution: Tucana::Aquila::ExecutionRequest.new( - project_id: Random.rand(1..1000), - execution_identifier: exec_identifier, - function_identifier: func.runtime_name, - parameters: construct_parameters(func) - ), - } - ) - end - end - end - - requests.each do |req| - unless req.result.nil? - puts "Received execution result for: #{req.result.execution_identifier}" - puts "Result value: #{req.result.result}" - next - end - - unless req.event.nil? - puts "Received event: #{req.event.event_type}" - puts "Event data: #{req.event.payload}" - puts "Project id: #{req.event.project_id}" - next - end - next if req.logon.nil? - - logon = req.logon - - @state.add_action_config_definition({ - auth_token: token, - action_identifier: logon.action_identifier, - version: logon.version, - config_definitions: logon.action_configurations, - }) - - puts "Action logon received: #{logon.action_identifier} (v#{logon.version})" - end - end - end -end - -state = State.new - -server = GRPC::RpcServer.new -server.add_http2_port('0.0.0.0:50051', :this_port_is_insecure) -server.handle(ActionTransferService.new(state)) -server.handle(DataTypeTransferService.new(state)) -server.handle(RuntimeFunctionDefinitionTransferService.new(state)) -server.handle(FlowTypeTransferService.new(state)) -server.run_till_terminated_or_interrupted(%w[INT TERM QUIT]) diff --git a/ts/examples/simple-example-ts/src/exampleDataType.ts b/ts/examples/simple-example-ts/src/exampleDataType.ts deleted file mode 100644 index c9ad177..0000000 --- a/ts/examples/simple-example-ts/src/exampleDataType.ts +++ /dev/null @@ -1,6 +0,0 @@ -import {HerculesDataType} from "@code0-tech/hercules"; - -export const someDataType: HerculesDataType = { - identifier: "SOME_DATATYPE", - type: "any", -} \ No newline at end of file diff --git a/ts/examples/simple-example-ts/src/exampleEventType.ts b/ts/examples/simple-example-ts/src/exampleEventType.ts deleted file mode 100644 index 9069207..0000000 --- a/ts/examples/simple-example-ts/src/exampleEventType.ts +++ /dev/null @@ -1,7 +0,0 @@ -import {HerculesEventType} from "@code0-tech/hercules" - -export const someEventType: HerculesEventType = { - signature: "(): string", - editable: false, - identifier: "test_flow", -} diff --git a/ts/examples/simple-example-ts/src/fibonacciFunction.ts b/ts/examples/simple-example-ts/src/fibonacciFunction.ts deleted file mode 100644 index 0f35fc8..0000000 --- a/ts/examples/simple-example-ts/src/fibonacciFunction.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { - DisplayMessage, - HerculesFunctionContext, - Identifier, - OmitFunctionDefinition, - RuntimeParameter, - Signature -} from "@code0-tech/hercules"; - -@Identifier("fib") -@Signature("(number: number): number") -@RuntimeParameter({ - runtimeName: "number", - defaultValue: 20 -}) -@DisplayMessage({ - code: "de-DE", - content: "" -}) -export class FibonacciFunction { - run(context: HerculesFunctionContext, number: number): number { - console.log(context) - console.log("Project id:", context.projectId); - console.log("Execution id:", context.executionId); - console.log("Matched configs:", context.matchedConfig); // matched configs for the current execution - - function fibonacci(num: number): number { - if (num <= 1) return num; - return fibonacci(num - 1) + fibonacci(num - 2); - } - - return fibonacci(number) - } -} \ No newline at end of file diff --git a/ts/src/action_sdk.ts b/ts/src/action_sdk.ts deleted file mode 100644 index b2d2d6a..0000000 --- a/ts/src/action_sdk.ts +++ /dev/null @@ -1,165 +0,0 @@ -import {GrpcTransport} from "@protobuf-ts/grpc-transport"; -import {ChannelCredentials} from "@grpc/grpc-js"; -import type {ActionSdk, HerculesActionConfigurationDefinition, SdkState} from "./types.js"; -import {ActionTransferServiceClient, TransferRequest} from "@code0-tech/tucana/aquila"; -import {FlowTypeSetting,} from "@code0-tech/tucana/shared"; -import {constructValue, toAllowedValue} from "@code0-tech/tucana/helpers"; -import 'reflect-metadata'; -import {connect} from "./handler/connection"; -import {registerFunctionDefinitionClass} from "./sdk/builder/registerFunctionDefinitionClass"; -import {registerRuntimeFunctionDefinitionClass} from "./builder/registerRuntimeFunctionDefinitionClass"; - - -const createSdk = (config: ActionSdk["config"], configDefinitions?: HerculesActionConfigurationDefinition[]): ActionSdk => { - const transport = new GrpcTransport( - { - host: config.aquilaUrl, - channelCredentials: ChannelCredentials.createInsecure() - } - ) - const client = new ActionTransferServiceClient(transport); - - const state: SdkState = { - functions: [], - runtimeFunctions: [], - dataTypes: [], - flowTypes: [], - configurationDefinitions: configDefinitions?.map(value => { - return { - identifier: value.identifier, - name: value.name || [], - description: value.description || [], - type: value.type, - linkedDataTypeIdentifiers: value.linkedDataTypes || [], - defaultValue: constructValue(value.defaultValue || null), - } - }) || [], - projectConfigurations: [], - transport: transport, - client: client, - stream: undefined, - fullyConnected: false - } - - return { - registerFunctionDefinitionClass: registerFunctionDefinitionClass(config, state), - registerRuntimeFunctionDefinitionClass: registerRuntimeFunctionDefinitionClass(config, state), - fullyConnected(): boolean { - return state.fullyConnected; - }, - config, - onError: handler => { - state.stream?.responses.onError(handler) - }, - connect: options => { - return connect(state, config, options); - }, - getProjectActionConfigurations: () => { - return state.projectConfigurations.map(value => { - return { - projectId: value.projectId, - configValues: value.actionConfigurations.map(value => { - return { - identifier: value.identifier, - value: toAllowedValue(value.value || constructValue(null)), - } - }), - findConfig: identifier => { - const config = value.actionConfigurations.find(config => config.identifier === identifier); - return config ? toAllowedValue(config.value || constructValue(null)) : undefined; - } - } - }); - }, - registerConfigDefinitions: async (...actionConfigurations) => { - state.configurationDefinitions.push(...(actionConfigurations?.map(value => { - return { - identifier: value.identifier, - name: value.name || [], - description: value.description || [], - type: value.type, - linkedDataTypeIdentifiers: value.linkedDataTypes || [], - defaultValue: constructValue(value.defaultValue || null), - } - }) || [])) - - return Promise.resolve() - }, - registerDataTypes: async (...dataTypes) => { - dataTypes.forEach(dataType => { - state.dataTypes.push({ - identifier: dataType.identifier, - name: dataType.name || [], - alias: dataType.alias || [], - rules: dataType.rules || [], - genericKeys: dataType.genericKeys || [], - type: dataType.type, - linkedDataTypeIdentifiers: dataType.linkedDataTypes || [], - displayMessage: dataType.displayMessage || [], - definitionSource: "action", - version: config.version, - }); - }) - - - return Promise.resolve() - }, - registerEventTypes: async (...flowTypes) => { - flowTypes.forEach(flowType => { - state.flowTypes.push({ - signature: flowType.signature, - identifier: flowType.identifier, - name: flowType.name || [], - alias: flowType.alias || [], - description: flowType.description || [], - displayIcon: flowType.displayIcon || "tabler:note", - displayMessage: flowType.displayMessage || [], - documentation: flowType.documentation || [], - definitionSource: "action", - version: config.version, - linkedDataTypeIdentifiers: flowType.linkedDataTypes || [], - settings: (flowType.settings || []).map(setting => ({ - name: setting.name || [], - defaultValue: constructValue(setting.defaultValue || null), - identifier: setting.identifier, - description: setting.description || [], - unique: setting.unique || 1, - linkedDataTypeIdentifiers: setting.linkedDataTypeIdentifiers || [], - } as FlowTypeSetting)), - editable: flowType.editable || false - }); - }) - return Promise.resolve() - }, - dispatchEvent: async (eventType, projectId, payload) => { - if (!state.stream) { - return Promise.reject("SDK is not connected. Call connect() before dispatching events."); - } - const projectIdBigInt = typeof projectId === "bigint" - ? projectId - : BigInt(projectId); - - return state.stream.requests.send( - TransferRequest.create({ - data: { - oneofKind: "event", - event: { - projectId: projectIdBigInt, - eventType: eventType, - payload: constructValue(payload || null), - } - } - }) - ).catch(reason => { - return Promise.reject(reason); - }).then(() => { - return Promise.resolve(); - }) - } - } -} - -export { - createSdk, - connect -} \ No newline at end of file diff --git a/ts/src/builder/registerRuntimeFunctionDefinitionClass.ts b/ts/src/builder/registerRuntimeFunctionDefinitionClass.ts deleted file mode 100644 index 50951a1..0000000 --- a/ts/src/builder/registerRuntimeFunctionDefinitionClass.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type {RegisteredFunction, RegisteredRuntimeFunction, RuntimeFunctionDefinitionClass, SdkState} from "../types"; -import {buildRuntimeFunctionDefinition} from "../sdk/builder/builder"; - -export function registerRuntimeFunctionDefinitionClass(config: { - authToken: string; - aquilaUrl: string; - actionId: string; - version: string -}, state: SdkState) { - return (klass: RuntimeFunctionDefinitionClass): Promise => { - const omitFunctionDefinition = Reflect.getMetadata('hercules:omit_function_definition', klass) || false - - const runtimeFunction = buildRuntimeFunctionDefinition(klass, config); - const definition = runtimeFunction.definition - - state.runtimeFunctions.push(runtimeFunction as RegisteredRuntimeFunction) - if (!omitFunctionDefinition) { - state.functions.push({ - identifier: definition.runtimeName, - definition: { - ...definition, - runtimeDefinitionName: definition.runtimeName, - parameterDefinitions: definition.runtimeParameterDefinitions.map(param => { - return { - ...param, - runtimeDefinitionName: param.runtimeName - } - }) - } - } as RegisteredFunction) - } - - return Promise.resolve(); - }; -} \ No newline at end of file diff --git a/ts/src/handler/connectionHandler.ts b/ts/src/handler/connectionHandler.ts deleted file mode 100644 index 467c704..0000000 --- a/ts/src/handler/connectionHandler.ts +++ /dev/null @@ -1,112 +0,0 @@ -import type {RpcOptions} from "@protobuf-ts/runtime-rpc"; -import {constructValue, toAllowedValue} from "@code0-tech/tucana/helpers"; -import {handleExecutionRequest} from "../sdk/execution"; -import {handleLogon} from "../sdk/connection/logon"; -import {handleRuntimeFunctionDefinitions} from "../sdk/connection/runtimeFunctionDefinition"; -import {handleFunctionDefinitions} from "../sdk/connection/functionDefinition"; -import {handleFlowTypes} from "../sdk/connection/flowTypes"; -import {CodeZeroAction, CodeZeroEvent} from "../index"; -import {ActionTransferServiceClient} from "@code0-tech/tucana/aquila"; -import {GrpcTransport} from "@protobuf-ts/grpc-transport"; -import {ChannelCredentials} from "@grpc/grpc-js"; -import {handleDataTypes} from "./dataTypeHandler"; - - -export async function connect(action: CodeZeroAction, aquilaUrl: string, authToken: string, options?: RpcOptions): Promise { - console.debug("Trying to connect to aquila") - action.transport = new GrpcTransport({ - host: aquilaUrl, - channelCredentials: ChannelCredentials.createInsecure() - }) - const actionTransferServiceClient = new ActionTransferServiceClient(action.transport!) - const builtOptions: RpcOptions = { - meta: { - "authorization": authToken, - }, - ...options - } - action.stream = actionTransferServiceClient.transfer(builtOptions) - - await handleDataTypes(action, builtOptions); - await handleRuntimeFunctionDefinitions(state, builtOptions, config) - await handleFunctionDefinitions(state, builtOptions, config) - await handleFlowTypes(state, builtOptions, config) - await handleLogon(state, config); - - console.info("Connected successfully to aquila") - - - for await (const message of action.stream!.responses) { - action.emit(CodeZeroEvent.streamMessageReceived, message) - console.debug({ - message: message, - }, "Received message from stream") - switch (message.data.oneofKind) { - case "actionConfigurations": { - console.info("Received action configurations") - action.emit(CodeZeroEvent.actionConfigurationsReceived, message.data.actionConfigurations) - break - } - case "execution": { - action.emit(CodeZeroEvent.executionRequestReceived, message.data.execution) - break - } - default: { - action.emit(CodeZeroEvent.error, new Error("Received unknown message type from stream")) - } - } - } - - return new Promise(async (resolve, reject) => { - try { - for await (const message of state?.stream?.responses || []) { - switch (message?.data.oneofKind) { - case "actionConfigurations": { - logger.info("Received action configurations") - - const configs = message.data.actionConfigurations as any; - state.projectConfigurations = configs.actionConfigurations - resolve(state.projectConfigurations.map(value => { - return { - projectId: value.projectId, - configValues: value.actionConfigurations.map(value => { - return { - identifier: value.identifier, - value: toAllowedValue(value.value || constructValue(null)), - } - }), - findConfig: identifier => { - const config = value.actionConfigurations.find(config => config.identifier === identifier); - return config ? toAllowedValue(config.value || constructValue(null)) : undefined; - } - } - })); - state.fullyConnected = true - break; - } - - case "execution": { - logger.info({ - executionD: message.data.execution.executionIdentifier, - config, - }, "Handling execution request") - - logger.debug({ - message: message, - config, - }, "Handling execution request") - handleExecutionRequest(state, message) - break; - } - } - } - } catch (reason) { - logger.error({ - err: reason, - config - }, "Error occurred in stream") - reject(reason); - } - }) -} - diff --git a/ts/src/handler/dataTypeHandler.ts b/ts/src/handler/dataTypeHandler.ts deleted file mode 100644 index 0747f43..0000000 --- a/ts/src/handler/dataTypeHandler.ts +++ /dev/null @@ -1,25 +0,0 @@ -import {DataTypeServiceClient, DataTypeUpdateRequest} from "@code0-tech/tucana/aquila"; -import {RpcOptions} from "@protobuf-ts/runtime-rpc"; -import {CodeZeroAction, CodeZeroEvent} from "../index"; - -export async function handleDataTypes(action: CodeZeroAction, grpcOptions: RpcOptions) { - const dataTypeClient = new DataTypeServiceClient(action.transport!) - try { - console.debug("Sent data types request") - const call = await dataTypeClient.update(DataTypeUpdateRequest.create({ - dataTypes: [ - ...action.dataTypes - ] - }), grpcOptions) - if (!call.response.success) { - action.emit(CodeZeroEvent.dataTypesUpdateFailed, new Error("Failed to update data types")) - return Promise.reject(call.response); - } - action.emit(CodeZeroEvent.dataTypesUpdated, call.response) - } catch (error) { - console.error({ - err: error, - }, "Error while updating data types") - return Promise.reject(error); - } -} diff --git a/ts/src/sdk/builder/builder.ts b/ts/src/sdk/builder/builder.ts deleted file mode 100644 index 2ec64e0..0000000 --- a/ts/src/sdk/builder/builder.ts +++ /dev/null @@ -1,15 +0,0 @@ -import 'reflect-metadata'; -import {constructValue} from "@code0-tech/tucana/helpers"; -import { - RuntimeFunctionDefinitionClass, - RegisteredRuntimeFunction, - HerculesRuntimeFunctionDefinitionParameter, - HerculesRuntimeFunctionDefinition, - ActionSdk, -} from "../../types"; -import {RuntimeParameterDefinition} from "@code0-tech/tucana/shared"; - -export function buildRuntimeFunctionDefinition(klass: RuntimeFunctionDefinitionClass, config: ActionSdk["config"]): RegisteredRuntimeFunction { - -} - diff --git a/ts/src/sdk/builder/registerFunctionDefinitionClass.ts b/ts/src/sdk/builder/registerFunctionDefinitionClass.ts deleted file mode 100644 index 7363003..0000000 --- a/ts/src/sdk/builder/registerFunctionDefinitionClass.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { - FunctionDefinitionConstructor, - HerculesFunctionDefinition, - HerculesFunctionDefinitionParameter, RegisteredFunction, - SdkState -} from "../../types"; -import {buildRuntimeFunctionDefinition} from "./builder"; -import {constructValue} from "@code0-tech/tucana/helpers"; - -export function registerFunctionDefinitionClass(config: { - authToken: string; - aquilaUrl: string; - actionId: string; - version: string -}, state: SdkState) { - return (klass: FunctionDefinitionConstructor): Promise => { - -} diff --git a/ts/src/sdk/connection/flowTypes.ts b/ts/src/sdk/connection/flowTypes.ts deleted file mode 100644 index 3a2cdba..0000000 --- a/ts/src/sdk/connection/flowTypes.ts +++ /dev/null @@ -1,34 +0,0 @@ -import {ActionSdk, SdkState} from "../../types"; -import {FlowTypeServiceClient, FlowTypeUpdateRequest} from "@code0-tech/tucana/aquila"; -import {RpcOptions} from "@protobuf-ts/runtime-rpc"; -import {logger} from "../../logger"; - -export async function handleFlowTypes(state: SdkState, builtOptions: RpcOptions | undefined, config: ActionSdk["config"]) { - const flowTypeClient = new FlowTypeServiceClient(state.transport) - const request = { - flowTypes: [ - ...state.flowTypes - ] - }; - try { - - await flowTypeClient.update(FlowTypeUpdateRequest.create(request), builtOptions).then(value => { - if (!value.response.success) { - logger.error({ - err: value.response, - request: value.request, - config, - }) - return Promise.reject(value.response); - } - }) - - } catch (error) { - logger.error({ - err: error, - request, - config, - }, "Error while updating flow types") - return Promise.reject(error); - } -} diff --git a/ts/src/sdk/connection/functionDefinition.ts b/ts/src/sdk/connection/functionDefinition.ts deleted file mode 100644 index 01065fe..0000000 --- a/ts/src/sdk/connection/functionDefinition.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type {ActionSdk, SdkState} from "../../types"; -import type {RpcOptions} from "@protobuf-ts/runtime-rpc"; -import {FunctionDefinitionServiceClient, FunctionDefinitionUpdateRequest} from "@code0-tech/tucana/aquila"; -import {logger} from "../../logger"; - -export async function handleFunctionDefinitions(state: SdkState, builtOptions: RpcOptions | undefined, config: ActionSdk["config"]) { - const FunctionDefinitionClient = new FunctionDefinitionServiceClient(state.transport) - try { - const finishedCall = await FunctionDefinitionClient.update( - FunctionDefinitionUpdateRequest.create( - { - functions: [ - ...state.functions.map(func => ({ - ...func.definition, - })) - ] - } - ), builtOptions - ); - - if (!finishedCall.response.success) { - logger.error({ - err: finishedCall.response, - request: finishedCall.request, - config, - }, "Error while updating function definitions") - return Promise.reject(finishedCall.response); - } - } catch (error) { - logger.error({ - err: error, - config, - }, "Error while updating function definitions") - return Promise.reject(error); - } - logger.debug("Updated function definitions") -} diff --git a/ts/src/sdk/connection/logon.ts b/ts/src/sdk/connection/logon.ts deleted file mode 100644 index a5c576a..0000000 --- a/ts/src/sdk/connection/logon.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type {SdkState} from "../../types"; -import {TransferRequest} from "@code0-tech/tucana/aquila"; -import {logger} from "../../logger"; - -export async function handleLogon(state: SdkState, config: { - authToken: string; - aquilaUrl: string; - actionId: string; - version: string -}) { - await state.stream!.requests.send( - TransferRequest.create({ - data: { - oneofKind: "logon", - logon: { - actionIdentifier: config.actionId, - version: config.version, - actionConfigurations: state.configurationDefinitions - } - } - } - ), - ).catch(reason => { - logger.error({ - err: reason, - config, - }, "Failed to send logon request") - return Promise.reject(reason); - }) - - logger.debug("Successfully sent logon request") -} diff --git a/ts/src/sdk/connection/runtimeFunctionDefinition.ts b/ts/src/sdk/connection/runtimeFunctionDefinition.ts deleted file mode 100644 index 2a389c6..0000000 --- a/ts/src/sdk/connection/runtimeFunctionDefinition.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type {ActionSdk, SdkState} from "../../types"; -import type {RpcOptions} from "@protobuf-ts/runtime-rpc"; -import { - RuntimeFunctionDefinitionServiceClient, - RuntimeFunctionDefinitionUpdateRequest -} from "@code0-tech/tucana/aquila"; - -export async function handleRuntimeFunctionDefinitions(state: SdkState, builtOptions: RpcOptions | undefined, config: ActionSdk["config"]) { - const request = RuntimeFunctionDefinitionUpdateRequest.create( - { - runtimeFunctions: [ - ...state.runtimeFunctions.map(func => ({ - ...func.definition, - })) - ] - } - ); - try { - const runtimeFunctionDefinitionClient = new RuntimeFunctionDefinitionServiceClient(state.transport) - await runtimeFunctionDefinitionClient.update( - request, builtOptions - ).then(value => { - if (!value.response.success) { - console.error({ - err: value.response, - request: value.request, - config, - }) - return Promise.reject(value.response); - } - }) - } catch (error) { - console.debug({ - ...request.runtimeFunctions[0].runtimeParameterDefinitions[0].defaultValue - }) - logger.error({ - err: error, - request: request, - config, - }, "Error while updating runtime function definitions") - return Promise.reject(error); - } - logger.debug("Successfully updated runtime function definitions") -} diff --git a/ts/src/sdk/definitions/functions/functions.mapper.ts b/ts/src/sdk/definitions/functions/functions.mapper.ts deleted file mode 100644 index 33f02ae..0000000 --- a/ts/src/sdk/definitions/functions/functions.mapper.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { - FunctionDefinitionClass, HerculesFunctionDefinition, HerculesFunctionDefinitionParameter, - HerculesRuntimeFunctionDefinition, HerculesRuntimeFunctionDefinitionParameter, RuntimeFunctionDefinitionClass -} from "./functions"; -import {constructValue} from "@code0-tech/tucana/helpers"; - -export const functionMap = (klass: FunctionDefinitionClass): HerculesFunctionDefinition => { - const parentClass = Object.getPrototypeOf(klass) - const runtimeFunction = runtimeFunctionMap(parentClass); - - const identifier: string = Reflect.getMetadata('hercules:identifier', klass) - const functionParameters: HerculesFunctionDefinitionParameter[] = Reflect.getMetadata('hercules:function_parameters', klass) - const names: HerculesFunctionDefinition["name"] = Reflect.getMetadata('hercules:name', klass) - const displayMessage: HerculesFunctionDefinition["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass) - const description: HerculesFunctionDefinition["description"] = Reflect.getMetadata('hercules:description', klass) - const deprecationMessage: HerculesFunctionDefinition["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass) - const alias: HerculesFunctionDefinition["alias"] = Reflect.getMetadata('hercules:alias', klass) - const documentation: HerculesFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass) - const signature: HerculesFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass) - const linkedDataTypeIdentifiers: HerculesFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) - const displayIcon: HerculesFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass) - const throwsError: HerculesFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass) - - if (functionParameters.length > (runtimeFunction?.parameters?.length ?? 0)) { - throw new Error(`Function definition class ${klass.name} has more function parameters than its runtime function.`) - } - - functionParameters.map(functionParameter => functionParameter.runtimeName).forEach(value => { - if (!runtimeFunction?.parameters?.map(value => value.runtimeName).includes(value)) { - throw new Error(`Function definition class ${klass.name} has a function parameter with runtime name ${value} that does not exist in its runtime function.`) - } - }) - - - runtimeFunction?.parameters?.forEach(runtimeDefinition => { - if (functionParameters.find((param: HerculesFunctionDefinitionParameter) => param.runtimeName === runtimeDefinition.runtimeName)) { - return; - } - functionParameters.push({ - ...runtimeDefinition, - runtimeDefinitionName: runtimeDefinition.runtimeName - }) - }) - - - return { - runtimeDefinitionName: runtimeFunction.runtimeName, - runtimeName: identifier || runtimeFunction.runtimeName, - signature: signature || runtimeFunction.signature, - throwsError: throwsError || runtimeFunction.throwsError, - alias: alias || runtimeFunction.alias, - description: description || runtimeFunction.description, - name: names || runtimeFunction.name, - documentation: documentation || runtimeFunction.documentation, - deprecationMessage: deprecationMessage || runtimeFunction.deprecationMessage, - displayMessage: displayMessage || runtimeFunction.displayMessage, - displayIcon: displayIcon || runtimeFunction.displayIcon, - linkedDataTypes: linkedDataTypeIdentifiers || runtimeFunction.linkedDataTypes, - parameters: functionParameters.map(value => { - return { - ...value, - runtimeDefinitionName: value.runtimeDefinitionName || value.runtimeName, - name: value.name || [], - description: value.description || [], - documentation: value.documentation || [], - hidden: value.hidden || false, - optional: value.optional || false, - defaultValue: value.defaultValue ? constructValue(value.defaultValue || null) : undefined, - } - }) - } -} -export const runtimeFunctionMap = (klass: RuntimeFunctionDefinitionClass): HerculesRuntimeFunctionDefinition => { - const identifier: string = Reflect.getMetadata('hercules:identifier', klass) - const runtimeParameters: HerculesRuntimeFunctionDefinitionParameter[] = Reflect.getMetadata('hercules:runtime_parameters', klass) - const names: HerculesRuntimeFunctionDefinition["name"] = Reflect.getMetadata('hercules:name', klass) || [] - const displayMessage: HerculesRuntimeFunctionDefinition["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass) || [] - const description: HerculesRuntimeFunctionDefinition["description"] = Reflect.getMetadata('hercules:description', klass) || [] - const deprecationMessage: HerculesRuntimeFunctionDefinition["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass) || [] - const alias: HerculesRuntimeFunctionDefinition["alias"] = Reflect.getMetadata('hercules:alias', klass) || [] - const documentation: HerculesRuntimeFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass) || [] - const signature: HerculesRuntimeFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass) - const linkedDataTypeIdentifiers: HerculesRuntimeFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) || [] - const displayIcon: HerculesRuntimeFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass) || "" - const throwsError: HerculesRuntimeFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass) || false - const runFunction = new klass().run - - if (!identifier) { - throw new Error(`Runtime function class ${klass.name} is missing an identifier. Please add @Identifier("your_identifier") decorator to the class.`) - } - if (!signature) { - throw new Error(`Runtime function class ${klass.name} is missing a signature. Please add @Signature("(param1: TYPE_1): RETURN_TYPE") decorator to the class.`) - } - - return { - alias: alias || [], - name: names || [], - description: description || [], - runtimeName: identifier, - deprecationMessage: deprecationMessage || [], - displayIcon: displayIcon || "tabler:note", - displayMessage: displayMessage || [], - documentation: documentation || [], - linkedDataTypes: linkedDataTypeIdentifiers || [], - parameters: runtimeParameters.map(param => { - return { - ...param, - name: param.name || [], - description: param.description || [], - documentation: param.documentation || [], - hidden: param.hidden || false, - optional: param.optional || false, - defaultValue: param.defaultValue ? constructValue(param.defaultValue) : undefined, - } - }), - signature: signature, - throwsError: throwsError || false, - handler: runFunction - } - -} diff --git a/ts/src/sdk/definitions/functions/functions.ts b/ts/src/sdk/definitions/functions/functions.ts deleted file mode 100644 index 118ebab..0000000 --- a/ts/src/sdk/definitions/functions/functions.ts +++ /dev/null @@ -1,95 +0,0 @@ -import {PlainValue} from "@code0-tech/tucana/helpers"; -import { - HerculesTranslation, -} from "../../../types"; - - -export interface HerculesRuntimeFunctionDefinitionParameter { - runtimeName: string, - defaultValue?: PlainValue, - name?: HerculesTranslation[], - description?: HerculesTranslation[], - documentation?: HerculesTranslation[], - hidden?: boolean, - optional?: boolean -} - -export interface HerculesRuntimeFunctionDefinition { - runtimeName: string, - parameters?: HerculesRuntimeFunctionDefinitionParameter[], - signature: string, - throwsError?: boolean, - name?: HerculesTranslation[], - description?: HerculesTranslation[], - documentation?: HerculesTranslation[], - deprecationMessage?: HerculesTranslation[], - displayMessage?: HerculesTranslation[], - alias?: HerculesTranslation[], - linkedDataTypes?: string[], - displayIcon?: string, - handler: (...args: any[]) => Promise | PlainValue, -} - -export interface HerculesFunctionDefinitionParameter { - runtimeName: string, - defaultValue?: PlainValue, - name?: HerculesTranslation[], - description?: HerculesTranslation[], - documentation?: HerculesTranslation[], - hidden?: boolean, - optional?: boolean, - runtimeDefinitionName?: string -} - -export interface HerculesFunctionDefinition { - runtimeDefinitionName: string, - runtimeName: string, - parameters?: HerculesFunctionDefinitionParameter[], - signature: string, - throwsError?: boolean, - name?: HerculesTranslation[], - description?: HerculesTranslation[], - documentation?: HerculesTranslation[], - deprecationMessage?: HerculesTranslation[], - displayMessage?: HerculesTranslation[], - alias?: HerculesTranslation[], - linkedDataTypes?: string[], - displayIcon?: string, -} - - -export type FunctionDefinitionClass = new () => T; - -export type RuntimeFunctionDefinitionRunnable = { - run: (...args: any[]) => Promise | PlainValue; -}; - -export type RuntimeFunctionDefinitionClass = - new () => T; - -export const OmitFunctionDefinition = (): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:omit_function_definition', true, target) - -export const RuntimeParameter = (parameter: HerculesRuntimeFunctionDefinitionParameter): ClassDecorator => - (target) => { - const parameters = Reflect.getMetadata('hercules:runtime_parameters', target) || []; - parameters.push(parameter); - - Reflect.defineMetadata('hercules:runtime_parameters', parameters, target) - } - -export const FunctionParameter = (parameter: HerculesFunctionDefinitionParameter): ClassDecorator => - (target) => { - const parameters = Reflect.getMetadata('hercules:function_parameters', target) || []; - parameters.push(parameter); - - Reflect.defineMetadata('hercules:function_parameters', parameters, target) - } - -export const ThrowsError = (throwsError: boolean = true): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:throws_error', throwsError, target) - - - -export const LinkedDataTypeIdentifiers = (...linkedDataTypeIdentifiers: string[]): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:linked_data_type_identifiers', linkedDataTypeIdentifiers, target) diff --git a/ts/src/sdk/execution.ts b/ts/src/sdk/execution.ts deleted file mode 100644 index 183f0d2..0000000 --- a/ts/src/sdk/execution.ts +++ /dev/null @@ -1,187 +0,0 @@ -import {logger} from "../logger"; -import {constructValue, PlainValue, toAllowedValue} from "@code0-tech/tucana/helpers"; -import { - SdkState, - HerculesFunctionContext, - RuntimeErrorException, RegisteredRuntimeFunction -} from "../types.js"; -import {TransferRequest, ExecutionRequest, TransferResponse} from "@code0-tech/tucana/aquila"; -import {ActionProjectConfiguration} from "@code0-tech/tucana/shared"; - -function buildParams(execution: ExecutionRequest, func: RegisteredRuntimeFunction, message: TransferResponse) { - const params = Object.entries(execution.parameters!.fields!).map(([key, value]) => { - const param = func.definition.runtimeParameterDefinitions - .find(p => p.runtimeName === key); - - const parameterValue = param ? toAllowedValue(value) : undefined; - if (!parameterValue) return parameterValue - return parameterValue; - }); - - logger.debug({ - message, - BuiltParameter: params - }) - return params -} - -function buildContext(message: TransferResponse, execution: ExecutionRequest, state: SdkState): { - func: RegisteredRuntimeFunction, - context: HerculesFunctionContext, - conf: ActionProjectConfiguration, - params: (PlainValue | undefined)[] -} { - const func = state.runtimeFunctions.find(value => value.identifier == execution.functionIdentifier); - - if (!func) { - logger.error({ - message, - state - }, "Received execution request but no matching function found") - throw new Error("Received execution request for function " + execution.functionIdentifier + " but no matching function found") - } - - const params = buildParams(execution, func, message); - - let conf = state.projectConfigurations.find(config => { - return config.projectId === execution.projectId - }) - - if (!conf) { - logger.error({ - message, - execution - }, "No configuration found") - conf = { - projectId: 0n, - actionConfigurations: [] - } - } - const context: HerculesFunctionContext = { - projectId: execution.projectId, - executionId: execution.executionIdentifier, - matchedConfig: { - projectId: conf.projectId, - configValues: conf.actionConfigurations.map(value => { - return { - identifier: value.identifier, - value: toAllowedValue(value.value || constructValue(null)), - } - }), - findConfig: identifier => { - const config = conf.actionConfigurations.find(config => config.identifier === identifier); - return config ? toAllowedValue(config.value || constructValue(null)) : undefined; - } - } - } - return { - func, - context, - conf, - params - }; -} - -export function handleExecutionRequest(state: SdkState, message: TransferResponse) { - if (!message.data || message.data.oneofKind !== "execution") { - return - } - const execution = message.data.execution as ExecutionRequest; - - - const {func, context, conf, params} = buildContext(message, execution, state); - logger.debug({ - message, - conf, - context - }) - - const funcHandler = func.handler - - if (funcHandler.length == params.length + 1) { - // handler has context parameter - params.unshift(context) - } else if (funcHandler.length > params.length + 1) { - logger.error({ - params, - func, - }, "Handler has more parameters than provided arguments") - return; - } - - Promise.resolve(funcHandler(...params)) .then((value: any) => { - const request = TransferRequest.create({ - data: { - oneofKind: "result", - result: { - executionIdentifier: execution.executionIdentifier, - result: { - oneofKind: "success", - success: constructValue(value) - }, - } - } - }); - logger.debug({ - request: request - }, "Responding with execution result") - - state.stream!.requests.send(request).catch(reason => { - logger.error({ - err: reason, - request: request, - message, - execution - }, "Responding with execution result lead to error") - }); - - }).catch(reason => { - logger.warn({ - err: reason - }, "Executed function lead to error") - let errorData - if (reason instanceof RuntimeErrorException) { - errorData = { - code: reason.code, - description: reason.description - } - } else { - errorData = { - code: "UNKNOWN_ERROR", - description: reason.toString() - } - - logger.warn({ - err: reason, - func, - execution - }, "Error occured while executing function, but not an RuntimeErrorException") - } - - - logger.debug({errorData}, "Responding with execution error") - - const request = TransferRequest.create({ - data: { - oneofKind: "result", - result: { - executionIdentifier: execution.executionIdentifier, - result: { - oneofKind: "error", - error: errorData - }, - } - } - }); - - state.stream!.requests.send(request).catch(reason => { - logger.error({ - err: reason, - request: request, - execution, - message - }, "Failed to send execution result error") - }); - }) -} - From cbeb2538775e78b2631ff655d9f049a152d40a62 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 00:47:12 +0200 Subject: [PATCH 13/43] feat: manager pattern --- ts/src/manager/BaseManager.ts | 85 ++++++++++++++++++++++++ ts/src/manager/EventManager.ts | 4 ++ ts/src/manager/FunctionManager.ts | 4 ++ ts/src/manager/RuntimeEventManager.ts | 4 ++ ts/src/manager/RuntimeFunctionManager.ts | 4 ++ ts/src/manager/config-manager.ts | 23 +++++++ 6 files changed, 124 insertions(+) create mode 100644 ts/src/manager/BaseManager.ts create mode 100644 ts/src/manager/EventManager.ts create mode 100644 ts/src/manager/FunctionManager.ts create mode 100644 ts/src/manager/RuntimeEventManager.ts create mode 100644 ts/src/manager/RuntimeFunctionManager.ts create mode 100644 ts/src/manager/config-manager.ts diff --git a/ts/src/manager/BaseManager.ts b/ts/src/manager/BaseManager.ts new file mode 100644 index 0000000..e716100 --- /dev/null +++ b/ts/src/manager/BaseManager.ts @@ -0,0 +1,85 @@ +export abstract class BaseManager { + readonly cache = new Map(); + + get size(): number { + return this.cache.size; + } + + get(key: K): V | undefined { + return this.cache.get(key); + } + + has(key: K): boolean { + return this.cache.has(key); + } + + set(key: K, value: V): this { + this.cache.set(key, value); + return this; + } + + delete(key: K): boolean { + return this.cache.delete(key); + } + + clear(): void { + this.cache.clear(); + } + + values(): V[] { + return [...this.cache.values()]; + } + + keys(): K[] { + return [...this.cache.keys()]; + } + + entries(): [K, V][] { + return [...this.cache.entries()]; + } + + find(predicate: (value: V, key: K) => boolean): V | undefined { + for (const [key, value] of this.cache) { + if (predicate(value, key)) return value; + } + return undefined; + } + + filter(predicate: (value: V, key: K) => boolean): V[] { + const result: V[] = []; + for (const [key, value] of this.cache) { + if (predicate(value, key)) result.push(value); + } + return result; + } + + map(fn: (value: V, key: K) => T): T[] { + const result: T[] = []; + for (const [key, value] of this.cache) { + result.push(fn(value, key)); + } + return result; + } + + some(predicate: (value: V, key: K) => boolean): boolean { + for (const [key, value] of this.cache) { + if (predicate(value, key)) return true; + } + return false; + } + + every(predicate: (value: V, key: K) => boolean): boolean { + for (const [key, value] of this.cache) { + if (!predicate(value, key)) return false; + } + return true; + } + + forEach(fn: (value: V, key: K) => void): void { + this.cache.forEach((value, key) => fn(value, key)); + } + + [Symbol.iterator](): IterableIterator<[K, V]> { + return this.cache[Symbol.iterator](); + } +} diff --git a/ts/src/manager/EventManager.ts b/ts/src/manager/EventManager.ts new file mode 100644 index 0000000..61c7cc3 --- /dev/null +++ b/ts/src/manager/EventManager.ts @@ -0,0 +1,4 @@ +import {BaseManager} from "./BaseManager.ts"; +import {HerculesEvent} from "../models/event.ts"; + +export class EventManager extends BaseManager {} diff --git a/ts/src/manager/FunctionManager.ts b/ts/src/manager/FunctionManager.ts new file mode 100644 index 0000000..e267cfb --- /dev/null +++ b/ts/src/manager/FunctionManager.ts @@ -0,0 +1,4 @@ +import {BaseManager} from "./BaseManager.ts"; +import type {HerculesFunctionDefinition} from "../models/function.ts"; + +export class FunctionManager extends BaseManager {} diff --git a/ts/src/manager/RuntimeEventManager.ts b/ts/src/manager/RuntimeEventManager.ts new file mode 100644 index 0000000..ddef553 --- /dev/null +++ b/ts/src/manager/RuntimeEventManager.ts @@ -0,0 +1,4 @@ +import {BaseManager} from "./BaseManager.ts"; +import {HerculesRuntimeEvent} from "../models/runtime-event.ts"; + +export class RuntimeEventManager extends BaseManager {} diff --git a/ts/src/manager/RuntimeFunctionManager.ts b/ts/src/manager/RuntimeFunctionManager.ts new file mode 100644 index 0000000..bf8402e --- /dev/null +++ b/ts/src/manager/RuntimeFunctionManager.ts @@ -0,0 +1,4 @@ +import {BaseManager} from "./BaseManager.ts"; +import type {HerculesRuntimeFunctionDefinition} from "../models/runtime-function.ts"; + +export class RuntimeFunctionManager extends BaseManager {} diff --git a/ts/src/manager/config-manager.ts b/ts/src/manager/config-manager.ts new file mode 100644 index 0000000..5078e73 --- /dev/null +++ b/ts/src/manager/config-manager.ts @@ -0,0 +1,23 @@ +import {constructValue, toAllowedValue} from "@code0-tech/tucana/helpers"; +import type {ModuleProjectConfigurations} from "@code0-tech/tucana/shared"; +import type {HerculesActionProjectConfiguration} from "../types.ts"; +import {BaseManager} from "./BaseManager.ts"; + +export class ConfigManager extends BaseManager { + update(configs: ModuleProjectConfigurations[]): void { + this.clear(); + for (const config of configs) { + this.set(config.projectId, { + projectId: config.projectId, + configValues: config.moduleConfigurations.map(mc => ({ + identifier: mc.identifier, + value: toAllowedValue(mc.value || constructValue(null)), + })), + findConfig: identifier => { + const mc = config.moduleConfigurations.find(c => c.identifier === identifier); + return mc ? toAllowedValue(mc.value || constructValue(null)) : undefined; + }, + }); + } + } +} From 6f669ddfdb3c3d6019204d9c378d375f232ca607 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 00:47:49 +0200 Subject: [PATCH 14/43] feat: actions / paket handler --- ts/src/actions/Execution.ts | 95 ++++++++++++++++++++++++++ ts/src/actions/ModuleConfigurations.ts | 10 +++ ts/src/actions/index.ts | 13 ++++ 3 files changed, 118 insertions(+) create mode 100644 ts/src/actions/Execution.ts create mode 100644 ts/src/actions/ModuleConfigurations.ts create mode 100644 ts/src/actions/index.ts diff --git a/ts/src/actions/Execution.ts b/ts/src/actions/Execution.ts new file mode 100644 index 0000000..aadf0fb --- /dev/null +++ b/ts/src/actions/Execution.ts @@ -0,0 +1,95 @@ +import {constructValue, PlainValue, toAllowedValue} from "@code0-tech/tucana/helpers"; +import {ActionExecutionRequest, ActionExecutionResponse, ActionTransferRequest} from "@code0-tech/tucana/aquila"; +import {NodeExecutionResult, Error as ProtoError} from "@code0-tech/tucana/shared"; +import {HerculesFunctionContext, RuntimeErrorException} from "../types.ts"; +import {HerculesRuntimeFunctionDefinition} from "../models/runtime-function.ts"; +import {CodeZeroEvent} from "../events.ts"; +import type {CodeZeroAction} from "../CodeZeroAction.ts"; + +export const packetType = "execution"; + +function buildParams(execution: ActionExecutionRequest, func: HerculesRuntimeFunctionDefinition): (PlainValue | undefined)[] { + return (func.parameters || []).map(param => { + const field = execution.parameters?.fields?.[param.runtimeName]; + return field ? toAllowedValue(field) : undefined; + }); +} + +export function handle(action: CodeZeroAction, execution: ActionExecutionRequest): void { + action.emit(CodeZeroEvent.executionRequestReceived, execution); + + const func = action.runtimeFunctions.get(execution.functionIdentifier); + if (!func) { + console.error("Received execution request for unknown function:", execution.functionIdentifier); + return; + } + + const params = buildParams(execution, func); + + const conf = action.configs.get(execution.projectId) ?? { + projectId: 0n, + configValues: [], + findConfig: () => undefined, + }; + + const context: HerculesFunctionContext = { + projectId: execution.projectId, + executionId: execution.executionIdentifier, + matchedConfig: conf, + }; + + const startedAt = BigInt(Date.now()); + const funcHandler = func.handler; + const allParams: (PlainValue | undefined)[] = + funcHandler.length === params.length + 1 ? [context as PlainValue, ...params] : params; + + Promise.resolve(funcHandler(...allParams)).then((value: PlainValue) => { + const finishedAt = BigInt(Date.now()); + action.stream!.requests.send(ActionTransferRequest.create({ + data: { + oneofKind: "result", + result: ActionExecutionResponse.create({ + executionIdentifier: execution.executionIdentifier, + nodeResult: NodeExecutionResult.create({ + id: {oneofKind: undefined}, + startedAt, + finishedAt, + parameterResults: [], + result: {oneofKind: "success", success: constructValue(value)}, + }), + }), + }, + })).catch(err => console.error("Failed to send execution result:", err)); + + }).catch((error: unknown) => { + const finishedAt = BigInt(Date.now()); + const isRuntimeError = error instanceof RuntimeErrorException; + action.stream!.requests.send(ActionTransferRequest.create({ + data: { + oneofKind: "result", + result: ActionExecutionResponse.create({ + executionIdentifier: execution.executionIdentifier, + nodeResult: NodeExecutionResult.create({ + id: {oneofKind: undefined}, + startedAt, + finishedAt, + parameterResults: [], + result: { + oneofKind: "error", + error: ProtoError.create({ + code: isRuntimeError ? (error as RuntimeErrorException).code : "UNKNOWN_ERROR", + category: "RUNTIME", + message: isRuntimeError + ? ((error as RuntimeErrorException).description || (error as Error).message) + : String(error), + timestamp: finishedAt, + version: action.version, + dependencies: {}, + }), + }, + }), + }), + }, + })).catch(err => console.error("Failed to send execution error:", err)); + }); +} diff --git a/ts/src/actions/ModuleConfigurations.ts b/ts/src/actions/ModuleConfigurations.ts new file mode 100644 index 0000000..2a6931f --- /dev/null +++ b/ts/src/actions/ModuleConfigurations.ts @@ -0,0 +1,10 @@ +import type {ModuleConfigurations} from "@code0-tech/tucana/shared"; +import {CodeZeroEvent} from "../events.ts"; +import type {CodeZeroAction} from "../CodeZeroAction.ts"; + +export const packetType = "moduleConfigurations"; + +export function handle(action: CodeZeroAction, data: ModuleConfigurations): void { + action.configs.update(data.moduleConfigurations); + action.emit(CodeZeroEvent.moduleUpdated, data); +} diff --git a/ts/src/actions/index.ts b/ts/src/actions/index.ts new file mode 100644 index 0000000..94272d7 --- /dev/null +++ b/ts/src/actions/index.ts @@ -0,0 +1,13 @@ +import type {CodeZeroAction} from "../CodeZeroAction.ts"; +import * as ModuleConfigurations from "./ModuleConfigurations.ts"; +import * as Execution from "./Execution.ts"; + +export interface Action { + packetType: string; + handle(action: CodeZeroAction, data: unknown): void; +} + +export const actions: Action[] = [ + ModuleConfigurations, + Execution, +]; From 9612bfc7a97ce4b1d6e5a9dd64ae526fd2583a12 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 00:48:13 +0200 Subject: [PATCH 15/43] feat: models --- ts/src/models/data-type.ts | 17 +++++++++++++++ ts/src/models/event.ts | 34 ++++++++++++++++++++++++++++++ ts/src/models/function.ts | 32 ++++++++++++++++++++++++++++ ts/src/models/runtime-event.ts | 31 +++++++++++++++++++++++++++ ts/src/models/runtime-function.ts | 35 +++++++++++++++++++++++++++++++ 5 files changed, 149 insertions(+) create mode 100644 ts/src/models/data-type.ts create mode 100644 ts/src/models/event.ts create mode 100644 ts/src/models/function.ts create mode 100644 ts/src/models/runtime-event.ts create mode 100644 ts/src/models/runtime-function.ts diff --git a/ts/src/models/data-type.ts b/ts/src/models/data-type.ts new file mode 100644 index 0000000..6c20759 --- /dev/null +++ b/ts/src/models/data-type.ts @@ -0,0 +1,17 @@ +import {DefinitionDataTypeRule} from "@code0-tech/tucana/shared"; +import {HerculesTranslation} from "../types.ts"; + +export interface HerculesDataType { + identifier: string, + name?: HerculesTranslation[], + displayMessage?: HerculesTranslation[], + alias?: HerculesTranslation[], + rules?: DefinitionDataTypeRule[], + genericKeys?: string[], + type: string, + linkedDataTypes?: string[], +} + +export interface DataTypeDefinitionRunnable {} + +export type DataTypeClass = new () => DataTypeDefinitionRunnable; diff --git a/ts/src/models/event.ts b/ts/src/models/event.ts new file mode 100644 index 0000000..f73ba66 --- /dev/null +++ b/ts/src/models/event.ts @@ -0,0 +1,34 @@ +import {PlainValue} from "@code0-tech/tucana/helpers"; +import {HerculesTranslation} from "../types.ts"; +import {FlowTypeSetting_UniquenessScope} from "@code0-tech/tucana/shared"; +import {RuntimeEventClass} from "./runtime-event.ts"; + +export interface HerculesEventSetting { + identifier: string, + unique?: FlowTypeSetting_UniquenessScope, + linkedDataTypeIdentifiers?: string[], + defaultValue?: PlainValue, + name?: HerculesTranslation[], + description?: HerculesTranslation[], + optional?: boolean, + hidden?: boolean, +} + +export interface HerculesEvent { + identifier: string, + settings?: HerculesEventSetting[], + signature: string, + linkedDataTypes?: string[], + editable?: boolean, + name?: HerculesTranslation[], + description?: HerculesTranslation[], + documentation?: HerculesTranslation[], + displayMessage?: HerculesTranslation[], + alias?: HerculesTranslation[], + displayIcon?: string, + runtimeIdentifier?: string, +} + +export interface EventDefinitionRunnable {} + +export type EventClass = new () => InstanceType; diff --git a/ts/src/models/function.ts b/ts/src/models/function.ts new file mode 100644 index 0000000..d2a09ea --- /dev/null +++ b/ts/src/models/function.ts @@ -0,0 +1,32 @@ +import {HerculesTranslation} from "../types.ts"; +import {PlainValue} from "@code0-tech/tucana/helpers"; +import {RuntimeFunctionDefinitionClass} from "./runtime-function.ts"; + +export interface HerculesFunctionDefinitionParameter { + runtimeName: string, + defaultValue?: PlainValue, + name?: HerculesTranslation[], + description?: HerculesTranslation[], + documentation?: HerculesTranslation[], + hidden?: boolean, + optional?: boolean, + runtimeDefinitionName?: string, +} + +export interface HerculesFunctionDefinition { + runtimeDefinitionName: string, + runtimeName: string, + parameters?: HerculesFunctionDefinitionParameter[], + signature: string, + throwsError?: boolean, + name?: HerculesTranslation[], + description?: HerculesTranslation[], + documentation?: HerculesTranslation[], + deprecationMessage?: HerculesTranslation[], + displayMessage?: HerculesTranslation[], + alias?: HerculesTranslation[], + linkedDataTypes?: string[], + displayIcon?: string, +} + +export type FunctionDefinitionClass = new () => InstanceType; diff --git a/ts/src/models/runtime-event.ts b/ts/src/models/runtime-event.ts new file mode 100644 index 0000000..4469edf --- /dev/null +++ b/ts/src/models/runtime-event.ts @@ -0,0 +1,31 @@ +import {PlainValue} from "@code0-tech/tucana/helpers"; +import {HerculesTranslation} from "../types.ts"; +import {RuntimeFlowTypeSetting_UniquenessScope} from "@code0-tech/tucana/shared"; + +export interface RuntimeEventDefinitionRunnable {} + +export interface HerculesRuntimeEventSetting { + identifier: string, + unique?: RuntimeFlowTypeSetting_UniquenessScope, + defaultValue?: PlainValue, + name?: HerculesTranslation[], + description?: HerculesTranslation[], + optional?: boolean, + hidden?: boolean, +} + +export interface HerculesRuntimeEvent { + identifier: string, + runtimeSettings?: HerculesRuntimeEventSetting[], + signature: string, + linkedDataTypes?: string[], + editable?: boolean, + name?: HerculesTranslation[], + description?: HerculesTranslation[], + documentation?: HerculesTranslation[], + displayMessage?: HerculesTranslation[], + alias?: HerculesTranslation[], + displayIcon?: string, +} + +export type RuntimeEventClass = new () => RuntimeEventDefinitionRunnable; diff --git a/ts/src/models/runtime-function.ts b/ts/src/models/runtime-function.ts new file mode 100644 index 0000000..3a17c1a --- /dev/null +++ b/ts/src/models/runtime-function.ts @@ -0,0 +1,35 @@ +import {PlainValue} from "@code0-tech/tucana/helpers"; +import {HerculesTranslation} from "../types.ts"; + +export interface HerculesRuntimeFunctionDefinitionParameter { + runtimeName: string, + defaultValue?: PlainValue, + name?: HerculesTranslation[], + description?: HerculesTranslation[], + documentation?: HerculesTranslation[], + hidden?: boolean, + optional?: boolean, +} + +export interface HerculesRuntimeFunctionDefinition { + runtimeName: string, + parameters?: HerculesRuntimeFunctionDefinitionParameter[], + signature: string, + throwsError?: boolean, + name?: HerculesTranslation[], + description?: HerculesTranslation[], + documentation?: HerculesTranslation[], + deprecationMessage?: HerculesTranslation[], + displayMessage?: HerculesTranslation[], + alias?: HerculesTranslation[], + linkedDataTypes?: string[], + displayIcon?: string, + handler: (...args: (PlainValue | undefined)[]) => Promise | PlainValue, +} + +export interface RuntimeFunctionDefinitionRunnable { + run(...args: (PlainValue | undefined)[]): Promise | PlainValue; +} + +export type RuntimeFunctionDefinitionClass = + new () => T; From 2dde53d62f21f2556cd31e7585392b8eb4432856 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 00:48:19 +0200 Subject: [PATCH 16/43] feat: mappings --- ts/src/map/data-type.ts | 28 +++++++++++++++ ts/src/map/event.ts | 38 +++++++++++++++++++++ ts/src/map/function.ts | 62 ++++++++++++++++++++++++++++++++++ ts/src/map/runtime-event.ts | 21 ++++++++++++ ts/src/map/runtime-function.ts | 50 +++++++++++++++++++++++++++ 5 files changed, 199 insertions(+) create mode 100644 ts/src/map/data-type.ts create mode 100644 ts/src/map/event.ts create mode 100644 ts/src/map/function.ts create mode 100644 ts/src/map/runtime-event.ts create mode 100644 ts/src/map/runtime-function.ts diff --git a/ts/src/map/data-type.ts b/ts/src/map/data-type.ts new file mode 100644 index 0000000..f4883d7 --- /dev/null +++ b/ts/src/map/data-type.ts @@ -0,0 +1,28 @@ +import {zodToRules, zodToTypeString} from "../internal/zod-schema.ts"; +import type {HerculesTranslation} from "../types.ts"; +import type {DataTypeClass, HerculesDataType} from "../models/data-type.ts"; + +export const dataTypeMap = (klass: DataTypeClass): HerculesDataType => { + const identifier: string = Reflect.getMetadata('hercules:identifier', klass); + const name: HerculesTranslation[] = Reflect.getMetadata('hercules:name', klass) || []; + const displayMessage: HerculesTranslation[] = Reflect.getMetadata('hercules:display_message', klass) || []; + const alias: HerculesTranslation[] = Reflect.getMetadata('hercules:alias', klass) || []; + const linkedDataTypes: string[] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) || []; + const genericKeys: string[] = Reflect.getMetadata('hercules:generic_keys', klass) || []; + + if (!identifier) throw new Error(`Data type class ${klass.name} is missing an identifier. Add @Identifier("your_identifier") to the class.`); + + const schema = Reflect.getMetadata('hercules:schema', klass); + if (!schema) throw new Error(`Data type class ${klass.name} is missing a schema. Add @Schema(z.string()) to the class.`); + + return { + identifier, + type: zodToTypeString(schema), + rules: zodToRules(schema), + name, + displayMessage, + alias, + linkedDataTypes, + genericKeys, + }; +}; diff --git a/ts/src/map/event.ts b/ts/src/map/event.ts new file mode 100644 index 0000000..f5ba4d1 --- /dev/null +++ b/ts/src/map/event.ts @@ -0,0 +1,38 @@ +import type {HerculesTranslation} from "../types.ts"; +import type {EventClass, HerculesEvent, HerculesEventSetting} from "../models/event.ts"; +import type {RuntimeEventClass} from "../models/runtime-event.ts"; +import {runtimeEventMap} from "./runtime-event.ts"; + +export const eventMap = (klass: EventClass): HerculesEvent => { + const parentClass = Object.getPrototypeOf(klass); + const runtimeEvent = runtimeEventMap(parentClass); + + const identifier: string = Reflect.getMetadata('hercules:identifier', klass); + const signature: string = Reflect.getMetadata('hercules:signature', klass); + const settings: HerculesEventSetting[] = Reflect.getMetadata('hercules:flow_settings', klass) || []; + const name: HerculesTranslation[] = Reflect.getMetadata('hercules:name', klass); + const description: HerculesTranslation[] = Reflect.getMetadata('hercules:description', klass); + const documentation: HerculesTranslation[] = Reflect.getMetadata('hercules:documentation', klass); + const displayMessage: HerculesTranslation[] = Reflect.getMetadata('hercules:display_message', klass); + const alias: HerculesTranslation[] = Reflect.getMetadata('hercules:alias', klass); + const linkedDataTypes: string[] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass); + const displayIcon: string | undefined = Reflect.getMetadata('hercules:display_icon', klass); + const editable: boolean = Reflect.getMetadata('hercules:editable', klass) ?? false; + + if (!identifier) throw new Error(`Event class ${klass.name} is missing an identifier. Add @Identifier("your_identifier") to the class.`); + + return { + runtimeIdentifier: runtimeEvent.identifier, + identifier, + signature: signature || runtimeEvent.signature, + settings, + name: name || runtimeEvent.name, + description: description || runtimeEvent.description, + documentation: documentation || runtimeEvent.documentation, + displayMessage: displayMessage || runtimeEvent.displayMessage, + alias: alias || runtimeEvent.alias, + linkedDataTypes: linkedDataTypes || runtimeEvent.linkedDataTypes, + displayIcon: displayIcon || runtimeEvent.displayIcon, + editable, + }; +}; diff --git a/ts/src/map/function.ts b/ts/src/map/function.ts new file mode 100644 index 0000000..dccae57 --- /dev/null +++ b/ts/src/map/function.ts @@ -0,0 +1,62 @@ +import {FunctionDefinitionClass, HerculesFunctionDefinition, HerculesFunctionDefinitionParameter} from "../models/function.ts"; +import {RuntimeFunctionDefinitionClass} from "../models/runtime-function.ts"; +import {runtimeFunctionMap} from "./runtime-function.ts"; + +export const functionMap = (klass: FunctionDefinitionClass): HerculesFunctionDefinition => { + const parentClass = Object.getPrototypeOf(klass); + const runtimeFunction = runtimeFunctionMap(parentClass); + + const identifier: string = Reflect.getMetadata('hercules:identifier', klass); + const functionParameters: HerculesFunctionDefinitionParameter[] = Reflect.getMetadata('hercules:function_parameters', klass) || []; + const name: HerculesFunctionDefinition["name"] = Reflect.getMetadata('hercules:name', klass); + const displayMessage: HerculesFunctionDefinition["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass); + const description: HerculesFunctionDefinition["description"] = Reflect.getMetadata('hercules:description', klass); + const deprecationMessage: HerculesFunctionDefinition["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass); + const alias: HerculesFunctionDefinition["alias"] = Reflect.getMetadata('hercules:alias', klass); + const documentation: HerculesFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass); + const signature: HerculesFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass); + const linkedDataTypes: HerculesFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass); + const displayIcon: HerculesFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass); + const throwsError: HerculesFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass); + + if (functionParameters.length > (runtimeFunction.parameters?.length ?? 0)) { + throw new Error(`Function definition class ${klass.name} has more function parameters than its runtime function.`); + } + + for (const fp of functionParameters) { + if (!runtimeFunction.parameters?.find(p => p.runtimeName === fp.runtimeName)) { + throw new Error(`Function definition class ${klass.name} has a function parameter "${fp.runtimeName}" that does not exist in its runtime function.`); + } + } + + const mergedParameters: HerculesFunctionDefinitionParameter[] = [...functionParameters]; + for (const rp of runtimeFunction.parameters ?? []) { + if (!mergedParameters.find(p => p.runtimeName === rp.runtimeName)) { + mergedParameters.push({...rp, runtimeDefinitionName: rp.runtimeName}); + } + } + + return { + runtimeDefinitionName: runtimeFunction.runtimeName, + runtimeName: identifier || runtimeFunction.runtimeName, + signature: signature || runtimeFunction.signature, + throwsError: throwsError ?? runtimeFunction.throwsError, + alias: alias || runtimeFunction.alias, + description: description || runtimeFunction.description, + name: name || runtimeFunction.name, + documentation: documentation || runtimeFunction.documentation, + deprecationMessage: deprecationMessage || runtimeFunction.deprecationMessage, + displayMessage: displayMessage || runtimeFunction.displayMessage, + displayIcon: displayIcon || runtimeFunction.displayIcon, + linkedDataTypes: linkedDataTypes || runtimeFunction.linkedDataTypes, + parameters: mergedParameters.map(p => ({ + ...p, + runtimeDefinitionName: p.runtimeDefinitionName || p.runtimeName, + name: p.name || [], + description: p.description || [], + documentation: p.documentation || [], + hidden: p.hidden || false, + optional: p.optional || false, + })), + }; +}; diff --git a/ts/src/map/runtime-event.ts b/ts/src/map/runtime-event.ts new file mode 100644 index 0000000..503f15a --- /dev/null +++ b/ts/src/map/runtime-event.ts @@ -0,0 +1,21 @@ +import type {HerculesTranslation} from "../types.ts"; +import type {HerculesRuntimeEvent, HerculesRuntimeEventSetting, RuntimeEventClass} from "../models/runtime-event.ts"; + +export const runtimeEventMap = (klass: RuntimeEventClass): HerculesRuntimeEvent => { + const identifier: string = Reflect.getMetadata('hercules:identifier', klass); + const signature: string = Reflect.getMetadata('hercules:signature', klass); + const runtimeSettings: HerculesRuntimeEventSetting[] = Reflect.getMetadata('hercules:runtime_flow_settings', klass) || []; + const name: HerculesTranslation[] = Reflect.getMetadata('hercules:name', klass) || []; + const description: HerculesTranslation[] = Reflect.getMetadata('hercules:description', klass) || []; + const documentation: HerculesTranslation[] = Reflect.getMetadata('hercules:documentation', klass) || []; + const displayMessage: HerculesTranslation[] = Reflect.getMetadata('hercules:display_message', klass) || []; + const alias: HerculesTranslation[] = Reflect.getMetadata('hercules:alias', klass) || []; + const linkedDataTypes: string[] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) || []; + const displayIcon: string | undefined = Reflect.getMetadata('hercules:display_icon', klass); + const editable: boolean = Reflect.getMetadata('hercules:editable', klass) ?? false; + + if (!identifier) throw new Error(`Runtime event class ${klass.name} is missing an identifier. Add @Identifier("your_identifier") to the class.`); + if (!signature) throw new Error(`Runtime event class ${klass.name} is missing a signature. Add @Signature("(): RETURN_TYPE") to the class.`); + + return {identifier, signature, runtimeSettings, name, description, documentation, displayMessage, alias, linkedDataTypes, displayIcon, editable}; +}; diff --git a/ts/src/map/runtime-function.ts b/ts/src/map/runtime-function.ts new file mode 100644 index 0000000..25f8486 --- /dev/null +++ b/ts/src/map/runtime-function.ts @@ -0,0 +1,50 @@ +import type {PlainValue} from "@code0-tech/tucana/helpers"; +import { + HerculesRuntimeFunctionDefinition, + HerculesRuntimeFunctionDefinitionParameter, + RuntimeFunctionDefinitionClass, +} from "../models/runtime-function.ts"; + +export const runtimeFunctionMap = (klass: RuntimeFunctionDefinitionClass): HerculesRuntimeFunctionDefinition => { + const identifier: string = Reflect.getMetadata('hercules:identifier', klass); + const runtimeParameters: HerculesRuntimeFunctionDefinitionParameter[] = Reflect.getMetadata('hercules:runtime_parameters', klass) || []; + const name: HerculesRuntimeFunctionDefinition["name"] = Reflect.getMetadata('hercules:name', klass) || []; + const displayMessage: HerculesRuntimeFunctionDefinition["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass) || []; + const description: HerculesRuntimeFunctionDefinition["description"] = Reflect.getMetadata('hercules:description', klass) || []; + const deprecationMessage: HerculesRuntimeFunctionDefinition["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass) || []; + const alias: HerculesRuntimeFunctionDefinition["alias"] = Reflect.getMetadata('hercules:alias', klass) || []; + const documentation: HerculesRuntimeFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass) || []; + const signature: HerculesRuntimeFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass); + const linkedDataTypes: HerculesRuntimeFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) || []; + const displayIcon: HerculesRuntimeFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass) || ""; + const throwsError: HerculesRuntimeFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass) || false; + + if (!identifier) throw new Error(`Runtime function class ${klass.name} is missing an identifier. Add @Identifier("your_identifier") to the class.`); + if (!signature) throw new Error(`Runtime function class ${klass.name} is missing a signature. Add @Signature("(param1: TYPE_1): RETURN_TYPE") to the class.`); + + const instance = new klass(); + const handler = instance.run.bind(instance) as (...args: (PlainValue | undefined)[]) => Promise | PlainValue; + + return { + runtimeName: identifier, + signature, + throwsError, + name, + description, + documentation, + deprecationMessage, + displayMessage, + alias, + linkedDataTypes, + displayIcon: displayIcon || "tabler:note", + parameters: runtimeParameters.map(param => ({ + ...param, + name: param.name || [], + description: param.description || [], + documentation: param.documentation || [], + hidden: param.hidden || false, + optional: param.optional || false, + })), + handler, + }; +}; From 7fe4b376e9061fd4a5b922b63e572c97352ac271 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 00:48:27 +0200 Subject: [PATCH 17/43] feat: data type manager --- ts/src/manager/DataTypeManager.ts | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 ts/src/manager/DataTypeManager.ts diff --git a/ts/src/manager/DataTypeManager.ts b/ts/src/manager/DataTypeManager.ts new file mode 100644 index 0000000..ba6fd4e --- /dev/null +++ b/ts/src/manager/DataTypeManager.ts @@ -0,0 +1,4 @@ +import {BaseManager} from "./BaseManager.ts"; +import {HerculesDataType} from "../models/data-type.ts"; + +export class DataTypeManager extends BaseManager {} From 85d2e5c33edbae7767117657f043a4ae3ecdfc47 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 00:48:34 +0200 Subject: [PATCH 18/43] feat: utilities --- ts/src/internal/connection.ts | 39 ++++++++ ts/src/internal/module-builder.ts | 156 ++++++++++++++++++++++++++++++ ts/src/internal/zod-schema.ts | 26 +++++ 3 files changed, 221 insertions(+) create mode 100644 ts/src/internal/connection.ts create mode 100644 ts/src/internal/module-builder.ts create mode 100644 ts/src/internal/zod-schema.ts diff --git a/ts/src/internal/connection.ts b/ts/src/internal/connection.ts new file mode 100644 index 0000000..7a22e43 --- /dev/null +++ b/ts/src/internal/connection.ts @@ -0,0 +1,39 @@ +import {GrpcOptions, GrpcTransport} from "@protobuf-ts/grpc-transport"; +import {ActionTransferRequest, ActionTransferResponse, ActionTransferServiceClient, ModuleServiceClient, ModuleUpdateRequest} from "@code0-tech/tucana/aquila"; +import type {Module} from "@code0-tech/tucana/shared"; +import {ChannelCredentials} from "@grpc/grpc-js"; +import {type RpcOptions} from "@protobuf-ts/runtime-rpc"; +import type {DuplexStreamingCall} from "@protobuf-ts/runtime-rpc"; + +export interface Connection { + transport: GrpcTransport; + stream: DuplexStreamingCall; +} + +export async function createConnection( + module: Module, + authToken: string, + aquilaUrl: string, + grpcOptions?: GrpcOptions, +): Promise { + const transport = new GrpcTransport({ + host: aquilaUrl, + channelCredentials: ChannelCredentials.createInsecure(), + ...grpcOptions, + }); + + const rpcOptions: RpcOptions = {meta: {"authorization": authToken}}; + + const response = await new ModuleServiceClient(transport).update( + ModuleUpdateRequest.create({modules: [module]}), + rpcOptions, + ); + + if (!response.response.success) { + throw new Error("Module update failed"); + } + + const stream = new ActionTransferServiceClient(transport).transfer(rpcOptions); + + return {transport, stream}; +} diff --git a/ts/src/internal/module-builder.ts b/ts/src/internal/module-builder.ts new file mode 100644 index 0000000..680ae0a --- /dev/null +++ b/ts/src/internal/module-builder.ts @@ -0,0 +1,156 @@ +import {constructValue} from "@code0-tech/tucana/helpers"; +import {DefinitionDataType, FlowType, FlowTypeSetting, Module, ModuleConfigurationDefinition, RuntimeFlowType, RuntimeFlowTypeSetting} from "@code0-tech/tucana/shared"; +import type {HerculesFunctionDefinition} from "../models/function.ts"; +import type {HerculesRuntimeFunctionDefinition} from "../models/runtime-function.ts"; +import type {HerculesActionConfigurationDefinition, HerculesTranslation} from "../types.ts"; +import {HerculesDataType} from "../models/data-type.ts"; +import {HerculesEvent} from "../models/event.ts"; +import {HerculesRuntimeEvent} from "../models/runtime-event.ts"; + +export interface ModuleBuildData { + identifier: string; + version: string; + author: string; + icon: string; + documentation: string; + name: HerculesTranslation[]; + configurationDefinitions: HerculesActionConfigurationDefinition[]; + dataTypes: HerculesDataType[]; + events: HerculesEvent[]; + runtimeEvents: HerculesRuntimeEvent[]; + functions: HerculesFunctionDefinition[]; + runtimeFunctions: HerculesRuntimeFunctionDefinition[]; +} + +export function buildModule(data: ModuleBuildData): Module { + return { + identifier: data.identifier, + version: data.version, + author: data.author, + icon: data.icon, + documentation: data.documentation, + name: data.name, + description: [], + configurations: data.configurationDefinitions.map(def => ({ + identifier: def.identifier, + name: def.name ?? [], + description: def.description ?? [], + type: def.type, + linkedDataTypeIdentifiers: def.linkedDataTypes ?? [], + defaultValue: def.defaultValue != null ? constructValue(def.defaultValue) : undefined, + optional: def.optional ?? false, + hidden: def.hidden ?? false, + } as ModuleConfigurationDefinition)), + definitionDataTypes: data.dataTypes.map(dt => ({ + identifier: dt.identifier, + name: dt.name ?? [], + alias: dt.alias ?? [], + rules: dt.rules ?? [], + genericKeys: dt.genericKeys ?? [], + type: dt.type, + linkedDataTypeIdentifiers: dt.linkedDataTypes ?? [], + displayMessage: dt.displayMessage ?? [], + version: data.version, + definitionSource: "action", + } as DefinitionDataType)), + flowTypes: data.events.map(ft => ({ + identifier: ft.identifier, + settings: (ft.settings ?? []).map(s => ({ + identifier: s.identifier, + unique: s.unique ?? 1, + linkedDataTypeIdentifiers: s.linkedDataTypeIdentifiers ?? [], + defaultValue: s.defaultValue != null ? constructValue(s.defaultValue) : undefined, + name: s.name ?? [], + description: s.description ?? [], + optional: s.optional ?? false, + hidden: s.hidden ?? false, + } as FlowTypeSetting)), + editable: ft.editable ?? false, + name: ft.name ?? [], + description: ft.description ?? [], + documentation: ft.documentation ?? [], + displayMessage: ft.displayMessage ?? [], + alias: ft.alias ?? [], + version: data.version, + displayIcon: ft.displayIcon ?? "tabler:note", + definitionSource: "action", + linkedDataTypeIdentifiers: ft.linkedDataTypes ?? [], + signature: ft.signature, + runtimeIdentifier: ft.runtimeIdentifier ?? ft.identifier, + } as FlowType)), + runtimeFlowTypes: data.runtimeEvents.map(rft => ({ + identifier: rft.identifier, + runtimeSettings: (rft.runtimeSettings ?? []).map(s => ({ + identifier: s.identifier, + unique: s.unique ?? 0, + defaultValue: s.defaultValue != null ? constructValue(s.defaultValue) : undefined, + name: s.name ?? [], + description: s.description ?? [], + optional: s.optional ?? false, + hidden: s.hidden ?? false, + } as RuntimeFlowTypeSetting)), + editable: rft.editable ?? false, + name: rft.name ?? [], + description: rft.description ?? [], + documentation: rft.documentation ?? [], + displayMessage: rft.displayMessage ?? [], + alias: rft.alias ?? [], + version: data.version, + displayIcon: rft.displayIcon ?? "tabler:note", + definitionSource: "action", + linkedDataTypeIdentifiers: rft.linkedDataTypes ?? [], + signature: rft.signature, + } as RuntimeFlowType)), + functionDefinitions: data.functions.map(f => ({ + runtimeName: f.runtimeName, + runtimeDefinitionName: f.runtimeDefinitionName, + signature: f.signature, + throwsError: f.throwsError ?? false, + name: f.name ?? [], + description: f.description ?? [], + documentation: f.documentation ?? [], + deprecationMessage: f.deprecationMessage ?? [], + displayMessage: f.displayMessage ?? [], + alias: f.alias ?? [], + linkedDataTypeIdentifiers: f.linkedDataTypes ?? [], + displayIcon: f.displayIcon ?? "tabler:note", + version: data.version, + definitionSource: "action", + parameterDefinitions: (f.parameters ?? []).map(p => ({ + runtimeName: p.runtimeName, + runtimeDefinitionName: p.runtimeDefinitionName ?? p.runtimeName, + name: p.name ?? [], + description: p.description ?? [], + documentation: p.documentation ?? [], + hidden: p.hidden ?? false, + optional: p.optional ?? false, + defaultValue: p.defaultValue != null ? constructValue(p.defaultValue) : undefined, + })), + })), + runtimeFunctionDefinitions: data.runtimeFunctions.map(f => ({ + runtimeName: f.runtimeName, + signature: f.signature, + throwsError: f.throwsError ?? false, + name: f.name ?? [], + description: f.description ?? [], + documentation: f.documentation ?? [], + deprecationMessage: f.deprecationMessage ?? [], + displayMessage: f.displayMessage ?? [], + alias: f.alias ?? [], + linkedDataTypeIdentifiers: f.linkedDataTypes ?? [], + displayIcon: f.displayIcon ?? "tabler:note", + version: data.version, + definitionSource: "action", + runtimeParameterDefinitions: (f.parameters ?? []).map(p => ({ + runtimeName: p.runtimeName, + name: p.name ?? [], + description: p.description ?? [], + documentation: p.documentation ?? [], + hidden: p.hidden ?? false, + optional: p.optional ?? false, + defaultValue: p.defaultValue != null ? constructValue(p.defaultValue) : undefined, + })), + })), + definitions: [], + }; +} diff --git a/ts/src/internal/zod-schema.ts b/ts/src/internal/zod-schema.ts new file mode 100644 index 0000000..3ef32a7 --- /dev/null +++ b/ts/src/internal/zod-schema.ts @@ -0,0 +1,26 @@ +import {toJSONSchema, type ZodTypeAny} from "zod"; +import {zodToTs, printNode, createAuxiliaryTypeStore} from "zod-to-ts"; +import type {DefinitionDataTypeRule} from "@code0-tech/tucana/shared"; + +type JsonSchema = { + pattern?: string; + minimum?: number; + maximum?: number; +}; + +export function zodToTypeString(schema: ZodTypeAny): string { + const {node} = zodToTs(schema, {auxiliaryTypeStore: createAuxiliaryTypeStore()}); + return printNode(node); +} + +export function zodToRules(schema: ZodTypeAny): DefinitionDataTypeRule[] { + const json = toJSONSchema(schema) as JsonSchema; + const rules: DefinitionDataTypeRule[] = []; + if (json.pattern) { + rules.push({config: {oneofKind: "regex", regex: {pattern: json.pattern}}}); + } + if (json.minimum !== undefined && json.maximum !== undefined) { + rules.push({config: {oneofKind: "numberRange", numberRange: {from: BigInt(json.minimum), to: BigInt(json.maximum)}}}); + } + return rules; +} From 91e7442800783d1a7aee143ad302f7cbac162a09 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 00:48:39 +0200 Subject: [PATCH 19/43] feat: decorators --- ts/src/decorators/data-type.ts | 4 +++ ts/src/decorators/event.ts | 8 ++++++ ts/src/decorators/function.ts | 25 +++++++++++++++++++ .../{sdk/definitions => decorators}/meta.ts | 25 ++++++++++++------- ts/src/decorators/runtime-event.ts | 8 ++++++ 5 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 ts/src/decorators/data-type.ts create mode 100644 ts/src/decorators/event.ts create mode 100644 ts/src/decorators/function.ts rename ts/src/{sdk/definitions => decorators}/meta.ts (87%) create mode 100644 ts/src/decorators/runtime-event.ts diff --git a/ts/src/decorators/data-type.ts b/ts/src/decorators/data-type.ts new file mode 100644 index 0000000..c8258a3 --- /dev/null +++ b/ts/src/decorators/data-type.ts @@ -0,0 +1,4 @@ +import type {ZodTypeAny} from "zod"; + +export const Schema = (schema: ZodTypeAny): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:schema', schema, target) diff --git a/ts/src/decorators/event.ts b/ts/src/decorators/event.ts new file mode 100644 index 0000000..08bec67 --- /dev/null +++ b/ts/src/decorators/event.ts @@ -0,0 +1,8 @@ +import {HerculesEventSetting} from "../models/event.ts"; + +export const EventSetting = (setting: HerculesEventSetting): ClassDecorator => + (target) => { + const settings = Reflect.getMetadata('hercules:flow_settings', target) || []; + settings.push(setting); + Reflect.defineMetadata('hercules:flow_settings', settings, target); + } diff --git a/ts/src/decorators/function.ts b/ts/src/decorators/function.ts new file mode 100644 index 0000000..82df6f5 --- /dev/null +++ b/ts/src/decorators/function.ts @@ -0,0 +1,25 @@ +import {HerculesFunctionDefinitionParameter} from "../models/function.ts"; +import {HerculesRuntimeFunctionDefinitionParameter} from "../models/runtime-function.ts"; + +export const OmitFunctionDefinition = (): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:omit_function_definition', true, target) + +export const ThrowsError = (throwsError: boolean = true): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:throws_error', throwsError, target) + +export const LinkedDataTypeIdentifiers = (...linkedDataTypeIdentifiers: string[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:linked_data_type_identifiers', linkedDataTypeIdentifiers, target) + +export const RuntimeParameter = (parameter: HerculesRuntimeFunctionDefinitionParameter): ClassDecorator => + (target) => { + const parameters = Reflect.getMetadata('hercules:runtime_parameters', target) || []; + parameters.push(parameter); + Reflect.defineMetadata('hercules:runtime_parameters', parameters, target); + } + +export const FunctionParameter = (parameter: HerculesFunctionDefinitionParameter): ClassDecorator => + (target) => { + const parameters = Reflect.getMetadata('hercules:function_parameters', target) || []; + parameters.push(parameter); + Reflect.defineMetadata('hercules:function_parameters', parameters, target); + } diff --git a/ts/src/sdk/definitions/meta.ts b/ts/src/decorators/meta.ts similarity index 87% rename from ts/src/sdk/definitions/meta.ts rename to ts/src/decorators/meta.ts index e152a00..30754a0 100644 --- a/ts/src/sdk/definitions/meta.ts +++ b/ts/src/decorators/meta.ts @@ -1,24 +1,31 @@ -import {HerculesTranslation} from "../../types"; +import {HerculesTranslation} from "../types.ts"; + +export const Identifier = (id: string): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:identifier', id, target) export const Name = (...translation: HerculesTranslation[]): ClassDecorator => (target) => Reflect.defineMetadata('hercules:name', translation, target) -export const DisplayMessage = (...translation: HerculesTranslation[]): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:display_message', translation, target) + export const Description = (...translation: HerculesTranslation[]): ClassDecorator => (target) => Reflect.defineMetadata('hercules:description', translation, target) -export const DeprecationMessage = (...translation: HerculesTranslation[]): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:deprecation_message', translation, target) -export const Alias = (...translation: HerculesTranslation[]): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:alias', translation, target) export const Documentation = (...translation: HerculesTranslation[]): ClassDecorator => (target) => Reflect.defineMetadata('hercules:documentation', translation, target) +export const DisplayMessage = (...translation: HerculesTranslation[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:display_message', translation, target) + +export const Alias = (...translation: HerculesTranslation[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:alias', translation, target) + +export const DeprecationMessage = (...translation: HerculesTranslation[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:deprecation_message', translation, target) + export const Signature = (signature: string): ClassDecorator => (target) => Reflect.defineMetadata('hercules:signature', signature, target) export const DisplayIcon = (displayIcon: string): ClassDecorator => (target) => Reflect.defineMetadata('hercules:display_icon', displayIcon, target) -export const Identifier = (id: string): ClassDecorator => - (target) => Reflect.defineMetadata('hercules:identifier', id, target); +export const Editable = (editable: boolean = true): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:editable', editable, target) diff --git a/ts/src/decorators/runtime-event.ts b/ts/src/decorators/runtime-event.ts new file mode 100644 index 0000000..04f5d3f --- /dev/null +++ b/ts/src/decorators/runtime-event.ts @@ -0,0 +1,8 @@ +import {HerculesRuntimeEventSetting} from "../models/runtime-event.ts"; + +export const RuntimeEventSetting = (setting: HerculesRuntimeEventSetting): ClassDecorator => + (target) => { + const settings = Reflect.getMetadata('hercules:runtime_flow_settings', target) || []; + settings.push(setting); + Reflect.defineMetadata('hercules:runtime_flow_settings', settings, target); + } From 54e3a2ec63aac269efc6e3116e655a7497decbea Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 00:48:56 +0200 Subject: [PATCH 20/43] feat: events from event emitter --- ts/src/events.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 ts/src/events.ts diff --git a/ts/src/events.ts b/ts/src/events.ts new file mode 100644 index 0000000..278c0cc --- /dev/null +++ b/ts/src/events.ts @@ -0,0 +1,22 @@ +import type {ActionExecutionRequest, ActionTransferRequest, ActionTransferResponse} from "@code0-tech/tucana/aquila"; +import type {ModuleConfigurations} from "@code0-tech/tucana/shared"; +import type {CodeZeroAction} from "./CodeZeroAction.ts"; + +export enum CodeZeroEvent { + error = "error", + connected = "connected", + streamMessageReceived = "streamMessageReceived", + streamMessageSent = "streamMessageSent", + moduleUpdated = "moduleUpdated", + executionRequestReceived = "executionRequestReceived", +} + +export interface CodeZeroEventMap { + [CodeZeroEvent.error]: [Error] + [CodeZeroEvent.connected]: [CodeZeroAction] + [CodeZeroEvent.streamMessageReceived]: [ActionTransferResponse] + [CodeZeroEvent.streamMessageSent]: [ActionTransferRequest] + [CodeZeroEvent.moduleUpdated]: [ModuleConfigurations] + [CodeZeroEvent.executionRequestReceived]: [ActionExecutionRequest] + [key: string]: unknown[] +} From 24812e463b7a6e1281c8c54db19f8875471ac16d Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 00:49:02 +0200 Subject: [PATCH 21/43] feat: general types --- ts/src/types.ts | 105 +++--------------------------------------------- 1 file changed, 6 insertions(+), 99 deletions(-) diff --git a/ts/src/types.ts b/ts/src/types.ts index e391114..8079344 100644 --- a/ts/src/types.ts +++ b/ts/src/types.ts @@ -1,14 +1,8 @@ -import {GrpcOptions, GrpcTransport} from "@protobuf-ts/grpc-transport"; -import {DuplexStreamingCall} from "@protobuf-ts/runtime-rpc"; -import { - DefinitionDataType, - DefinitionDataTypeRule, FlowType, - FlowTypeSetting_UniquenessScope, FunctionDefinition, - RuntimeFunctionDefinition -} from "@code0-tech/tucana/shared"; +import {DefinitionDataTypeRule, FlowTypeSetting_UniquenessScope, RuntimeFlowTypeSetting_UniquenessScope} from "@code0-tech/tucana/shared"; import {PlainValue} from "@code0-tech/tucana/helpers"; import 'reflect-metadata'; -import {FunctionDefinitionClass, RuntimeFunctionDefinitionClass} from "./sdk/definitions/functions/functions"; + +export {FlowTypeSetting_UniquenessScope, RuntimeFlowTypeSetting_UniquenessScope}; export interface HerculesTranslation { code: "en-US" | "de-DE" | string, @@ -21,46 +15,9 @@ export interface HerculesFunctionContext { matchedConfig: HerculesActionProjectConfiguration } -export interface HerculesDataType { - identifier: string, - name?: HerculesTranslation[], - displayMessage?: HerculesTranslation[], - alias?: HerculesTranslation[], - rules?: DefinitionDataTypeRule[], - genericKeys?: string[], - type: string, - linkedDataTypes?: string[] -} - -export interface HerculesEventTypeSetting { - identifier: string, - unique?: FlowTypeSetting_UniquenessScope, - linkedDataTypeIdentifiers?: string[], - defaultValue?: PlainValue, - name?: HerculesTranslation[], - description?: HerculesTranslation[], -} - -export interface HerculesEventType { - identifier: string, - settings?: HerculesEventTypeSetting[], - signature: string, - linkedDataTypes?: string[], - editable: boolean, - name?: HerculesTranslation[], - description?: HerculesTranslation[], - documentation?: HerculesTranslation[], - displayMessage?: HerculesTranslation[], - alias?: HerculesTranslation[], - displayIcon?: string, -} - export interface HerculesActionProjectConfiguration { projectId: number | bigint, - configValues: { - identifier: string, - value: PlainValue - }[], + configValues: {identifier: string, value: PlainValue}[], findConfig: (identifier: string) => PlainValue | undefined } @@ -68,39 +25,13 @@ export interface HerculesActionConfigurationDefinition { name?: HerculesTranslation[], description?: HerculesTranslation[], type: string, - hidden: boolean, - optional: boolean, + hidden?: boolean, + optional?: boolean, linkedDataTypes?: string[], defaultValue?: PlainValue, identifier: string, } -// export type HerculesRegisterRuntimeFunctionParameter = { -// definition: HerculesRuntimeFunctionDefinition, -// handler: (...args: any[]) => Promise | PlainValue, -// } - -// export interface ActionSdk { -// config: { -// authToken: string, -// aquilaUrl: string, -// actionId: string, -// version: string, -// }, -// fullyConnected: () => boolean, // indicates whether the SDK is fully connected and ready to send/receive messages. Becomes true after connect() resolves successfully -// connect: (options?: GrpcOptions) => Promise, // after registering the functions and events -// onError: (handler: (error: Error) => void) => void, -// -// getProjectActionConfigurations(): HerculesActionProjectConfiguration[], -// -// registerConfigDefinitions: (...actionConfigurations: Array) => Promise, -// registerDataTypes: (...dataType: Array) => Promise, -// registerEventTypes: (...flowTypes: Array) => Promise, -// registerRuntimeFunctionDefinitionClass: (klass: RuntimeFunctionDefinitionClass) => Promise, -// registerFunctionDefinitionClass: (klass: FunctionDefinitionClass) => Promise, -// dispatchEvent: (eventType: string, projectId: number | bigint, payload: PlainValue) => Promise, -// } - export class RuntimeErrorException extends Error { code: string description?: string @@ -112,27 +43,3 @@ export class RuntimeErrorException extends Error { this.description = description } } - -// -// export interface RegisteredFunction { -// identifier: string, -// definition: FunctionDefinition -// } -// -// export interface RegisteredRuntimeFunction { -// identifier: string, -// definition: RuntimeFunctionDefinition, -// } -// -// export interface SdkState { -// functions: RegisteredFunction[], -// runtimeFunctions: RegisteredRuntimeFunction[], -// dataTypes: DefinitionDataType[], -// flowTypes: FlowType[], -// configurationDefinitions: ActionConfigurationDefinition[], -// projectConfigurations: ActionProjectConfiguration[], -// transport: GrpcTransport, -// client: ActionTransferServiceClient, -// stream: DuplexStreamingCall | undefined, -// fullyConnected: boolean, -// } \ No newline at end of file From a6203e46e4ca8feb29af20a68e6ff11a5344e934 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 00:49:17 +0200 Subject: [PATCH 22/43] feat: action client --- ts/src/CodeZeroAction.ts | 150 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 ts/src/CodeZeroAction.ts diff --git a/ts/src/CodeZeroAction.ts b/ts/src/CodeZeroAction.ts new file mode 100644 index 0000000..d62b7d4 --- /dev/null +++ b/ts/src/CodeZeroAction.ts @@ -0,0 +1,150 @@ +import {EventEmitter} from "node:events"; +import type {GrpcOptions, GrpcTransport} from "@protobuf-ts/grpc-transport"; +import {ActionTransferRequest, type ActionTransferResponse} from "@code0-tech/tucana/aquila"; +import {constructValue, type PlainValue} from "@code0-tech/tucana/helpers"; +import type {DuplexStreamingCall} from "@protobuf-ts/runtime-rpc"; +import type {FunctionDefinitionClass} from "./models/function.ts"; +import type {RuntimeFunctionDefinitionClass} from "./models/runtime-function.ts"; +import {runtimeFunctionMap} from "./map/runtime-function.ts"; +import {functionMap} from "./map/function.ts"; +import type {DataTypeClass} from "./models/data-type.ts"; +import {dataTypeMap} from "./map/data-type.ts"; +import type {EventClass} from "./models/event.ts"; +import {eventMap} from "./map/event.ts"; +import type {RuntimeEventClass} from "./models/runtime-event.ts"; +import {runtimeEventMap} from "./map/runtime-event.ts"; +import type {HerculesActionConfigurationDefinition, HerculesTranslation} from "./types.ts"; +import {CodeZeroEvent, type CodeZeroEventMap} from "./events.ts"; +import {createConnection} from "./internal/connection.ts"; +import {buildModule} from "./internal/module-builder.ts"; +import {ConfigManager} from "./manager/config-manager.ts"; +import {FunctionManager} from "./manager/FunctionManager.ts"; +import {RuntimeFunctionManager} from "./manager/RuntimeFunctionManager.ts"; +import {DataTypeManager} from "./manager/DataTypeManager.ts"; +import {EventManager} from "./manager/EventManager.ts"; +import {RuntimeEventManager} from "./manager/RuntimeEventManager.ts"; +import {actions} from "./actions/index.ts"; + +export class CodeZeroAction extends EventEmitter { + private _transport?: GrpcTransport; + private _stream?: DuplexStreamingCall; + private readonly _actions = new Map(actions.map(a => [a.packetType, a.handle])); + + readonly configs = new ConfigManager(); + readonly functions = new FunctionManager(); + readonly runtimeFunctions = new RuntimeFunctionManager(); + readonly dataTypes = new DataTypeManager(); + readonly events = new EventManager(); + readonly runtimeEvents = new RuntimeEventManager(); + + constructor( + private readonly _identifier: string, + private readonly _version: string, + private readonly _aquilaUrl: string | undefined, + private readonly _author: string, + private readonly _icon: string, + private readonly _documentation: string, + private readonly _name: HerculesTranslation[], + private readonly _configurationDefinitions: HerculesActionConfigurationDefinition[] = [], + ) { + super(); + } + + get identifier() { return this._identifier; } + get version() { return this._version; } + get stream() { return this._stream; } + + registerFunction(klass: FunctionDefinitionClass) { + const def = functionMap(klass); + this.functions.set(def.runtimeName, def); + } + + registerRuntimeFunction(klass: RuntimeFunctionDefinitionClass) { + const omitDefinition = Reflect.getMetadata('hercules:omit_function_definition', klass) || false; + const def = runtimeFunctionMap(klass); + this.runtimeFunctions.set(def.runtimeName, def); + if (!omitDefinition) { + this.functions.set(def.runtimeName, { + ...def, + runtimeDefinitionName: def.runtimeName, + parameters: def.parameters?.map(p => ({...p, runtimeDefinitionName: p.runtimeName})) || [], + }); + } + } + + registerDataTypeClass(klass: DataTypeClass) { + const def = dataTypeMap(klass); + this.dataTypes.set(def.identifier, def); + } + + registerEventClass(klass: EventClass) { + const def = eventMap(klass); + this.events.set(def.identifier, def); + } + + registerRuntimeEventClass(klass: RuntimeEventClass) { + const def = runtimeEventMap(klass); + this.runtimeEvents.set(def.identifier, def); + } + + async fire(eventClass: EventClass | RuntimeEventClass, projectId: number | bigint, payload: PlainValue) { + if (!this._stream) throw new Error("Not connected. Call connect() first."); + const eventType: string = Reflect.getMetadata('hercules:identifier', eventClass); + if (!eventType) throw new Error(`${eventClass.name} is missing an @Identifier decorator.`); + const request = ActionTransferRequest.create({ + data: { + oneofKind: "event", + event: { + projectId: typeof projectId === "bigint" ? projectId : BigInt(projectId), + eventType, + payload: constructValue(payload ?? null), + }, + }, + }); + await this._stream.requests.send(request); + this.emit(eventType as Extract, projectId, payload); + this.emit(CodeZeroEvent.streamMessageSent, request); + } + + async connect(authToken: string, aquilaUrl?: string, grpcOptions?: GrpcOptions) { + const url = aquilaUrl ?? this._aquilaUrl; + if (!url) throw new Error("aquilaUrl must be provided in the constructor or connect()"); + + try { + const {transport, stream} = await createConnection(this._buildModule(), authToken, url, grpcOptions); + this._transport = transport; + this._stream = stream; + } catch (err) { + this.emit(CodeZeroEvent.error, err as Error); + throw err; + } + + this.emit(CodeZeroEvent.connected, this); + await this._processStream(); + } + + private async _processStream() { + for await (const message of this._stream!.responses) { + this.emit(CodeZeroEvent.streamMessageReceived, message); + const {data} = message; + if (data.oneofKind === undefined) { + this.emit(CodeZeroEvent.error, new Error("Received unknown message type from stream")); + continue; + } + this._actions.get(data.oneofKind)?.(this, (data as Record)[data.oneofKind]); + } + } + + private _buildModule() { + return buildModule({ + identifier: this._identifier, version: this._version, + author: this._author, icon: this._icon, documentation: this._documentation, + name: this._name, configurationDefinitions: this._configurationDefinitions, + dataTypes: this.dataTypes.values(), + events: this.events.values(), + runtimeEvents: this.runtimeEvents.values(), + functions: this.functions.values(), + runtimeFunctions: this.runtimeFunctions.values(), + }); + } +} From 1d199b664deb531d47ff61c5733b3679a6e86332 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 00:49:27 +0200 Subject: [PATCH 23/43] feat: package json --- ts/package-lock.json | 112 +++++++++++++++++++++++++------------------ ts/package.json | 4 +- 2 files changed, 69 insertions(+), 47 deletions(-) diff --git a/ts/package-lock.json b/ts/package-lock.json index a1d0e73..421d0d2 100644 --- a/ts/package-lock.json +++ b/ts/package-lock.json @@ -17,7 +17,9 @@ "@protobuf-ts/runtime-rpc": "^2.11.1", "pino": "^10.3.1", "pino-pretty": "^13.1.3", - "reflect-metadata": "^0.2.2" + "reflect-metadata": "^0.2.2", + "zod": "^4.4.3", + "zod-to-ts": "^2.1.0" }, "devDependencies": { "@types/node": "^25.0.10", @@ -84,33 +86,10 @@ "integrity": "sha512-AgCl812Sn/MyY1+cRG0pdN0Uj7z93hDa4E9bclaf9hS5wc1PrlQSutDgePvJFR/VBWoeYQczne7MNP7RDu9NRg==", "license": "MIT" }, - "node_modules/@emnapi/core": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.1.tgz", - "integrity": "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.0", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz", - "integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@emnapi/wasi-threads": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz", - "integrity": "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", "dev": true, "license": "MIT", "optional": true, @@ -565,6 +544,7 @@ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.3.tgz", "integrity": "sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@grpc/proto-loader": "^0.8.0", "@js-sdsl/ordered-map": "^4.4.2" @@ -646,6 +626,7 @@ "integrity": "sha512-kF3GFME4lN22O5zbnXk2RP4y/4PDQdps0xKiYTipMYprkwCmmpsWLZt/N2Fkbil540cSLfJX0BW7LkHzgMVUYg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@microsoft/api-extractor-model": "7.33.5", "@microsoft/tsdoc": "~0.16.0", @@ -941,9 +922,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -961,9 +939,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -981,9 +956,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -1001,9 +973,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -1021,9 +990,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -1041,9 +1007,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -1089,6 +1052,40 @@ "node": ">=14.0.0" } }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.1.tgz", + "integrity": "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz", + "integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz", + "integrity": "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@rolldown/binding-win32-arm64-msvc": { "version": "1.0.0-rc.13", "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.13.tgz", @@ -2283,6 +2280,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -3241,6 +3239,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -3890,8 +3889,8 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3929,6 +3928,7 @@ "integrity": "sha512-P1PbweD+2/udplnThz3btF4cf6AgPky7kk23RtHUkJIU5BIxwPprhRGmOAHs6FTI7UiGbTNrgNP6jSYD6JaRnw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", @@ -4209,6 +4209,26 @@ "engines": { "node": ">=12" } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-ts": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/zod-to-ts/-/zod-to-ts-2.1.0.tgz", + "integrity": "sha512-jZP1GokTqR99FLmtGU+B9acjD9u/R++b++Vxe1sWpBQDd82/9/j5LyLZZ7/Oy3h2nxcz5NihikgX4D0hhdu3+g==", + "license": "MIT", + "peerDependencies": { + "typescript": "^5 || ^6", + "zod": "^3.25.0 || ^4.0.0" + } } } } diff --git a/ts/package.json b/ts/package.json index e4a5c5f..a1dea2c 100644 --- a/ts/package.json +++ b/ts/package.json @@ -38,7 +38,9 @@ "@protobuf-ts/runtime-rpc": "^2.11.1", "pino": "^10.3.1", "pino-pretty": "^13.1.3", - "reflect-metadata": "^0.2.2" + "reflect-metadata": "^0.2.2", + "zod": "^4.4.3", + "zod-to-ts": "^2.1.0" }, "devDependencies": { "@types/node": "^25.0.10", From 298ea172af21a1deecdd7128b705872ccf919e89 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 00:49:34 +0200 Subject: [PATCH 24/43] feat: tsconfig.json --- ts/tsconfig.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ts/tsconfig.json b/ts/tsconfig.json index a48423f..974407d 100644 --- a/ts/tsconfig.json +++ b/ts/tsconfig.json @@ -1,12 +1,14 @@ { "compilerOptions": { "esModuleInterop": true, - "module": "commonjs", + "module": "esnext", "moduleResolution": "bundler", "target": "es2020", "lib": ["es2020", "dom"], "strict": true, "skipLibCheck": true, + "allowImportingTsExtensions": true, + "noEmit": true, "types": ["vite/client"] }, "include": ["src/**/*"] From 8910019db4a64e8d6066f31e521086d3d29c7cff Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 00:49:41 +0200 Subject: [PATCH 25/43] feat: vitest.config.ts --- ts/vitest.config.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ts/vitest.config.ts b/ts/vitest.config.ts index 39e458a..2e7a0ac 100644 --- a/ts/vitest.config.ts +++ b/ts/vitest.config.ts @@ -2,6 +2,7 @@ import { defineConfig } from 'vitest/config' export default defineConfig({ test: { - exclude: ['**/dist/**', "node_modules"], + include: ['src/**/*.test.ts'], + exclude: ['**/dist/**', '**/node_modules/**', '**/examples/**'], }, }) From e44b8f970319629f3d651221e4f3f069231470b4 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 00:49:46 +0200 Subject: [PATCH 26/43] feat: export --- ts/src/index.ts | 229 +++++------------------------------------------- 1 file changed, 20 insertions(+), 209 deletions(-) diff --git a/ts/src/index.ts b/ts/src/index.ts index 4219ff3..035a865 100644 --- a/ts/src/index.ts +++ b/ts/src/index.ts @@ -1,209 +1,20 @@ -import {EventEmitter} from "node:events"; -import { - DefinitionDataType, Error, - FlowType, ModuleConfigurationDefinition, ModuleProjectConfigurations, RuntimeFunctionDefinition -} from "@code0-tech/tucana/shared"; -import {GrpcOptions, GrpcTransport} from "@protobuf-ts/grpc-transport"; -import { - ActionTransferRequest, ActionTransferResponse, - ActionTransferServiceClient, DataTypeServiceClient, DataTypeUpdateRequest, ModuleServiceClient, ModuleUpdateRequest, -} from "@code0-tech/tucana/aquila"; -import {DuplexStreamingCall, type RpcOptions} from "@protobuf-ts/runtime-rpc"; -import { - FunctionDefinitionClass, - HerculesFunctionDefinition, HerculesRuntimeFunctionDefinition, - RuntimeFunctionDefinitionClass, RuntimeFunctionDefinitionRunnable -} from "./sdk/definitions/functions/functions"; -import {functionMap, runtimeFunctionMap} from "./sdk/definitions/functions/functions.mapper"; -import {buildRuntimeFunctionDefinition} from "./sdk/builder/builder"; -import type { - HerculesActionConfigurationDefinition, - HerculesTranslation, - RegisteredFunction, - RegisteredRuntimeFunction -} from "./types"; -import {ChannelCredentials} from "@grpc/grpc-js"; -import {handleDataTypes} from "./handler/dataTypeHandler"; -import {handleRuntimeFunctionDefinitions} from "./sdk/connection/runtimeFunctionDefinition"; -import {handleFunctionDefinitions} from "./sdk/connection/functionDefinition"; -import {handleFlowTypes} from "./sdk/connection/flowTypes"; -import {handleLogon} from "./sdk/connection/logon"; -import {name} from "pino-pretty"; -import * as console from "node:console"; -import * as console from "node:console"; -import {call} from "pino"; -import * as console from "node:console"; -import * as console from "node:console"; -import * as console from "node:console"; -import * as console from "node:console"; - -export * from "./action_sdk.js" -export * from "./types.js" - -export enum CodeZeroEvent { - error = "error", - connected = "connected", - streamMessageReceived = "streamMessageReceived", - executionRequestReceived = "executionRequestReceived", - streamMessageSent = "streamMessageSent", - - moduleUpdated = "moduleUpdated", - moduleUpdateFailed = "moduleUpdateFailed", -} - -export interface CodeZeroEventMap { - [CodeZeroEvent.error]: [Error] - [CodeZeroEvent.connected]: [CodeZeroAction] - [CodeZeroEvent.streamMessageReceived]: [ActionTransferResponse] - [CodeZeroEvent.streamMessageSent]: [ActionTransferRequest] - [CodeZeroEvent.moduleUpdated]: [ModuleUpdateRequest] - [CodeZeroEvent.moduleUpdateFailed]: [Error] - - [flowType: string]: any[] -} - -export class CodeZeroAction extends EventEmitter { - private _functions: HerculesFunctionDefinition[] = []; - private _runtimeFunctions: HerculesRuntimeFunctionDefinition[] = []; - private _dataTypes: DefinitionDataType[] = []; - private _eventTypes: FlowType[] = []; - private _projectConfigurations: ModuleProjectConfigurations[] = []; - private _transport?: GrpcTransport - private _actionTransferServiceClient?: ActionTransferServiceClient - - private _stream?: DuplexStreamingCall - - private _identifier: string; - private _version: string - private _aquilaUrl?: string - private _author: string - private _icon: string; - private _name: HerculesTranslation[]; - private _documentation: string; - private _configurationDefinitions: HerculesActionConfigurationDefinition[]; - - - constructor(identifier: string, version: string, aquilaUrl: string, author: string, icon: string, documentation: string, name: HerculesTranslation[], configurationDefinitions: HerculesActionConfigurationDefinition[]) { - super(); - this._identifier = identifier; - this._version = version; - this._aquilaUrl = aquilaUrl; - this._author = author; - this._icon = icon; - this._name = name; - this._documentation = documentation; - } - - registerFunction(klass: FunctionDefinitionClass) { - const functionDefinition = functionMap(klass); - - this._functions.push(functionDefinition) - } - - registerRuntimeFunction(klass: RuntimeFunctionDefinitionClass) { - const omitFunctionDefinition = Reflect.getMetadata('hercules:omit_function_definition', klass) || false - - const runtimeFunction = runtimeFunctionMap(klass); - - this._runtimeFunctions.push(runtimeFunction) - if (!omitFunctionDefinition) { - this._functions.push({ - ...runtimeFunction, - runtimeDefinitionName: runtimeFunction.runtimeName, - parameters: runtimeFunction.parameters?.map(param => { - return { - ...param, - runtimeDefinitionName: param.runtimeName - } - }) || [] - }) - } - } - - connect(authToken: string, aquilaUrl: string, author: string, grpcOptions?: GrpcOptions) { - console.debug("Trying to connect to aquila") - this._transport = new GrpcTransport({ - host: aquilaUrl, - channelCredentials: ChannelCredentials.createInsecure() - }) - const actionTransferServiceClient = new ActionTransferServiceClient(this._transport!) - const builtOptions: RpcOptions = { - meta: { - "authorization": authToken, - }, - ...grpcOptions - } - this._stream = actionTransferServiceClient.transfer(builtOptions) - - - const moduleClient = new ModuleServiceClient(this._transport!) - try { - console.debug("Sent data types request") - const call = moduleClient.update(ModuleUpdateRequest.create({ - modules: [ - { - author: this._author, - version: this._version, - name: this._name, - icon: this._icon, - documentation: this._documentation, - identifier: this._identifier, - configurations: this._configurationDefinitions.map(definition => { - return { - identifier: definition.identifier, - name: definition.name, - type: definition.type, - hidden: definition.hidden || false, - defaultValue: definition.defaultValue, - description: definition.description, - optional: definition.optional || false, - linkedDataTypeIdentifiers: definition.linkedDataTypes - } as ModuleConfigurationDefinition - }) - - } - ] - }), grpcOptions) - if (!call.response.success) { - action.emit(CodeZeroEvent.dataTypesUpdateFailed, new Error("Failed to update data types")) - return Promise.reject(call.response); - } - action.emit(CodeZeroEvent.dataTypesUpdated, call.response) - } catch (error) { - console.error({ - err: error, - }, "Error while updating data types") - return Promise.reject(error); - } - - // await handleDataTypes(action, builtOptions); - // await handleRuntimeFunctionDefinitions(state, builtOptions, config) - // await handleFunctionDefinitions(state, builtOptions, config) - // await handleFlowTypes(state, builtOptions, config) - // await handleLogon(state, config); - - console.info("Connected successfully to aquila") - - - for await (const message of action.stream!.responses) { - action.emit(CodeZeroEvent.streamMessageReceived, message) - console.debug({ - message: message, - }, "Received message from stream") - switch (message.data.oneofKind) { - case "actionConfigurations": { - console.info("Received action configurations") - action.emit(CodeZeroEvent.actionConfigurationsReceived, message.data.actionConfigurations) - break - } - case "execution": { - action.emit(CodeZeroEvent.executionRequestReceived, message.data.execution) - break - } - default: { - action.emit(CodeZeroEvent.error, new Error("Received unknown message type from stream")) - } - } - } - } -} +export * from "./types.ts" +export * from "./events.ts" +export * from "./decorators/meta.ts" +export * from "./decorators/function.ts" +export * from "./decorators/data-type.ts" +export * from "./decorators/event.ts" +export * from "./decorators/runtime-event.ts" +export * from "./models/function.ts" +export * from "./models/runtime-function.ts" +export * from "./models/data-type.ts" +export * from "./models/event.ts" +export * from "./models/runtime-event.ts" +export * from "./manager/BaseManager.ts" +export * from "./manager/config-manager.ts" +export * from "./manager/FunctionManager.ts" +export * from "./manager/RuntimeFunctionManager.ts" +export * from "./manager/DataTypeManager.ts" +export * from "./manager/EventManager.ts" +export * from "./manager/RuntimeEventManager.ts" +export * from "./CodeZeroAction.ts" From 401d8ff67f272bf47e8e1502ee7f0657a7ab4760 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 00:50:01 +0200 Subject: [PATCH 27/43] feat: example action --- .../simple-example-ts/package-lock.json | 676 +----------------- ts/examples/simple-example-ts/package.json | 8 +- .../src/data_types/emailDataType.ts | 10 + .../src/events/userCreatedEvent.ts | 13 + .../src/events/userCreatedRuntimeEvent.ts | 12 + .../src/functions/fibonacciFunction.ts | 12 + .../src/functions/fibonacciRuntimeFunction.ts | 27 + ts/examples/simple-example-ts/src/index.ts | 94 +-- ts/examples/simple-example-ts/tsconfig.json | 10 +- 9 files changed, 153 insertions(+), 709 deletions(-) create mode 100644 ts/examples/simple-example-ts/src/data_types/emailDataType.ts create mode 100644 ts/examples/simple-example-ts/src/events/userCreatedEvent.ts create mode 100644 ts/examples/simple-example-ts/src/events/userCreatedRuntimeEvent.ts create mode 100644 ts/examples/simple-example-ts/src/functions/fibonacciFunction.ts create mode 100644 ts/examples/simple-example-ts/src/functions/fibonacciRuntimeFunction.ts diff --git a/ts/examples/simple-example-ts/package-lock.json b/ts/examples/simple-example-ts/package-lock.json index ca17b67..577815c 100644 --- a/ts/examples/simple-example-ts/package-lock.json +++ b/ts/examples/simple-example-ts/package-lock.json @@ -9,678 +9,36 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@code0-tech/hercules": "file:../../code0-tech-hercules-0.0.0.tgz" - } - }, - "node_modules/@code0-tech/hercules": { - "version": "0.0.0", - "resolved": "file:../../code0-tech-hercules-0.0.0.tgz", - "integrity": "sha512-WNWRc5+auZ15MBHcilAA+HPpASKW0CaTTe1QAYCUlcC1a+t9a8/yBEWQr4Ol8FA72yrR3+1/5r4C0YPm5cDVcQ==", - "license": "ISC", - "dependencies": { - "@code0-tech/tucana": "0.0.68", - "@grpc/grpc-js": "^1.14.3", - "@protobuf-ts/grpc-backend": "^2.11.1", - "@protobuf-ts/grpc-transport": "^2.11.1", - "@protobuf-ts/runtime": "^2.11.1", - "@protobuf-ts/runtime-rpc": "^2.11.1", - "pino": "^10.3.1", - "pino-pretty": "^13.1.3", - "reflect-metadata": "^0.2.2" - } - }, - "node_modules/@code0-tech/tucana": { - "version": "0.0.68", - "resolved": "https://registry.npmjs.org/@code0-tech/tucana/-/tucana-0.0.68.tgz", - "integrity": "sha512-kbjLiKjJyZLnPmNi5JabWRNZcWZyXnfnld8jCFrUkvKbGj77CAwggR0uH8SqaxwWNWqQZlavYzCZWO/ob3+uKA==", - "license": "Apache-2.0" - }, - "node_modules/@grpc/grpc-js": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.3.tgz", - "integrity": "sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/proto-loader": "^0.8.0", - "@js-sdsl/ordered-map": "^4.4.2" - }, - "engines": { - "node": ">=12.10.0" - } - }, - "node_modules/@grpc/proto-loader": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.0.tgz", - "integrity": "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==", - "license": "Apache-2.0", - "dependencies": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.5.3", - "yargs": "^17.7.2" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + "zod": "^4.4.3" }, - "engines": { - "node": ">=6" + "devDependencies": { + "@types/node": "^22.0.0" } }, - "node_modules/@js-sdsl/ordered-map": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", - "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/@pinojs/redact": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", - "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==", - "license": "MIT" - }, - "node_modules/@protobuf-ts/grpc-backend": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/@protobuf-ts/grpc-backend/-/grpc-backend-2.11.1.tgz", - "integrity": "sha512-llAkJ03SlR/+p70YBTMOAQqdkXWghsTWwlPuGXC+Hj99hDQq6fa2CoVePPqbcn7A7/aLBcPG/9Ag3yqlltldxw==", - "license": "Apache-2.0", - "dependencies": { - "@protobuf-ts/runtime": "^2.11.1", - "@protobuf-ts/runtime-rpc": "^2.11.1" - }, - "peerDependencies": { - "@grpc/grpc-js": "^1.8.22" - } - }, - "node_modules/@protobuf-ts/grpc-transport": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/@protobuf-ts/grpc-transport/-/grpc-transport-2.11.1.tgz", - "integrity": "sha512-l6wrcFffY+tuNnuyrNCkRM8hDIsAZVLA8Mn7PKdVyYxITosYh60qW663p9kL6TWXYuDCL3oxH8ih3vLKTDyhtg==", - "license": "Apache-2.0", - "dependencies": { - "@protobuf-ts/runtime": "^2.11.1", - "@protobuf-ts/runtime-rpc": "^2.11.1" - }, - "peerDependencies": { - "@grpc/grpc-js": "^1.6.0" - } - }, - "node_modules/@protobuf-ts/runtime": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/@protobuf-ts/runtime/-/runtime-2.11.1.tgz", - "integrity": "sha512-KuDaT1IfHkugM2pyz+FwiY80ejWrkH1pAtOBOZFuR6SXEFTsnb/jiQWQ1rCIrcKx2BtyxnxW6BWwsVSA/Ie+WQ==", - "license": "(Apache-2.0 AND BSD-3-Clause)" - }, - "node_modules/@protobuf-ts/runtime-rpc": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/@protobuf-ts/runtime-rpc/-/runtime-rpc-2.11.1.tgz", - "integrity": "sha512-4CqqUmNA+/uMz00+d3CYKgElXO9VrEbucjnBFEjqI4GuDrEQ32MaI3q+9qPBvIGOlL4PmHXrzM32vBPWRhQKWQ==", - "license": "Apache-2.0", - "dependencies": { - "@protobuf-ts/runtime": "^2.11.1" - } - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", - "license": "BSD-3-Clause" - }, "node_modules/@types/node": { - "version": "25.5.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.2.tgz", - "integrity": "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==", + "version": "22.19.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.21.tgz", + "integrity": "sha512-VMeFBSCKQKmm2swI2kW51SFusDqekC6q9trBCvJ/JliDchFSuoYYKN7yVNjPthP1HKZcx3U1gI/wTcEBjEFKTA==", + "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~7.18.0" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/atomic-sleep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "license": "MIT" - }, - "node_modules/dateformat": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/fast-copy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-4.0.2.tgz", - "integrity": "sha512-ybA6PDXIXOXivLJK/z9e+Otk7ve13I4ckBvGO5I2RRmBU1gMHLVDJYEuJYhGwez7YNlYji2M2DvVU+a9mSFDlw==", - "license": "MIT" - }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "license": "MIT" - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/help-me": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", - "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", - "license": "MIT" - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/joycon": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", - "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "license": "MIT" - }, - "node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0" - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-exit-leak-free": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", - "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/pino": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/pino/-/pino-10.3.1.tgz", - "integrity": "sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg==", - "license": "MIT", - "dependencies": { - "@pinojs/redact": "^0.4.0", - "atomic-sleep": "^1.0.0", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^3.0.0", - "pino-std-serializers": "^7.0.0", - "process-warning": "^5.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.2.0", - "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^4.0.1", - "thread-stream": "^4.0.0" - }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/pino-abstract-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz", - "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", - "license": "MIT", - "dependencies": { - "split2": "^4.0.0" - } - }, - "node_modules/pino-pretty": { - "version": "13.1.3", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.1.3.tgz", - "integrity": "sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg==", - "license": "MIT", - "dependencies": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^4.0.0", - "fast-safe-stringify": "^2.1.1", - "help-me": "^5.0.0", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^3.0.0", - "pump": "^3.0.0", - "secure-json-parse": "^4.0.0", - "sonic-boom": "^4.0.1", - "strip-json-comments": "^5.0.2" - }, - "bin": { - "pino-pretty": "bin.js" - } - }, - "node_modules/pino-std-serializers": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz", - "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==", - "license": "MIT" - }, - "node_modules/process-warning": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", - "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "node_modules/protobufjs": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", - "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/pump": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", - "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/quick-format-unescaped": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", - "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", - "license": "MIT" - }, - "node_modules/real-require": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", - "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", - "license": "MIT", - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/reflect-metadata": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", - "license": "Apache-2.0" - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/safe-stable-stringify": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", - "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/secure-json-parse": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.1.0.tgz", - "integrity": "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/sonic-boom": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz", - "integrity": "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==", - "license": "MIT", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "license": "ISC", - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.3.tgz", - "integrity": "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==", - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/thread-stream": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-4.0.0.tgz", - "integrity": "sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA==", - "license": "MIT", - "dependencies": { - "real-require": "^0.2.0" - }, - "engines": { - "node": ">=20" + "undici-types": "~6.21.0" } }, "node_modules/undici-types": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", - "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, "license": "MIT" }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "license": "ISC" - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "engines": { - "node": ">=12" + "url": "https://github.com/sponsors/colinhacks" } } } diff --git a/ts/examples/simple-example-ts/package.json b/ts/examples/simple-example-ts/package.json index dd44023..a5a0a98 100644 --- a/ts/examples/simple-example-ts/package.json +++ b/ts/examples/simple-example-ts/package.json @@ -7,10 +7,14 @@ "type": "module", "main": "index.js", "scripts": { + "typecheck": "tsc --noEmit", "build": "vite build .", - "start": "cd ../.. && npm install && npm run build && npm pack && cd examples/simple-example-ts && npm install && npm run build && node dist/index.js" + "start": "npm run build && node dist/index.js" + }, + "devDependencies": { + "@types/node": "^22.0.0" }, "dependencies": { - "@code0-tech/hercules": "file:../../code0-tech-hercules-0.0.0.tgz" + "zod": "^4.4.3" } } diff --git a/ts/examples/simple-example-ts/src/data_types/emailDataType.ts b/ts/examples/simple-example-ts/src/data_types/emailDataType.ts new file mode 100644 index 0000000..2acb9bf --- /dev/null +++ b/ts/examples/simple-example-ts/src/data_types/emailDataType.ts @@ -0,0 +1,10 @@ +import {Identifier, Name, Schema} from "@code0-tech/hercules"; +import {z} from "zod"; + +const EmailSchema = z.string().regex(/^[^@]+@[^@]+\.[^@]+$/) +export type EmailType = z.infer + +@Identifier("email_address") +@Name({code: "en-US", content: "Email Address"}) +@Schema(EmailSchema) +export class EmailDataType {} diff --git a/ts/examples/simple-example-ts/src/events/userCreatedEvent.ts b/ts/examples/simple-example-ts/src/events/userCreatedEvent.ts new file mode 100644 index 0000000..d7d9c7f --- /dev/null +++ b/ts/examples/simple-example-ts/src/events/userCreatedEvent.ts @@ -0,0 +1,13 @@ +import {Editable, EventSetting, Identifier, Name} from "@code0-tech/hercules"; +import {UserCreatedRuntimeEvent} from "./userCreatedRuntimeEvent.ts"; + +@Identifier("user_created_event") +@Name({code: "en-US", content: "On User Created"}) +@Editable(false) +@EventSetting({ + identifier: "FILTER_ROLE", + name: [{code: "en-US", content: "Role Filter"}], + description: [{code: "en-US", content: "Only trigger for users with this role"}], + optional: true, +}) +export class UserCreatedEvent extends UserCreatedRuntimeEvent {} diff --git a/ts/examples/simple-example-ts/src/events/userCreatedRuntimeEvent.ts b/ts/examples/simple-example-ts/src/events/userCreatedRuntimeEvent.ts new file mode 100644 index 0000000..ff8ad79 --- /dev/null +++ b/ts/examples/simple-example-ts/src/events/userCreatedRuntimeEvent.ts @@ -0,0 +1,12 @@ +import {Identifier, Name, RuntimeEventSetting, Signature} from "@code0-tech/hercules"; + +@Identifier("user_created") +@Signature("(userId: number): void") +@Name({code: "en-US", content: "User Created"}) +@RuntimeEventSetting({ + identifier: "FILTER_ROLE", + name: [{code: "en-US", content: "Role Filter"}], + description: [{code: "en-US", content: "Only trigger for users with this role"}], + optional: true, +}) +export class UserCreatedRuntimeEvent {} diff --git a/ts/examples/simple-example-ts/src/functions/fibonacciFunction.ts b/ts/examples/simple-example-ts/src/functions/fibonacciFunction.ts new file mode 100644 index 0000000..145a187 --- /dev/null +++ b/ts/examples/simple-example-ts/src/functions/fibonacciFunction.ts @@ -0,0 +1,12 @@ +import {FunctionParameter, Identifier, Name} from "@code0-tech/hercules"; +import {FibonacciRuntimeFunction} from "./fibonacciRuntimeFunction.js"; + +@Identifier("fibonacci") +@Name({code: "en-US", content: "Compute Fibonacci Number"}) +@FunctionParameter({ + runtimeName: "n", + name: [{code: "en-US", content: "Input Number"}], + description: [{code: "en-US", content: "The position in the Fibonacci sequence"}], + defaultValue: 10, +}) +export class FibonacciFunction extends FibonacciRuntimeFunction {} diff --git a/ts/examples/simple-example-ts/src/functions/fibonacciRuntimeFunction.ts b/ts/examples/simple-example-ts/src/functions/fibonacciRuntimeFunction.ts new file mode 100644 index 0000000..db8e0f3 --- /dev/null +++ b/ts/examples/simple-example-ts/src/functions/fibonacciRuntimeFunction.ts @@ -0,0 +1,27 @@ +import { + DisplayMessage, + HerculesFunctionContext, + Identifier, + Name, + OmitFunctionDefinition, + RuntimeParameter, + Signature, +} from "@code0-tech/hercules"; + +@Identifier("fibonacci_runtime") +@Signature("(n: number): number") +@Name({code: "en-US", content: "Fibonacci (Runtime)"}) +@DisplayMessage({code: "en-US", content: "Computes the n-th Fibonacci number"}) +@OmitFunctionDefinition() +@RuntimeParameter({runtimeName: "n", name: [{code: "en-US", content: "N"}]}) +export class FibonacciRuntimeFunction { + run(context: HerculesFunctionContext, n: number): number { + console.log(`[fibonacci] project=${context.projectId} execution=${context.executionId}`); + return this.fib(n); + } + + private fib(n: number): number { + if (n <= 1) return n; + return this.fib(n - 1) + this.fib(n - 2); + } +} diff --git a/ts/examples/simple-example-ts/src/index.ts b/ts/examples/simple-example-ts/src/index.ts index 5d5ce03..1643a4c 100644 --- a/ts/examples/simple-example-ts/src/index.ts +++ b/ts/examples/simple-example-ts/src/index.ts @@ -1,44 +1,50 @@ -import {createSdk, HerculesActionProjectConfiguration} from "@code0-tech/hercules"; -import {FibonacciFunction} from "./fibonacciFunction"; -import {someEventType} from "./exampleEventType"; -import {someDataType} from "./exampleDataType"; - -const sdk = createSdk({ - authToken: process.env.AUTH_TOKEN || "token", - aquilaUrl: process.env.AQUILA_URL || "127.0.0.1:8081", - actionId: process.env.ACTION_ID || "example", - version: process.env.VERSION || "0.0.0", -}, [ - { - type: "string[]", - identifier: "EXAMPLE_CONFIG_IDENTIFIER", - } -]) - -sdk.registerDataTypes(someDataType) -sdk.registerRuntimeFunctionDefinitionClass(FibonacciFunction) -sdk.registerEventTypes(someEventType) - - -connectToSdk(); - -function connectToSdk() { - sdk.connect().then((configs: HerculesActionProjectConfiguration[]) => { - console.log("SDK connected successfully"); - - sdk.dispatchEvent("test_flow", configs[0].projectId, "Hello, World! Configs loaded: " + configs.length).then(() => { - console.log("Event dispatched successfully"); - }) - }).catch(() => { - // will be handled by logger internally - process.exit(1) - }) - - sdk.onError((error) => { - console.error("SDK Error occurred:", error.message); - console.log("Attempting to reconnect in 5s..."); - setTimeout(() => { - connectToSdk(); - }, 5000) - }) -} +import {CodeZeroAction, CodeZeroEvent} from "@code0-tech/hercules"; +import {FibonacciRuntimeFunction} from "./functions/fibonacciRuntimeFunction.js"; +import {FibonacciFunction} from "./functions/fibonacciFunction.js"; +import {UserCreatedRuntimeEvent} from "./events/userCreatedRuntimeEvent.js"; +import {UserCreatedEvent} from "./events/userCreatedEvent.js"; +import {EmailDataType} from "./data_types/emailDataType.js"; + +const action = new CodeZeroAction( + process.env.ACTION_ID ?? "example-action", + process.env.VERSION ?? "0.0.0", + process.env.AQUILA_URL ?? "127.0.0.1:8081", + "code0-tech", + "tabler:bolt", + "A simple example action", + [{code: "en-US", content: "Example Action"}], + [{ + identifier: "EXAMPLE_CONFIG", + type: "string", + name: [{code: "en-US", content: "Example Config"}], + }], +); + +// Runtime function (with OmitFunctionDefinition — no auto-generated function def) +action.registerRuntimeFunction(FibonacciRuntimeFunction); + +// Function: named public variant that extends the runtime function +action.registerFunction(FibonacciFunction); + +// Data type: derived from Zod schema +action.registerDataTypeClass(EmailDataType); + +// Runtime flow type: the internal event definition +action.registerRuntimeEventClass(UserCreatedRuntimeEvent); + +// Flow type: the user-facing event linked to the runtime flow type +action.registerEventClass(UserCreatedEvent); + +action.on(CodeZeroEvent.connected, () => { + console.log("Connected to aquila"); +}); + +action.on(CodeZeroEvent.error, (error: Error) => { + console.error("Stream error:", error.message); +}); + + +action.connect(process.env.AUTH_TOKEN ?? "token").catch((err: unknown) => { + console.error("Failed to connect:", err); + process.exit(1); +}); diff --git a/ts/examples/simple-example-ts/tsconfig.json b/ts/examples/simple-example-ts/tsconfig.json index d2af2bc..e9dd4f5 100644 --- a/ts/examples/simple-example-ts/tsconfig.json +++ b/ts/examples/simple-example-ts/tsconfig.json @@ -5,18 +5,20 @@ "moduleResolution": "Bundler", "declaration": true, "outDir": "dist", - "strict": false, + "strict": true, "esModuleInterop": true, "skipLibCheck": true, + "allowImportingTsExtensions": true, + "noEmit": true, "baseUrl": ".", "paths": { - "@code0-tech/hercules": ["../../ts"] + "@code0-tech/hercules": ["../../src/index.ts"] }, "experimentalDecorators": true, "emitDecoratorMetadata": true, - "types": ["vite/client"] + "types": ["node", "vite/client"] }, "include": [ - "src/index.ts" + "src/**/*" ] } \ No newline at end of file From 67f57bc1e8bf94218933f0214aafebbafa55cdac Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 13:04:36 +0200 Subject: [PATCH 28/43] feat: correct imports --- ts/src/CodeZeroAction.ts | 42 ++++++++++++------------ ts/src/actions/Execution.ts | 8 ++--- ts/src/actions/ModuleConfigurations.ts | 4 +-- ts/src/actions/index.ts | 6 ++-- ts/src/decorators/data-type.ts | 3 ++ ts/src/decorators/event.ts | 2 +- ts/src/decorators/function.ts | 4 +-- ts/src/decorators/meta.ts | 2 +- ts/src/decorators/runtime-event.ts | 2 +- ts/src/index.ts | 40 +++++++++++----------- ts/src/internal/module-builder.ts | 12 +++---- ts/src/manager/DataTypeManager.ts | 4 +-- ts/src/manager/EventManager.ts | 4 +-- ts/src/manager/FunctionManager.ts | 4 +-- ts/src/manager/RuntimeEventManager.ts | 4 +-- ts/src/manager/RuntimeFunctionManager.ts | 4 +-- ts/src/manager/config-manager.ts | 4 +-- ts/src/map/data-type.ts | 6 ++-- ts/src/map/event.ts | 8 ++--- ts/src/map/function.ts | 6 ++-- ts/src/map/runtime-event.ts | 4 +-- ts/src/map/runtime-function.ts | 2 +- ts/src/models/data-type.ts | 2 +- ts/src/models/event.ts | 4 +-- ts/src/models/function.ts | 4 +-- ts/src/models/runtime-event.ts | 2 +- ts/src/models/runtime-function.ts | 2 +- ts/src/types.ts | 4 +-- 28 files changed, 98 insertions(+), 95 deletions(-) diff --git a/ts/src/CodeZeroAction.ts b/ts/src/CodeZeroAction.ts index d62b7d4..41002d5 100644 --- a/ts/src/CodeZeroAction.ts +++ b/ts/src/CodeZeroAction.ts @@ -3,27 +3,27 @@ import type {GrpcOptions, GrpcTransport} from "@protobuf-ts/grpc-transport"; import {ActionTransferRequest, type ActionTransferResponse} from "@code0-tech/tucana/aquila"; import {constructValue, type PlainValue} from "@code0-tech/tucana/helpers"; import type {DuplexStreamingCall} from "@protobuf-ts/runtime-rpc"; -import type {FunctionDefinitionClass} from "./models/function.ts"; -import type {RuntimeFunctionDefinitionClass} from "./models/runtime-function.ts"; -import {runtimeFunctionMap} from "./map/runtime-function.ts"; -import {functionMap} from "./map/function.ts"; -import type {DataTypeClass} from "./models/data-type.ts"; -import {dataTypeMap} from "./map/data-type.ts"; -import type {EventClass} from "./models/event.ts"; -import {eventMap} from "./map/event.ts"; -import type {RuntimeEventClass} from "./models/runtime-event.ts"; -import {runtimeEventMap} from "./map/runtime-event.ts"; -import type {HerculesActionConfigurationDefinition, HerculesTranslation} from "./types.ts"; -import {CodeZeroEvent, type CodeZeroEventMap} from "./events.ts"; -import {createConnection} from "./internal/connection.ts"; -import {buildModule} from "./internal/module-builder.ts"; -import {ConfigManager} from "./manager/config-manager.ts"; -import {FunctionManager} from "./manager/FunctionManager.ts"; -import {RuntimeFunctionManager} from "./manager/RuntimeFunctionManager.ts"; -import {DataTypeManager} from "./manager/DataTypeManager.ts"; -import {EventManager} from "./manager/EventManager.ts"; -import {RuntimeEventManager} from "./manager/RuntimeEventManager.ts"; -import {actions} from "./actions/index.ts"; +import type {FunctionDefinitionClass} from "./models/function"; +import type {RuntimeFunctionDefinitionClass} from "./models/runtime-function"; +import {runtimeFunctionMap} from "./map/runtime-function"; +import {functionMap} from "./map/function"; +import type {DataTypeClass} from "./models/data-type"; +import {dataTypeMap} from "./map/data-type"; +import type {EventClass} from "./models/event"; +import {eventMap} from "./map/event"; +import type {RuntimeEventClass} from "./models/runtime-event"; +import {runtimeEventMap} from "./map/runtime-event"; +import type {HerculesActionConfigurationDefinition, HerculesTranslation} from "./types"; +import {CodeZeroEvent, type CodeZeroEventMap} from "./events"; +import {createConnection} from "./internal/connection"; +import {buildModule} from "./internal/module-builder"; +import {ConfigManager} from "./manager/config-manager"; +import {FunctionManager} from "./manager/FunctionManager"; +import {RuntimeFunctionManager} from "./manager/RuntimeFunctionManager"; +import {DataTypeManager} from "./manager/DataTypeManager"; +import {EventManager} from "./manager/EventManager"; +import {RuntimeEventManager} from "./manager/RuntimeEventManager"; +import {actions} from "./actions"; export class CodeZeroAction extends EventEmitter { private _transport?: GrpcTransport; diff --git a/ts/src/actions/Execution.ts b/ts/src/actions/Execution.ts index aadf0fb..77e398e 100644 --- a/ts/src/actions/Execution.ts +++ b/ts/src/actions/Execution.ts @@ -1,10 +1,10 @@ import {constructValue, PlainValue, toAllowedValue} from "@code0-tech/tucana/helpers"; import {ActionExecutionRequest, ActionExecutionResponse, ActionTransferRequest} from "@code0-tech/tucana/aquila"; import {NodeExecutionResult, Error as ProtoError} from "@code0-tech/tucana/shared"; -import {HerculesFunctionContext, RuntimeErrorException} from "../types.ts"; -import {HerculesRuntimeFunctionDefinition} from "../models/runtime-function.ts"; -import {CodeZeroEvent} from "../events.ts"; -import type {CodeZeroAction} from "../CodeZeroAction.ts"; +import {HerculesFunctionContext, RuntimeErrorException} from "../types"; +import {HerculesRuntimeFunctionDefinition} from "../models/runtime-function"; +import {CodeZeroEvent} from "../events"; +import type {CodeZeroAction} from "../CodeZeroAction"; export const packetType = "execution"; diff --git a/ts/src/actions/ModuleConfigurations.ts b/ts/src/actions/ModuleConfigurations.ts index 2a6931f..1ee4010 100644 --- a/ts/src/actions/ModuleConfigurations.ts +++ b/ts/src/actions/ModuleConfigurations.ts @@ -1,6 +1,6 @@ import type {ModuleConfigurations} from "@code0-tech/tucana/shared"; -import {CodeZeroEvent} from "../events.ts"; -import type {CodeZeroAction} from "../CodeZeroAction.ts"; +import {CodeZeroEvent} from "../events"; +import type {CodeZeroAction} from "../CodeZeroAction"; export const packetType = "moduleConfigurations"; diff --git a/ts/src/actions/index.ts b/ts/src/actions/index.ts index 94272d7..93c34bf 100644 --- a/ts/src/actions/index.ts +++ b/ts/src/actions/index.ts @@ -1,6 +1,6 @@ -import type {CodeZeroAction} from "../CodeZeroAction.ts"; -import * as ModuleConfigurations from "./ModuleConfigurations.ts"; -import * as Execution from "./Execution.ts"; +import type {CodeZeroAction} from "../CodeZeroAction"; +import * as ModuleConfigurations from "./ModuleConfigurations"; +import * as Execution from "./Execution"; export interface Action { packetType: string; diff --git a/ts/src/decorators/data-type.ts b/ts/src/decorators/data-type.ts index c8258a3..35aac7d 100644 --- a/ts/src/decorators/data-type.ts +++ b/ts/src/decorators/data-type.ts @@ -2,3 +2,6 @@ import type {ZodTypeAny} from "zod"; export const Schema = (schema: ZodTypeAny): ClassDecorator => (target) => Reflect.defineMetadata('hercules:schema', schema, target) + +export const GenericKeys = (...keys: string[]): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:generic_keys', keys, target) diff --git a/ts/src/decorators/event.ts b/ts/src/decorators/event.ts index 08bec67..92bb49d 100644 --- a/ts/src/decorators/event.ts +++ b/ts/src/decorators/event.ts @@ -1,4 +1,4 @@ -import {HerculesEventSetting} from "../models/event.ts"; +import {HerculesEventSetting} from "../models/event"; export const EventSetting = (setting: HerculesEventSetting): ClassDecorator => (target) => { diff --git a/ts/src/decorators/function.ts b/ts/src/decorators/function.ts index 82df6f5..97d8de5 100644 --- a/ts/src/decorators/function.ts +++ b/ts/src/decorators/function.ts @@ -1,5 +1,5 @@ -import {HerculesFunctionDefinitionParameter} from "../models/function.ts"; -import {HerculesRuntimeFunctionDefinitionParameter} from "../models/runtime-function.ts"; +import {HerculesFunctionDefinitionParameter} from "../models/function"; +import {HerculesRuntimeFunctionDefinitionParameter} from "../models/runtime-function"; export const OmitFunctionDefinition = (): ClassDecorator => (target) => Reflect.defineMetadata('hercules:omit_function_definition', true, target) diff --git a/ts/src/decorators/meta.ts b/ts/src/decorators/meta.ts index 30754a0..ec1f57f 100644 --- a/ts/src/decorators/meta.ts +++ b/ts/src/decorators/meta.ts @@ -1,4 +1,4 @@ -import {HerculesTranslation} from "../types.ts"; +import {HerculesTranslation} from "../types"; export const Identifier = (id: string): ClassDecorator => (target) => Reflect.defineMetadata('hercules:identifier', id, target) diff --git a/ts/src/decorators/runtime-event.ts b/ts/src/decorators/runtime-event.ts index 04f5d3f..3787668 100644 --- a/ts/src/decorators/runtime-event.ts +++ b/ts/src/decorators/runtime-event.ts @@ -1,4 +1,4 @@ -import {HerculesRuntimeEventSetting} from "../models/runtime-event.ts"; +import {HerculesRuntimeEventSetting} from "../models/runtime-event"; export const RuntimeEventSetting = (setting: HerculesRuntimeEventSetting): ClassDecorator => (target) => { diff --git a/ts/src/index.ts b/ts/src/index.ts index 035a865..61bb5c5 100644 --- a/ts/src/index.ts +++ b/ts/src/index.ts @@ -1,20 +1,20 @@ -export * from "./types.ts" -export * from "./events.ts" -export * from "./decorators/meta.ts" -export * from "./decorators/function.ts" -export * from "./decorators/data-type.ts" -export * from "./decorators/event.ts" -export * from "./decorators/runtime-event.ts" -export * from "./models/function.ts" -export * from "./models/runtime-function.ts" -export * from "./models/data-type.ts" -export * from "./models/event.ts" -export * from "./models/runtime-event.ts" -export * from "./manager/BaseManager.ts" -export * from "./manager/config-manager.ts" -export * from "./manager/FunctionManager.ts" -export * from "./manager/RuntimeFunctionManager.ts" -export * from "./manager/DataTypeManager.ts" -export * from "./manager/EventManager.ts" -export * from "./manager/RuntimeEventManager.ts" -export * from "./CodeZeroAction.ts" +export * from "./types" +export * from "./events" +export * from "./decorators/meta" +export * from "./decorators/function" +export * from "./decorators/data-type" +export * from "./decorators/event" +export * from "./decorators/runtime-event" +export * from "./models/function" +export * from "./models/runtime-function" +export * from "./models/data-type" +export * from "./models/event" +export * from "./models/runtime-event" +export * from "./manager/BaseManager" +export * from "./manager/config-manager" +export * from "./manager/FunctionManager" +export * from "./manager/RuntimeFunctionManager" +export * from "./manager/DataTypeManager" +export * from "./manager/EventManager" +export * from "./manager/RuntimeEventManager" +export * from "./CodeZeroAction" diff --git a/ts/src/internal/module-builder.ts b/ts/src/internal/module-builder.ts index 680ae0a..2c87a94 100644 --- a/ts/src/internal/module-builder.ts +++ b/ts/src/internal/module-builder.ts @@ -1,11 +1,11 @@ import {constructValue} from "@code0-tech/tucana/helpers"; import {DefinitionDataType, FlowType, FlowTypeSetting, Module, ModuleConfigurationDefinition, RuntimeFlowType, RuntimeFlowTypeSetting} from "@code0-tech/tucana/shared"; -import type {HerculesFunctionDefinition} from "../models/function.ts"; -import type {HerculesRuntimeFunctionDefinition} from "../models/runtime-function.ts"; -import type {HerculesActionConfigurationDefinition, HerculesTranslation} from "../types.ts"; -import {HerculesDataType} from "../models/data-type.ts"; -import {HerculesEvent} from "../models/event.ts"; -import {HerculesRuntimeEvent} from "../models/runtime-event.ts"; +import type {HerculesFunctionDefinition} from "../models/function"; +import type {HerculesRuntimeFunctionDefinition} from "../models/runtime-function"; +import type {HerculesActionConfigurationDefinition, HerculesTranslation} from "../types"; +import {HerculesDataType} from "../models/data-type"; +import {HerculesEvent} from "../models/event"; +import {HerculesRuntimeEvent} from "../models/runtime-event"; export interface ModuleBuildData { identifier: string; diff --git a/ts/src/manager/DataTypeManager.ts b/ts/src/manager/DataTypeManager.ts index ba6fd4e..b6a78fd 100644 --- a/ts/src/manager/DataTypeManager.ts +++ b/ts/src/manager/DataTypeManager.ts @@ -1,4 +1,4 @@ -import {BaseManager} from "./BaseManager.ts"; -import {HerculesDataType} from "../models/data-type.ts"; +import {BaseManager} from "./BaseManager"; +import {HerculesDataType} from "../models/data-type"; export class DataTypeManager extends BaseManager {} diff --git a/ts/src/manager/EventManager.ts b/ts/src/manager/EventManager.ts index 61c7cc3..4552267 100644 --- a/ts/src/manager/EventManager.ts +++ b/ts/src/manager/EventManager.ts @@ -1,4 +1,4 @@ -import {BaseManager} from "./BaseManager.ts"; -import {HerculesEvent} from "../models/event.ts"; +import {BaseManager} from "./BaseManager"; +import {HerculesEvent} from "../models/event"; export class EventManager extends BaseManager {} diff --git a/ts/src/manager/FunctionManager.ts b/ts/src/manager/FunctionManager.ts index e267cfb..8aa0216 100644 --- a/ts/src/manager/FunctionManager.ts +++ b/ts/src/manager/FunctionManager.ts @@ -1,4 +1,4 @@ -import {BaseManager} from "./BaseManager.ts"; -import type {HerculesFunctionDefinition} from "../models/function.ts"; +import {BaseManager} from "./BaseManager"; +import type {HerculesFunctionDefinition} from "../models/function"; export class FunctionManager extends BaseManager {} diff --git a/ts/src/manager/RuntimeEventManager.ts b/ts/src/manager/RuntimeEventManager.ts index ddef553..84765de 100644 --- a/ts/src/manager/RuntimeEventManager.ts +++ b/ts/src/manager/RuntimeEventManager.ts @@ -1,4 +1,4 @@ -import {BaseManager} from "./BaseManager.ts"; -import {HerculesRuntimeEvent} from "../models/runtime-event.ts"; +import {BaseManager} from "./BaseManager"; +import {HerculesRuntimeEvent} from "../models/runtime-event"; export class RuntimeEventManager extends BaseManager {} diff --git a/ts/src/manager/RuntimeFunctionManager.ts b/ts/src/manager/RuntimeFunctionManager.ts index bf8402e..5e7a850 100644 --- a/ts/src/manager/RuntimeFunctionManager.ts +++ b/ts/src/manager/RuntimeFunctionManager.ts @@ -1,4 +1,4 @@ -import {BaseManager} from "./BaseManager.ts"; -import type {HerculesRuntimeFunctionDefinition} from "../models/runtime-function.ts"; +import {BaseManager} from "./BaseManager"; +import type {HerculesRuntimeFunctionDefinition} from "../models/runtime-function"; export class RuntimeFunctionManager extends BaseManager {} diff --git a/ts/src/manager/config-manager.ts b/ts/src/manager/config-manager.ts index 5078e73..5ba436c 100644 --- a/ts/src/manager/config-manager.ts +++ b/ts/src/manager/config-manager.ts @@ -1,7 +1,7 @@ import {constructValue, toAllowedValue} from "@code0-tech/tucana/helpers"; import type {ModuleProjectConfigurations} from "@code0-tech/tucana/shared"; -import type {HerculesActionProjectConfiguration} from "../types.ts"; -import {BaseManager} from "./BaseManager.ts"; +import type {HerculesActionProjectConfiguration} from "../types"; +import {BaseManager} from "./BaseManager"; export class ConfigManager extends BaseManager { update(configs: ModuleProjectConfigurations[]): void { diff --git a/ts/src/map/data-type.ts b/ts/src/map/data-type.ts index f4883d7..56f1c3d 100644 --- a/ts/src/map/data-type.ts +++ b/ts/src/map/data-type.ts @@ -1,6 +1,6 @@ -import {zodToRules, zodToTypeString} from "../internal/zod-schema.ts"; -import type {HerculesTranslation} from "../types.ts"; -import type {DataTypeClass, HerculesDataType} from "../models/data-type.ts"; +import {zodToRules, zodToTypeString} from "../internal/zod-schema"; +import type {HerculesTranslation} from "../types"; +import type {DataTypeClass, HerculesDataType} from "../models/data-type"; export const dataTypeMap = (klass: DataTypeClass): HerculesDataType => { const identifier: string = Reflect.getMetadata('hercules:identifier', klass); diff --git a/ts/src/map/event.ts b/ts/src/map/event.ts index f5ba4d1..e88b1b9 100644 --- a/ts/src/map/event.ts +++ b/ts/src/map/event.ts @@ -1,7 +1,7 @@ -import type {HerculesTranslation} from "../types.ts"; -import type {EventClass, HerculesEvent, HerculesEventSetting} from "../models/event.ts"; -import type {RuntimeEventClass} from "../models/runtime-event.ts"; -import {runtimeEventMap} from "./runtime-event.ts"; +import type {HerculesTranslation} from "../types"; +import type {EventClass, HerculesEvent, HerculesEventSetting} from "../models/event"; +import type {RuntimeEventClass} from "../models/runtime-event"; +import {runtimeEventMap} from "./runtime-event"; export const eventMap = (klass: EventClass): HerculesEvent => { const parentClass = Object.getPrototypeOf(klass); diff --git a/ts/src/map/function.ts b/ts/src/map/function.ts index dccae57..4c21e3a 100644 --- a/ts/src/map/function.ts +++ b/ts/src/map/function.ts @@ -1,6 +1,6 @@ -import {FunctionDefinitionClass, HerculesFunctionDefinition, HerculesFunctionDefinitionParameter} from "../models/function.ts"; -import {RuntimeFunctionDefinitionClass} from "../models/runtime-function.ts"; -import {runtimeFunctionMap} from "./runtime-function.ts"; +import {FunctionDefinitionClass, HerculesFunctionDefinition, HerculesFunctionDefinitionParameter} from "../models/function"; +import {RuntimeFunctionDefinitionClass} from "../models/runtime-function"; +import {runtimeFunctionMap} from "./runtime-function"; export const functionMap = (klass: FunctionDefinitionClass): HerculesFunctionDefinition => { const parentClass = Object.getPrototypeOf(klass); diff --git a/ts/src/map/runtime-event.ts b/ts/src/map/runtime-event.ts index 503f15a..f57dd2b 100644 --- a/ts/src/map/runtime-event.ts +++ b/ts/src/map/runtime-event.ts @@ -1,5 +1,5 @@ -import type {HerculesTranslation} from "../types.ts"; -import type {HerculesRuntimeEvent, HerculesRuntimeEventSetting, RuntimeEventClass} from "../models/runtime-event.ts"; +import type {HerculesTranslation} from "../types"; +import type {HerculesRuntimeEvent, HerculesRuntimeEventSetting, RuntimeEventClass} from "../models/runtime-event"; export const runtimeEventMap = (klass: RuntimeEventClass): HerculesRuntimeEvent => { const identifier: string = Reflect.getMetadata('hercules:identifier', klass); diff --git a/ts/src/map/runtime-function.ts b/ts/src/map/runtime-function.ts index 25f8486..8ebbe39 100644 --- a/ts/src/map/runtime-function.ts +++ b/ts/src/map/runtime-function.ts @@ -3,7 +3,7 @@ import { HerculesRuntimeFunctionDefinition, HerculesRuntimeFunctionDefinitionParameter, RuntimeFunctionDefinitionClass, -} from "../models/runtime-function.ts"; +} from "../models/runtime-function"; export const runtimeFunctionMap = (klass: RuntimeFunctionDefinitionClass): HerculesRuntimeFunctionDefinition => { const identifier: string = Reflect.getMetadata('hercules:identifier', klass); diff --git a/ts/src/models/data-type.ts b/ts/src/models/data-type.ts index 6c20759..f2dbe04 100644 --- a/ts/src/models/data-type.ts +++ b/ts/src/models/data-type.ts @@ -1,5 +1,5 @@ import {DefinitionDataTypeRule} from "@code0-tech/tucana/shared"; -import {HerculesTranslation} from "../types.ts"; +import {HerculesTranslation} from "../types"; export interface HerculesDataType { identifier: string, diff --git a/ts/src/models/event.ts b/ts/src/models/event.ts index f73ba66..a3d81bd 100644 --- a/ts/src/models/event.ts +++ b/ts/src/models/event.ts @@ -1,7 +1,7 @@ import {PlainValue} from "@code0-tech/tucana/helpers"; -import {HerculesTranslation} from "../types.ts"; +import {HerculesTranslation} from "../types"; import {FlowTypeSetting_UniquenessScope} from "@code0-tech/tucana/shared"; -import {RuntimeEventClass} from "./runtime-event.ts"; +import {RuntimeEventClass} from "./runtime-event"; export interface HerculesEventSetting { identifier: string, diff --git a/ts/src/models/function.ts b/ts/src/models/function.ts index d2a09ea..0186469 100644 --- a/ts/src/models/function.ts +++ b/ts/src/models/function.ts @@ -1,6 +1,6 @@ -import {HerculesTranslation} from "../types.ts"; +import {HerculesTranslation} from "../types"; import {PlainValue} from "@code0-tech/tucana/helpers"; -import {RuntimeFunctionDefinitionClass} from "./runtime-function.ts"; +import {RuntimeFunctionDefinitionClass} from "./runtime-function"; export interface HerculesFunctionDefinitionParameter { runtimeName: string, diff --git a/ts/src/models/runtime-event.ts b/ts/src/models/runtime-event.ts index 4469edf..fcdd1eb 100644 --- a/ts/src/models/runtime-event.ts +++ b/ts/src/models/runtime-event.ts @@ -1,5 +1,5 @@ import {PlainValue} from "@code0-tech/tucana/helpers"; -import {HerculesTranslation} from "../types.ts"; +import {HerculesTranslation} from "../types"; import {RuntimeFlowTypeSetting_UniquenessScope} from "@code0-tech/tucana/shared"; export interface RuntimeEventDefinitionRunnable {} diff --git a/ts/src/models/runtime-function.ts b/ts/src/models/runtime-function.ts index 3a17c1a..7ace2d3 100644 --- a/ts/src/models/runtime-function.ts +++ b/ts/src/models/runtime-function.ts @@ -1,5 +1,5 @@ import {PlainValue} from "@code0-tech/tucana/helpers"; -import {HerculesTranslation} from "../types.ts"; +import {HerculesTranslation} from "../types"; export interface HerculesRuntimeFunctionDefinitionParameter { runtimeName: string, diff --git a/ts/src/types.ts b/ts/src/types.ts index 8079344..67c2581 100644 --- a/ts/src/types.ts +++ b/ts/src/types.ts @@ -1,4 +1,4 @@ -import {DefinitionDataTypeRule, FlowTypeSetting_UniquenessScope, RuntimeFlowTypeSetting_UniquenessScope} from "@code0-tech/tucana/shared"; +import {FlowTypeSetting_UniquenessScope, RuntimeFlowTypeSetting_UniquenessScope} from "@code0-tech/tucana/shared"; import {PlainValue} from "@code0-tech/tucana/helpers"; import 'reflect-metadata'; @@ -17,7 +17,7 @@ export interface HerculesFunctionContext { export interface HerculesActionProjectConfiguration { projectId: number | bigint, - configValues: {identifier: string, value: PlainValue}[], + configValues: { identifier: string, value: PlainValue }[], findConfig: (identifier: string) => PlainValue | undefined } From 6bd377f9a0a67ad06d633025c641e4eae533558f Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 13:04:55 +0200 Subject: [PATCH 29/43] feat: adding generated definitions to .gitignore --- ts/.gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ts/.gitignore b/ts/.gitignore index 9acd6ff..337f5b2 100644 --- a/ts/.gitignore +++ b/ts/.gitignore @@ -27,7 +27,9 @@ Thumbs.db *.ntvs* *.njsproj *.sln -CLAUDE.md # Test coverage coverage/ + +#definitions +/src/definitions/**/* From 4d2c5023c24deb5f4a883fca0dce81b79ab3e64d Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 13:05:09 +0200 Subject: [PATCH 30/43] feat: adding definitions build script --- ts/package-lock.json | 1089 ++++++++++++++++++++++++++++++++++++++++-- ts/package.json | 5 +- 2 files changed, 1055 insertions(+), 39 deletions(-) diff --git a/ts/package-lock.json b/ts/package-lock.json index 421d0d2..e358d51 100644 --- a/ts/package-lock.json +++ b/ts/package-lock.json @@ -18,6 +18,8 @@ "pino": "^10.3.1", "pino-pretty": "^13.1.3", "reflect-metadata": "^0.2.2", + "ts-morph": "^28.0.0", + "ts-to-zod": "^5.1.0", "zod": "^4.4.3", "zod-to-ts": "^2.1.0" }, @@ -80,6 +82,27 @@ "node": ">=6.9.0" } }, + "node_modules/@clack/core": { + "version": "1.0.0-alpha.4", + "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.0.0-alpha.4.tgz", + "integrity": "sha512-VCtU+vjyKPMSakVrB9q1bOnXN7QW/w4+YQDQCOF59GrzydW+169i0fVx/qzRRXJgt8KGj/pZZ/JxXroFZIDByg==", + "license": "MIT", + "dependencies": { + "picocolors": "^1.0.0", + "sisteransi": "^1.0.5" + } + }, + "node_modules/@clack/prompts": { + "version": "1.0.0-alpha.4", + "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.0.0-alpha.4.tgz", + "integrity": "sha512-KnmtDF2xQGoI5AlBme9akHtvCRV0RKAARUXHBQO2tMwnY8B08/4zPWigT7uLK25UPrMCEqnyQPkKRjNdhPbf8g==", + "license": "MIT", + "dependencies": { + "@clack/core": "1.0.0-alpha.4", + "picocolors": "^1.0.0", + "sisteransi": "^1.0.5" + } + }, "node_modules/@code0-tech/tucana": { "version": "0.0.74", "resolved": "https://registry.npmjs.org/@code0-tech/tucana/-/tucana-0.0.74.tgz", @@ -708,6 +731,62 @@ "@emnapi/runtime": "^1.7.1" } }, + "node_modules/@oclif/core": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@oclif/core/-/core-4.11.6.tgz", + "integrity": "sha512-8OTkBkWA0HJz2bSIQI0AoiIeL7ok4bZhUaJNEzfLu+iAn3liAyj4KmXRdXAUZBCjPEfdBTpyxKDAg1l/BDJKVg==", + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.3.2", + "ansis": "^3.17.0", + "clean-stack": "^3.0.1", + "cli-spinners": "^2.9.2", + "debug": "^4.4.3", + "ejs": "^3.1.10", + "get-package-type": "^0.1.0", + "indent-string": "^4.0.0", + "is-wsl": "^2.2.0", + "lilconfig": "^3.1.3", + "minimatch": "^10.2.5", + "semver": "^7.8.1", + "string-width": "^4.2.3", + "supports-color": "^8", + "tinyglobby": "^0.2.16", + "widest-line": "^3.1.0", + "wordwrap": "^1.0.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@oclif/core/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@oclif/core/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@oxc-project/types": { "version": "0.123.0", "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.123.0.tgz", @@ -1598,6 +1677,17 @@ "dev": true, "license": "MIT" }, + "node_modules/@ts-morph/common": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.29.0.tgz", + "integrity": "sha512-35oUmphHbJvQ/+UTwFNme/t2p3FoKiGJ5auTjjpNTop2dyREspirjMy82PLSC1pnDJ8ah1GU98hwpVt64YXQsg==", + "license": "MIT", + "dependencies": { + "minimatch": "^10.0.1", + "path-browserify": "^1.0.1", + "tinyglobby": "^0.2.14" + } + }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", @@ -1650,6 +1740,18 @@ "undici-types": "~7.18.0" } }, + "node_modules/@typescript/vfs": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/@typescript/vfs/-/vfs-1.6.4.tgz", + "integrity": "sha512-PJFXFS4ZJKiJ9Qiuix6Dz/OwEIqHD7Dme1UwZhTK11vR+5dqW2ACbdndWQexBzCx+CPuMe5WBYQWCsFyGlQLlQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3" + }, + "peerDependencies": { + "typescript": "*" + } + }, "node_modules/@vitest/expect": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.2.tgz", @@ -1970,6 +2072,21 @@ "dev": true, "license": "MIT" }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -1994,6 +2111,15 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/ansis": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.17.0.tgz", + "integrity": "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==", + "license": "ISC", + "engines": { + "node": ">=14" + } + }, "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -2021,6 +2147,12 @@ "node": ">=12" } }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, "node_modules/atomic-sleep": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", @@ -2034,7 +2166,6 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, "license": "MIT", "engines": { "node": "18 || 20 || >=22" @@ -2044,7 +2175,6 @@ "version": "5.0.5", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -2093,7 +2223,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, "license": "MIT", "dependencies": { "readdirp": "^4.0.1" @@ -2105,6 +2234,107 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/clean-stack": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-3.0.1.tgz", + "integrity": "sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.2.0.tgz", + "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", + "license": "MIT", + "dependencies": { + "slice-ansi": "^8.0.0", + "string-width": "^8.2.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.1.tgz", + "integrity": "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==", + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -2119,6 +2349,12 @@ "node": ">=12" } }, + "node_modules/code-block-writer": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz", + "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==", + "license": "MIT" + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2204,7 +2440,6 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2238,6 +2473,21 @@ "node": ">=0.3.1" } }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -2266,6 +2516,18 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/es-module-lexer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", @@ -2325,6 +2587,18 @@ "node": ">=6" } }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -2335,6 +2609,12 @@ "@types/estree": "^1.0.0" } }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT" + }, "node_modules/expect-type": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", @@ -2392,7 +2672,6 @@ "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, "license": "MIT", "engines": { "node": ">=12.0.0" @@ -2406,6 +2685,42 @@ } } }, + "node_modules/filelist": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", + "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/fix-dts-default-cjs-exports": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fix-dts-default-cjs-exports/-/fix-dts-default-cjs-exports-1.0.1.tgz", @@ -2467,6 +2782,27 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -2478,7 +2814,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2523,6 +2858,15 @@ "node": ">=8" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", @@ -2539,6 +2883,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -2548,6 +2907,35 @@ "node": ">=8" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jju": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", @@ -2856,7 +3244,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "dev": true, "license": "MIT", "engines": { "node": ">=14" @@ -2872,27 +3259,123 @@ "dev": true, "license": "MIT" }, - "node_modules/load-tsconfig": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", - "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", - "dev": true, + "node_modules/listr2": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", + "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", "license": "MIT", + "dependencies": { + "cli-truncate": "^5.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=20.0.0" } }, - "node_modules/local-pkg": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.2.tgz", - "integrity": "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==", - "dev": true, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "license": "MIT", - "dependencies": { - "mlly": "^1.7.4", - "pkg-types": "^2.3.0", - "quansync": "^0.2.11" - }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/load-tsconfig": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", + "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/local-pkg": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.2.tgz", + "integrity": "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mlly": "^1.7.4", + "pkg-types": "^2.3.0", + "quansync": "^0.2.11" + }, "engines": { "node": ">=14" }, @@ -2932,6 +3415,150 @@ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "license": "MIT" }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/long": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", @@ -2961,11 +3588,22 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "10.2.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.3.tgz", "integrity": "sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg==", - "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "brace-expansion": "^5.0.2" @@ -3003,7 +3641,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/muggle-string": { @@ -3083,11 +3720,25 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true, "license": "MIT" }, "node_modules/path-parse": { @@ -3108,14 +3759,12 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -3369,7 +4018,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 14.18.0" @@ -3444,6 +4092,28 @@ "node": ">=8" } }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "license": "MIT" + }, "node_modules/rolldown": { "version": "1.0.0-rc.13", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.13.tgz", @@ -3571,6 +4241,79 @@ "dev": true, "license": "ISC" }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/slice-ansi": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-8.0.0.tgz", + "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.3", + "is-fullwidth-code-point": "^5.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/sonic-boom": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz", @@ -3706,7 +4449,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -3731,6 +4473,197 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/text-camel-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-camel-case/-/text-camel-case-1.2.11.tgz", + "integrity": "sha512-2ZsM/gOlB1tyza+8lGLvs6gtPuZ9qEYuKPa+gwo38m65wkY4k323SK4hT7ku8r5wIKyspUYIWSk1aB9/Jjxr7A==", + "license": "MIT", + "dependencies": { + "text-pascal-case": "^1.2.11" + } + }, + "node_modules/text-capital-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-capital-case/-/text-capital-case-1.2.11.tgz", + "integrity": "sha512-30A7B7+VUvevEmPE0xWK1Z2z0ncl/JTjSUBLfjpoXrkwuPpmNTVbjHShRTN3cX9GIuZn/P3jvR+TO9JiTZcl8A==", + "license": "MIT", + "dependencies": { + "text-no-case": "^1.2.11", + "text-upper-case-first": "^1.2.11" + } + }, + "node_modules/text-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-case/-/text-case-1.2.11.tgz", + "integrity": "sha512-LbdWNQeuXWbfav+pxBxvaefkziffMYeSA53BHp52cgJa9rjiC0dkjum9AKrH8iQWoQJ4InGPSGexLeerGFaZ1Q==", + "license": "MIT", + "dependencies": { + "text-camel-case": "^1.2.11", + "text-capital-case": "^1.2.11", + "text-constant-case": "^1.2.11", + "text-dot-case": "^1.2.11", + "text-header-case": "^1.2.11", + "text-is-lower-case": "^1.2.11", + "text-is-upper-case": "^1.2.11", + "text-kebab-case": "^1.2.11", + "text-lower-case": "^1.2.11", + "text-lower-case-first": "^1.2.11", + "text-no-case": "^1.2.11", + "text-param-case": "^1.2.11", + "text-pascal-case": "^1.2.11", + "text-path-case": "^1.2.11", + "text-sentence-case": "^1.2.11", + "text-snake-case": "^1.2.11", + "text-swap-case": "^1.2.11", + "text-title-case": "^1.2.11", + "text-upper-case": "^1.2.11", + "text-upper-case-first": "^1.2.11" + } + }, + "node_modules/text-constant-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-constant-case/-/text-constant-case-1.2.11.tgz", + "integrity": "sha512-XnTBILsa7UpMWncUCchqIybZlg15FUcrlyNaWIJ8ybPy54qcoN513EXFswueyizuAgyJFXPCwwSFbSji6kw/Uw==", + "license": "MIT", + "dependencies": { + "text-no-case": "^1.2.11", + "text-upper-case": "^1.2.11" + } + }, + "node_modules/text-dot-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-dot-case/-/text-dot-case-1.2.11.tgz", + "integrity": "sha512-7SLKiT45KZO0qad0+p+GvC0+F+6pZ851HJcTcBJiSF88HsK/e1qErlGLtVBT6hkTHIaAj48WfSyQr4lZRv1xJQ==", + "license": "MIT", + "dependencies": { + "text-no-case": "^1.2.11" + } + }, + "node_modules/text-header-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-header-case/-/text-header-case-1.2.11.tgz", + "integrity": "sha512-7OBHd2g7X+aH6rXMC3cANFh6yvhXjXkyumw2NaRwJRIk343pP2e1SQCTCfowPDmmi8wkZVqz1fdWNq5LwvcBOQ==", + "license": "MIT", + "dependencies": { + "text-capital-case": "^1.2.11" + } + }, + "node_modules/text-is-lower-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-is-lower-case/-/text-is-lower-case-1.2.11.tgz", + "integrity": "sha512-dBqPAkNmX7eTM7ZbS3D/UBCQ5i9EXt5tujF2wIGGbZ1+aN8bY7Qda4mDpxgd6Hbzf/z10uQWRNzupl99wFQ8CQ==", + "license": "MIT" + }, + "node_modules/text-is-upper-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-is-upper-case/-/text-is-upper-case-1.2.11.tgz", + "integrity": "sha512-MZeUIYEYfKZ2FSeg0vnHCH4mHXLgGzes+iz2K+4BYnhnkEa2svKA1nNjQAqTUiVNHOPqPCuzmUr1LsyQZ73uyA==", + "license": "MIT" + }, + "node_modules/text-kebab-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-kebab-case/-/text-kebab-case-1.2.11.tgz", + "integrity": "sha512-RIg9iN6VwH+JrX9dFdm1nd1efPGR9LjNc0CiQz496sQETeKGkDEzxES/ZzxbkerrAL2DFEMGdLXckzDz1OEDBQ==", + "license": "MIT", + "dependencies": { + "text-no-case": "^1.2.11" + } + }, + "node_modules/text-lower-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-lower-case/-/text-lower-case-1.2.11.tgz", + "integrity": "sha512-txTy6y0y8M23Lhf0mk8WcvXTqlf4OQ3AGnDsRB6o3uMNfIa0CJDol2s1PdKNa63rt5B2277zkZCCn6Xeq//big==", + "license": "MIT" + }, + "node_modules/text-lower-case-first": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-lower-case-first/-/text-lower-case-first-1.2.11.tgz", + "integrity": "sha512-QR483XLyuyIpq8tKu1ds3Q1jfsgfaa/p9rtoQKHe6Rv5ah9ic/SUzTGN0MQ7UIS9APADd8SUPn5TTh1Z2/ACyg==", + "license": "MIT" + }, + "node_modules/text-no-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-no-case/-/text-no-case-1.2.11.tgz", + "integrity": "sha512-wazS7FEq0Ct3aJzeE8MEMcSs0eW4+/X/fwdotv/rG66bLS+g1T0pa0gUsbBGjjLFs191AIXVIry+bYE0uaaBBQ==", + "license": "MIT", + "dependencies": { + "text-lower-case": "^1.2.11" + } + }, + "node_modules/text-param-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-param-case/-/text-param-case-1.2.11.tgz", + "integrity": "sha512-3EMMAMLSz/mJXOnATNnrS+dZAvghpq09VhOVYDOkUnbm5zlYc6iU5AZOKVDpiAVVllQ9P1h5IKVZzsEYrdIRGw==", + "license": "MIT", + "dependencies": { + "text-dot-case": "^1.2.11" + } + }, + "node_modules/text-pascal-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-pascal-case/-/text-pascal-case-1.2.11.tgz", + "integrity": "sha512-BNhQ1O/g/Q4dH5gPyLIJLDLDknl2dipBwV629ScsiZCKJaCLGXYhTXp23rp9Htg3O5OSSsiU3mqDKq+pBmwTSw==", + "license": "MIT", + "dependencies": { + "text-no-case": "^1.2.11" + } + }, + "node_modules/text-path-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-path-case/-/text-path-case-1.2.11.tgz", + "integrity": "sha512-FsJU4BmMdtLtmnBK/XRJPqTwLF8yFiTEClHjxlQjSAG5Xt9R4p6D1WNaM1CI2dG5Lr4rsFM4jiVC620m0AsRbw==", + "license": "MIT", + "dependencies": { + "text-dot-case": "^1.2.11" + } + }, + "node_modules/text-sentence-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-sentence-case/-/text-sentence-case-1.2.11.tgz", + "integrity": "sha512-ApiVsvdLy+Wb8x7mZRVuoy8VO12jJ22G2djVM3ZZbUhXVIkqGgHxmiXRwdhRPoWGojK9n53m7jviJgBVNdRn+g==", + "license": "MIT", + "dependencies": { + "text-no-case": "^1.2.11", + "text-upper-case-first": "^1.2.11" + } + }, + "node_modules/text-snake-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-snake-case/-/text-snake-case-1.2.11.tgz", + "integrity": "sha512-NOEQvjyyVABB41SS8dUx423Y6hWS+Z4TrAAJg1xzCkOD3q9y0JtdJjCvCA1FWI8oDu+HiIOp/N446uDM8j54XQ==", + "license": "MIT", + "dependencies": { + "text-dot-case": "^1.2.11" + } + }, + "node_modules/text-swap-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-swap-case/-/text-swap-case-1.2.11.tgz", + "integrity": "sha512-PBmC5xvZdDZ4suikydpeXH0s4JV2XHelMj9/OEXEbA3oLpdV2A+B4BspVDWVw7C2Gi5eCareqk/7EE8I1/WwgQ==", + "license": "MIT" + }, + "node_modules/text-title-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-title-case/-/text-title-case-1.2.11.tgz", + "integrity": "sha512-V1GZy0XlqdkYUQm0tqm1jqtYlXJqFVMreBCTUReOaz8d/JbozTSpZrcakIeV8+1bN7LsvfhPFhA5zREiax6YIA==", + "license": "MIT", + "dependencies": { + "text-no-case": "^1.2.11", + "text-upper-case-first": "^1.2.11" + } + }, + "node_modules/text-upper-case": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-upper-case/-/text-upper-case-1.2.11.tgz", + "integrity": "sha512-BfTL7yB1YIRlVGNdZUvno013hOq2cRs07fDR2ApppOXRDuKrEmsLDEY82xXlDzQHELp0jexqkI+NeyPIl6MtMw==", + "license": "MIT" + }, + "node_modules/text-upper-case-first": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/text-upper-case-first/-/text-upper-case-first-1.2.11.tgz", + "integrity": "sha512-vgfbwKo8TEJbRsapR9LWWvIJRnv8u9aXVa6cyYOAQQmurCx54Cnt59x5fKdiq+hFaBJ51AbzCgMpbP3p65/pHQ==", + "license": "MIT" + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -3781,14 +4714,13 @@ "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "license": "MIT", "dependencies": { "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "picomatch": "^4.0.4" }, "engines": { "node": ">=12.0.0" @@ -3824,13 +4756,43 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/ts-morph": { + "version": "28.0.0", + "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-28.0.0.tgz", + "integrity": "sha512-Wp3tnZ2bzwxyTZMtgWVzXDfm7lB1Drz+y9DmmYH/L702PQhPyVrp3pkou3yIz4qjS14GY9kcpmLiOOMvl8oG1g==", + "license": "MIT", + "dependencies": { + "@ts-morph/common": "~0.29.0", + "code-block-writer": "^13.0.3" + } + }, + "node_modules/ts-to-zod": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ts-to-zod/-/ts-to-zod-5.1.0.tgz", + "integrity": "sha512-giqqlvRHunlJqG9tBL/KAO3wWIVZGF//mZiWLKm/fdQnKnz4EN2mtiK5cugN9slytBkdMEXQIaLvMzIScbhhFw==", + "license": "MIT", + "dependencies": { + "@clack/prompts": "1.0.0-alpha.4", + "@oclif/core": "^4.5.4", + "@typescript/vfs": "^1.5.0", + "chokidar": "^4.0.3", + "listr2": "^9.0.4", + "slash": "^5.1.0", + "text-case": "^1.2.4", + "tslib": "^2.3.1", + "tsutils": "^3.21.0", + "typescript": "^5.2.2", + "zod": "^4.1.5" + }, + "bin": { + "ts-to-zod": "bin/run" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD", - "optional": true + "license": "0BSD" }, "node_modules/tsup": { "version": "8.5.1", @@ -3885,6 +4847,39 @@ } } }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "license": "MIT", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typescript": { "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", @@ -4144,6 +5139,24 @@ "node": ">=8" } }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "license": "MIT", + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "license": "MIT" + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/ts/package.json b/ts/package.json index a1dea2c..61ba0ca 100644 --- a/ts/package.json +++ b/ts/package.json @@ -23,7 +23,8 @@ "build": "vite build", "clean": "rm -rf dist", "typecheck": "tsc --noEmit", - "test": "vitest run" + "test": "vitest run", + "build:definitions": "npx tsx scripts/build-definitions.ts" }, "keywords": [], "author": "", @@ -39,6 +40,8 @@ "pino": "^10.3.1", "pino-pretty": "^13.1.3", "reflect-metadata": "^0.2.2", + "ts-morph": "^28.0.0", + "ts-to-zod": "^5.1.0", "zod": "^4.4.3", "zod-to-ts": "^2.1.0" }, From 67ff51cd2bc794e21d4b5efaf8c0fa01286fa990 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 13:05:17 +0200 Subject: [PATCH 31/43] feat: updating bundler --- ts/tsconfig.json | 18 ++++++++++++------ ts/vite.config.ts | 22 +++++++++++++++------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/ts/tsconfig.json b/ts/tsconfig.json index 974407d..4a59bc5 100644 --- a/ts/tsconfig.json +++ b/ts/tsconfig.json @@ -1,15 +1,21 @@ { "compilerOptions": { "esModuleInterop": true, - "module": "esnext", "moduleResolution": "bundler", + "module": "commonjs", "target": "es2020", - "lib": ["es2020", "dom"], + "lib": ["ESNext", "dom"], "strict": true, "skipLibCheck": true, - "allowImportingTsExtensions": true, - "noEmit": true, - "types": ["vite/client"] + "rootDir": "src", + "baseUrl": "src/" }, - "include": ["src/**/*"] + "exclude": [ + "node_modules", + "dist", + "examples" + ], + "types": [ + "typePatches" + ] } \ No newline at end of file diff --git a/ts/vite.config.ts b/ts/vite.config.ts index e0a8c6b..6dd196c 100644 --- a/ts/vite.config.ts +++ b/ts/vite.config.ts @@ -4,17 +4,24 @@ import { resolve } from 'path'; export default defineConfig({ build: { - target: "node18", - ssr: true, lib: { entry: resolve(__dirname, 'src/index.ts'), - name: 'hercules', - fileName: 'hercules', + name: 'triangulum', + fileName: (format) => `hercules.${format}.js`, formats: ['es', 'cjs'] }, rollupOptions: { - external: (id) => - ['fs', 'path', 'typescript'].includes(id) || id.startsWith('node:') + external: [ + 'typescript', + '@code0-tech/tucana', + 'path', + 'fs' + ], + output: { + globals: { + typescript: 'ts' + } + } } }, plugins: [ @@ -28,4 +35,5 @@ export default defineConfig({ } }) ] -}); \ No newline at end of file +}); + From cf06d687f426d6c01fe6c67eecedef243a852ea4 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 13:05:42 +0200 Subject: [PATCH 32/43] feat: updating example by removing unnecessary setting override --- .../simple-example-ts/src/events/userCreatedEvent.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ts/examples/simple-example-ts/src/events/userCreatedEvent.ts b/ts/examples/simple-example-ts/src/events/userCreatedEvent.ts index d7d9c7f..0aa5603 100644 --- a/ts/examples/simple-example-ts/src/events/userCreatedEvent.ts +++ b/ts/examples/simple-example-ts/src/events/userCreatedEvent.ts @@ -4,10 +4,4 @@ import {UserCreatedRuntimeEvent} from "./userCreatedRuntimeEvent.ts"; @Identifier("user_created_event") @Name({code: "en-US", content: "On User Created"}) @Editable(false) -@EventSetting({ - identifier: "FILTER_ROLE", - name: [{code: "en-US", content: "Role Filter"}], - description: [{code: "en-US", content: "Only trigger for users with this role"}], - optional: true, -}) export class UserCreatedEvent extends UserCreatedRuntimeEvent {} From 1ceb9f7ede84eca241d82f0a04b10616861d49f5 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 14:20:13 +0200 Subject: [PATCH 33/43] feat: build script --- ts/scripts/build-definitions.ts | 382 ++++++++++++++++++++++++++++++++ 1 file changed, 382 insertions(+) create mode 100644 ts/scripts/build-definitions.ts diff --git a/ts/scripts/build-definitions.ts b/ts/scripts/build-definitions.ts new file mode 100644 index 0000000..95007ff --- /dev/null +++ b/ts/scripts/build-definitions.ts @@ -0,0 +1,382 @@ +import * as fs from "node:fs"; +import * as path from "node:path"; +import * as os from "node:os"; +import {execSync} from "node:child_process"; +import {generate} from "ts-to-zod"; +import {Project} from "ts-morph"; + +const args = process.argv.slice(2); +const versionIndex = args.indexOf("--version"); +if (versionIndex === -1 || !args[versionIndex + 1]) { + console.error("Usage: npm run build:definitions -- --version "); + process.exit(1); +} +const version = args[versionIndex + 1]; + +const REPO = "code0-tech/code0-definition"; +const OUTPUT_DIR = path.resolve("src/definitions"); + +// ── Helpers ─────────────────────────────────────────────────────────────────── + +function toPascalCase(str: string): string { + return str + .replace(/::/g, "_") + .split(/[_-]/) + .map(p => p.charAt(0).toUpperCase() + p.slice(1).toLowerCase()) + .join(""); +} + +function fileNameToClassName(file: string): string { + return toPascalCase(path.basename(file, ".proto.json")); +} + +function toSchemaName(identifier: string): string { + // HTTP_METHOD → httpMethodSchema + return identifier.toLowerCase().replace(/_([a-z])/g, (_, c) => c.toUpperCase()) + "Schema"; +} + +function srcRelativePath(relModule: string, ...segments: string[]): string { + const depth = relModule.split(path.sep).filter(Boolean).length + 1; + return "../".repeat(depth) + segments.join("/"); +} + +type Translation = { code: string; content: string }; + +function renderTranslations(decorator: string, arr: Translation[]): string[] { + if (!arr?.length) return []; + return [ + `@${decorator}(`, + ...arr.map(t => ` {code: "${t.code}", content: ${JSON.stringify(t.content)}},`), + `)`, + ]; +} + +function renderTranslationsInline(arr: Translation[]): string { + return arr.map(t => `{code: "${t.code}", content: ${JSON.stringify(t.content)}}`).join(", "); +} + +// ── Data type definitions ───────────────────────────────────────────────────── + +interface DataTypeDef { + identifier: string; + type: string; + genericKeys: string[]; + relModule: string; + className: string; + fileName: string; +} + +function buildCombinedSource(defs: DataTypeDef[]): string { + return defs.map(({identifier, type, genericKeys}) => { + let resolved = type; + if (/\[.*in keyof/.test(resolved)) { + // Identity mapped type (e.g. { [K in keyof T]: T[K] }) → Record + resolved = "Record"; + } else { + for (const key of genericKeys) { + resolved = resolved.replace(new RegExp(`\\b${key}\\b`, "g"), "unknown"); + } + } + return `export type ${identifier} = ${resolved};`; + }).join("\n"); +} + +function relativeImport(fromRelModule: string, toDef: DataTypeDef, toFile: string): string { + const from = fromRelModule.split(path.sep).filter(Boolean); + const to = toDef.relModule.split(path.sep).filter(Boolean); + let common = 0; + while (common < from.length && common < to.length && from[common] === to[common]) + common++; + const up = "../".repeat(from.length - common); + const down = [...to.slice(common), toFile].join("/"); + return up ? up + down : "./" + down; +} + +// ── Meta-decorator helpers ──────────────────────────────────────────────────── + +function collectMetaDecorators(json: Record): string[] { + return [ + "Identifier", + ...(json.signature ? ["Signature"] : []), + ...(Array.isArray(json.name) && json.name.length ? ["Name"] : []), + ...(Array.isArray(json.description) && json.description.length ? ["Description"] : []), + ...(Array.isArray(json.documentation) && json.documentation.length ? ["Documentation"] : []), + ...(Array.isArray(json.displayMessage) && json.displayMessage.length ? ["DisplayMessage"] : []), + ...(Array.isArray(json.alias) && json.alias.length ? ["Alias"] : []), + ...(json.displayIcon ? ["DisplayIcon"] : []), + ]; +} + +function buildMetaDecorators(json: Record, identifierKey: string): string[] { + return [ + `@Identifier(${JSON.stringify(json[identifierKey])})`, + ...(json.signature + ? [`@Signature(${JSON.stringify(json.signature)})`] + : []), + ...(Array.isArray(json.name) && json.name.length + ? renderTranslations("Name", json.name as Translation[]) + : []), + ...(Array.isArray(json.description) && json.description.length + ? renderTranslations("Description", json.description as Translation[]) + : []), + ...(Array.isArray(json.documentation) && json.documentation.length + ? renderTranslations("Documentation", json.documentation as Translation[]) + : []), + ...(Array.isArray(json.displayMessage) && json.displayMessage.length + ? renderTranslations("DisplayMessage", json.displayMessage as Translation[]) + : []), + ...(Array.isArray(json.alias) && json.alias.length + ? renderTranslations("Alias", json.alias as Translation[]) + : []), + ...(json.displayIcon + ? [`@DisplayIcon(${JSON.stringify(json.displayIcon)})`] + : []), + ]; +} + +// ── Generators ──────────────────────────────────────────────────────────────── + +function buildSettingDecorators(settings: any[]): string[] { + return settings.flatMap(s => { + const props = [ + `identifier: ${JSON.stringify(s.identifier)},`, + ...(s.unique && s.unique !== "NONE" ? [`unique: ${JSON.stringify(s.unique)} as any,`] : []), + ...(Array.isArray(s.name) && s.name.length ? [`name: [${renderTranslationsInline(s.name)}],`] : []), + ...(Array.isArray(s.description) && s.description.length ? [`description: [${renderTranslationsInline(s.description)}],`] : []), + ...(s.optional ? [`optional: true,`] : []), + ...(s.hidden ? [`hidden: true,`] : []), + ]; + return [`@RuntimeEventSetting({`, ...props.map(p => ` ${p}`), `})`]; + }); +} + +function buildParameterDecorators(params: any[]): string[] { + return params.flatMap(p => { + const props = [ + `runtimeName: ${JSON.stringify(p.runtimeName)},`, + ...(Array.isArray(p.name) && p.name.length ? [`name: [${renderTranslationsInline(p.name)}],`] : []), + ...(Array.isArray(p.description) && p.description.length ? [`description: [${renderTranslationsInline(p.description)}],`] : []), + ...(p.optional ? [`optional: true,`] : []), + ...(p.hidden ? [`hidden: true,`] : []), + ]; + return [`@RuntimeParameter({`, ...props.map(p => ` ${p}`), `})`]; + }); +} + +function generateRuntimeFlowType(json: Record, className: string, relModule: string): string { + const src = (seg: string) => srcRelativePath(relModule, seg); + const linkedIds = json.linkedDataTypeIdentifiers as string[] | undefined; + const settings = json.runtimeSettings as any[] | undefined; + const metaDecorators = collectMetaDecorators(json); + + const imports = [ + `import {RuntimeEventDefinitionRunnable} from "${src("models/runtime-event")}";`, + `import {${metaDecorators.join(", ")}} from "${src("decorators/meta")}";`, + ...(linkedIds?.length ? [`import {LinkedDataTypeIdentifiers} from "${src("decorators/function")}";`] : []), + ...(settings?.length ? [`import {RuntimeEventSetting} from "${src("decorators/runtime-event")}";`] : []), + ]; + + const decorators = [ + ...buildMetaDecorators(json, "identifier"), + ...(linkedIds?.length ? [`@LinkedDataTypeIdentifiers(${linkedIds.map(s => JSON.stringify(s)).join(", ")})`] : []), + ...buildSettingDecorators(settings ?? []), + ]; + + return [ + ...imports, + "", + ...decorators, + `export class ${className} implements RuntimeEventDefinitionRunnable {}`, + "", + ].join("\n"); +} + +function generateRuntimeFunction(json: Record, className: string, relModule: string): string { + const src = (seg: string) => srcRelativePath(relModule, seg); + const linkedIds = json.linkedDataTypeIdentifiers as string[] | undefined; + const params = json.runtimeParameterDefinitions as any[] | undefined; + const metaDecorators = collectMetaDecorators(json); + const funcDecorators = [ + "OmitFunctionDefinition", + ...(json.throwsError ? ["ThrowsError"] : []), + ...(params?.length ? ["RuntimeParameter"] : []), + ...(linkedIds?.length ? ["LinkedDataTypeIdentifiers"] : []), + ]; + + const imports = [ + `import {RuntimeFunctionDefinitionRunnable} from "${src("models/runtime-function")}";`, + `import {${metaDecorators.join(", ")}} from "${src("decorators/meta")}";`, + `import {${funcDecorators.join(", ")}} from "${src("decorators/function")}";`, + `import type {PlainValue} from "@code0-tech/tucana/helpers";`, + ]; + + const decorators = [ + `@OmitFunctionDefinition()`, + ...buildMetaDecorators(json, "runtimeName"), + ...(json.throwsError ? [`@ThrowsError()`] : []), + ...(linkedIds?.length ? [`@LinkedDataTypeIdentifiers(${linkedIds.map(s => JSON.stringify(s)).join(", ")})`] : []), + ...buildParameterDecorators(params ?? []), + ]; + + return [ + ...imports, + "", + ...decorators, + `export class ${className} implements RuntimeFunctionDefinitionRunnable {`, + ` run(..._args: (PlainValue | undefined)[]): Promise | PlainValue {`, + ` throw new Error(\`${className}.run() is not implemented\`);`, + ` }`, + `}`, + "", + ].join("\n"); +} + +// ── Directory walker ────────────────────────────────────────────────────────── + +type DefHandler = ( + json: Record, + className: string, + fileName: string, + relModule: string, + typeFolder: string, +) => void; + +function walkDefs(dir: string, relModule: string, handler: DefHandler): void { + for (const entry of fs.readdirSync(dir, {withFileTypes: true})) { + const fullPath = path.join(dir, entry.name); + if (entry.isDirectory()) { + walkDefs(fullPath, path.join(relModule, entry.name), handler); + continue; + } + if (!entry.name.endsWith(".proto.json")) continue; + const json = JSON.parse(fs.readFileSync(fullPath, "utf-8")) as Record; + const typeFolder = relModule.split(path.sep).at(-1) ?? ""; + const className = fileNameToClassName(entry.name); + const fileName = path.basename(entry.name, ".proto.json"); + handler(json, className, fileName, relModule, typeFolder); + } +} + +// ── Main ────────────────────────────────────────────────────────────────────── + +async function main() { + const url = `https://github.com/${REPO}/releases/download/${version}/definitions.zip`; + console.log(`Downloading ${url}...`); + + const response = await fetch(url); + if (!response.ok) throw new Error(`Download failed: ${response.status} ${response.statusText}`); + + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "hercules-definitions-")); + const zipPath = path.join(tmpDir, "definitions.zip"); + const extractDir = path.join(tmpDir, "extracted"); + + fs.writeFileSync(zipPath, Buffer.from(await response.arrayBuffer())); + fs.mkdirSync(extractDir, {recursive: true}); + execSync(`unzip -q "${zipPath}" -d "${extractDir}"`); + + const defsDir = path.join(extractDir, "definitions"); + + // ── Collect all data type definitions ───────────────────────────────────── + const dataTypeDefs: DataTypeDef[] = []; + walkDefs(defsDir, "", (json, className, fileName, relModule, typeFolder) => { + if (typeFolder !== "data_types" || !json.identifier || !json.type) return; + dataTypeDefs.push({ + identifier: json.identifier as string, + type: json.type as string, + genericKeys: (json.genericKeys as string[]) ?? [], + relModule, + className, + fileName, + }); + }); + + // ── Generate all schemas via ts-to-zod ──────────────────────────────────── + const combinedSource = buildCombinedSource(dataTypeDefs); + const {getZodSchemasFile, errors} = generate({sourceText: combinedSource}); + if (errors.length) console.warn("ts-to-zod warnings:", errors); + const schemasSource = getZodSchemasFile("schemas"); + + // ── Parse ts-to-zod output with ts-morph ────────────────────────────────── + const morphProject = new Project({useInMemoryFileSystem: true}); + const sf = morphProject.createSourceFile("schemas", schemasSource); + + const schemaBodyMap = new Map(); + for (const stmt of sf.getVariableStatements()) { + for (const decl of stmt.getDeclarations()) { + const init = decl.getInitializer()?.getText(); + if (init) schemaBodyMap.set(decl.getName(), init); + } + } + + const schemaToFile = new Map(); + for (const def of dataTypeDefs) { + schemaToFile.set(toSchemaName(def.identifier), def); + } + + // ── Write output ────────────────────────────────────────────────────────── + fs.rmSync(OUTPUT_DIR, {recursive: true, force: true}); + fs.mkdirSync(OUTPUT_DIR, {recursive: true}); + + let count = 0; + const allSchemaNames = new Set(schemaBodyMap.keys()); + const generatedFiles: string[] = []; + + for (const def of dataTypeDefs) { + const schemaName = toSchemaName(def.identifier); + const body = schemaBodyMap.get(schemaName); + if (!body) continue; + + const refs = [ + ...new Set( + [...body.matchAll(/\b(\w+Schema)\b/g)] + .map(m => m[1]) + .filter(n => n !== schemaName && allSchemaNames.has(n)) + ), + ]; + const typeParams = def.genericKeys.length > 0 + ? `<${def.genericKeys.map(k => `${k} = unknown`).join(", ")}>` + : ""; + + const lines = [ + `import {z} from "zod";`, + ...refs.flatMap(ref => { + const refDef = schemaToFile.get(ref); + return refDef ? [`import {${ref}} from "${relativeImport(def.relModule, refDef, refDef.fileName)}";`] : []; + }), + ``, + `export const ${schemaName} = ${body};`, + `export type ${def.className}${typeParams} = z.infer;`, + ``, + ]; + + const outDir = path.join(OUTPUT_DIR, def.relModule); + fs.mkdirSync(outDir, {recursive: true}); + fs.writeFileSync(path.join(outDir, `${def.fileName}.ts`), lines.join("\n")); + generatedFiles.push([def.relModule, def.fileName].filter(Boolean).join("/")); + count++; + } + + walkDefs(defsDir, "", (json, className, fileName, relModule, typeFolder) => { + let content: string | null = null; + if (typeFolder === "runtime_flow_types") content = generateRuntimeFlowType(json, className, relModule); + else if (typeFolder === "runtime_functions") content = generateRuntimeFunction(json, className, relModule); + if (content === null) return; + + const outDir = path.join(OUTPUT_DIR, relModule); + fs.mkdirSync(outDir, {recursive: true}); + fs.writeFileSync(path.join(outDir, `${fileName}.ts`), content); + generatedFiles.push([relModule, fileName].filter(Boolean).join("/")); + count++; + }); + + const indexContent = generatedFiles + .sort() + .map(f => `export * from "./${f}";`) + .join("\n") + "\n"; + fs.writeFileSync(path.join(OUTPUT_DIR, "index.ts"), indexContent); + + fs.rmSync(tmpDir, {recursive: true, force: true}); + console.log(`Generated ${count} definition files in src/definitions/`); +} + +main().catch(err => { console.error(err); process.exit(1); }); From 521b44707ec910b7a3b69ef09180452ad5b8a45a Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 14:21:44 +0200 Subject: [PATCH 34/43] feat: renaming CodeZeroAction.ts to action.ts --- ts/examples/simple-example-ts/src/index.ts | 4 ++-- ts/src/{CodeZeroAction.ts => action.ts} | 2 +- ts/src/actions/Execution.ts | 4 ++-- ts/src/actions/ModuleConfigurations.ts | 4 ++-- ts/src/actions/index.ts | 8 ++++---- ts/src/events.ts | 4 ++-- ts/src/index.ts | 13 +++++++------ 7 files changed, 20 insertions(+), 19 deletions(-) rename ts/src/{CodeZeroAction.ts => action.ts} (98%) diff --git a/ts/examples/simple-example-ts/src/index.ts b/ts/examples/simple-example-ts/src/index.ts index 1643a4c..ea5ce77 100644 --- a/ts/examples/simple-example-ts/src/index.ts +++ b/ts/examples/simple-example-ts/src/index.ts @@ -1,11 +1,11 @@ -import {CodeZeroAction, CodeZeroEvent} from "@code0-tech/hercules"; +import {Action, CodeZeroEvent} from "@code0-tech/hercules"; import {FibonacciRuntimeFunction} from "./functions/fibonacciRuntimeFunction.js"; import {FibonacciFunction} from "./functions/fibonacciFunction.js"; import {UserCreatedRuntimeEvent} from "./events/userCreatedRuntimeEvent.js"; import {UserCreatedEvent} from "./events/userCreatedEvent.js"; import {EmailDataType} from "./data_types/emailDataType.js"; -const action = new CodeZeroAction( +const action = new Action( process.env.ACTION_ID ?? "example-action", process.env.VERSION ?? "0.0.0", process.env.AQUILA_URL ?? "127.0.0.1:8081", diff --git a/ts/src/CodeZeroAction.ts b/ts/src/action.ts similarity index 98% rename from ts/src/CodeZeroAction.ts rename to ts/src/action.ts index 41002d5..04dc1f7 100644 --- a/ts/src/CodeZeroAction.ts +++ b/ts/src/action.ts @@ -25,7 +25,7 @@ import {EventManager} from "./manager/EventManager"; import {RuntimeEventManager} from "./manager/RuntimeEventManager"; import {actions} from "./actions"; -export class CodeZeroAction extends EventEmitter { +export class Action extends EventEmitter { private _transport?: GrpcTransport; private _stream?: DuplexStreamingCall; private readonly _actions = new Map(actions.map(a => [a.packetType, a.handle])); diff --git a/ts/src/actions/Execution.ts b/ts/src/actions/Execution.ts index 77e398e..72e0c67 100644 --- a/ts/src/actions/Execution.ts +++ b/ts/src/actions/Execution.ts @@ -4,7 +4,7 @@ import {NodeExecutionResult, Error as ProtoError} from "@code0-tech/tucana/share import {HerculesFunctionContext, RuntimeErrorException} from "../types"; import {HerculesRuntimeFunctionDefinition} from "../models/runtime-function"; import {CodeZeroEvent} from "../events"; -import type {CodeZeroAction} from "../CodeZeroAction"; +import type {Action} from "../action"; export const packetType = "execution"; @@ -15,7 +15,7 @@ function buildParams(execution: ActionExecutionRequest, func: HerculesRuntimeFun }); } -export function handle(action: CodeZeroAction, execution: ActionExecutionRequest): void { +export function handle(action: Action, execution: ActionExecutionRequest): void { action.emit(CodeZeroEvent.executionRequestReceived, execution); const func = action.runtimeFunctions.get(execution.functionIdentifier); diff --git a/ts/src/actions/ModuleConfigurations.ts b/ts/src/actions/ModuleConfigurations.ts index 1ee4010..cf573e0 100644 --- a/ts/src/actions/ModuleConfigurations.ts +++ b/ts/src/actions/ModuleConfigurations.ts @@ -1,10 +1,10 @@ import type {ModuleConfigurations} from "@code0-tech/tucana/shared"; import {CodeZeroEvent} from "../events"; -import type {CodeZeroAction} from "../CodeZeroAction"; +import type {Action} from "../action"; export const packetType = "moduleConfigurations"; -export function handle(action: CodeZeroAction, data: ModuleConfigurations): void { +export function handle(action: Action, data: ModuleConfigurations): void { action.configs.update(data.moduleConfigurations); action.emit(CodeZeroEvent.moduleUpdated, data); } diff --git a/ts/src/actions/index.ts b/ts/src/actions/index.ts index 93c34bf..d531f3b 100644 --- a/ts/src/actions/index.ts +++ b/ts/src/actions/index.ts @@ -1,13 +1,13 @@ -import type {CodeZeroAction} from "../CodeZeroAction"; +import type {Action} from "../action"; import * as ModuleConfigurations from "./ModuleConfigurations"; import * as Execution from "./Execution"; -export interface Action { +export interface ActionHandler { packetType: string; - handle(action: CodeZeroAction, data: unknown): void; + handle(action: Action, data: unknown): void; } -export const actions: Action[] = [ +export const actions: ActionHandler[] = [ ModuleConfigurations, Execution, ]; diff --git a/ts/src/events.ts b/ts/src/events.ts index 278c0cc..8c06e82 100644 --- a/ts/src/events.ts +++ b/ts/src/events.ts @@ -1,6 +1,6 @@ import type {ActionExecutionRequest, ActionTransferRequest, ActionTransferResponse} from "@code0-tech/tucana/aquila"; import type {ModuleConfigurations} from "@code0-tech/tucana/shared"; -import type {CodeZeroAction} from "./CodeZeroAction.ts"; +import type {Action} from "./action.ts"; export enum CodeZeroEvent { error = "error", @@ -13,7 +13,7 @@ export enum CodeZeroEvent { export interface CodeZeroEventMap { [CodeZeroEvent.error]: [Error] - [CodeZeroEvent.connected]: [CodeZeroAction] + [CodeZeroEvent.connected]: [Action] [CodeZeroEvent.streamMessageReceived]: [ActionTransferResponse] [CodeZeroEvent.streamMessageSent]: [ActionTransferRequest] [CodeZeroEvent.moduleUpdated]: [ModuleConfigurations] diff --git a/ts/src/index.ts b/ts/src/index.ts index 61bb5c5..0939677 100644 --- a/ts/src/index.ts +++ b/ts/src/index.ts @@ -5,11 +5,7 @@ export * from "./decorators/function" export * from "./decorators/data-type" export * from "./decorators/event" export * from "./decorators/runtime-event" -export * from "./models/function" -export * from "./models/runtime-function" -export * from "./models/data-type" -export * from "./models/event" -export * from "./models/runtime-event" +export * from "./definitions" export * from "./manager/BaseManager" export * from "./manager/config-manager" export * from "./manager/FunctionManager" @@ -17,4 +13,9 @@ export * from "./manager/RuntimeFunctionManager" export * from "./manager/DataTypeManager" export * from "./manager/EventManager" export * from "./manager/RuntimeEventManager" -export * from "./CodeZeroAction" +export * from "./models/function" +export * from "./models/runtime-function" +export * from "./models/data-type" +export * from "./models/event" +export * from "./models/runtime-event" +export * from "./action" From 5183eeb4d4b7f80eb43bd15bc6bec99578281f0c Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 14:38:38 +0200 Subject: [PATCH 35/43] feat: renaming --- .../src/functions/fibonacciRuntimeFunction.ts | 4 +-- ts/scripts/build-definitions.ts | 8 ++--- ts/src/action.ts | 20 +++++------ ts/src/actions/Execution.ts | 14 ++++---- ts/src/decorators/event.ts | 4 +-- ts/src/decorators/function.ts | 8 ++--- ts/src/decorators/meta.ts | 14 ++++---- ts/src/decorators/runtime-event.ts | 4 +-- ts/src/index.ts | 10 +++--- ts/src/internal/module-builder.ts | 26 +++++++------- ts/src/manager/DataTypeManager.ts | 4 +-- ts/src/manager/EventManager.ts | 4 +-- ts/src/manager/FunctionManager.ts | 4 +-- ts/src/manager/RuntimeEventManager.ts | 4 +-- ts/src/manager/RuntimeFunctionManager.ts | 4 +-- ts/src/manager/config-manager.ts | 4 +-- ts/src/map/data-type.ts | 12 +++---- ts/src/map/event.ts | 20 +++++------ ts/src/map/function.ts | 30 ++++++++-------- ts/src/map/runtime-event.ts | 18 +++++----- ts/src/map/runtime-function.ts | 32 ++++++++--------- ts/src/models/data-type.ts | 17 --------- ts/src/models/datatype.model.ts | 17 +++++++++ ts/src/models/{event.ts => event.model.ts} | 27 +++++++------- ts/src/models/function.model.ts | 32 +++++++++++++++++ ts/src/models/function.ts | 32 ----------------- ts/src/models/runtime-event.ts | 31 ---------------- ts/src/models/runtime-function.ts | 35 ------------------- ts/src/models/runtime_event.model.ts | 31 ++++++++++++++++ ts/src/models/runtime_function.model.ts | 35 +++++++++++++++++++ ts/src/types.ts | 16 ++++----- 31 files changed, 259 insertions(+), 262 deletions(-) delete mode 100644 ts/src/models/data-type.ts create mode 100644 ts/src/models/datatype.model.ts rename ts/src/models/{event.ts => event.model.ts} (52%) create mode 100644 ts/src/models/function.model.ts delete mode 100644 ts/src/models/function.ts delete mode 100644 ts/src/models/runtime-event.ts delete mode 100644 ts/src/models/runtime-function.ts create mode 100644 ts/src/models/runtime_event.model.ts create mode 100644 ts/src/models/runtime_function.model.ts diff --git a/ts/examples/simple-example-ts/src/functions/fibonacciRuntimeFunction.ts b/ts/examples/simple-example-ts/src/functions/fibonacciRuntimeFunction.ts index db8e0f3..0f7ff52 100644 --- a/ts/examples/simple-example-ts/src/functions/fibonacciRuntimeFunction.ts +++ b/ts/examples/simple-example-ts/src/functions/fibonacciRuntimeFunction.ts @@ -1,6 +1,6 @@ import { DisplayMessage, - HerculesFunctionContext, + FunctionContext, Identifier, Name, OmitFunctionDefinition, @@ -15,7 +15,7 @@ import { @OmitFunctionDefinition() @RuntimeParameter({runtimeName: "n", name: [{code: "en-US", content: "N"}]}) export class FibonacciRuntimeFunction { - run(context: HerculesFunctionContext, n: number): number { + run(context: FunctionContext, n: number): number { console.log(`[fibonacci] project=${context.projectId} execution=${context.executionId}`); return this.fib(n); } diff --git a/ts/scripts/build-definitions.ts b/ts/scripts/build-definitions.ts index 95007ff..e611999 100644 --- a/ts/scripts/build-definitions.ts +++ b/ts/scripts/build-definitions.ts @@ -170,7 +170,7 @@ function generateRuntimeFlowType(json: Record, className: strin const metaDecorators = collectMetaDecorators(json); const imports = [ - `import {RuntimeEventDefinitionRunnable} from "${src("models/runtime-event")}";`, + `import {RuntimeEventRunnable} from "${src("models/runtime_event.model")}";`, `import {${metaDecorators.join(", ")}} from "${src("decorators/meta")}";`, ...(linkedIds?.length ? [`import {LinkedDataTypeIdentifiers} from "${src("decorators/function")}";`] : []), ...(settings?.length ? [`import {RuntimeEventSetting} from "${src("decorators/runtime-event")}";`] : []), @@ -186,7 +186,7 @@ function generateRuntimeFlowType(json: Record, className: strin ...imports, "", ...decorators, - `export class ${className} implements RuntimeEventDefinitionRunnable {}`, + `export class ${className} implements RuntimeEventRunnable {}`, "", ].join("\n"); } @@ -204,7 +204,7 @@ function generateRuntimeFunction(json: Record, className: strin ]; const imports = [ - `import {RuntimeFunctionDefinitionRunnable} from "${src("models/runtime-function")}";`, + `import {RuntimeFunctionRunnable} from "${src("models/runtime_function.model")}";`, `import {${metaDecorators.join(", ")}} from "${src("decorators/meta")}";`, `import {${funcDecorators.join(", ")}} from "${src("decorators/function")}";`, `import type {PlainValue} from "@code0-tech/tucana/helpers";`, @@ -222,7 +222,7 @@ function generateRuntimeFunction(json: Record, className: strin ...imports, "", ...decorators, - `export class ${className} implements RuntimeFunctionDefinitionRunnable {`, + `export class ${className} implements RuntimeFunctionRunnable {`, ` run(..._args: (PlainValue | undefined)[]): Promise | PlainValue {`, ` throw new Error(\`${className}.run() is not implemented\`);`, ` }`, diff --git a/ts/src/action.ts b/ts/src/action.ts index 04dc1f7..ac89c6d 100644 --- a/ts/src/action.ts +++ b/ts/src/action.ts @@ -3,17 +3,17 @@ import type {GrpcOptions, GrpcTransport} from "@protobuf-ts/grpc-transport"; import {ActionTransferRequest, type ActionTransferResponse} from "@code0-tech/tucana/aquila"; import {constructValue, type PlainValue} from "@code0-tech/tucana/helpers"; import type {DuplexStreamingCall} from "@protobuf-ts/runtime-rpc"; -import type {FunctionDefinitionClass} from "./models/function"; -import type {RuntimeFunctionDefinitionClass} from "./models/runtime-function"; +import type {FunctionClass} from "./models/function.model"; +import type {RuntimeFunctionClass} from "./models/runtime_function.model"; import {runtimeFunctionMap} from "./map/runtime-function"; import {functionMap} from "./map/function"; -import type {DataTypeClass} from "./models/data-type"; +import type {DataTypeClass} from "./models/datatype.model"; import {dataTypeMap} from "./map/data-type"; -import type {EventClass} from "./models/event"; +import type {EventClass} from "./models/event.model"; import {eventMap} from "./map/event"; -import type {RuntimeEventClass} from "./models/runtime-event"; +import type {RuntimeEventClass} from "./models/runtime_event.model"; import {runtimeEventMap} from "./map/runtime-event"; -import type {HerculesActionConfigurationDefinition, HerculesTranslation} from "./types"; +import type {ConfigurationDefinition, Translation} from "./types"; import {CodeZeroEvent, type CodeZeroEventMap} from "./events"; import {createConnection} from "./internal/connection"; import {buildModule} from "./internal/module-builder"; @@ -44,8 +44,8 @@ export class Action extends EventEmitter { private readonly _author: string, private readonly _icon: string, private readonly _documentation: string, - private readonly _name: HerculesTranslation[], - private readonly _configurationDefinitions: HerculesActionConfigurationDefinition[] = [], + private readonly _name: Translation[], + private readonly _configurationDefinitions: ConfigurationDefinition[] = [], ) { super(); } @@ -54,12 +54,12 @@ export class Action extends EventEmitter { get version() { return this._version; } get stream() { return this._stream; } - registerFunction(klass: FunctionDefinitionClass) { + registerFunction(klass: FunctionClass) { const def = functionMap(klass); this.functions.set(def.runtimeName, def); } - registerRuntimeFunction(klass: RuntimeFunctionDefinitionClass) { + registerRuntimeFunction(klass: RuntimeFunctionClass) { const omitDefinition = Reflect.getMetadata('hercules:omit_function_definition', klass) || false; const def = runtimeFunctionMap(klass); this.runtimeFunctions.set(def.runtimeName, def); diff --git a/ts/src/actions/Execution.ts b/ts/src/actions/Execution.ts index 72e0c67..0d37da5 100644 --- a/ts/src/actions/Execution.ts +++ b/ts/src/actions/Execution.ts @@ -1,14 +1,14 @@ import {constructValue, PlainValue, toAllowedValue} from "@code0-tech/tucana/helpers"; import {ActionExecutionRequest, ActionExecutionResponse, ActionTransferRequest} from "@code0-tech/tucana/aquila"; import {NodeExecutionResult, Error as ProtoError} from "@code0-tech/tucana/shared"; -import {HerculesFunctionContext, RuntimeErrorException} from "../types"; -import {HerculesRuntimeFunctionDefinition} from "../models/runtime-function"; +import {FunctionContext, RuntimeError} from "../types"; +import {RuntimeFunctionProps} from "../models/runtime_function.model"; import {CodeZeroEvent} from "../events"; import type {Action} from "../action"; export const packetType = "execution"; -function buildParams(execution: ActionExecutionRequest, func: HerculesRuntimeFunctionDefinition): (PlainValue | undefined)[] { +function buildParams(execution: ActionExecutionRequest, func: RuntimeFunctionProps): (PlainValue | undefined)[] { return (func.parameters || []).map(param => { const field = execution.parameters?.fields?.[param.runtimeName]; return field ? toAllowedValue(field) : undefined; @@ -32,7 +32,7 @@ export function handle(action: Action, execution: ActionExecutionRequest): void findConfig: () => undefined, }; - const context: HerculesFunctionContext = { + const context: FunctionContext = { projectId: execution.projectId, executionId: execution.executionIdentifier, matchedConfig: conf, @@ -63,7 +63,7 @@ export function handle(action: Action, execution: ActionExecutionRequest): void }).catch((error: unknown) => { const finishedAt = BigInt(Date.now()); - const isRuntimeError = error instanceof RuntimeErrorException; + const isRuntimeError = error instanceof RuntimeError; action.stream!.requests.send(ActionTransferRequest.create({ data: { oneofKind: "result", @@ -77,10 +77,10 @@ export function handle(action: Action, execution: ActionExecutionRequest): void result: { oneofKind: "error", error: ProtoError.create({ - code: isRuntimeError ? (error as RuntimeErrorException).code : "UNKNOWN_ERROR", + code: isRuntimeError ? (error as RuntimeError).code : "UNKNOWN_ERROR", category: "RUNTIME", message: isRuntimeError - ? ((error as RuntimeErrorException).description || (error as Error).message) + ? ((error as RuntimeError).description || (error as Error).message) : String(error), timestamp: finishedAt, version: action.version, diff --git a/ts/src/decorators/event.ts b/ts/src/decorators/event.ts index 92bb49d..d8847e8 100644 --- a/ts/src/decorators/event.ts +++ b/ts/src/decorators/event.ts @@ -1,6 +1,6 @@ -import {HerculesEventSetting} from "../models/event"; +import {EventSettingProps} from "../models/event.model"; -export const EventSetting = (setting: HerculesEventSetting): ClassDecorator => +export const EventSetting = (setting: EventSettingProps): ClassDecorator => (target) => { const settings = Reflect.getMetadata('hercules:flow_settings', target) || []; settings.push(setting); diff --git a/ts/src/decorators/function.ts b/ts/src/decorators/function.ts index 97d8de5..99f975c 100644 --- a/ts/src/decorators/function.ts +++ b/ts/src/decorators/function.ts @@ -1,5 +1,5 @@ -import {HerculesFunctionDefinitionParameter} from "../models/function"; -import {HerculesRuntimeFunctionDefinitionParameter} from "../models/runtime-function"; +import {FunctionParameterProps} from "../models/function.model"; +import {RuntimeFunctionParameterProps} from "../models/runtime_function.model"; export const OmitFunctionDefinition = (): ClassDecorator => (target) => Reflect.defineMetadata('hercules:omit_function_definition', true, target) @@ -10,14 +10,14 @@ export const ThrowsError = (throwsError: boolean = true): ClassDecorator => export const LinkedDataTypeIdentifiers = (...linkedDataTypeIdentifiers: string[]): ClassDecorator => (target) => Reflect.defineMetadata('hercules:linked_data_type_identifiers', linkedDataTypeIdentifiers, target) -export const RuntimeParameter = (parameter: HerculesRuntimeFunctionDefinitionParameter): ClassDecorator => +export const RuntimeParameter = (parameter: RuntimeFunctionParameterProps): ClassDecorator => (target) => { const parameters = Reflect.getMetadata('hercules:runtime_parameters', target) || []; parameters.push(parameter); Reflect.defineMetadata('hercules:runtime_parameters', parameters, target); } -export const FunctionParameter = (parameter: HerculesFunctionDefinitionParameter): ClassDecorator => +export const FunctionParameter = (parameter: FunctionParameterProps): ClassDecorator => (target) => { const parameters = Reflect.getMetadata('hercules:function_parameters', target) || []; parameters.push(parameter); diff --git a/ts/src/decorators/meta.ts b/ts/src/decorators/meta.ts index ec1f57f..01e1e24 100644 --- a/ts/src/decorators/meta.ts +++ b/ts/src/decorators/meta.ts @@ -1,24 +1,24 @@ -import {HerculesTranslation} from "../types"; +import {Translation} from "../types"; export const Identifier = (id: string): ClassDecorator => (target) => Reflect.defineMetadata('hercules:identifier', id, target) -export const Name = (...translation: HerculesTranslation[]): ClassDecorator => +export const Name = (...translation: Translation[]): ClassDecorator => (target) => Reflect.defineMetadata('hercules:name', translation, target) -export const Description = (...translation: HerculesTranslation[]): ClassDecorator => +export const Description = (...translation: Translation[]): ClassDecorator => (target) => Reflect.defineMetadata('hercules:description', translation, target) -export const Documentation = (...translation: HerculesTranslation[]): ClassDecorator => +export const Documentation = (...translation: Translation[]): ClassDecorator => (target) => Reflect.defineMetadata('hercules:documentation', translation, target) -export const DisplayMessage = (...translation: HerculesTranslation[]): ClassDecorator => +export const DisplayMessage = (...translation: Translation[]): ClassDecorator => (target) => Reflect.defineMetadata('hercules:display_message', translation, target) -export const Alias = (...translation: HerculesTranslation[]): ClassDecorator => +export const Alias = (...translation: Translation[]): ClassDecorator => (target) => Reflect.defineMetadata('hercules:alias', translation, target) -export const DeprecationMessage = (...translation: HerculesTranslation[]): ClassDecorator => +export const DeprecationMessage = (...translation: Translation[]): ClassDecorator => (target) => Reflect.defineMetadata('hercules:deprecation_message', translation, target) export const Signature = (signature: string): ClassDecorator => diff --git a/ts/src/decorators/runtime-event.ts b/ts/src/decorators/runtime-event.ts index 3787668..dbc11f8 100644 --- a/ts/src/decorators/runtime-event.ts +++ b/ts/src/decorators/runtime-event.ts @@ -1,6 +1,6 @@ -import {HerculesRuntimeEventSetting} from "../models/runtime-event"; +import {RuntimeEventSettingProps} from "../models/runtime_event.model"; -export const RuntimeEventSetting = (setting: HerculesRuntimeEventSetting): ClassDecorator => +export const RuntimeEventSetting = (setting: RuntimeEventSettingProps): ClassDecorator => (target) => { const settings = Reflect.getMetadata('hercules:runtime_flow_settings', target) || []; settings.push(setting); diff --git a/ts/src/index.ts b/ts/src/index.ts index 0939677..4705a2d 100644 --- a/ts/src/index.ts +++ b/ts/src/index.ts @@ -13,9 +13,9 @@ export * from "./manager/RuntimeFunctionManager" export * from "./manager/DataTypeManager" export * from "./manager/EventManager" export * from "./manager/RuntimeEventManager" -export * from "./models/function" -export * from "./models/runtime-function" -export * from "./models/data-type" -export * from "./models/event" -export * from "./models/runtime-event" +export * from "./models/function.model" +export * from "./models/runtime_function.model" +export * from "./models/datatype.model" +export * from "./models/event.model" +export * from "./models/runtime_event.model" export * from "./action" diff --git a/ts/src/internal/module-builder.ts b/ts/src/internal/module-builder.ts index 2c87a94..d08dcd0 100644 --- a/ts/src/internal/module-builder.ts +++ b/ts/src/internal/module-builder.ts @@ -1,11 +1,11 @@ import {constructValue} from "@code0-tech/tucana/helpers"; import {DefinitionDataType, FlowType, FlowTypeSetting, Module, ModuleConfigurationDefinition, RuntimeFlowType, RuntimeFlowTypeSetting} from "@code0-tech/tucana/shared"; -import type {HerculesFunctionDefinition} from "../models/function"; -import type {HerculesRuntimeFunctionDefinition} from "../models/runtime-function"; -import type {HerculesActionConfigurationDefinition, HerculesTranslation} from "../types"; -import {HerculesDataType} from "../models/data-type"; -import {HerculesEvent} from "../models/event"; -import {HerculesRuntimeEvent} from "../models/runtime-event"; +import type {FunctionProps} from "../models/function.model"; +import type {RuntimeFunctionProps} from "../models/runtime_function.model"; +import type {ConfigurationDefinition, Translation} from "../types"; +import {DataTypeProps} from "../models/datatype.model"; +import {EventModel} from "../models/event.model"; +import {RuntimeEventProps} from "../models/runtime_event.model"; export interface ModuleBuildData { identifier: string; @@ -13,13 +13,13 @@ export interface ModuleBuildData { author: string; icon: string; documentation: string; - name: HerculesTranslation[]; - configurationDefinitions: HerculesActionConfigurationDefinition[]; - dataTypes: HerculesDataType[]; - events: HerculesEvent[]; - runtimeEvents: HerculesRuntimeEvent[]; - functions: HerculesFunctionDefinition[]; - runtimeFunctions: HerculesRuntimeFunctionDefinition[]; + name: Translation[]; + configurationDefinitions: ConfigurationDefinition[]; + dataTypes: DataTypeProps[]; + events: EventModel[]; + runtimeEvents: RuntimeEventProps[]; + functions: FunctionProps[]; + runtimeFunctions: RuntimeFunctionProps[]; } export function buildModule(data: ModuleBuildData): Module { diff --git a/ts/src/manager/DataTypeManager.ts b/ts/src/manager/DataTypeManager.ts index b6a78fd..aa79083 100644 --- a/ts/src/manager/DataTypeManager.ts +++ b/ts/src/manager/DataTypeManager.ts @@ -1,4 +1,4 @@ import {BaseManager} from "./BaseManager"; -import {HerculesDataType} from "../models/data-type"; +import {DataTypeProps} from "../models/datatype.model"; -export class DataTypeManager extends BaseManager {} +export class DataTypeManager extends BaseManager {} diff --git a/ts/src/manager/EventManager.ts b/ts/src/manager/EventManager.ts index 4552267..a9b25c1 100644 --- a/ts/src/manager/EventManager.ts +++ b/ts/src/manager/EventManager.ts @@ -1,4 +1,4 @@ import {BaseManager} from "./BaseManager"; -import {HerculesEvent} from "../models/event"; +import {EventModel} from "../models/event.model"; -export class EventManager extends BaseManager {} +export class EventManager extends BaseManager {} diff --git a/ts/src/manager/FunctionManager.ts b/ts/src/manager/FunctionManager.ts index 8aa0216..af7f5df 100644 --- a/ts/src/manager/FunctionManager.ts +++ b/ts/src/manager/FunctionManager.ts @@ -1,4 +1,4 @@ import {BaseManager} from "./BaseManager"; -import type {HerculesFunctionDefinition} from "../models/function"; +import type {FunctionProps} from "../models/function.model"; -export class FunctionManager extends BaseManager {} +export class FunctionManager extends BaseManager {} diff --git a/ts/src/manager/RuntimeEventManager.ts b/ts/src/manager/RuntimeEventManager.ts index 84765de..e55e9f2 100644 --- a/ts/src/manager/RuntimeEventManager.ts +++ b/ts/src/manager/RuntimeEventManager.ts @@ -1,4 +1,4 @@ import {BaseManager} from "./BaseManager"; -import {HerculesRuntimeEvent} from "../models/runtime-event"; +import {RuntimeEventProps} from "../models/runtime_event.model"; -export class RuntimeEventManager extends BaseManager {} +export class RuntimeEventManager extends BaseManager {} diff --git a/ts/src/manager/RuntimeFunctionManager.ts b/ts/src/manager/RuntimeFunctionManager.ts index 5e7a850..facb8a3 100644 --- a/ts/src/manager/RuntimeFunctionManager.ts +++ b/ts/src/manager/RuntimeFunctionManager.ts @@ -1,4 +1,4 @@ import {BaseManager} from "./BaseManager"; -import type {HerculesRuntimeFunctionDefinition} from "../models/runtime-function"; +import type {RuntimeFunctionProps} from "../models/runtime_function.model"; -export class RuntimeFunctionManager extends BaseManager {} +export class RuntimeFunctionManager extends BaseManager {} diff --git a/ts/src/manager/config-manager.ts b/ts/src/manager/config-manager.ts index 5ba436c..5d5b4b4 100644 --- a/ts/src/manager/config-manager.ts +++ b/ts/src/manager/config-manager.ts @@ -1,9 +1,9 @@ import {constructValue, toAllowedValue} from "@code0-tech/tucana/helpers"; import type {ModuleProjectConfigurations} from "@code0-tech/tucana/shared"; -import type {HerculesActionProjectConfiguration} from "../types"; +import type {ProjectConfiguration} from "../types"; import {BaseManager} from "./BaseManager"; -export class ConfigManager extends BaseManager { +export class ConfigManager extends BaseManager { update(configs: ModuleProjectConfigurations[]): void { this.clear(); for (const config of configs) { diff --git a/ts/src/map/data-type.ts b/ts/src/map/data-type.ts index 56f1c3d..1e61a9f 100644 --- a/ts/src/map/data-type.ts +++ b/ts/src/map/data-type.ts @@ -1,12 +1,12 @@ import {zodToRules, zodToTypeString} from "../internal/zod-schema"; -import type {HerculesTranslation} from "../types"; -import type {DataTypeClass, HerculesDataType} from "../models/data-type"; +import type {Translation} from "../types"; +import type {DataTypeClass, DataTypeProps} from "../models/datatype.model"; -export const dataTypeMap = (klass: DataTypeClass): HerculesDataType => { +export const dataTypeMap = (klass: DataTypeClass): DataTypeProps => { const identifier: string = Reflect.getMetadata('hercules:identifier', klass); - const name: HerculesTranslation[] = Reflect.getMetadata('hercules:name', klass) || []; - const displayMessage: HerculesTranslation[] = Reflect.getMetadata('hercules:display_message', klass) || []; - const alias: HerculesTranslation[] = Reflect.getMetadata('hercules:alias', klass) || []; + const name: Translation[] = Reflect.getMetadata('hercules:name', klass) || []; + const displayMessage: Translation[] = Reflect.getMetadata('hercules:display_message', klass) || []; + const alias: Translation[] = Reflect.getMetadata('hercules:alias', klass) || []; const linkedDataTypes: string[] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) || []; const genericKeys: string[] = Reflect.getMetadata('hercules:generic_keys', klass) || []; diff --git a/ts/src/map/event.ts b/ts/src/map/event.ts index e88b1b9..ddc2932 100644 --- a/ts/src/map/event.ts +++ b/ts/src/map/event.ts @@ -1,20 +1,20 @@ -import type {HerculesTranslation} from "../types"; -import type {EventClass, HerculesEvent, HerculesEventSetting} from "../models/event"; -import type {RuntimeEventClass} from "../models/runtime-event"; +import type {Translation} from "../types"; +import type {EventClass, EventModel, EventSettingProps} from "../models/event.model"; +import type {RuntimeEventClass} from "../models/runtime_event.model"; import {runtimeEventMap} from "./runtime-event"; -export const eventMap = (klass: EventClass): HerculesEvent => { +export const eventMap = (klass: EventClass): EventModel => { const parentClass = Object.getPrototypeOf(klass); const runtimeEvent = runtimeEventMap(parentClass); const identifier: string = Reflect.getMetadata('hercules:identifier', klass); const signature: string = Reflect.getMetadata('hercules:signature', klass); - const settings: HerculesEventSetting[] = Reflect.getMetadata('hercules:flow_settings', klass) || []; - const name: HerculesTranslation[] = Reflect.getMetadata('hercules:name', klass); - const description: HerculesTranslation[] = Reflect.getMetadata('hercules:description', klass); - const documentation: HerculesTranslation[] = Reflect.getMetadata('hercules:documentation', klass); - const displayMessage: HerculesTranslation[] = Reflect.getMetadata('hercules:display_message', klass); - const alias: HerculesTranslation[] = Reflect.getMetadata('hercules:alias', klass); + const settings: EventSettingProps[] = Reflect.getMetadata('hercules:flow_settings', klass) || []; + const name: Translation[] = Reflect.getMetadata('hercules:name', klass); + const description: Translation[] = Reflect.getMetadata('hercules:description', klass); + const documentation: Translation[] = Reflect.getMetadata('hercules:documentation', klass); + const displayMessage: Translation[] = Reflect.getMetadata('hercules:display_message', klass); + const alias: Translation[] = Reflect.getMetadata('hercules:alias', klass); const linkedDataTypes: string[] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass); const displayIcon: string | undefined = Reflect.getMetadata('hercules:display_icon', klass); const editable: boolean = Reflect.getMetadata('hercules:editable', klass) ?? false; diff --git a/ts/src/map/function.ts b/ts/src/map/function.ts index 4c21e3a..d5ce55c 100644 --- a/ts/src/map/function.ts +++ b/ts/src/map/function.ts @@ -1,23 +1,23 @@ -import {FunctionDefinitionClass, HerculesFunctionDefinition, HerculesFunctionDefinitionParameter} from "../models/function"; -import {RuntimeFunctionDefinitionClass} from "../models/runtime-function"; +import {FunctionClass, FunctionProps, FunctionParameterProps} from "../models/function.model"; +import {RuntimeFunctionClass} from "../models/runtime_function.model"; import {runtimeFunctionMap} from "./runtime-function"; -export const functionMap = (klass: FunctionDefinitionClass): HerculesFunctionDefinition => { +export const functionMap = (klass: FunctionClass): FunctionProps => { const parentClass = Object.getPrototypeOf(klass); const runtimeFunction = runtimeFunctionMap(parentClass); const identifier: string = Reflect.getMetadata('hercules:identifier', klass); - const functionParameters: HerculesFunctionDefinitionParameter[] = Reflect.getMetadata('hercules:function_parameters', klass) || []; - const name: HerculesFunctionDefinition["name"] = Reflect.getMetadata('hercules:name', klass); - const displayMessage: HerculesFunctionDefinition["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass); - const description: HerculesFunctionDefinition["description"] = Reflect.getMetadata('hercules:description', klass); - const deprecationMessage: HerculesFunctionDefinition["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass); - const alias: HerculesFunctionDefinition["alias"] = Reflect.getMetadata('hercules:alias', klass); - const documentation: HerculesFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass); - const signature: HerculesFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass); - const linkedDataTypes: HerculesFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass); - const displayIcon: HerculesFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass); - const throwsError: HerculesFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass); + const functionParameters: FunctionParameterProps[] = Reflect.getMetadata('hercules:function_parameters', klass) || []; + const name: FunctionProps["name"] = Reflect.getMetadata('hercules:name', klass); + const displayMessage: FunctionProps["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass); + const description: FunctionProps["description"] = Reflect.getMetadata('hercules:description', klass); + const deprecationMessage: FunctionProps["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass); + const alias: FunctionProps["alias"] = Reflect.getMetadata('hercules:alias', klass); + const documentation: FunctionProps["documentation"] = Reflect.getMetadata('hercules:documentation', klass); + const signature: FunctionProps["signature"] = Reflect.getMetadata('hercules:signature', klass); + const linkedDataTypes: FunctionProps["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass); + const displayIcon: FunctionProps["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass); + const throwsError: FunctionProps["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass); if (functionParameters.length > (runtimeFunction.parameters?.length ?? 0)) { throw new Error(`Function definition class ${klass.name} has more function parameters than its runtime function.`); @@ -29,7 +29,7 @@ export const functionMap = (klass: Fun } } - const mergedParameters: HerculesFunctionDefinitionParameter[] = [...functionParameters]; + const mergedParameters: FunctionParameterProps[] = [...functionParameters]; for (const rp of runtimeFunction.parameters ?? []) { if (!mergedParameters.find(p => p.runtimeName === rp.runtimeName)) { mergedParameters.push({...rp, runtimeDefinitionName: rp.runtimeName}); diff --git a/ts/src/map/runtime-event.ts b/ts/src/map/runtime-event.ts index f57dd2b..fdc63a9 100644 --- a/ts/src/map/runtime-event.ts +++ b/ts/src/map/runtime-event.ts @@ -1,15 +1,15 @@ -import type {HerculesTranslation} from "../types"; -import type {HerculesRuntimeEvent, HerculesRuntimeEventSetting, RuntimeEventClass} from "../models/runtime-event"; +import type {Translation} from "../types"; +import type {RuntimeEventProps, RuntimeEventSettingProps, RuntimeEventClass} from "../models/runtime_event.model"; -export const runtimeEventMap = (klass: RuntimeEventClass): HerculesRuntimeEvent => { +export const runtimeEventMap = (klass: RuntimeEventClass): RuntimeEventProps => { const identifier: string = Reflect.getMetadata('hercules:identifier', klass); const signature: string = Reflect.getMetadata('hercules:signature', klass); - const runtimeSettings: HerculesRuntimeEventSetting[] = Reflect.getMetadata('hercules:runtime_flow_settings', klass) || []; - const name: HerculesTranslation[] = Reflect.getMetadata('hercules:name', klass) || []; - const description: HerculesTranslation[] = Reflect.getMetadata('hercules:description', klass) || []; - const documentation: HerculesTranslation[] = Reflect.getMetadata('hercules:documentation', klass) || []; - const displayMessage: HerculesTranslation[] = Reflect.getMetadata('hercules:display_message', klass) || []; - const alias: HerculesTranslation[] = Reflect.getMetadata('hercules:alias', klass) || []; + const runtimeSettings: RuntimeEventSettingProps[] = Reflect.getMetadata('hercules:runtime_flow_settings', klass) || []; + const name: Translation[] = Reflect.getMetadata('hercules:name', klass) || []; + const description: Translation[] = Reflect.getMetadata('hercules:description', klass) || []; + const documentation: Translation[] = Reflect.getMetadata('hercules:documentation', klass) || []; + const displayMessage: Translation[] = Reflect.getMetadata('hercules:display_message', klass) || []; + const alias: Translation[] = Reflect.getMetadata('hercules:alias', klass) || []; const linkedDataTypes: string[] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) || []; const displayIcon: string | undefined = Reflect.getMetadata('hercules:display_icon', klass); const editable: boolean = Reflect.getMetadata('hercules:editable', klass) ?? false; diff --git a/ts/src/map/runtime-function.ts b/ts/src/map/runtime-function.ts index 8ebbe39..7cab977 100644 --- a/ts/src/map/runtime-function.ts +++ b/ts/src/map/runtime-function.ts @@ -1,23 +1,23 @@ import type {PlainValue} from "@code0-tech/tucana/helpers"; import { - HerculesRuntimeFunctionDefinition, - HerculesRuntimeFunctionDefinitionParameter, - RuntimeFunctionDefinitionClass, -} from "../models/runtime-function"; + RuntimeFunctionProps, + RuntimeFunctionParameterProps, + RuntimeFunctionClass, +} from "../models/runtime_function.model"; -export const runtimeFunctionMap = (klass: RuntimeFunctionDefinitionClass): HerculesRuntimeFunctionDefinition => { +export const runtimeFunctionMap = (klass: RuntimeFunctionClass): RuntimeFunctionProps => { const identifier: string = Reflect.getMetadata('hercules:identifier', klass); - const runtimeParameters: HerculesRuntimeFunctionDefinitionParameter[] = Reflect.getMetadata('hercules:runtime_parameters', klass) || []; - const name: HerculesRuntimeFunctionDefinition["name"] = Reflect.getMetadata('hercules:name', klass) || []; - const displayMessage: HerculesRuntimeFunctionDefinition["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass) || []; - const description: HerculesRuntimeFunctionDefinition["description"] = Reflect.getMetadata('hercules:description', klass) || []; - const deprecationMessage: HerculesRuntimeFunctionDefinition["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass) || []; - const alias: HerculesRuntimeFunctionDefinition["alias"] = Reflect.getMetadata('hercules:alias', klass) || []; - const documentation: HerculesRuntimeFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass) || []; - const signature: HerculesRuntimeFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass); - const linkedDataTypes: HerculesRuntimeFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) || []; - const displayIcon: HerculesRuntimeFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass) || ""; - const throwsError: HerculesRuntimeFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass) || false; + const runtimeParameters: RuntimeFunctionParameterProps[] = Reflect.getMetadata('hercules:runtime_parameters', klass) || []; + const name: RuntimeFunctionProps["name"] = Reflect.getMetadata('hercules:name', klass) || []; + const displayMessage: RuntimeFunctionProps["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass) || []; + const description: RuntimeFunctionProps["description"] = Reflect.getMetadata('hercules:description', klass) || []; + const deprecationMessage: RuntimeFunctionProps["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass) || []; + const alias: RuntimeFunctionProps["alias"] = Reflect.getMetadata('hercules:alias', klass) || []; + const documentation: RuntimeFunctionProps["documentation"] = Reflect.getMetadata('hercules:documentation', klass) || []; + const signature: RuntimeFunctionProps["signature"] = Reflect.getMetadata('hercules:signature', klass); + const linkedDataTypes: RuntimeFunctionProps["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) || []; + const displayIcon: RuntimeFunctionProps["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass) || ""; + const throwsError: RuntimeFunctionProps["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass) || false; if (!identifier) throw new Error(`Runtime function class ${klass.name} is missing an identifier. Add @Identifier("your_identifier") to the class.`); if (!signature) throw new Error(`Runtime function class ${klass.name} is missing a signature. Add @Signature("(param1: TYPE_1): RETURN_TYPE") to the class.`); diff --git a/ts/src/models/data-type.ts b/ts/src/models/data-type.ts deleted file mode 100644 index f2dbe04..0000000 --- a/ts/src/models/data-type.ts +++ /dev/null @@ -1,17 +0,0 @@ -import {DefinitionDataTypeRule} from "@code0-tech/tucana/shared"; -import {HerculesTranslation} from "../types"; - -export interface HerculesDataType { - identifier: string, - name?: HerculesTranslation[], - displayMessage?: HerculesTranslation[], - alias?: HerculesTranslation[], - rules?: DefinitionDataTypeRule[], - genericKeys?: string[], - type: string, - linkedDataTypes?: string[], -} - -export interface DataTypeDefinitionRunnable {} - -export type DataTypeClass = new () => DataTypeDefinitionRunnable; diff --git a/ts/src/models/datatype.model.ts b/ts/src/models/datatype.model.ts new file mode 100644 index 0000000..70cd6f8 --- /dev/null +++ b/ts/src/models/datatype.model.ts @@ -0,0 +1,17 @@ +import {DefinitionDataTypeRule} from "@code0-tech/tucana/shared"; +import {Translation} from "../types"; + +export interface DataTypeProps { + identifier: string, + name?: Translation[], + displayMessage?: Translation[], + alias?: Translation[], + rules?: DefinitionDataTypeRule[], + genericKeys?: string[], + type: string, + linkedDataTypes?: string[], +} + +export interface DataTypeRunnable {} + +export type DataTypeClass = new () => DataTypeRunnable; diff --git a/ts/src/models/event.ts b/ts/src/models/event.model.ts similarity index 52% rename from ts/src/models/event.ts rename to ts/src/models/event.model.ts index a3d81bd..fcbb4d3 100644 --- a/ts/src/models/event.ts +++ b/ts/src/models/event.model.ts @@ -1,34 +1,31 @@ import {PlainValue} from "@code0-tech/tucana/helpers"; -import {HerculesTranslation} from "../types"; +import {Translation} from "../types"; import {FlowTypeSetting_UniquenessScope} from "@code0-tech/tucana/shared"; -import {RuntimeEventClass} from "./runtime-event"; +import {RuntimeEventClass} from "./runtime_event.model"; -export interface HerculesEventSetting { +export interface EventSettingProps { identifier: string, unique?: FlowTypeSetting_UniquenessScope, linkedDataTypeIdentifiers?: string[], defaultValue?: PlainValue, - name?: HerculesTranslation[], - description?: HerculesTranslation[], + name?: Translation[], + description?: Translation[], optional?: boolean, hidden?: boolean, } -export interface HerculesEvent { +export interface EventModel { identifier: string, - settings?: HerculesEventSetting[], + settings?: EventSettingProps[], signature: string, linkedDataTypes?: string[], editable?: boolean, - name?: HerculesTranslation[], - description?: HerculesTranslation[], - documentation?: HerculesTranslation[], - displayMessage?: HerculesTranslation[], - alias?: HerculesTranslation[], + name?: Translation[], + description?: Translation[], + documentation?: Translation[], + displayMessage?: Translation[], + alias?: Translation[], displayIcon?: string, runtimeIdentifier?: string, } - -export interface EventDefinitionRunnable {} - export type EventClass = new () => InstanceType; diff --git a/ts/src/models/function.model.ts b/ts/src/models/function.model.ts new file mode 100644 index 0000000..c7fde99 --- /dev/null +++ b/ts/src/models/function.model.ts @@ -0,0 +1,32 @@ +import {Translation} from "../types"; +import {PlainValue} from "@code0-tech/tucana/helpers"; +import {RuntimeFunctionClass} from "./runtime_function.model"; + +export interface FunctionParameterProps { + runtimeName: string, + defaultValue?: PlainValue, + name?: Translation[], + description?: Translation[], + documentation?: Translation[], + hidden?: boolean, + optional?: boolean, + runtimeDefinitionName?: string, +} + +export interface FunctionProps { + runtimeDefinitionName: string, + runtimeName: string, + parameters?: FunctionParameterProps[], + signature: string, + throwsError?: boolean, + name?: Translation[], + description?: Translation[], + documentation?: Translation[], + deprecationMessage?: Translation[], + displayMessage?: Translation[], + alias?: Translation[], + linkedDataTypes?: string[], + displayIcon?: string, +} + +export type FunctionClass = new () => InstanceType; diff --git a/ts/src/models/function.ts b/ts/src/models/function.ts deleted file mode 100644 index 0186469..0000000 --- a/ts/src/models/function.ts +++ /dev/null @@ -1,32 +0,0 @@ -import {HerculesTranslation} from "../types"; -import {PlainValue} from "@code0-tech/tucana/helpers"; -import {RuntimeFunctionDefinitionClass} from "./runtime-function"; - -export interface HerculesFunctionDefinitionParameter { - runtimeName: string, - defaultValue?: PlainValue, - name?: HerculesTranslation[], - description?: HerculesTranslation[], - documentation?: HerculesTranslation[], - hidden?: boolean, - optional?: boolean, - runtimeDefinitionName?: string, -} - -export interface HerculesFunctionDefinition { - runtimeDefinitionName: string, - runtimeName: string, - parameters?: HerculesFunctionDefinitionParameter[], - signature: string, - throwsError?: boolean, - name?: HerculesTranslation[], - description?: HerculesTranslation[], - documentation?: HerculesTranslation[], - deprecationMessage?: HerculesTranslation[], - displayMessage?: HerculesTranslation[], - alias?: HerculesTranslation[], - linkedDataTypes?: string[], - displayIcon?: string, -} - -export type FunctionDefinitionClass = new () => InstanceType; diff --git a/ts/src/models/runtime-event.ts b/ts/src/models/runtime-event.ts deleted file mode 100644 index fcdd1eb..0000000 --- a/ts/src/models/runtime-event.ts +++ /dev/null @@ -1,31 +0,0 @@ -import {PlainValue} from "@code0-tech/tucana/helpers"; -import {HerculesTranslation} from "../types"; -import {RuntimeFlowTypeSetting_UniquenessScope} from "@code0-tech/tucana/shared"; - -export interface RuntimeEventDefinitionRunnable {} - -export interface HerculesRuntimeEventSetting { - identifier: string, - unique?: RuntimeFlowTypeSetting_UniquenessScope, - defaultValue?: PlainValue, - name?: HerculesTranslation[], - description?: HerculesTranslation[], - optional?: boolean, - hidden?: boolean, -} - -export interface HerculesRuntimeEvent { - identifier: string, - runtimeSettings?: HerculesRuntimeEventSetting[], - signature: string, - linkedDataTypes?: string[], - editable?: boolean, - name?: HerculesTranslation[], - description?: HerculesTranslation[], - documentation?: HerculesTranslation[], - displayMessage?: HerculesTranslation[], - alias?: HerculesTranslation[], - displayIcon?: string, -} - -export type RuntimeEventClass = new () => RuntimeEventDefinitionRunnable; diff --git a/ts/src/models/runtime-function.ts b/ts/src/models/runtime-function.ts deleted file mode 100644 index 7ace2d3..0000000 --- a/ts/src/models/runtime-function.ts +++ /dev/null @@ -1,35 +0,0 @@ -import {PlainValue} from "@code0-tech/tucana/helpers"; -import {HerculesTranslation} from "../types"; - -export interface HerculesRuntimeFunctionDefinitionParameter { - runtimeName: string, - defaultValue?: PlainValue, - name?: HerculesTranslation[], - description?: HerculesTranslation[], - documentation?: HerculesTranslation[], - hidden?: boolean, - optional?: boolean, -} - -export interface HerculesRuntimeFunctionDefinition { - runtimeName: string, - parameters?: HerculesRuntimeFunctionDefinitionParameter[], - signature: string, - throwsError?: boolean, - name?: HerculesTranslation[], - description?: HerculesTranslation[], - documentation?: HerculesTranslation[], - deprecationMessage?: HerculesTranslation[], - displayMessage?: HerculesTranslation[], - alias?: HerculesTranslation[], - linkedDataTypes?: string[], - displayIcon?: string, - handler: (...args: (PlainValue | undefined)[]) => Promise | PlainValue, -} - -export interface RuntimeFunctionDefinitionRunnable { - run(...args: (PlainValue | undefined)[]): Promise | PlainValue; -} - -export type RuntimeFunctionDefinitionClass = - new () => T; diff --git a/ts/src/models/runtime_event.model.ts b/ts/src/models/runtime_event.model.ts new file mode 100644 index 0000000..d0dc33d --- /dev/null +++ b/ts/src/models/runtime_event.model.ts @@ -0,0 +1,31 @@ +import {PlainValue} from "@code0-tech/tucana/helpers"; +import {Translation} from "../types"; +import {RuntimeFlowTypeSetting_UniquenessScope} from "@code0-tech/tucana/shared"; + +export interface RuntimeEventRunnable {} + +export interface RuntimeEventSettingProps { + identifier: string, + unique?: RuntimeFlowTypeSetting_UniquenessScope, + defaultValue?: PlainValue, + name?: Translation[], + description?: Translation[], + optional?: boolean, + hidden?: boolean, +} + +export interface RuntimeEventProps { + identifier: string, + runtimeSettings?: RuntimeEventSettingProps[], + signature: string, + linkedDataTypes?: string[], + editable?: boolean, + name?: Translation[], + description?: Translation[], + documentation?: Translation[], + displayMessage?: Translation[], + alias?: Translation[], + displayIcon?: string, +} + +export type RuntimeEventClass = new () => RuntimeEventRunnable; diff --git a/ts/src/models/runtime_function.model.ts b/ts/src/models/runtime_function.model.ts new file mode 100644 index 0000000..cab43a0 --- /dev/null +++ b/ts/src/models/runtime_function.model.ts @@ -0,0 +1,35 @@ +import {PlainValue} from "@code0-tech/tucana/helpers"; +import {Translation} from "../types"; + +export interface RuntimeFunctionParameterProps { + runtimeName: string, + defaultValue?: PlainValue, + name?: Translation[], + description?: Translation[], + documentation?: Translation[], + hidden?: boolean, + optional?: boolean, +} + +export interface RuntimeFunctionProps { + runtimeName: string, + parameters?: RuntimeFunctionParameterProps[], + signature: string, + throwsError?: boolean, + name?: Translation[], + description?: Translation[], + documentation?: Translation[], + deprecationMessage?: Translation[], + displayMessage?: Translation[], + alias?: Translation[], + linkedDataTypes?: string[], + displayIcon?: string, + handler: (...args: (PlainValue | undefined)[]) => Promise | PlainValue, +} + +export interface RuntimeFunctionRunnable { + run(...args: (PlainValue | undefined)[]): Promise | PlainValue; +} + +export type RuntimeFunctionClass = + new () => T; diff --git a/ts/src/types.ts b/ts/src/types.ts index 67c2581..2f2453f 100644 --- a/ts/src/types.ts +++ b/ts/src/types.ts @@ -4,26 +4,26 @@ import 'reflect-metadata'; export {FlowTypeSetting_UniquenessScope, RuntimeFlowTypeSetting_UniquenessScope}; -export interface HerculesTranslation { +export interface Translation { code: "en-US" | "de-DE" | string, content: string } -export interface HerculesFunctionContext { +export interface FunctionContext { projectId: number | bigint, executionId: string, - matchedConfig: HerculesActionProjectConfiguration + matchedConfig: ProjectConfiguration } -export interface HerculesActionProjectConfiguration { +export interface ProjectConfiguration { projectId: number | bigint, configValues: { identifier: string, value: PlainValue }[], findConfig: (identifier: string) => PlainValue | undefined } -export interface HerculesActionConfigurationDefinition { - name?: HerculesTranslation[], - description?: HerculesTranslation[], +export interface ConfigurationDefinition { + name?: Translation[], + description?: Translation[], type: string, hidden?: boolean, optional?: boolean, @@ -32,7 +32,7 @@ export interface HerculesActionConfigurationDefinition { identifier: string, } -export class RuntimeErrorException extends Error { +export class RuntimeError extends Error { code: string description?: string From e1901e14d16d2aa7db88abb98b6f0accf9bf7120 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 14:39:04 +0200 Subject: [PATCH 36/43] feat: example test --- ts/{src => test}/index.test.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ts/{src => test}/index.test.ts (100%) diff --git a/ts/src/index.test.ts b/ts/test/index.test.ts similarity index 100% rename from ts/src/index.test.ts rename to ts/test/index.test.ts From 4e496931a916357bb853922aaa549b3cd54d6a28 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 16:49:14 +0200 Subject: [PATCH 37/43] feat: changing names of files --- ts/src/decorators/{data-type.ts => datatype.dec.ts} | 0 ts/src/decorators/{event.ts => event.dec.ts} | 0 ts/src/decorators/{function.ts => function.dec.ts} | 0 ts/src/decorators/{meta.ts => meta.dec.ts} | 0 .../{runtime-event.ts => runtime_event.dec.ts} | 0 ts/src/index.ts | 10 +++++----- 6 files changed, 5 insertions(+), 5 deletions(-) rename ts/src/decorators/{data-type.ts => datatype.dec.ts} (100%) rename ts/src/decorators/{event.ts => event.dec.ts} (100%) rename ts/src/decorators/{function.ts => function.dec.ts} (100%) rename ts/src/decorators/{meta.ts => meta.dec.ts} (100%) rename ts/src/decorators/{runtime-event.ts => runtime_event.dec.ts} (100%) diff --git a/ts/src/decorators/data-type.ts b/ts/src/decorators/datatype.dec.ts similarity index 100% rename from ts/src/decorators/data-type.ts rename to ts/src/decorators/datatype.dec.ts diff --git a/ts/src/decorators/event.ts b/ts/src/decorators/event.dec.ts similarity index 100% rename from ts/src/decorators/event.ts rename to ts/src/decorators/event.dec.ts diff --git a/ts/src/decorators/function.ts b/ts/src/decorators/function.dec.ts similarity index 100% rename from ts/src/decorators/function.ts rename to ts/src/decorators/function.dec.ts diff --git a/ts/src/decorators/meta.ts b/ts/src/decorators/meta.dec.ts similarity index 100% rename from ts/src/decorators/meta.ts rename to ts/src/decorators/meta.dec.ts diff --git a/ts/src/decorators/runtime-event.ts b/ts/src/decorators/runtime_event.dec.ts similarity index 100% rename from ts/src/decorators/runtime-event.ts rename to ts/src/decorators/runtime_event.dec.ts diff --git a/ts/src/index.ts b/ts/src/index.ts index 4705a2d..108e51d 100644 --- a/ts/src/index.ts +++ b/ts/src/index.ts @@ -1,10 +1,10 @@ export * from "./types" export * from "./events" -export * from "./decorators/meta" -export * from "./decorators/function" -export * from "./decorators/data-type" -export * from "./decorators/event" -export * from "./decorators/runtime-event" +export * from "./decorators/meta.dec" +export * from "./decorators/function.dec" +export * from "./decorators/datatype.dec" +export * from "./decorators/event.dec" +export * from "./decorators/runtime_event.dec" export * from "./definitions" export * from "./manager/BaseManager" export * from "./manager/config-manager" From 31f08e2fe1c383f7ec10572e1829f0ba08c20a10 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 16:55:38 +0200 Subject: [PATCH 38/43] feat: removing unnecessary RuntimeFuctionParameter --- ts/src/decorators/function.dec.ts | 8 -------- ts/src/map/runtime-function.ts | 9 +++------ ts/src/models/runtime_function.model.ts | 13 ++----------- 3 files changed, 5 insertions(+), 25 deletions(-) diff --git a/ts/src/decorators/function.dec.ts b/ts/src/decorators/function.dec.ts index 99f975c..92191eb 100644 --- a/ts/src/decorators/function.dec.ts +++ b/ts/src/decorators/function.dec.ts @@ -1,5 +1,4 @@ import {FunctionParameterProps} from "../models/function.model"; -import {RuntimeFunctionParameterProps} from "../models/runtime_function.model"; export const OmitFunctionDefinition = (): ClassDecorator => (target) => Reflect.defineMetadata('hercules:omit_function_definition', true, target) @@ -10,13 +9,6 @@ export const ThrowsError = (throwsError: boolean = true): ClassDecorator => export const LinkedDataTypeIdentifiers = (...linkedDataTypeIdentifiers: string[]): ClassDecorator => (target) => Reflect.defineMetadata('hercules:linked_data_type_identifiers', linkedDataTypeIdentifiers, target) -export const RuntimeParameter = (parameter: RuntimeFunctionParameterProps): ClassDecorator => - (target) => { - const parameters = Reflect.getMetadata('hercules:runtime_parameters', target) || []; - parameters.push(parameter); - Reflect.defineMetadata('hercules:runtime_parameters', parameters, target); - } - export const FunctionParameter = (parameter: FunctionParameterProps): ClassDecorator => (target) => { const parameters = Reflect.getMetadata('hercules:function_parameters', target) || []; diff --git a/ts/src/map/runtime-function.ts b/ts/src/map/runtime-function.ts index 7cab977..6c3d243 100644 --- a/ts/src/map/runtime-function.ts +++ b/ts/src/map/runtime-function.ts @@ -1,13 +1,10 @@ import type {PlainValue} from "@code0-tech/tucana/helpers"; -import { - RuntimeFunctionProps, - RuntimeFunctionParameterProps, - RuntimeFunctionClass, -} from "../models/runtime_function.model"; +import {RuntimeFunctionProps, RuntimeFunctionClass} from "../models/runtime_function.model"; +import {FunctionParameterProps} from "../models/function.model"; export const runtimeFunctionMap = (klass: RuntimeFunctionClass): RuntimeFunctionProps => { const identifier: string = Reflect.getMetadata('hercules:identifier', klass); - const runtimeParameters: RuntimeFunctionParameterProps[] = Reflect.getMetadata('hercules:runtime_parameters', klass) || []; + const runtimeParameters: FunctionParameterProps[] = Reflect.getMetadata('hercules:function_parameters', klass) || []; const name: RuntimeFunctionProps["name"] = Reflect.getMetadata('hercules:name', klass) || []; const displayMessage: RuntimeFunctionProps["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass) || []; const description: RuntimeFunctionProps["description"] = Reflect.getMetadata('hercules:description', klass) || []; diff --git a/ts/src/models/runtime_function.model.ts b/ts/src/models/runtime_function.model.ts index cab43a0..aed60ea 100644 --- a/ts/src/models/runtime_function.model.ts +++ b/ts/src/models/runtime_function.model.ts @@ -1,19 +1,10 @@ import {PlainValue} from "@code0-tech/tucana/helpers"; import {Translation} from "../types"; - -export interface RuntimeFunctionParameterProps { - runtimeName: string, - defaultValue?: PlainValue, - name?: Translation[], - description?: Translation[], - documentation?: Translation[], - hidden?: boolean, - optional?: boolean, -} +import {FunctionParameterProps} from "./function.model"; export interface RuntimeFunctionProps { runtimeName: string, - parameters?: RuntimeFunctionParameterProps[], + parameters?: FunctionParameterProps[], signature: string, throwsError?: boolean, name?: Translation[], From cd0cb5583771dacb2da4c57a06e0632118320f9c Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 17:00:40 +0200 Subject: [PATCH 39/43] feat: renaming files --- ts/src/action.ts | 10 +++++----- ts/src/map/{data-type.ts => datatype.map.ts} | 0 ts/src/map/{event.ts => event.map.ts} | 0 ts/src/map/{function.ts => function.map.ts} | 0 ts/src/map/{runtime-event.ts => runtime_event.map.ts} | 0 .../{runtime-function.ts => runtime_function.map.ts} | 0 6 files changed, 5 insertions(+), 5 deletions(-) rename ts/src/map/{data-type.ts => datatype.map.ts} (100%) rename ts/src/map/{event.ts => event.map.ts} (100%) rename ts/src/map/{function.ts => function.map.ts} (100%) rename ts/src/map/{runtime-event.ts => runtime_event.map.ts} (100%) rename ts/src/map/{runtime-function.ts => runtime_function.map.ts} (100%) diff --git a/ts/src/action.ts b/ts/src/action.ts index ac89c6d..f06c588 100644 --- a/ts/src/action.ts +++ b/ts/src/action.ts @@ -5,14 +5,14 @@ import {constructValue, type PlainValue} from "@code0-tech/tucana/helpers"; import type {DuplexStreamingCall} from "@protobuf-ts/runtime-rpc"; import type {FunctionClass} from "./models/function.model"; import type {RuntimeFunctionClass} from "./models/runtime_function.model"; -import {runtimeFunctionMap} from "./map/runtime-function"; -import {functionMap} from "./map/function"; +import {runtimeFunctionMap} from "./map/runtime_function.map"; +import {functionMap} from "./map/function.map"; import type {DataTypeClass} from "./models/datatype.model"; -import {dataTypeMap} from "./map/data-type"; +import {dataTypeMap} from "./map/datatype.map"; import type {EventClass} from "./models/event.model"; -import {eventMap} from "./map/event"; +import {eventMap} from "./map/event.map"; import type {RuntimeEventClass} from "./models/runtime_event.model"; -import {runtimeEventMap} from "./map/runtime-event"; +import {runtimeEventMap} from "./map/runtime_event.map"; import type {ConfigurationDefinition, Translation} from "./types"; import {CodeZeroEvent, type CodeZeroEventMap} from "./events"; import {createConnection} from "./internal/connection"; diff --git a/ts/src/map/data-type.ts b/ts/src/map/datatype.map.ts similarity index 100% rename from ts/src/map/data-type.ts rename to ts/src/map/datatype.map.ts diff --git a/ts/src/map/event.ts b/ts/src/map/event.map.ts similarity index 100% rename from ts/src/map/event.ts rename to ts/src/map/event.map.ts diff --git a/ts/src/map/function.ts b/ts/src/map/function.map.ts similarity index 100% rename from ts/src/map/function.ts rename to ts/src/map/function.map.ts diff --git a/ts/src/map/runtime-event.ts b/ts/src/map/runtime_event.map.ts similarity index 100% rename from ts/src/map/runtime-event.ts rename to ts/src/map/runtime_event.map.ts diff --git a/ts/src/map/runtime-function.ts b/ts/src/map/runtime_function.map.ts similarity index 100% rename from ts/src/map/runtime-function.ts rename to ts/src/map/runtime_function.map.ts From 0dc3c38603dc62c90eebed9cb13505b49105ef81 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 17:08:05 +0200 Subject: [PATCH 40/43] feat: fix import errors --- ts/src/map/event.map.ts | 2 +- ts/src/map/function.map.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ts/src/map/event.map.ts b/ts/src/map/event.map.ts index ddc2932..9c8f61f 100644 --- a/ts/src/map/event.map.ts +++ b/ts/src/map/event.map.ts @@ -1,7 +1,7 @@ import type {Translation} from "../types"; import type {EventClass, EventModel, EventSettingProps} from "../models/event.model"; import type {RuntimeEventClass} from "../models/runtime_event.model"; -import {runtimeEventMap} from "./runtime-event"; +import {runtimeEventMap} from "./runtime_event.map"; export const eventMap = (klass: EventClass): EventModel => { const parentClass = Object.getPrototypeOf(klass); diff --git a/ts/src/map/function.map.ts b/ts/src/map/function.map.ts index d5ce55c..a550f6d 100644 --- a/ts/src/map/function.map.ts +++ b/ts/src/map/function.map.ts @@ -1,6 +1,6 @@ import {FunctionClass, FunctionProps, FunctionParameterProps} from "../models/function.model"; import {RuntimeFunctionClass} from "../models/runtime_function.model"; -import {runtimeFunctionMap} from "./runtime-function"; +import {runtimeFunctionMap} from "./runtime_function.map"; export const functionMap = (klass: FunctionClass): FunctionProps => { const parentClass = Object.getPrototypeOf(klass); From 234ad5cd3cb72d8eaaf5f0819cdba24f6cc470d6 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 17:23:30 +0200 Subject: [PATCH 41/43] feat: correct mapping of settings for events and eliminating runtime setting --- ts/src/action.ts | 7 +++++++ ts/src/decorators/runtime_event.dec.ts | 10 ++-------- ts/src/internal/module-builder.ts | 2 +- ts/src/map/event.map.ts | 15 ++++++++++++++- ts/src/map/runtime_event.map.ts | 7 ++++--- ts/src/models/runtime_event.model.ts | 15 ++------------- 6 files changed, 30 insertions(+), 26 deletions(-) diff --git a/ts/src/action.ts b/ts/src/action.ts index f06c588..ec8608b 100644 --- a/ts/src/action.ts +++ b/ts/src/action.ts @@ -83,8 +83,15 @@ export class Action extends EventEmitter { } registerRuntimeEventClass(klass: RuntimeEventClass) { + const omitDefinition = Reflect.getMetadata('hercules:omit_event_definition', klass) || false; const def = runtimeEventMap(klass); this.runtimeEvents.set(def.identifier, def); + if (!omitDefinition) { + this.events.set(def.identifier, { + ...def, + runtimeIdentifier: def.identifier, + }); + } } async fire(eventClass: EventClass | RuntimeEventClass, projectId: number | bigint, payload: PlainValue) { diff --git a/ts/src/decorators/runtime_event.dec.ts b/ts/src/decorators/runtime_event.dec.ts index dbc11f8..3b90fc5 100644 --- a/ts/src/decorators/runtime_event.dec.ts +++ b/ts/src/decorators/runtime_event.dec.ts @@ -1,8 +1,2 @@ -import {RuntimeEventSettingProps} from "../models/runtime_event.model"; - -export const RuntimeEventSetting = (setting: RuntimeEventSettingProps): ClassDecorator => - (target) => { - const settings = Reflect.getMetadata('hercules:runtime_flow_settings', target) || []; - settings.push(setting); - Reflect.defineMetadata('hercules:runtime_flow_settings', settings, target); - } +export const OmitEventDefinition = (): ClassDecorator => + (target) => Reflect.defineMetadata('hercules:omit_event_definition', true, target) diff --git a/ts/src/internal/module-builder.ts b/ts/src/internal/module-builder.ts index d08dcd0..3520756 100644 --- a/ts/src/internal/module-builder.ts +++ b/ts/src/internal/module-builder.ts @@ -80,7 +80,7 @@ export function buildModule(data: ModuleBuildData): Module { } as FlowType)), runtimeFlowTypes: data.runtimeEvents.map(rft => ({ identifier: rft.identifier, - runtimeSettings: (rft.runtimeSettings ?? []).map(s => ({ + runtimeSettings: (rft.settings ?? []).map(s => ({ identifier: s.identifier, unique: s.unique ?? 0, defaultValue: s.defaultValue != null ? constructValue(s.defaultValue) : undefined, diff --git a/ts/src/map/event.map.ts b/ts/src/map/event.map.ts index 9c8f61f..27f746d 100644 --- a/ts/src/map/event.map.ts +++ b/ts/src/map/event.map.ts @@ -21,11 +21,24 @@ export const eventMap = (klass: EventClass): Eve if (!identifier) throw new Error(`Event class ${klass.name} is missing an identifier. Add @Identifier("your_identifier") to the class.`); + for (const es of settings) { + if (!runtimeEvent.settings?.find(s => s.identifier === es.identifier)) { + throw new Error(`Event class ${klass.name} has a setting "${es.identifier}" that does not exist in its runtime event.`); + } + } + + const mergedSettings: EventSettingProps[] = [...settings]; + for (const rs of runtimeEvent.settings ?? []) { + if (!mergedSettings.find(s => s.identifier === rs.identifier)) { + mergedSettings.push({...rs}); + } + } + return { runtimeIdentifier: runtimeEvent.identifier, identifier, signature: signature || runtimeEvent.signature, - settings, + settings: mergedSettings, name: name || runtimeEvent.name, description: description || runtimeEvent.description, documentation: documentation || runtimeEvent.documentation, diff --git a/ts/src/map/runtime_event.map.ts b/ts/src/map/runtime_event.map.ts index fdc63a9..b991c4f 100644 --- a/ts/src/map/runtime_event.map.ts +++ b/ts/src/map/runtime_event.map.ts @@ -1,10 +1,11 @@ import type {Translation} from "../types"; -import type {RuntimeEventProps, RuntimeEventSettingProps, RuntimeEventClass} from "../models/runtime_event.model"; +import type {RuntimeEventProps, RuntimeEventClass} from "../models/runtime_event.model"; +import type {EventSettingProps} from "../models/event.model"; export const runtimeEventMap = (klass: RuntimeEventClass): RuntimeEventProps => { const identifier: string = Reflect.getMetadata('hercules:identifier', klass); const signature: string = Reflect.getMetadata('hercules:signature', klass); - const runtimeSettings: RuntimeEventSettingProps[] = Reflect.getMetadata('hercules:runtime_flow_settings', klass) || []; + const settings: EventSettingProps[] = Reflect.getMetadata('hercules:flow_settings', klass) || []; const name: Translation[] = Reflect.getMetadata('hercules:name', klass) || []; const description: Translation[] = Reflect.getMetadata('hercules:description', klass) || []; const documentation: Translation[] = Reflect.getMetadata('hercules:documentation', klass) || []; @@ -17,5 +18,5 @@ export const runtimeEventMap = (klass: RuntimeEventClass): RuntimeEventProps => if (!identifier) throw new Error(`Runtime event class ${klass.name} is missing an identifier. Add @Identifier("your_identifier") to the class.`); if (!signature) throw new Error(`Runtime event class ${klass.name} is missing a signature. Add @Signature("(): RETURN_TYPE") to the class.`); - return {identifier, signature, runtimeSettings, name, description, documentation, displayMessage, alias, linkedDataTypes, displayIcon, editable}; + return {identifier, signature, settings, name, description, documentation, displayMessage, alias, linkedDataTypes, displayIcon, editable}; }; diff --git a/ts/src/models/runtime_event.model.ts b/ts/src/models/runtime_event.model.ts index d0dc33d..be11d4d 100644 --- a/ts/src/models/runtime_event.model.ts +++ b/ts/src/models/runtime_event.model.ts @@ -1,22 +1,11 @@ -import {PlainValue} from "@code0-tech/tucana/helpers"; import {Translation} from "../types"; -import {RuntimeFlowTypeSetting_UniquenessScope} from "@code0-tech/tucana/shared"; +import {EventSettingProps} from "./event.model"; export interface RuntimeEventRunnable {} -export interface RuntimeEventSettingProps { - identifier: string, - unique?: RuntimeFlowTypeSetting_UniquenessScope, - defaultValue?: PlainValue, - name?: Translation[], - description?: Translation[], - optional?: boolean, - hidden?: boolean, -} - export interface RuntimeEventProps { identifier: string, - runtimeSettings?: RuntimeEventSettingProps[], + settings?: EventSettingProps[], signature: string, linkedDataTypes?: string[], editable?: boolean, From ca29906f310b322c3420c6781cb98a6d601db572 Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 17:23:58 +0200 Subject: [PATCH 42/43] feat: correct setting usage --- .../simple-example-ts/src/events/userCreatedRuntimeEvent.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ts/examples/simple-example-ts/src/events/userCreatedRuntimeEvent.ts b/ts/examples/simple-example-ts/src/events/userCreatedRuntimeEvent.ts index ff8ad79..c390f85 100644 --- a/ts/examples/simple-example-ts/src/events/userCreatedRuntimeEvent.ts +++ b/ts/examples/simple-example-ts/src/events/userCreatedRuntimeEvent.ts @@ -1,9 +1,9 @@ -import {Identifier, Name, RuntimeEventSetting, Signature} from "@code0-tech/hercules"; +import {Identifier, Name, EventSetting, Signature} from "@code0-tech/hercules"; @Identifier("user_created") @Signature("(userId: number): void") @Name({code: "en-US", content: "User Created"}) -@RuntimeEventSetting({ +@EventSetting({ identifier: "FILTER_ROLE", name: [{code: "en-US", content: "Role Filter"}], description: [{code: "en-US", content: "Only trigger for users with this role"}], From 522dbe523ed1f6fd6f5dbc1f4a2f19b5e36ecfdd Mon Sep 17 00:00:00 2001 From: nicosammito Date: Tue, 16 Jun 2026 17:23:58 +0200 Subject: [PATCH 43/43] feat: correct imports --- ts/examples/simple-example-ts/src/events/userCreatedEvent.ts | 5 +++-- .../src/functions/fibonacciRuntimeFunction.ts | 5 ++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ts/examples/simple-example-ts/src/events/userCreatedEvent.ts b/ts/examples/simple-example-ts/src/events/userCreatedEvent.ts index 0aa5603..5ac9074 100644 --- a/ts/examples/simple-example-ts/src/events/userCreatedEvent.ts +++ b/ts/examples/simple-example-ts/src/events/userCreatedEvent.ts @@ -1,7 +1,8 @@ -import {Editable, EventSetting, Identifier, Name} from "@code0-tech/hercules"; +import {Editable, Identifier, Name} from "@code0-tech/hercules"; import {UserCreatedRuntimeEvent} from "./userCreatedRuntimeEvent.ts"; @Identifier("user_created_event") @Name({code: "en-US", content: "On User Created"}) @Editable(false) -export class UserCreatedEvent extends UserCreatedRuntimeEvent {} +export class UserCreatedEvent extends UserCreatedRuntimeEvent { +} diff --git a/ts/examples/simple-example-ts/src/functions/fibonacciRuntimeFunction.ts b/ts/examples/simple-example-ts/src/functions/fibonacciRuntimeFunction.ts index 0f7ff52..bec8e16 100644 --- a/ts/examples/simple-example-ts/src/functions/fibonacciRuntimeFunction.ts +++ b/ts/examples/simple-example-ts/src/functions/fibonacciRuntimeFunction.ts @@ -1,10 +1,9 @@ import { DisplayMessage, - FunctionContext, + FunctionContext, FunctionParameter, Identifier, Name, OmitFunctionDefinition, - RuntimeParameter, Signature, } from "@code0-tech/hercules"; @@ -13,7 +12,7 @@ import { @Name({code: "en-US", content: "Fibonacci (Runtime)"}) @DisplayMessage({code: "en-US", content: "Computes the n-th Fibonacci number"}) @OmitFunctionDefinition() -@RuntimeParameter({runtimeName: "n", name: [{code: "en-US", content: "N"}]}) +@FunctionParameter({runtimeName: "n", name: [{code: "en-US", content: "N"}]}) export class FibonacciRuntimeFunction { run(context: FunctionContext, n: number): number { console.log(`[fibonacci] project=${context.projectId} execution=${context.executionId}`);