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/.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/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 f1a9ede..0000000
--- a/ts/examples/simple-example-ts/index.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import {
- createSdk,
- HerculesActionProjectConfiguration,
- HerculesFunctionContext,
- RuntimeErrorException
-} 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",
-})
-
-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);
- }
-
- return fibonacci(number)
- }
- }
-)
-
-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 b9a1c24..ca17b67 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-WNWRc5+auZ15MBHcilAA+HPpASKW0CaTTe1QAYCUlcC1a+t9a8/yBEWQr4Ol8FA72yrR3+1/5r4C0YPm5cDVcQ==",
"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": {
@@ -187,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"
@@ -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/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/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 7193a07..d2af2bc 100644
--- a/ts/examples/simple-example-ts/tsconfig.json
+++ b/ts/examples/simple-example-ts/tsconfig.json
@@ -11,9 +11,12 @@
"baseUrl": ".",
"paths": {
"@code0-tech/hercules": ["../../ts"]
- }
+ },
+ "experimentalDecorators": true,
+ "emitDecoratorMetadata": true,
+ "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
new file mode 100644
index 0000000..303b4a4
--- /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, 'src/index.ts'),
+ rollupOptions: {
+ external: (id) =>
+ [
+ 'fs',
+ 'path',
+ 'typescript',
+ '@code0-tech/hercules'
+ ].includes(id) || id.startsWith('node:')
+ }
+ }
+});
\ No newline at end of file
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..1bffdd2 100644
--- a/ts/src/action_sdk.ts
+++ b/ts/src/action_sdk.ts
@@ -1,27 +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,
- HerculesRegisterRuntimeFunctionParameter, HerculesRegisterFunctionDefinition
-} from "./types.js";
-import {
- ActionTransferServiceClient,
- DataTypeServiceClient,
- DataTypeUpdateRequest, ExecutionRequest,
- FlowTypeServiceClient,
- FlowTypeUpdateRequest,
- FunctionDefinitionServiceClient,
- FunctionDefinitionUpdateRequest, RuntimeFunctionDefinitionServiceClient, RuntimeFunctionDefinitionUpdateRequest,
- TransferRequest, TransferResponse
-} from "@code0-tech/tucana/aquila";
-import {
- ActionConfigurations,
- FlowTypeSetting,
-} 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} 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(
@@ -54,74 +41,9 @@ 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,
- 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
- }
- });
- }
- 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,
- 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,
- 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,
- },
- handler: handler,
- });
- }
- return Promise.resolve()
- };
return {
+ registerFunctionDefinitionClass: registerFunctionDefinitionClass(config, state),
+ registerRuntimeFunctionDefinitionClass: registerRuntimeFunctionDefinitionClass(config, state),
fullyConnected(): boolean {
return state.fullyConnected;
},
@@ -175,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,
@@ -190,11 +112,11 @@ 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",
- version: flowType.version || config.version,
+ version: config.version,
linkedDataTypeIdentifiers: flowType.linkedDataTypes || [],
settings: (flowType.settings || []).map(setting => ({
name: setting.name || [],
@@ -209,29 +131,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.");
@@ -247,7 +146,7 @@ const createSdk = (config: ActionSdk["config"], configDefinitions?: HerculesActi
event: {
projectId: projectIdBigInt,
eventType: eventType,
- payload: constructValue(payload) || constructValue(null),
+ payload: constructValue(payload || null),
}
}
})
@@ -260,353 +159,6 @@ 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 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);
- }
- })
- 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
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..5f38180
--- /dev/null
+++ b/ts/src/sdk/builder/builder.ts
@@ -0,0 +1,65 @@
+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 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
new file mode 100644
index 0000000..765ec9f
--- /dev/null
+++ b/ts/src/sdk/builder/registerFunctionDefinitionClass.ts
@@ -0,0 +1,77 @@
+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 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/connection/connection.ts b/ts/src/sdk/connection/connection.ts
new file mode 100644
index 0000000..c220e67
--- /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 handleRuntimeFunctionDefinitions(state, builtOptions, config)
+ await handleFunctionDefinitions(state, builtOptions, config)
+ await handleFlowTypes(state, builtOptions, config)
+ await handleLogon(state, config);
+
+ logger.info("Connected successfully to aquila")
+
+
+ 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")
+
+ 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..183f0d2
--- /dev/null
+++ b/ts/src/sdk/execution.ts
@@ -0,0 +1,187 @@
+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")
+ });
+ })
+}
+
diff --git a/ts/src/types.ts b/ts/src/types.ts
index 7215e86..76bd448 100644
--- a/ts/src/types.ts
+++ b/ts/src/types.ts
@@ -5,12 +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,
@@ -20,89 +24,87 @@ 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,
- linkedDataTypes?: string[],
- // Will default to sdk version
- version?: string
+ linkedDataTypes?: string[]
}
-export interface HerculesFlowTypeSetting {
+export interface HerculesEventTypeSetting {
identifier: string,
unique?: FlowTypeSetting_UniquenessScope,
linkedDataTypeIdentifiers?: string[],
defaultValue?: PlainValue,
- name?: Translation[],
- description?: Translation[],
+ name?: HerculesTranslation[],
+ description?: HerculesTranslation[],
}
-export interface HerculesFlowType {
+export interface HerculesEventType {
identifier: string,
- settings?: HerculesFlowTypeSetting[],
+ settings?: HerculesEventTypeSetting[],
signature: string,
linkedDataTypes?: string[],
editable: boolean,
- name?: Translation[],
- description?: Translation[],
- documentation?: Translation[],
- displayMessage?: Translation[],
- alias?: Translation[],
- version?: string,
+ name?: HerculesTranslation[],
+ description?: HerculesTranslation[],
+ documentation?: HerculesTranslation[],
+ displayMessage?: HerculesTranslation[],
+ alias?: HerculesTranslation[],
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?: {
- runtimeName: string,
- defaultValue?: PlainValue,
- name?: Translation[],
- description?: Translation[],
- documentation?: Translation[],
- hidden?: boolean,
- optional?: boolean
- }[],
+ 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,
}
-export interface HerculesRegisterFunctionDefinition {
+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?: {
- runtimeName: string,
- defaultValue?: PlainValue,
- name?: Translation[],
- description?: Translation[],
- documentation?: Translation[],
- hidden?: boolean,
- optional?: boolean,
- runtimeDefinitionName?: string
- }[],
+ 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,
}
@@ -116,8 +118,8 @@ export interface HerculesActionProjectConfiguration {
}
export interface HerculesActionConfigurationDefinition {
- name?: Translation[],
- description?: Translation[],
+ name?: HerculesTranslation[],
+ description?: HerculesTranslation[],
type: string,
linkedDataTypes?: string[],
defaultValue?: PlainValue,
@@ -144,10 +146,9 @@ 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,
+ registerEventTypes: (...flowTypes: Array) => Promise,
+ registerRuntimeFunctionDefinitionClass: (klass: RuntimeFunctionDefinitionClass) => Promise,
+ registerFunctionDefinitionClass: (klass: FunctionDefinitionConstructor) => Promise,
dispatchEvent: (eventType: string, projectId: number | bigint, payload: PlainValue) => Promise,
}
@@ -163,6 +164,65 @@ 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
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