Skip to content

Commit 667265f

Browse files
committed
Refactor some code to make the structure clearer
1 parent 1e73962 commit 667265f

12 files changed

Lines changed: 657 additions & 528 deletions

ts/.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
node_modules
22
dist
3-
code0-tech-hercules-*.tgz
3+
code0-tech-hercules-*.tgz
4+
.env

ts/src/action_sdk.ts

Lines changed: 12 additions & 527 deletions
Large diffs are not rendered by default.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import type {RegisteredFunction, RegisteredRuntimeFunction, RuntimeFunctionDefinitionClass, SdkState} from "../types";
2+
import {buildRuntimeFunctionDefinition} from "../sdk/builder/builder";
3+
4+
export function registerRuntimeFunctionDefinitionClass(config: {
5+
authToken: string;
6+
aquilaUrl: string;
7+
actionId: string;
8+
version: string
9+
}, state: SdkState) {
10+
return (klass: RuntimeFunctionDefinitionClass): Promise<void> => {
11+
const omitFunctionDefinition = Reflect.getMetadata('hercules:omit_function_definition', klass) || false
12+
13+
const runtimeFunction = buildRuntimeFunctionDefinition(klass, config);
14+
const definition = runtimeFunction.definition
15+
16+
state.runtimeFunctions.push(runtimeFunction as RegisteredRuntimeFunction)
17+
if (!omitFunctionDefinition) {
18+
state.functions.push({
19+
identifier: definition.runtimeName,
20+
definition: {
21+
...definition,
22+
runtimeDefinitionName: definition.runtimeName,
23+
parameterDefinitions: definition.runtimeParameterDefinitions.map(param => {
24+
return {
25+
...param,
26+
runtimeDefinitionName: param.runtimeName
27+
}
28+
})
29+
}
30+
} as RegisteredFunction)
31+
}
32+
33+
return Promise.resolve();
34+
};
35+
}

