@motiadev/core 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/src/call-step-file.d.ts +2 -0
- package/dist/src/call-step-file.js +72 -0
- package/dist/src/flows-endpoint.d.ts +14 -1
- package/dist/src/flows-endpoint.js +104 -54
- package/dist/src/node/get-config.d.ts +2 -0
- package/dist/src/node/get-config.js +14 -0
- package/dist/src/node/get-module-export.d.ts +1 -0
- package/dist/src/node/get-module-export.js +63 -0
- package/dist/src/server.js +2 -2
- package/dist/src/step-handlers.js +2 -69
- package/package.json +2 -1
- package/tsconfig.json +2 -2
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -22,3 +22,4 @@ __exportStar(require("./src/logger"), exports);
|
|
|
22
22
|
__exportStar(require("./src/state/create-state-adapter"), exports);
|
|
23
23
|
__exportStar(require("./src/python/get-python-config"), exports);
|
|
24
24
|
__exportStar(require("./src/ruby/get-ruby-config"), exports);
|
|
25
|
+
__exportStar(require("./src/node/get-config"), exports);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.callStepFile = void 0;
|
|
7
|
+
const step_handler_rpc_processor_1 = require("./step-handler-rpc-processor");
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const nodeRunner = path_1.default.join(__dirname, 'node', 'node-runner.js');
|
|
11
|
+
const pythonRunner = path_1.default.join(__dirname, 'python', 'python-runner.py');
|
|
12
|
+
const rubyRunner = path_1.default.join(__dirname, 'ruby', 'ruby_runner.rb');
|
|
13
|
+
const getLanguageBasedRunner = (stepFilePath = '') => {
|
|
14
|
+
const isPython = stepFilePath.endsWith('.py');
|
|
15
|
+
const isRuby = stepFilePath.endsWith('.rb');
|
|
16
|
+
const isNode = stepFilePath.endsWith('.js') || stepFilePath.endsWith('.ts');
|
|
17
|
+
if (isPython) {
|
|
18
|
+
return { runner: pythonRunner, command: 'python' };
|
|
19
|
+
}
|
|
20
|
+
else if (isRuby) {
|
|
21
|
+
return { runner: rubyRunner, command: 'ruby' };
|
|
22
|
+
}
|
|
23
|
+
else if (isNode) {
|
|
24
|
+
return { runner: nodeRunner, command: 'node' };
|
|
25
|
+
}
|
|
26
|
+
throw Error(`Unsupported file extension ${stepFilePath}`);
|
|
27
|
+
};
|
|
28
|
+
const callStepFile = (stepPath, step, event, eventManager, state) => {
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
const jsonData = JSON.stringify({ ...event });
|
|
31
|
+
const { runner, command } = getLanguageBasedRunner(stepPath);
|
|
32
|
+
const child = (0, child_process_1.spawn)(command, [runner, stepPath, jsonData], {
|
|
33
|
+
stdio: [undefined, undefined, undefined, 'ipc'],
|
|
34
|
+
});
|
|
35
|
+
const rpcProcessor = new step_handler_rpc_processor_1.RpcProcessor(child);
|
|
36
|
+
rpcProcessor.handler('log', async (input) => {
|
|
37
|
+
event.logger.log(input);
|
|
38
|
+
});
|
|
39
|
+
rpcProcessor.handler('state.get', (input) => state.get(input.traceId, input.key));
|
|
40
|
+
rpcProcessor.handler('state.set', (input) => state.set(input.traceId, input.key, input.value));
|
|
41
|
+
rpcProcessor.handler('state.delete', (input) => state.delete(input.traceId, input.key));
|
|
42
|
+
rpcProcessor.handler('state.clear', (input) => state.clear(input.traceId));
|
|
43
|
+
rpcProcessor.handler('emit', (input) => {
|
|
44
|
+
return eventManager.emit({
|
|
45
|
+
...input,
|
|
46
|
+
traceId: event.traceId,
|
|
47
|
+
flows: event.flows,
|
|
48
|
+
logger: event.logger,
|
|
49
|
+
}, stepPath);
|
|
50
|
+
});
|
|
51
|
+
rpcProcessor.init();
|
|
52
|
+
child.stdout?.on('data', (data) => {
|
|
53
|
+
try {
|
|
54
|
+
const message = JSON.parse(data.toString());
|
|
55
|
+
event.logger.log(message);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
event.logger.info(Buffer.from(data).toString(), { step });
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
child.stderr?.on('data', (data) => event.logger.error(Buffer.from(data).toString(), { step }));
|
|
62
|
+
child.on('close', (code) => {
|
|
63
|
+
if (code !== 0) {
|
|
64
|
+
reject(new Error(`Process exited with code ${code}`));
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
resolve();
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
exports.callStepFile = callStepFile;
|
|
@@ -4,6 +4,17 @@ type FlowListResponse = {
|
|
|
4
4
|
id: string;
|
|
5
5
|
name: string;
|
|
6
6
|
};
|
|
7
|
+
export type EdgeData = {
|
|
8
|
+
label?: string;
|
|
9
|
+
variant: 'event' | 'virtual';
|
|
10
|
+
emitType: string;
|
|
11
|
+
};
|
|
12
|
+
type FlowEdge = {
|
|
13
|
+
id: string;
|
|
14
|
+
source: string;
|
|
15
|
+
target: string;
|
|
16
|
+
data: EdgeData;
|
|
17
|
+
};
|
|
7
18
|
type FlowStepResponse = {
|
|
8
19
|
id: string;
|
|
9
20
|
name: string;
|
|
@@ -11,6 +22,7 @@ type FlowStepResponse = {
|
|
|
11
22
|
description?: string;
|
|
12
23
|
subscribes?: string[];
|
|
13
24
|
emits: Emit[];
|
|
25
|
+
virtualEmits?: Emit[];
|
|
14
26
|
action?: 'webhook';
|
|
15
27
|
webhookUrl?: string;
|
|
16
28
|
bodySchema?: any;
|
|
@@ -19,7 +31,8 @@ type FlowStepResponse = {
|
|
|
19
31
|
};
|
|
20
32
|
type FlowResponse = FlowListResponse & {
|
|
21
33
|
steps: FlowStepResponse[];
|
|
34
|
+
edges: FlowEdge[];
|
|
22
35
|
};
|
|
23
|
-
export declare const generateFlowsList: (flows: LockedData["flows"]) => FlowResponse[];
|
|
24
36
|
export declare const flowsEndpoint: (flows: LockedData["flows"], app: Express) => void;
|
|
37
|
+
export declare const generateFlowsList: (flows: LockedData["flows"]) => FlowResponse[];
|
|
25
38
|
export {};
|
|
@@ -3,65 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.generateFlowsList = exports.flowsEndpoint = void 0;
|
|
7
7
|
const crypto_1 = require("crypto");
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
9
|
const zod_to_json_schema_1 = __importDefault(require("zod-to-json-schema"));
|
|
10
10
|
const guards_1 = require("./guards");
|
|
11
11
|
const get_step_language_1 = require("./get-step-language");
|
|
12
|
-
const generateFlowsList = (flows) => {
|
|
13
|
-
const list = [];
|
|
14
|
-
Object.keys(flows).forEach((flowId) => {
|
|
15
|
-
const steps = [];
|
|
16
|
-
const flowSteps = flows[flowId].steps;
|
|
17
|
-
flowSteps.forEach((step) => {
|
|
18
|
-
const filePathWithoutExtension = step.filePath.replace(/\.[^/.]+$/, '');
|
|
19
|
-
const tsxPath = filePathWithoutExtension + '.tsx';
|
|
20
|
-
const nodeComponentPath = fs_1.default.existsSync(tsxPath) ? tsxPath : undefined;
|
|
21
|
-
if ((0, guards_1.isApiStep)(step)) {
|
|
22
|
-
steps.push({
|
|
23
|
-
id: (0, crypto_1.randomUUID)(),
|
|
24
|
-
type: 'api',
|
|
25
|
-
name: step.config.name,
|
|
26
|
-
description: step.config.description,
|
|
27
|
-
emits: [...step.config.emits, ...(step.config.virtualEmits ?? [])],
|
|
28
|
-
subscribes: step.config.virtualSubscribes ?? undefined,
|
|
29
|
-
action: 'webhook',
|
|
30
|
-
language: (0, get_step_language_1.getStepLanguage)(step.filePath),
|
|
31
|
-
webhookUrl: `${step.config.method} ${step.config.path}`,
|
|
32
|
-
bodySchema: step?.config.bodySchema ? (0, zod_to_json_schema_1.default)(step.config.bodySchema) : undefined,
|
|
33
|
-
nodeComponentPath,
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
else if ((0, guards_1.isEventStep)(step)) {
|
|
37
|
-
steps.push({
|
|
38
|
-
id: (0, crypto_1.randomUUID)(),
|
|
39
|
-
type: 'event',
|
|
40
|
-
name: step.config.name,
|
|
41
|
-
description: step.config.description,
|
|
42
|
-
emits: [...step.config.emits, ...(step.config.virtualEmits ?? [])],
|
|
43
|
-
subscribes: step.config.subscribes,
|
|
44
|
-
language: (0, get_step_language_1.getStepLanguage)(step.filePath),
|
|
45
|
-
nodeComponentPath,
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
else if ((0, guards_1.isNoopStep)(step)) {
|
|
49
|
-
steps.push({
|
|
50
|
-
id: (0, crypto_1.randomUUID)(),
|
|
51
|
-
type: 'noop',
|
|
52
|
-
name: step.config.name,
|
|
53
|
-
description: step.config.description,
|
|
54
|
-
emits: step.config.virtualEmits,
|
|
55
|
-
subscribes: step.config.virtualSubscribes,
|
|
56
|
-
nodeComponentPath,
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
list.push({ id: flowId, name: flowId, steps });
|
|
61
|
-
});
|
|
62
|
-
return list;
|
|
63
|
-
};
|
|
64
|
-
exports.generateFlowsList = generateFlowsList;
|
|
65
12
|
const flowsEndpoint = (flows, app) => {
|
|
66
13
|
const list = (0, exports.generateFlowsList)(flows);
|
|
67
14
|
app.get('/flows', async (_, res) => {
|
|
@@ -79,3 +26,106 @@ const flowsEndpoint = (flows, app) => {
|
|
|
79
26
|
});
|
|
80
27
|
};
|
|
81
28
|
exports.flowsEndpoint = flowsEndpoint;
|
|
29
|
+
const generateFlowsList = (flows) => {
|
|
30
|
+
return Object.entries(flows).map(([flowId, flow]) => generateFlow(flowId, flow.steps));
|
|
31
|
+
};
|
|
32
|
+
exports.generateFlowsList = generateFlowsList;
|
|
33
|
+
// Helper functions
|
|
34
|
+
const getNodeComponentPath = (filePath) => {
|
|
35
|
+
const filePathWithoutExtension = filePath.replace(/\.[^/.]+$/, '');
|
|
36
|
+
const tsxPath = filePathWithoutExtension + '.tsx';
|
|
37
|
+
return fs_1.default.existsSync(tsxPath) ? tsxPath : undefined;
|
|
38
|
+
};
|
|
39
|
+
const createEdge = (sourceId, targetId, emitType, label, variant) => ({
|
|
40
|
+
id: `${sourceId}-${targetId}`,
|
|
41
|
+
source: sourceId,
|
|
42
|
+
target: targetId,
|
|
43
|
+
data: { variant, label, emitType },
|
|
44
|
+
});
|
|
45
|
+
const processEmit = (emit) => {
|
|
46
|
+
const isString = typeof emit === 'string';
|
|
47
|
+
return {
|
|
48
|
+
type: isString ? emit : emit.type,
|
|
49
|
+
label: isString ? undefined : emit.label,
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
const createEdgesForEmits = (sourceStep, targetSteps, emits, variant) => {
|
|
53
|
+
const edges = [];
|
|
54
|
+
emits.forEach((emit) => {
|
|
55
|
+
const { type: emitType, label } = processEmit(emit);
|
|
56
|
+
targetSteps.forEach((targetStep) => {
|
|
57
|
+
if (targetStep.subscribes?.includes(emitType)) {
|
|
58
|
+
edges.push(createEdge(sourceStep.id, targetStep.id, emitType, label, variant));
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
return edges;
|
|
63
|
+
};
|
|
64
|
+
const createBaseStepResponse = (step, id) => ({
|
|
65
|
+
id,
|
|
66
|
+
name: step.config.name,
|
|
67
|
+
description: step.config.description,
|
|
68
|
+
nodeComponentPath: getNodeComponentPath(step.filePath),
|
|
69
|
+
language: (0, get_step_language_1.getStepLanguage)(step.filePath),
|
|
70
|
+
});
|
|
71
|
+
const createApiStepResponse = (step, id) => {
|
|
72
|
+
if (!(0, guards_1.isApiStep)(step)) {
|
|
73
|
+
throw new Error('Attempted to create API step response with non-API step');
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
...createBaseStepResponse(step, id),
|
|
77
|
+
type: 'api',
|
|
78
|
+
emits: step.config.emits,
|
|
79
|
+
virtualEmits: step.config.virtualEmits ?? [],
|
|
80
|
+
subscribes: step.config.virtualSubscribes ?? undefined,
|
|
81
|
+
action: 'webhook',
|
|
82
|
+
webhookUrl: `${step.config.method} ${step.config.path}`,
|
|
83
|
+
bodySchema: step.config.bodySchema ? (0, zod_to_json_schema_1.default)(step.config.bodySchema) : undefined,
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
const createEventStepResponse = (step, id) => {
|
|
87
|
+
if (!(0, guards_1.isEventStep)(step)) {
|
|
88
|
+
throw new Error('Attempted to create Event step response with non-Event step');
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
...createBaseStepResponse(step, id),
|
|
92
|
+
type: 'event',
|
|
93
|
+
emits: step.config.emits,
|
|
94
|
+
virtualEmits: step.config.virtualEmits ?? [],
|
|
95
|
+
subscribes: step.config.subscribes,
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
const createNoopStepResponse = (step, id) => {
|
|
99
|
+
if (!(0, guards_1.isNoopStep)(step)) {
|
|
100
|
+
throw new Error('Attempted to create Noop step response with non-Noop step');
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
...createBaseStepResponse(step, id),
|
|
104
|
+
type: 'noop',
|
|
105
|
+
emits: [],
|
|
106
|
+
virtualEmits: step.config.virtualEmits,
|
|
107
|
+
subscribes: step.config.virtualSubscribes,
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
const createStepResponse = (step) => {
|
|
111
|
+
const id = (0, crypto_1.randomUUID)();
|
|
112
|
+
if ((0, guards_1.isApiStep)(step))
|
|
113
|
+
return createApiStepResponse(step, id);
|
|
114
|
+
if ((0, guards_1.isEventStep)(step))
|
|
115
|
+
return createEventStepResponse(step, id);
|
|
116
|
+
if ((0, guards_1.isNoopStep)(step))
|
|
117
|
+
return createNoopStepResponse(step, id);
|
|
118
|
+
throw new Error(`Unknown step type for step: ${step.config.name}`);
|
|
119
|
+
};
|
|
120
|
+
const createEdgesForStep = (sourceStep, allSteps) => {
|
|
121
|
+
const regularEdges = createEdgesForEmits(sourceStep, allSteps, sourceStep.emits, 'event');
|
|
122
|
+
const virtualEdges = sourceStep.virtualEmits
|
|
123
|
+
? createEdgesForEmits(sourceStep, allSteps, sourceStep.virtualEmits, 'virtual')
|
|
124
|
+
: [];
|
|
125
|
+
return [...regularEdges, ...virtualEdges];
|
|
126
|
+
};
|
|
127
|
+
const generateFlow = (flowId, flowSteps) => {
|
|
128
|
+
const steps = flowSteps.map(createStepResponse);
|
|
129
|
+
const edges = steps.flatMap((step) => createEdgesForStep(step, steps));
|
|
130
|
+
return { id: flowId, name: flowId, steps, edges };
|
|
131
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getNodeFileConfig = void 0;
|
|
4
|
+
const get_module_export_1 = require("./get-module-export");
|
|
5
|
+
const getNodeFileConfig = async (filePath) => {
|
|
6
|
+
try {
|
|
7
|
+
return await (0, get_module_export_1.getModuleExport)(filePath, 'config');
|
|
8
|
+
}
|
|
9
|
+
catch (error) {
|
|
10
|
+
console.error(`Failed to extract config from ${filePath}:`, error);
|
|
11
|
+
throw new Error(`No config found in step ${filePath}`);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
exports.getNodeFileConfig = getNodeFileConfig;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getModuleExport: (filePath: string, exportName: string) => Promise<any>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.getModuleExport = void 0;
|
|
40
|
+
const path_1 = __importDefault(require("path"));
|
|
41
|
+
const tsconfigPaths = __importStar(require("tsconfig-paths"));
|
|
42
|
+
const tsConfigPath = path_1.default.resolve(process.cwd(), 'tsconfig.json');
|
|
43
|
+
const result = tsconfigPaths.loadConfig(tsConfigPath);
|
|
44
|
+
if (result.resultType !== 'success') {
|
|
45
|
+
throw Error('Failed to load tsconfig.json');
|
|
46
|
+
}
|
|
47
|
+
const { absoluteBaseUrl, paths } = result;
|
|
48
|
+
require('ts-node').register({
|
|
49
|
+
transpileOnly: true,
|
|
50
|
+
compilerOptions: { module: 'commonjs', baseUrl: absoluteBaseUrl, paths },
|
|
51
|
+
});
|
|
52
|
+
const getModuleExport = async (filePath, exportName) => {
|
|
53
|
+
try {
|
|
54
|
+
const resolvedFilePath = require.resolve(filePath);
|
|
55
|
+
const module = require(resolvedFilePath);
|
|
56
|
+
return module[exportName];
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.error(`Failed to extract ${exportName} from ${filePath}:`, error);
|
|
60
|
+
throw new Error(`No ${exportName} found in step ${filePath}`);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
exports.getModuleExport = getModuleExport;
|
package/dist/src/server.js
CHANGED
|
@@ -12,6 +12,7 @@ const socket_io_1 = require("socket.io");
|
|
|
12
12
|
const flows_endpoint_1 = require("./flows-endpoint");
|
|
13
13
|
const guards_1 = require("./guards");
|
|
14
14
|
const logger_1 = require("./logger");
|
|
15
|
+
const get_module_export_1 = require("./node/get-module-export");
|
|
15
16
|
const createServer = async (options) => {
|
|
16
17
|
const { flows, steps, eventManager, state } = options;
|
|
17
18
|
const app = (0, express_1.default)();
|
|
@@ -22,8 +23,7 @@ const createServer = async (options) => {
|
|
|
22
23
|
const traceId = (0, crypto_1.randomUUID)();
|
|
23
24
|
const logger = new logger_1.Logger(traceId, flows, step.config.name, io);
|
|
24
25
|
logger.debug('[API] Received request, processing step', { path: req.path, step });
|
|
25
|
-
const
|
|
26
|
-
const handler = module.handler;
|
|
26
|
+
const handler = (await (0, get_module_export_1.getModuleExport)(step.filePath, 'handler'));
|
|
27
27
|
const request = {
|
|
28
28
|
body: req.body,
|
|
29
29
|
headers: req.headers,
|
|
@@ -1,76 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.createStepHandlers = void 0;
|
|
7
|
-
const child_process_1 = require("child_process");
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
4
|
const logger_1 = require("./logger");
|
|
10
5
|
const guards_1 = require("./guards");
|
|
11
|
-
const
|
|
12
|
-
const nodeRunner = path_1.default.join(__dirname, 'node', 'node-runner.js');
|
|
13
|
-
const pythonRunner = path_1.default.join(__dirname, 'python', 'python-runner.py');
|
|
14
|
-
const rubyRunner = path_1.default.join(__dirname, 'ruby', 'ruby_runner.rb');
|
|
15
|
-
const getLanguageBasedRunner = (stepFilePath = '') => {
|
|
16
|
-
const isPython = stepFilePath.endsWith('.py');
|
|
17
|
-
const isRuby = stepFilePath.endsWith('.rb');
|
|
18
|
-
const isNode = stepFilePath.endsWith('.js') || stepFilePath.endsWith('.ts');
|
|
19
|
-
if (isPython) {
|
|
20
|
-
return { runner: pythonRunner, command: 'python' };
|
|
21
|
-
}
|
|
22
|
-
else if (isRuby) {
|
|
23
|
-
return { runner: rubyRunner, command: 'ruby' };
|
|
24
|
-
}
|
|
25
|
-
else if (isNode) {
|
|
26
|
-
return { runner: nodeRunner, command: 'node' };
|
|
27
|
-
}
|
|
28
|
-
throw Error(`Unsupported file extension ${stepFilePath}`);
|
|
29
|
-
};
|
|
30
|
-
const callStepFile = (stepPath, step, event, eventManager, state) => {
|
|
31
|
-
return new Promise((resolve, reject) => {
|
|
32
|
-
const jsonData = JSON.stringify({ ...event });
|
|
33
|
-
const { runner, command } = getLanguageBasedRunner(stepPath);
|
|
34
|
-
const child = (0, child_process_1.spawn)(command, [runner, stepPath, jsonData], {
|
|
35
|
-
stdio: [undefined, undefined, undefined, 'ipc'],
|
|
36
|
-
});
|
|
37
|
-
const rpcProcessor = new step_handler_rpc_processor_1.RpcProcessor(child);
|
|
38
|
-
rpcProcessor.handler('log', async (input) => {
|
|
39
|
-
event.logger.log(input);
|
|
40
|
-
});
|
|
41
|
-
rpcProcessor.handler('state.get', (input) => state.get(input.traceId, input.key));
|
|
42
|
-
rpcProcessor.handler('state.set', (input) => state.set(input.traceId, input.key, input.value));
|
|
43
|
-
rpcProcessor.handler('state.delete', (input) => state.delete(input.traceId, input.key));
|
|
44
|
-
rpcProcessor.handler('state.clear', (input) => state.clear(input.traceId));
|
|
45
|
-
rpcProcessor.handler('emit', (input) => {
|
|
46
|
-
return eventManager.emit({
|
|
47
|
-
...input,
|
|
48
|
-
traceId: event.traceId,
|
|
49
|
-
flows: event.flows,
|
|
50
|
-
logger: event.logger,
|
|
51
|
-
}, stepPath);
|
|
52
|
-
});
|
|
53
|
-
rpcProcessor.init();
|
|
54
|
-
child.stdout?.on('data', (data) => {
|
|
55
|
-
try {
|
|
56
|
-
const message = JSON.parse(data.toString());
|
|
57
|
-
event.logger.log(message);
|
|
58
|
-
}
|
|
59
|
-
catch (error) {
|
|
60
|
-
event.logger.info(Buffer.from(data).toString(), { step });
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
child.stderr?.on('data', (data) => event.logger.error(Buffer.from(data).toString(), { step }));
|
|
64
|
-
child.on('close', (code) => {
|
|
65
|
-
if (code !== 0) {
|
|
66
|
-
reject(new Error(`Process exited with code ${code}`));
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
resolve();
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
};
|
|
6
|
+
const call_step_file_1 = require("./call-step-file");
|
|
74
7
|
const createStepHandlers = (steps, eventManager, state) => {
|
|
75
8
|
logger_1.globalLogger.debug(`[step handler] creating step handlers for ${steps.length} steps`);
|
|
76
9
|
steps.filter(guards_1.isEventStep).forEach((step) => {
|
|
@@ -82,7 +15,7 @@ const createStepHandlers = (steps, eventManager, state) => {
|
|
|
82
15
|
const { logger, ...rest } = event;
|
|
83
16
|
logger_1.globalLogger.debug('[step handler] received event', { event: rest, step: step.config.name });
|
|
84
17
|
try {
|
|
85
|
-
await callStepFile(filePath, step.config.name, event, eventManager, state);
|
|
18
|
+
await (0, call_step_file_1.callStepFile)(filePath, step.config.name, event, eventManager, state);
|
|
86
19
|
}
|
|
87
20
|
catch (error) {
|
|
88
21
|
logger_1.globalLogger.error(`[step handler] error calling step`, {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@motiadev/core",
|
|
3
3
|
"main": "dist/index.js",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.3",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"body-parser": "^1.20.3",
|
|
7
7
|
"express": "^4.21.2",
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"pino": "^9.6.0",
|
|
10
10
|
"socket.io": "^4.8.1",
|
|
11
11
|
"ts-node": "^10.9.2",
|
|
12
|
+
"tsconfig-paths": "^4.2.0",
|
|
12
13
|
"yaml": "^2.7.0",
|
|
13
14
|
"zod": "^3.24.1",
|
|
14
15
|
"zod-to-json-schema": "^3.24.1"
|
package/tsconfig.json
CHANGED