ts/src/sdk/builder/builder.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import 'reflect-metadata';
2+
import {constructValue} from "@code0-tech/tucana/helpers";
3+
import {
4+
RuntimeFunctionDefinitionClass,
5+
RegisteredRuntimeFunction,
6+
HerculesRuntimeFunctionDefinitionParameter,
7+
HerculesRuntimeFunctionDefinition,
8+
ActionSdk,
9+
} from "../../types";
10+
import {RuntimeParameterDefinition} from "@code0-tech/tucana/shared";
11+
12+
export function buildRuntimeFunctionDefinition(klass: RuntimeFunctionDefinitionClass, config: ActionSdk["config"]): RegisteredRuntimeFunction {
13+
const identifier: string = Reflect.getMetadata('hercules:identifier', klass)
14+
const runtimeParameters: HerculesRuntimeFunctionDefinitionParameter[] = Reflect.getMetadata('hercules:runtime_parameters', klass)
15+
const names: HerculesRuntimeFunctionDefinition["name"] = Reflect.getMetadata('hercules:name', klass) || []
16+
const displayMessage: HerculesRuntimeFunctionDefinition["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass) || []
17+
const description: HerculesRuntimeFunctionDefinition["description"] = Reflect.getMetadata('hercules:description', klass) || []
18+
const deprecationMessage: HerculesRuntimeFunctionDefinition["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass) || []
19+
const alias: HerculesRuntimeFunctionDefinition["alias"] = Reflect.getMetadata('hercules:alias', klass) || []
20+
const documentation: HerculesRuntimeFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass) || []
21+
const signature: HerculesRuntimeFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass)
22+
const linkedDataTypeIdentifiers: HerculesRuntimeFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass) || []
23+
const version: HerculesRuntimeFunctionDefinition["version"] = Reflect.getMetadata('hercules:version', klass) || config.version
24+
const displayIcon: HerculesRuntimeFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass) || ""
25+
const throwsError: HerculesRuntimeFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass) || false
26+
const runFunction = new klass().run
27+
28+
if (!identifier) {
29+
throw new Error(`Runtime function class ${klass.name} is missing an identifier. Please add @Identifier("your_identifier") decorator to the class.`)
30+
}
31+
if (!signature) {
32+
throw new Error(`Runtime function class ${klass.name} is missing a signature. Please add @Signature("(param1: TYPE_1): RETURN_TYPE") decorator to the class.`)
33+
}
34+
35+
return {
36+
identifier: identifier as string,
37+
definition: {
38+
alias: alias || [],
39+
name: names || [],
40+
description: description || [],
41+
version: version || config.version,
42+
runtimeName: identifier,
43+
deprecationMessage: deprecationMessage || [],
44+
displayIcon: displayIcon || "tabler:note",
45+
displayMessage: displayMessage || [],
46+
documentation: documentation || [],
47+
linkedDataTypeIdentifiers: linkedDataTypeIdentifiers || [],
48+
runtimeParameterDefinitions: runtimeParameters.map(param => {
49+
return {
50+
...param,
51+
name: param.name || [],
52+
description: param.description || [],
53+
documentation: param.documentation || [],
54+
hidden: param.hidden || false,
55+
optional: param.optional || false,
56+
defaultValue: param.defaultValue ? constructValue(param.defaultValue) : undefined,
57+
} as RuntimeParameterDefinition
58+
}),
59+
signature: signature,
60+
throwsError: throwsError || false,
61+
definitionSource: "action"
62+
},
63+
handler: runFunction
64+
} as RegisteredRuntimeFunction
65+
}
66+
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import type {
2+
FunctionDefinitionConstructor,
3+
HerculesFunctionDefinition,
4+
HerculesFunctionDefinitionParameter, RegisteredFunction,
5+
SdkState
6+
} from "../../types";
7+
import {buildRuntimeFunctionDefinition} from "./builder";
8+
import {constructValue} from "@code0-tech/tucana/helpers";
9+
10+
export function registerFunctionDefinitionClass(config: {
11+
authToken: string;
12+
aquilaUrl: string;
13+
actionId: string;
14+
version: string
15+
}, state: SdkState) {
16+
return <T>(klass: FunctionDefinitionConstructor<T>): Promise<void> => {
17+
const parentClass = Object.getPrototypeOf(klass)
18+
const runtimeFunction = buildRuntimeFunctionDefinition(parentClass, config);
19+
const runtimeDefinition = runtimeFunction.definition
20+
21+
const functionParameters: HerculesFunctionDefinitionParameter[] = Reflect.getMetadata('hercules:function_parameters', klass)
22+
const names: HerculesFunctionDefinition["name"] = Reflect.getMetadata('hercules:name', klass)
23+
const displayMessage: HerculesFunctionDefinition["displayMessage"] = Reflect.getMetadata('hercules:display_message', klass)
24+
const description: HerculesFunctionDefinition["description"] = Reflect.getMetadata('hercules:description', klass)
25+
const deprecationMessage: HerculesFunctionDefinition["deprecationMessage"] = Reflect.getMetadata('hercules:deprecation_message', klass)
26+
const alias: HerculesFunctionDefinition["alias"] = Reflect.getMetadata('hercules:alias', klass)
27+
const documentation: HerculesFunctionDefinition["documentation"] = Reflect.getMetadata('hercules:documentation', klass)
28+
const signature: HerculesFunctionDefinition["signature"] = Reflect.getMetadata('hercules:signature', klass)
29+
const linkedDataTypeIdentifiers: HerculesFunctionDefinition["linkedDataTypes"] = Reflect.getMetadata('hercules:linked_data_type_identifiers', klass)
30+
const version: HerculesFunctionDefinition["version"] = Reflect.getMetadata('hercules:version', klass)
31+
const displayIcon: HerculesFunctionDefinition["displayIcon"] = Reflect.getMetadata('hercules:display_icon', klass)
32+
const throwsError: HerculesFunctionDefinition["throwsError"] = Reflect.getMetadata('hercules:throws_error', klass)
33+
34+
runtimeDefinition.runtimeParameterDefinitions.forEach(runtimeDefinition => {
35+
if (functionParameters.find((param: HerculesFunctionDefinitionParameter) => param.runtimeName === runtimeDefinition.runtimeName)) {
36+
return;
37+
}
38+
functionParameters.push({
39+
...runtimeDefinition,
40+
runtimeDefinitionName: runtimeDefinition.runtimeName
41+
})
42+
})
43+
44+
state.functions.push({
45+
identifier: runtimeFunction.identifier,
46+
definition: {
47+
runtimeDefinitionName: runtimeDefinition.runtimeName,
48+
runtimeName: runtimeDefinition.runtimeName || runtimeDefinition.runtimeName,
49+
signature: signature || runtimeDefinition.signature,
50+
throwsError: throwsError || runtimeDefinition.throwsError,
51+
alias: alias || runtimeDefinition.alias,
52+
version: version || runtimeDefinition.version,
53+
description: description || runtimeDefinition.description,
54+
name: names || runtimeDefinition.name,
55+
documentation: documentation || runtimeDefinition.documentation,
56+
deprecationMessage: deprecationMessage || runtimeDefinition.deprecationMessage,
57+
displayMessage: displayMessage || runtimeDefinition.displayMessage,
58+
displayIcon: displayIcon || runtimeDefinition.displayIcon,
59+
definitionSource: "action",
60+
linkedDataTypeIdentifiers: linkedDataTypeIdentifiers || runtimeDefinition.linkedDataTypeIdentifiers,
61+
parameterDefinitions: functionParameters.map(value => {
62+
return {
63+
...value,
64+
runtimeDefinitionName: value.runtimeDefinitionName || value.runtimeName,
65+
name: value.name || [],
66+
description: value.description || [],
67+
documentation: value.documentation || [],
68+
hidden: value.hidden || false,
69+
optional: value.optional || false,
70+
defaultValue: value.defaultValue ? constructValue(value.defaultValue || null) : undefined,
71+
}
72+
})
73+
},
74+
} as RegisteredFunction)
75+
76+
return Promise.resolve();
77+
};
78+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import type {RpcOptions} from "@protobuf-ts/runtime-rpc";
2+
import {logger} from "../../logger";
3+
import {constructValue, toAllowedValue} from "@code0-tech/tucana/helpers";
4+
import type {
5+
ActionSdk,
6+
SdkState,
7+
HerculesActionProjectConfiguration
8+
} from "../../types";
9+
import {handleExecutionRequest} from "../execution";
10+
import {handleLogon} from "./logon";
11+
import {handleRuntimeFunctionDefinitions} from "./runtimeFunctionDefinition";
12+
import {handleDataTypes} from "./dataType";
13+
import {handleFunctionDefinitions} from "./functionDefinition";
14+
import {handleFlowTypes} from "./flowTypes";
15+
16+
17+
export async function connect(state: SdkState, config: ActionSdk["config"], options?: RpcOptions): Promise<HerculesActionProjectConfiguration[]> {
18+
logger.debug("Trying to connect to aquila")
19+
const builtOptions: RpcOptions = {
20+
meta: {
21+
"Authorization": config.authToken,
22+
},
23+
...options
24+
}
25+
state.stream = state.client.transfer(builtOptions);
26+
27+
await handleDataTypes(state, builtOptions, config);
28+
await handleLogon(state, config);
29+
await handleRuntimeFunctionDefinitions(state, builtOptions, config)
30+
await handleFunctionDefinitions(state, builtOptions, config)
31+
await handleFlowTypes(state, builtOptions, config)
32+
33+
logger.info("Connected successfully to aquila")
34+
35+
36+
return new Promise(async (resolve, reject) => {
37+
try {
38+
for await (let message of state?.stream?.responses || []) {
39+
logger.debug({
40+
message: message,
41+
config,
42+
}, "Received message from stream")
43+
switch (message?.data.oneofKind) {
44+
case "actionConfigurations": {
45+
logger.info("Received action configurations")
46+
47+
const configs = message.data.actionConfigurations as any;
48+
state.projectConfigurations = configs.actionConfigurations
49+
resolve(state.projectConfigurations.map(value => {
50+
return {
51+
projectId: value.projectId,
52+
configValues: value.actionConfigurations.map(value => {
53+
return {
54+
identifier: value.identifier,
55+
value: toAllowedValue(value.value || constructValue(null)),
56+
}
57+
}),
58+
findConfig: identifier => {
59+
const config = value.actionConfigurations.find(config => config.identifier === identifier);
60+
return config ? toAllowedValue(config.value || constructValue(null)) : undefined;
61+
}
62+
}
63+
}));
64+
state.fullyConnected = true
65+
break;
66+
}
67+
68+
case "execution": {
69+
logger.info({
70+
executionD: message.data.execution.executionIdentifier,
71+
config,
72+
}, "Handling execution request")
73+
74+
logger.debug({
75+
message: message,
76+
config,
77+
}, "Handling execution request")
78+
handleExecutionRequest(state, message)
79+
break;
80+
}
81+
}
82+
}
83+
} catch (reason) {
84+
logger.error({
85+
err: reason,
86+
config
87+
}, "Error occurred in stream")
88+
reject(reason);
89+
}
90+
})
91+
}
92+

ts/src/sdk/connection/dataType.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {DataTypeServiceClient, DataTypeUpdateRequest} from "@code0-tech/tucana/aquila";
2+
import {logger} from "../../logger";
3+
import {SdkState} from "../../types";
4+
import {RpcOptions} from "@protobuf-ts/runtime-rpc";
5+
6+
export async function handleDataTypes(state: SdkState, builtOptions: RpcOptions, config: {
7+
authToken: string;
8+
aquilaUrl: string;
9+
actionId: string;
10+
version: string
11+
}) {
12+
const dataTypeClient = new DataTypeServiceClient(state.transport)
13+
await dataTypeClient.update(DataTypeUpdateRequest.create({
14+
dataTypes: [
15+
...state.dataTypes
16+
]
17+
}), builtOptions).then(value => {
18+
if (!value.response.success) {
19+
return Promise.reject(value.response);
20+
}
21+
}).catch(reason => {
22+
logger.error({
23+
err: reason,
24+
config,
25+
}, "Error while updating data types")
26+
return Promise.reject(reason);
27+
})
28+
logger.debug("Sent data types request")
29+
}

ts/src/sdk/connection/flowTypes.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {ActionSdk, SdkState} from "../../types";
2+
import {FlowTypeServiceClient, FlowTypeUpdateRequest} from "@code0-tech/tucana/aquila";
3+
import {RpcOptions} from "@protobuf-ts/runtime-rpc";
4+
import {logger} from "../../logger";
5+
6+
export async function handleFlowTypes(state: SdkState, builtOptions: RpcOptions | undefined, config: ActionSdk["config"]) {
7+
const flowTypeClient = new FlowTypeServiceClient(state.transport)
8+
const request = {
9+
flowTypes: [
10+
...state.flowTypes
11+
]
12+
};
13+
try {
14+
15+
await flowTypeClient.update(FlowTypeUpdateRequest.create(request), builtOptions).then(value => {
16+
if (!value.response.success) {
17+
logger.error({
18+
err: value.response,
19+
request: value.request,
20+
config,
21+
})
22+
return Promise.reject(value.response);
23+
}
24+
})
25+
26+
} catch (error) {
27+
logger.error({
28+
err: error,
29+
request,
30+
config,
31+
}, "Error while updating flow types")
32+
return Promise.reject(error);
33+
}
34+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import type {ActionSdk, SdkState} from "../../types";
2+
import type {RpcOptions} from "@protobuf-ts/runtime-rpc";
3+
import {FunctionDefinitionServiceClient, FunctionDefinitionUpdateRequest} from "@code0-tech/tucana/aquila";
4+
import {logger} from "../../logger";
5+
6+
export async function handleFunctionDefinitions(state: SdkState, builtOptions: RpcOptions | undefined, config: ActionSdk["config"]) {
7+
const FunctionDefinitionClient = new FunctionDefinitionServiceClient(state.transport)
8+
try {
9+
const finishedCall = await FunctionDefinitionClient.update(
10+
FunctionDefinitionUpdateRequest.create(
11+
{
12+
functions: [
13+
...state.functions.map(func => ({
14+
...func.definition,
15+
}))
16+
]
17+
}
18+
), builtOptions
19+
);
20+
21+
if (!finishedCall.response.success) {
22+
logger.error({
23+
err: finishedCall.response,
24+
request: finishedCall.request,
25+
config,
26+
}, "Error while updating function definitions")
27+
return Promise.reject(finishedCall.response);
28+
}
29+
} catch (error) {
30+
logger.error({
31+
err: error,
32+
config,
33+
}, "Error while updating function definitions")
34+
return Promise.reject(error);
35+
}
36+
logger.debug("Updated function definitions")
37+
}

0 commit comments

Comments
 (0)