@motiadev/core 0.0.22 → 0.0.24
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/src/call-step-file.d.ts +15 -3
- package/dist/src/call-step-file.js +28 -23
- package/dist/src/cron-handler.d.ts +3 -2
- package/dist/src/cron-handler.js +18 -22
- package/dist/src/flows-endpoint.d.ts +2 -1
- package/dist/src/flows-endpoint.js +11 -6
- package/dist/src/get-step-config.d.ts +1 -1
- package/dist/src/get-step-config.js +49 -13
- package/dist/src/logger.d.ts +6 -2
- package/dist/src/logger.js +13 -8
- package/dist/src/node/get-config.d.ts +1 -2
- package/dist/src/node/get-config.js +39 -8
- package/dist/src/node/logger.d.ts +1 -2
- package/dist/src/node/logger.js +1 -3
- package/dist/src/node/node-runner.js +6 -3
- package/dist/src/python/logger.py +1 -3
- package/dist/src/python/python-runner.py +12 -5
- package/dist/src/ruby/{get_config.rb → get-config.rb} +4 -11
- package/dist/src/ruby/logger.rb +1 -3
- package/dist/src/ruby/{ruby_runner.rb → ruby-runner.rb} +13 -10
- package/dist/src/server.js +24 -17
- package/dist/src/step-handlers.js +20 -6
- package/dist/src/step-validator.js +35 -2
- package/dist/src/types.d.ts +2 -1
- package/dist/src/utils.js +3 -0
- package/package.json +3 -3
- package/dist/src/node/get-module-export.d.ts +0 -1
- package/dist/src/node/get-module-export.js +0 -68
- package/dist/src/python/get-python-config.d.ts +0 -2
- package/dist/src/python/get-python-config.js +0 -34
|
@@ -1,3 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { EventManager, InternalStateManager, Step } from './types';
|
|
2
|
+
import { BaseLogger } from './logger';
|
|
3
|
+
import { Printer } from './printer';
|
|
4
|
+
type CallStepFileOptions = {
|
|
5
|
+
step: Step;
|
|
6
|
+
logger: BaseLogger;
|
|
7
|
+
eventManager: EventManager;
|
|
8
|
+
state: InternalStateManager;
|
|
9
|
+
traceId: string;
|
|
10
|
+
printer: Printer;
|
|
11
|
+
data?: any;
|
|
12
|
+
contextInFirstArg: boolean;
|
|
13
|
+
};
|
|
14
|
+
export declare const callStepFile: <TData>(options: CallStepFileOptions) => Promise<TData | undefined>;
|
|
15
|
+
export {};
|
|
@@ -8,67 +8,72 @@ const step_handler_rpc_processor_1 = require("./step-handler-rpc-processor");
|
|
|
8
8
|
const child_process_1 = require("child_process");
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
10
|
const utils_1 = require("./utils");
|
|
11
|
-
const nodeRunner = path_1.default.join(__dirname, 'node', 'node-runner.js');
|
|
12
|
-
const pythonRunner = path_1.default.join(__dirname, 'python', 'python-runner.py');
|
|
13
|
-
const rubyRunner = path_1.default.join(__dirname, 'ruby', 'ruby_runner.rb');
|
|
14
11
|
const getLanguageBasedRunner = (stepFilePath = '') => {
|
|
15
12
|
const isPython = stepFilePath.endsWith('.py');
|
|
16
13
|
const isRuby = stepFilePath.endsWith('.rb');
|
|
17
14
|
const isNode = stepFilePath.endsWith('.js') || stepFilePath.endsWith('.ts');
|
|
18
15
|
if (isPython) {
|
|
19
|
-
|
|
16
|
+
const pythonRunner = path_1.default.join(__dirname, 'python', 'python-runner.py');
|
|
17
|
+
return { runner: pythonRunner, command: 'python', args: [] };
|
|
20
18
|
}
|
|
21
19
|
else if (isRuby) {
|
|
22
|
-
|
|
20
|
+
const rubyRunner = path_1.default.join(__dirname, 'ruby', 'ruby-runner.rb');
|
|
21
|
+
return { runner: rubyRunner, command: 'ruby', args: [] };
|
|
23
22
|
}
|
|
24
23
|
else if (isNode) {
|
|
25
|
-
|
|
24
|
+
if (process.env._MOTIA_TEST_MODE === 'true') {
|
|
25
|
+
const nodeRunner = path_1.default.join(__dirname, 'node', 'node-runner.ts');
|
|
26
|
+
return { runner: nodeRunner, command: 'node', args: ['-r', 'ts-node/register'] };
|
|
27
|
+
}
|
|
28
|
+
const nodeRunner = path_1.default.join(__dirname, 'node', 'node-runner.js');
|
|
29
|
+
return { runner: nodeRunner, command: 'node', args: [] };
|
|
26
30
|
}
|
|
27
31
|
throw Error(`Unsupported file extension ${stepFilePath}`);
|
|
28
32
|
};
|
|
29
|
-
const callStepFile = (
|
|
33
|
+
const callStepFile = (options) => {
|
|
34
|
+
const { step, printer, eventManager, state, traceId, data, contextInFirstArg } = options;
|
|
35
|
+
const logger = options.logger.child({ step: step.config.name });
|
|
36
|
+
const flows = step.config.flows;
|
|
30
37
|
return new Promise((resolve, reject) => {
|
|
31
|
-
const jsonData = JSON.stringify({
|
|
32
|
-
const { runner, command } = getLanguageBasedRunner(step.filePath);
|
|
33
|
-
|
|
38
|
+
const jsonData = JSON.stringify({ data, flows, traceId, contextInFirstArg });
|
|
39
|
+
const { runner, command, args } = getLanguageBasedRunner(step.filePath);
|
|
40
|
+
let result;
|
|
41
|
+
const child = (0, child_process_1.spawn)(command, [...args, runner, step.filePath, jsonData], {
|
|
34
42
|
stdio: [undefined, undefined, undefined, 'ipc'],
|
|
35
43
|
});
|
|
36
44
|
const rpcProcessor = new step_handler_rpc_processor_1.RpcProcessor(child);
|
|
37
45
|
rpcProcessor.handler('close', async () => child.kill());
|
|
38
|
-
rpcProcessor.handler('log', async (input) =>
|
|
46
|
+
rpcProcessor.handler('log', async (input) => logger.log(input));
|
|
39
47
|
rpcProcessor.handler('state.get', (input) => state.get(input.traceId, input.key));
|
|
40
48
|
rpcProcessor.handler('state.set', (input) => state.set(input.traceId, input.key, input.value));
|
|
41
49
|
rpcProcessor.handler('state.delete', (input) => state.delete(input.traceId, input.key));
|
|
42
50
|
rpcProcessor.handler('state.clear', (input) => state.clear(input.traceId));
|
|
51
|
+
rpcProcessor.handler('result', async (input) => {
|
|
52
|
+
result = input;
|
|
53
|
+
});
|
|
43
54
|
rpcProcessor.handler('emit', async (input) => {
|
|
44
55
|
if (!(0, utils_1.isAllowedToEmit)(step, input.type)) {
|
|
45
|
-
|
|
46
|
-
return;
|
|
56
|
+
return printer.printInvalidEmit(step, input.type);
|
|
47
57
|
}
|
|
48
|
-
return eventManager.emit({
|
|
49
|
-
...input,
|
|
50
|
-
traceId: event.traceId,
|
|
51
|
-
flows: event.flows,
|
|
52
|
-
logger: event.logger,
|
|
53
|
-
}, step.filePath);
|
|
58
|
+
return eventManager.emit({ ...input, traceId, flows: step.config.flows, logger }, step.filePath);
|
|
54
59
|
});
|
|
55
60
|
rpcProcessor.init();
|
|
56
61
|
child.stdout?.on('data', (data) => {
|
|
57
62
|
try {
|
|
58
63
|
const message = JSON.parse(data.toString());
|
|
59
|
-
|
|
64
|
+
logger.log(message);
|
|
60
65
|
}
|
|
61
66
|
catch {
|
|
62
|
-
|
|
67
|
+
logger.info(Buffer.from(data).toString());
|
|
63
68
|
}
|
|
64
69
|
});
|
|
65
|
-
child.stderr?.on('data', (data) =>
|
|
70
|
+
child.stderr?.on('data', (data) => logger.error(Buffer.from(data).toString()));
|
|
66
71
|
child.on('close', (code) => {
|
|
67
72
|
if (code !== 0 && code !== null) {
|
|
68
73
|
reject(new Error(`Process exited with code ${code}`));
|
|
69
74
|
}
|
|
70
75
|
else {
|
|
71
|
-
resolve();
|
|
76
|
+
resolve(result);
|
|
72
77
|
}
|
|
73
78
|
});
|
|
74
79
|
});
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { Server } from 'socket.io';
|
|
2
2
|
import { LockedData } from './locked-data';
|
|
3
|
-
import {
|
|
3
|
+
import { StateAdapter } from './state/state-adapter';
|
|
4
|
+
import { CronConfig, EventManager, Step } from './types';
|
|
4
5
|
export type CronManager = {
|
|
5
6
|
createCronJob: (step: Step<CronConfig>) => void;
|
|
6
7
|
removeCronJob: (step: Step<CronConfig>) => void;
|
|
7
8
|
close: () => void;
|
|
8
9
|
};
|
|
9
|
-
export declare const setupCronHandlers: (lockedData: LockedData, eventManager: EventManager, socketServer: Server) => {
|
|
10
|
+
export declare const setupCronHandlers: (lockedData: LockedData, eventManager: EventManager, state: StateAdapter, socketServer: Server) => {
|
|
10
11
|
createCronJob: (step: Step<CronConfig>) => void;
|
|
11
12
|
removeCronJob: (step: Step<CronConfig>) => void;
|
|
12
13
|
close: () => void;
|
package/dist/src/cron-handler.js
CHANGED
|
@@ -34,45 +34,41 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.setupCronHandlers = void 0;
|
|
37
|
+
const crypto_1 = require("crypto");
|
|
37
38
|
const cron = __importStar(require("node-cron"));
|
|
39
|
+
const call_step_file_1 = require("./call-step-file");
|
|
38
40
|
const logger_1 = require("./logger");
|
|
39
|
-
const
|
|
40
|
-
const setupCronHandlers = (lockedData, eventManager, socketServer) => {
|
|
41
|
+
const setupCronHandlers = (lockedData, eventManager, state, socketServer) => {
|
|
41
42
|
const cronJobs = new Map();
|
|
43
|
+
const printer = lockedData.printer;
|
|
42
44
|
const createCronJob = (step) => {
|
|
43
45
|
const { config, filePath } = step;
|
|
44
|
-
const { cron: cronExpression } = config;
|
|
46
|
+
const { cron: cronExpression, name: stepName } = config;
|
|
45
47
|
if (!cron.validate(cronExpression)) {
|
|
46
48
|
logger_1.globalLogger.error('[cron handler] invalid cron expression', {
|
|
47
49
|
expression: cronExpression,
|
|
48
|
-
step:
|
|
50
|
+
step: stepName,
|
|
49
51
|
});
|
|
50
52
|
return;
|
|
51
53
|
}
|
|
52
54
|
logger_1.globalLogger.debug('[cron handler] setting up cron job', {
|
|
53
55
|
filePath,
|
|
54
|
-
step:
|
|
56
|
+
step: stepName,
|
|
55
57
|
cron: cronExpression,
|
|
56
58
|
});
|
|
57
59
|
const task = cron.schedule(cronExpression, async () => {
|
|
58
|
-
const traceId =
|
|
59
|
-
const logger = new logger_1.Logger(traceId, config.flows,
|
|
60
|
-
const flows = config.flows;
|
|
60
|
+
const traceId = (0, crypto_1.randomUUID)();
|
|
61
|
+
const logger = new logger_1.Logger(traceId, config.flows, stepName, socketServer);
|
|
61
62
|
try {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
await Promise.all(config.emits.map((item) => {
|
|
72
|
-
const type = typeof item === 'string' ? item : item.type;
|
|
73
|
-
emit({ type, data });
|
|
74
|
-
}));
|
|
75
|
-
}
|
|
63
|
+
await (0, call_step_file_1.callStepFile)({
|
|
64
|
+
contextInFirstArg: true,
|
|
65
|
+
step,
|
|
66
|
+
eventManager,
|
|
67
|
+
printer,
|
|
68
|
+
state,
|
|
69
|
+
traceId,
|
|
70
|
+
logger,
|
|
71
|
+
});
|
|
76
72
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
77
73
|
}
|
|
78
74
|
catch (error) {
|
|
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.generateFlowsList = exports.flowsEndpoint = void 0;
|
|
7
7
|
const crypto_1 = require("crypto");
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
|
-
const zod_to_json_schema_1 = __importDefault(require("zod-to-json-schema"));
|
|
10
9
|
const guards_1 = require("./guards");
|
|
11
10
|
const get_step_language_1 = require("./get-step-language");
|
|
12
11
|
const flowsEndpoint = (lockedData, app) => {
|
|
@@ -37,26 +36,32 @@ const getNodeComponentPath = (filePath) => {
|
|
|
37
36
|
const tsxPath = filePathWithoutExtension + '.tsx';
|
|
38
37
|
return fs_1.default.existsSync(tsxPath) ? tsxPath : undefined;
|
|
39
38
|
};
|
|
40
|
-
const createEdge = (sourceId, targetId, emitType, label, variant) => ({
|
|
39
|
+
const createEdge = (sourceId, targetId, emitType, label, variant, conditional) => ({
|
|
41
40
|
id: `${sourceId}-${targetId}`,
|
|
42
41
|
source: sourceId,
|
|
43
42
|
target: targetId,
|
|
44
|
-
data: {
|
|
43
|
+
data: {
|
|
44
|
+
variant,
|
|
45
|
+
label,
|
|
46
|
+
emitType,
|
|
47
|
+
labelVariant: conditional ? 'conditional' : 'default',
|
|
48
|
+
},
|
|
45
49
|
});
|
|
46
50
|
const processEmit = (emit) => {
|
|
47
51
|
const isString = typeof emit === 'string';
|
|
48
52
|
return {
|
|
49
53
|
type: isString ? emit : emit.type,
|
|
50
54
|
label: isString ? undefined : emit.label,
|
|
55
|
+
conditional: isString ? undefined : emit.conditional,
|
|
51
56
|
};
|
|
52
57
|
};
|
|
53
58
|
const createEdgesForEmits = (sourceStep, targetSteps, emits, variant) => {
|
|
54
59
|
const edges = [];
|
|
55
60
|
emits.forEach((emit) => {
|
|
56
|
-
const { type: emitType, label } = processEmit(emit);
|
|
61
|
+
const { type: emitType, label, conditional } = processEmit(emit);
|
|
57
62
|
targetSteps.forEach((targetStep) => {
|
|
58
63
|
if (targetStep.subscribes?.includes(emitType)) {
|
|
59
|
-
edges.push(createEdge(sourceStep.id, targetStep.id, emitType, label, variant));
|
|
64
|
+
edges.push(createEdge(sourceStep.id, targetStep.id, emitType, label, variant, conditional));
|
|
60
65
|
}
|
|
61
66
|
});
|
|
62
67
|
});
|
|
@@ -81,7 +86,7 @@ const createApiStepResponse = (step, id) => {
|
|
|
81
86
|
subscribes: step.config.virtualSubscribes ?? undefined,
|
|
82
87
|
action: 'webhook',
|
|
83
88
|
webhookUrl: `${step.config.method} ${step.config.path}`,
|
|
84
|
-
bodySchema: step.config.bodySchema
|
|
89
|
+
bodySchema: step.config.bodySchema ?? undefined,
|
|
85
90
|
};
|
|
86
91
|
};
|
|
87
92
|
const createEventStepResponse = (step, id) => {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { StepConfig } from './types';
|
|
2
|
-
export declare const getStepConfig: (
|
|
2
|
+
export declare const getStepConfig: (file: string) => Promise<StepConfig | null>;
|
|
@@ -1,22 +1,58 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.getStepConfig = void 0;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const isNode =
|
|
11
|
-
if (
|
|
12
|
-
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const logger_1 = require("./logger");
|
|
10
|
+
const getLanguageBasedRunner = (stepFilePath = '') => {
|
|
11
|
+
const isPython = stepFilePath.endsWith('.py');
|
|
12
|
+
const isRuby = stepFilePath.endsWith('.rb');
|
|
13
|
+
const isNode = stepFilePath.endsWith('.js') || stepFilePath.endsWith('.ts');
|
|
14
|
+
if (isPython) {
|
|
15
|
+
const pythonRunner = path_1.default.join(__dirname, 'python', 'get-config.py');
|
|
16
|
+
return { runner: pythonRunner, command: 'python', args: [] };
|
|
13
17
|
}
|
|
14
|
-
else if (
|
|
15
|
-
|
|
18
|
+
else if (isRuby) {
|
|
19
|
+
const rubyRunner = path_1.default.join(__dirname, 'ruby', 'get-config.rb');
|
|
20
|
+
return { runner: rubyRunner, command: 'ruby', args: [] };
|
|
16
21
|
}
|
|
17
22
|
else if (isNode) {
|
|
18
|
-
|
|
23
|
+
if (process.env._MOTIA_TEST_MODE === 'true') {
|
|
24
|
+
const nodeRunner = path_1.default.join(__dirname, 'node', 'get-config.ts');
|
|
25
|
+
return { runner: nodeRunner, command: 'node', args: ['-r', 'ts-node/register'] };
|
|
26
|
+
}
|
|
27
|
+
const nodeRunner = path_1.default.join(__dirname, 'node', 'get-config.js');
|
|
28
|
+
return { runner: nodeRunner, command: 'node', args: [] };
|
|
19
29
|
}
|
|
20
|
-
|
|
30
|
+
throw Error(`Unsupported file extension ${stepFilePath}`);
|
|
31
|
+
};
|
|
32
|
+
const getStepConfig = (file) => {
|
|
33
|
+
const { runner, command, args } = getLanguageBasedRunner(file);
|
|
34
|
+
return new Promise((resolve, reject) => {
|
|
35
|
+
let config = null;
|
|
36
|
+
const child = (0, child_process_1.spawn)(command, [...args, runner, file], {
|
|
37
|
+
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
|
|
38
|
+
});
|
|
39
|
+
child.on('message', (message) => {
|
|
40
|
+
logger_1.globalLogger.debug('[Config] Read config', { config: message });
|
|
41
|
+
config = message;
|
|
42
|
+
resolve(config);
|
|
43
|
+
child.kill(); // we can kill the child process since we already received the message
|
|
44
|
+
});
|
|
45
|
+
child.on('close', (code) => {
|
|
46
|
+
if (config) {
|
|
47
|
+
return; // Config was already resolved
|
|
48
|
+
}
|
|
49
|
+
else if (code !== 0) {
|
|
50
|
+
reject(new Error(`Process exited with code ${code}`));
|
|
51
|
+
}
|
|
52
|
+
else if (!config) {
|
|
53
|
+
reject(new Error(`No config found for file ${file}`));
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
});
|
|
21
57
|
};
|
|
22
58
|
exports.getStepConfig = getStepConfig;
|
package/dist/src/logger.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Server } from 'socket.io';
|
|
2
2
|
export declare class BaseLogger {
|
|
3
|
+
private readonly meta;
|
|
3
4
|
private logger;
|
|
4
5
|
constructor(meta?: Record<string, unknown>);
|
|
6
|
+
child(meta?: Record<string, unknown>): this;
|
|
5
7
|
info(message: string, args?: unknown): void;
|
|
6
8
|
error(message: string, args?: unknown): void;
|
|
7
9
|
debug(message: string, args?: unknown): void;
|
|
@@ -11,9 +13,11 @@ export declare class BaseLogger {
|
|
|
11
13
|
export declare class Logger extends BaseLogger {
|
|
12
14
|
private readonly traceId;
|
|
13
15
|
private readonly flows;
|
|
14
|
-
private readonly
|
|
16
|
+
private readonly step;
|
|
17
|
+
private readonly socketServer?;
|
|
15
18
|
private emitLog;
|
|
16
|
-
constructor(traceId: string, flows: string[] | undefined,
|
|
19
|
+
constructor(traceId: string, flows: string[] | undefined, step: string, socketServer?: Server | undefined);
|
|
20
|
+
child(meta?: Record<string, unknown>): this;
|
|
17
21
|
log(message: any): void;
|
|
18
22
|
info: (message: string, args?: unknown) => void;
|
|
19
23
|
error: (message: string, args?: unknown) => void;
|
package/dist/src/logger.js
CHANGED
|
@@ -8,6 +8,7 @@ const pino_1 = __importDefault(require("pino"));
|
|
|
8
8
|
const isDebugEnabled = () => process.env.LOG_LEVEL === 'debug';
|
|
9
9
|
class BaseLogger {
|
|
10
10
|
constructor(meta = {}) {
|
|
11
|
+
this.meta = meta;
|
|
11
12
|
this.logger = (0, pino_1.default)({
|
|
12
13
|
level: process.env.LOG_LEVEL || 'info',
|
|
13
14
|
formatters: { level: (level) => ({ level }) },
|
|
@@ -15,6 +16,9 @@ class BaseLogger {
|
|
|
15
16
|
mixin: () => meta,
|
|
16
17
|
});
|
|
17
18
|
}
|
|
19
|
+
child(meta = {}) {
|
|
20
|
+
return new BaseLogger({ ...this.meta, ...meta });
|
|
21
|
+
}
|
|
18
22
|
info(message, args) {
|
|
19
23
|
this.logger.info(args, message);
|
|
20
24
|
}
|
|
@@ -33,11 +37,12 @@ class BaseLogger {
|
|
|
33
37
|
}
|
|
34
38
|
exports.BaseLogger = BaseLogger;
|
|
35
39
|
class Logger extends BaseLogger {
|
|
36
|
-
constructor(traceId, flows,
|
|
37
|
-
super({ traceId, flows,
|
|
40
|
+
constructor(traceId, flows, step, socketServer) {
|
|
41
|
+
super({ traceId, flows, step });
|
|
38
42
|
this.traceId = traceId;
|
|
39
43
|
this.flows = flows;
|
|
40
|
-
this.
|
|
44
|
+
this.step = step;
|
|
45
|
+
this.socketServer = socketServer;
|
|
41
46
|
this.info = (message, args) => {
|
|
42
47
|
super.info(message, args);
|
|
43
48
|
this.emitLog('info', message, args);
|
|
@@ -57,11 +62,8 @@ class Logger extends BaseLogger {
|
|
|
57
62
|
this.emitLog('warn', message, args);
|
|
58
63
|
};
|
|
59
64
|
this.emitLog = (level, msg, args) => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
socketServer.emit('log', {
|
|
64
|
-
file: this.file,
|
|
65
|
+
socketServer?.emit('log', {
|
|
66
|
+
step: this.step,
|
|
65
67
|
...(args ?? {}),
|
|
66
68
|
level,
|
|
67
69
|
time: Date.now(),
|
|
@@ -71,6 +73,9 @@ class Logger extends BaseLogger {
|
|
|
71
73
|
});
|
|
72
74
|
};
|
|
73
75
|
}
|
|
76
|
+
child(meta = {}) {
|
|
77
|
+
return new Logger(this.traceId, this.flows, meta.step, this.socketServer);
|
|
78
|
+
}
|
|
74
79
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
75
80
|
log(message) {
|
|
76
81
|
console.log(JSON.stringify(message));
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const getNodeFileConfig: (filePath: string) => Promise<StepConfig>;
|
|
1
|
+
export {};
|
|
@@ -1,14 +1,45 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
+
const path_1 = __importDefault(require("path"));
|
|
7
|
+
const zod_1 = require("zod");
|
|
8
|
+
const zod_to_json_schema_1 = __importDefault(require("zod-to-json-schema"));
|
|
9
|
+
// Add ts-node registration before dynamic imports
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
11
|
+
require('ts-node').register({
|
|
12
|
+
transpileOnly: true,
|
|
13
|
+
compilerOptions: { module: 'commonjs' },
|
|
14
|
+
});
|
|
15
|
+
async function getConfig(filePath) {
|
|
6
16
|
try {
|
|
7
|
-
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
18
|
+
const module = require(path_1.default.resolve(filePath));
|
|
19
|
+
// Check if the specified function exists in the module
|
|
20
|
+
if (!module.config) {
|
|
21
|
+
throw new Error(`Config not found in module ${filePath}`);
|
|
22
|
+
}
|
|
23
|
+
if (module.config.input instanceof zod_1.ZodObject) {
|
|
24
|
+
module.config.input = (0, zod_to_json_schema_1.default)(module.config.input);
|
|
25
|
+
}
|
|
26
|
+
else if (module.config.bodySchema instanceof zod_1.ZodObject) {
|
|
27
|
+
module.config.bodySchema = (0, zod_to_json_schema_1.default)(module.config.bodySchema);
|
|
28
|
+
}
|
|
29
|
+
process.send?.(module.config);
|
|
30
|
+
process.exit(0);
|
|
8
31
|
}
|
|
9
32
|
catch (error) {
|
|
10
|
-
console.error(
|
|
11
|
-
|
|
33
|
+
console.error('Error running TypeScript module:', error);
|
|
34
|
+
process.exit(1);
|
|
12
35
|
}
|
|
13
|
-
}
|
|
14
|
-
|
|
36
|
+
}
|
|
37
|
+
const [, , filePath] = process.argv;
|
|
38
|
+
if (!filePath) {
|
|
39
|
+
console.error('Usage: node get-config.js <file-path>');
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
getConfig(filePath).catch((err) => {
|
|
43
|
+
console.error('Error:', err);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
});
|
|
@@ -2,9 +2,8 @@ import { RpcSender } from './rpc';
|
|
|
2
2
|
export declare class Logger {
|
|
3
3
|
private readonly traceId;
|
|
4
4
|
private readonly flows;
|
|
5
|
-
private readonly fileName;
|
|
6
5
|
private readonly sender;
|
|
7
|
-
constructor(traceId: string, flows: string[],
|
|
6
|
+
constructor(traceId: string, flows: string[], sender: RpcSender);
|
|
8
7
|
private _log;
|
|
9
8
|
info(message: string, args?: Record<string, unknown>): void;
|
|
10
9
|
error(message: string, args?: Record<string, unknown>): void;
|
package/dist/src/node/logger.js
CHANGED
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Logger = void 0;
|
|
4
4
|
class Logger {
|
|
5
|
-
constructor(traceId, flows,
|
|
5
|
+
constructor(traceId, flows, sender) {
|
|
6
6
|
this.traceId = traceId;
|
|
7
7
|
this.flows = flows;
|
|
8
|
-
this.fileName = fileName;
|
|
9
8
|
this.sender = sender;
|
|
10
9
|
}
|
|
11
10
|
_log(level, message, args) {
|
|
@@ -15,7 +14,6 @@ class Logger {
|
|
|
15
14
|
time: Date.now(),
|
|
16
15
|
traceId: this.traceId,
|
|
17
16
|
flows: this.flows,
|
|
18
|
-
file: this.fileName,
|
|
19
17
|
msg: message,
|
|
20
18
|
};
|
|
21
19
|
this.sender.sendNoWait('log', logEntry);
|
|
@@ -7,6 +7,8 @@ const path_1 = __importDefault(require("path"));
|
|
|
7
7
|
const logger_1 = require("./logger");
|
|
8
8
|
const rpc_state_manager_1 = require("./rpc-state-manager");
|
|
9
9
|
const rpc_1 = require("./rpc");
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
11
|
+
require('dotenv').config();
|
|
10
12
|
// Add ts-node registration before dynamic imports
|
|
11
13
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
12
14
|
require('ts-node').register({
|
|
@@ -29,15 +31,16 @@ async function runTypescriptModule(filePath, event) {
|
|
|
29
31
|
if (typeof module.handler !== 'function') {
|
|
30
32
|
throw new Error(`Function handler not found in module ${filePath}`);
|
|
31
33
|
}
|
|
32
|
-
const { traceId, flows } = event;
|
|
34
|
+
const { traceId, flows, contextInFirstArg } = event;
|
|
33
35
|
const sender = new rpc_1.RpcSender(process);
|
|
34
|
-
const logger = new logger_1.Logger(traceId, flows,
|
|
36
|
+
const logger = new logger_1.Logger(traceId, flows, sender);
|
|
35
37
|
const state = new rpc_state_manager_1.RpcStateManager(sender);
|
|
36
38
|
const emit = async (data) => sender.send('emit', data);
|
|
37
39
|
const context = { traceId, flows, logger, state, emit };
|
|
38
40
|
sender.init();
|
|
39
41
|
// Call the function with provided arguments
|
|
40
|
-
await module.handler(event.data, context);
|
|
42
|
+
const result = contextInFirstArg ? await module.handler(context) : await module.handler(event.data, context);
|
|
43
|
+
await sender.send('result', result);
|
|
41
44
|
await sender.close();
|
|
42
45
|
process.exit(0);
|
|
43
46
|
}
|
|
@@ -3,10 +3,9 @@ from typing import Any, Dict, Optional
|
|
|
3
3
|
from rpc import RpcSender
|
|
4
4
|
|
|
5
5
|
class Logger:
|
|
6
|
-
def __init__(self, trace_id: str, flows: list[str],
|
|
6
|
+
def __init__(self, trace_id: str, flows: list[str], rpc: RpcSender):
|
|
7
7
|
self.trace_id = trace_id
|
|
8
8
|
self.flows = flows
|
|
9
|
-
self.file_name = file_path.split('/')[-1]
|
|
10
9
|
self.rpc = rpc
|
|
11
10
|
|
|
12
11
|
def _log(self, level: str, message: str, args: Optional[Dict[str, Any]] = None) -> None:
|
|
@@ -15,7 +14,6 @@ class Logger:
|
|
|
15
14
|
"time": int(time.time() * 1000),
|
|
16
15
|
"traceId": self.trace_id,
|
|
17
16
|
"flows": self.flows,
|
|
18
|
-
"file": self.file_name,
|
|
19
17
|
"msg": message
|
|
20
18
|
}
|
|
21
19
|
|
|
@@ -20,13 +20,13 @@ def parse_args(arg: str) -> Any:
|
|
|
20
20
|
return arg
|
|
21
21
|
|
|
22
22
|
class Context:
|
|
23
|
-
def __init__(self, args: Any, rpc: RpcSender
|
|
23
|
+
def __init__(self, args: Any, rpc: RpcSender):
|
|
24
24
|
self.trace_id = args.traceId
|
|
25
|
+
self.traceId = args.traceId
|
|
25
26
|
self.flows = args.flows
|
|
26
|
-
self.file_name = file_name
|
|
27
27
|
self.rpc = rpc
|
|
28
28
|
self.state = RpcStateManager(rpc)
|
|
29
|
-
self.logger = Logger(self.trace_id, self.flows,
|
|
29
|
+
self.logger = Logger(self.trace_id, self.flows, rpc)
|
|
30
30
|
|
|
31
31
|
async def emit(self, event: Any):
|
|
32
32
|
return await self.rpc.send('emit', event)
|
|
@@ -36,6 +36,7 @@ async def run_python_module(file_path: str, rpc: RpcSender, args: Any) -> None:
|
|
|
36
36
|
# Construct path relative to steps directory
|
|
37
37
|
flows_dir = os.path.join(os.getcwd(), 'steps')
|
|
38
38
|
module_path = os.path.join(flows_dir, file_path)
|
|
39
|
+
contextInFirstArg = args.contextInFirstArg
|
|
39
40
|
|
|
40
41
|
# Load the module dynamically
|
|
41
42
|
spec = importlib.util.spec_from_file_location("dynamic_module", module_path)
|
|
@@ -49,9 +50,15 @@ async def run_python_module(file_path: str, rpc: RpcSender, args: Any) -> None:
|
|
|
49
50
|
if not hasattr(module, 'handler'):
|
|
50
51
|
raise AttributeError(f"Function 'handler' not found in module {module_path}")
|
|
51
52
|
|
|
52
|
-
context = Context(args, rpc
|
|
53
|
+
context = Context(args, rpc)
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
if contextInFirstArg:
|
|
56
|
+
result = await module.handler(context)
|
|
57
|
+
else:
|
|
58
|
+
result = await module.handler(args.data, context)
|
|
59
|
+
|
|
60
|
+
if (result):
|
|
61
|
+
await rpc.send('result', result)
|
|
55
62
|
|
|
56
63
|
rpc.close()
|
|
57
64
|
|
|
@@ -10,8 +10,7 @@ def send_message(message)
|
|
|
10
10
|
io.write(json_message)
|
|
11
11
|
io.flush
|
|
12
12
|
rescue Errno::EBADF => e
|
|
13
|
-
|
|
14
|
-
exit(1)
|
|
13
|
+
raise "Error writing to IPC channel: #{e.message}"
|
|
15
14
|
ensure
|
|
16
15
|
io.close if io && !io.closed?
|
|
17
16
|
end
|
|
@@ -41,20 +40,17 @@ end
|
|
|
41
40
|
# Main execution block
|
|
42
41
|
begin
|
|
43
42
|
if ARGV.empty?
|
|
44
|
-
|
|
45
|
-
exit(1)
|
|
43
|
+
raise 'Error: No file path provided'
|
|
46
44
|
end
|
|
47
45
|
|
|
48
46
|
file_path = ARGV[0]
|
|
49
47
|
|
|
50
48
|
unless File.exist?(file_path)
|
|
51
|
-
|
|
52
|
-
exit(1)
|
|
49
|
+
raise "Error: File not found: #{file_path}"
|
|
53
50
|
end
|
|
54
51
|
|
|
55
52
|
unless File.readable?(file_path)
|
|
56
|
-
|
|
57
|
-
exit(1)
|
|
53
|
+
raise "Error: File is not readable: #{file_path}"
|
|
58
54
|
end
|
|
59
55
|
|
|
60
56
|
# Extract and send config
|
|
@@ -62,7 +58,4 @@ begin
|
|
|
62
58
|
send_message(config)
|
|
63
59
|
|
|
64
60
|
exit(0)
|
|
65
|
-
rescue => e
|
|
66
|
-
warn "Error: #{e.message}"
|
|
67
|
-
exit(1)
|
|
68
61
|
end
|
package/dist/src/ruby/logger.rb
CHANGED
|
@@ -2,10 +2,9 @@ require 'json'
|
|
|
2
2
|
require 'time'
|
|
3
3
|
|
|
4
4
|
class CustomLogger
|
|
5
|
-
def initialize(trace_id, flows,
|
|
5
|
+
def initialize(trace_id, flows, sender)
|
|
6
6
|
@trace_id = trace_id
|
|
7
7
|
@flows = flows
|
|
8
|
-
@file_name = file_path.split('/').last
|
|
9
8
|
@sender = sender
|
|
10
9
|
end
|
|
11
10
|
|
|
@@ -25,7 +24,6 @@ class CustomLogger
|
|
|
25
24
|
time: (Time.now.to_f * 1000).to_i, # Milliseconds since epoch to match Node
|
|
26
25
|
traceId: @trace_id,
|
|
27
26
|
flows: @flows,
|
|
28
|
-
file: @file_name,
|
|
29
27
|
msg: message
|
|
30
28
|
}
|
|
31
29
|
|
|
@@ -16,7 +16,7 @@ def parse_args(arg)
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
class Context
|
|
19
|
-
attr_reader :trace_id, :flows, :file_name, :state, :logger
|
|
19
|
+
attr_reader :trace_id, :traceId, :flows, :file_name, :state, :logger
|
|
20
20
|
|
|
21
21
|
def emit(event)
|
|
22
22
|
# Add type field if not present to match Node.js/Python behavior
|
|
@@ -25,13 +25,13 @@ class Context
|
|
|
25
25
|
promise # Return promise to maintain async pattern
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
def initialize(rpc, args
|
|
28
|
+
def initialize(rpc, args)
|
|
29
29
|
@rpc = rpc
|
|
30
30
|
@trace_id = args.traceId
|
|
31
|
+
@traceId = args.traceId
|
|
31
32
|
@flows = args.flows
|
|
32
|
-
@file_name = file_path.split('/').last # Consistent with Python/Node
|
|
33
33
|
@state = RpcStateManager.new(rpc)
|
|
34
|
-
@logger = CustomLogger.new(@trace_id, @flows, @
|
|
34
|
+
@logger = CustomLogger.new(@trace_id, @flows, @rpc)
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
@@ -50,15 +50,18 @@ def run_ruby_module(file_path, args)
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
rpc = RpcSender.new
|
|
53
|
-
context = Context.new(rpc, args
|
|
53
|
+
context = Context.new(rpc, args)
|
|
54
54
|
rpc.init
|
|
55
55
|
|
|
56
56
|
# Call handler and wait for any promises
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
if args.contextInFirstArg
|
|
58
|
+
result = handler(context)
|
|
59
|
+
else
|
|
60
|
+
result = handler(args.data, context)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
if result
|
|
64
|
+
rpc.send('result', result)
|
|
62
65
|
end
|
|
63
66
|
|
|
64
67
|
rescue => e
|
package/dist/src/server.js
CHANGED
|
@@ -13,36 +13,43 @@ const socket_io_1 = require("socket.io");
|
|
|
13
13
|
const flows_endpoint_1 = require("./flows-endpoint");
|
|
14
14
|
const guards_1 = require("./guards");
|
|
15
15
|
const logger_1 = require("./logger");
|
|
16
|
-
const get_module_export_1 = require("./node/get-module-export");
|
|
17
16
|
const steps_1 = require("./steps");
|
|
18
|
-
const
|
|
17
|
+
const call_step_file_1 = require("./call-step-file");
|
|
19
18
|
const createServer = async (lockedData, eventManager, state) => {
|
|
19
|
+
const printer = lockedData.printer;
|
|
20
20
|
const app = (0, express_1.default)();
|
|
21
21
|
const server = http_1.default.createServer(app);
|
|
22
22
|
const io = new socket_io_1.Server(server);
|
|
23
23
|
const allSteps = [...steps_1.systemSteps, ...lockedData.activeSteps];
|
|
24
|
-
const cronManager = (0, cron_handler_1.setupCronHandlers)(lockedData, eventManager, io);
|
|
25
|
-
const asyncHandler = (step
|
|
24
|
+
const cronManager = (0, cron_handler_1.setupCronHandlers)(lockedData, eventManager, state, io);
|
|
25
|
+
const asyncHandler = (step) => {
|
|
26
26
|
return async (req, res) => {
|
|
27
27
|
const traceId = (0, crypto_1.randomUUID)();
|
|
28
|
-
const
|
|
29
|
-
logger.
|
|
30
|
-
|
|
28
|
+
const { name, flows } = step.config;
|
|
29
|
+
const logger = new logger_1.Logger(traceId, flows, name, io);
|
|
30
|
+
logger.debug('[API] Received request, processing step', { path: req.path });
|
|
31
31
|
const request = {
|
|
32
32
|
body: req.body,
|
|
33
33
|
headers: req.headers,
|
|
34
34
|
pathParams: req.params,
|
|
35
35
|
queryParams: req.query,
|
|
36
36
|
};
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
try {
|
|
38
|
+
const data = request;
|
|
39
|
+
const result = await (0, call_step_file_1.callStepFile)({
|
|
40
|
+
contextInFirstArg: false,
|
|
41
|
+
data,
|
|
42
|
+
step,
|
|
43
|
+
printer,
|
|
44
|
+
logger,
|
|
45
|
+
eventManager,
|
|
46
|
+
state,
|
|
47
|
+
traceId,
|
|
48
|
+
});
|
|
49
|
+
if (!result) {
|
|
50
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
40
51
|
return;
|
|
41
52
|
}
|
|
42
|
-
await eventManager.emit({ data, type, traceId, flows, logger }, step.filePath);
|
|
43
|
-
};
|
|
44
|
-
try {
|
|
45
|
-
const result = await handler(request, { emit, state, logger, traceId });
|
|
46
53
|
if (result.headers) {
|
|
47
54
|
Object.entries(result.headers).forEach(([key, value]) => res.setHeader(key, value));
|
|
48
55
|
}
|
|
@@ -60,13 +67,13 @@ const createServer = async (lockedData, eventManager, state) => {
|
|
|
60
67
|
app.use(body_parser_1.default.urlencoded({ extended: true }));
|
|
61
68
|
const router = express_1.default.Router();
|
|
62
69
|
const addRoute = (step) => {
|
|
63
|
-
const { method,
|
|
70
|
+
const { method, path } = step.config;
|
|
64
71
|
logger_1.globalLogger.debug('[API] Registering route', step.config);
|
|
65
72
|
if (method === 'POST') {
|
|
66
|
-
router.post(path, asyncHandler(step
|
|
73
|
+
router.post(path, asyncHandler(step));
|
|
67
74
|
}
|
|
68
75
|
else if (method === 'GET') {
|
|
69
|
-
router.get(path, asyncHandler(step
|
|
76
|
+
router.get(path, asyncHandler(step));
|
|
70
77
|
}
|
|
71
78
|
else {
|
|
72
79
|
throw new Error(`Unsupported method: ${method}`);
|
|
@@ -5,10 +5,16 @@ const logger_1 = require("./logger");
|
|
|
5
5
|
const call_step_file_1 = require("./call-step-file");
|
|
6
6
|
const createStepHandlers = (lockedData, eventManager, state) => {
|
|
7
7
|
const eventSteps = lockedData.eventSteps();
|
|
8
|
+
const printer = lockedData.printer;
|
|
8
9
|
logger_1.globalLogger.debug(`[step handler] creating step handlers for ${eventSteps.length} steps`);
|
|
10
|
+
const removeLogger = (event) => {
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
12
|
+
const { logger, ...rest } = event;
|
|
13
|
+
return rest;
|
|
14
|
+
};
|
|
9
15
|
const createHandler = (step) => {
|
|
10
16
|
const { config, filePath } = step;
|
|
11
|
-
const { subscribes } = config;
|
|
17
|
+
const { subscribes, name } = config;
|
|
12
18
|
logger_1.globalLogger.debug('[step handler] establishing step subscriptions', { filePath, step: step.config.name });
|
|
13
19
|
subscribes.forEach((subscribe) => {
|
|
14
20
|
eventManager.subscribe({
|
|
@@ -16,18 +22,26 @@ const createStepHandlers = (lockedData, eventManager, state) => {
|
|
|
16
22
|
event: subscribe,
|
|
17
23
|
handlerName: step.config.name,
|
|
18
24
|
handler: async (event) => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
logger_1.globalLogger.debug('[step handler] received event', { event: rest, step: step.config.name });
|
|
25
|
+
const { logger, data, traceId } = event;
|
|
26
|
+
logger_1.globalLogger.debug('[step handler] received event', { event: removeLogger(event), step: name });
|
|
22
27
|
try {
|
|
23
|
-
await (0, call_step_file_1.callStepFile)(
|
|
28
|
+
await (0, call_step_file_1.callStepFile)({
|
|
29
|
+
contextInFirstArg: false,
|
|
30
|
+
step,
|
|
31
|
+
printer,
|
|
32
|
+
eventManager,
|
|
33
|
+
state,
|
|
34
|
+
data,
|
|
35
|
+
traceId,
|
|
36
|
+
logger,
|
|
37
|
+
});
|
|
24
38
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
39
|
}
|
|
26
40
|
catch (error) {
|
|
27
41
|
logger_1.globalLogger.error(`[step handler] error calling step`, {
|
|
28
42
|
error: error.message,
|
|
29
43
|
filePath,
|
|
30
|
-
step:
|
|
44
|
+
step: name,
|
|
31
45
|
});
|
|
32
46
|
}
|
|
33
47
|
},
|
|
@@ -2,6 +2,39 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.validateStep = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
+
const jsonSchema = zod_1.z.object({
|
|
6
|
+
type: zod_1.z.string(),
|
|
7
|
+
properties: zod_1.z.record(zod_1.z.any()),
|
|
8
|
+
required: zod_1.z.array(zod_1.z.string()).optional(),
|
|
9
|
+
additionalProperties: zod_1.z.boolean().optional(),
|
|
10
|
+
description: zod_1.z.string().optional(),
|
|
11
|
+
title: zod_1.z.string().optional(),
|
|
12
|
+
definitions: zod_1.z.record(zod_1.z.any()).optional(),
|
|
13
|
+
$ref: zod_1.z.string().optional(),
|
|
14
|
+
items: zod_1.z.any().optional(),
|
|
15
|
+
enum: zod_1.z.array(zod_1.z.any()).optional(),
|
|
16
|
+
allOf: zod_1.z.array(zod_1.z.any()).optional(),
|
|
17
|
+
anyOf: zod_1.z.array(zod_1.z.any()).optional(),
|
|
18
|
+
oneOf: zod_1.z.array(zod_1.z.any()).optional(),
|
|
19
|
+
not: zod_1.z.any().optional(),
|
|
20
|
+
format: zod_1.z.string().optional(),
|
|
21
|
+
default: zod_1.z.any().optional(),
|
|
22
|
+
examples: zod_1.z.array(zod_1.z.any()).optional(),
|
|
23
|
+
multipleOf: zod_1.z.number().optional(),
|
|
24
|
+
maximum: zod_1.z.number().optional(),
|
|
25
|
+
exclusiveMaximum: zod_1.z.union([zod_1.z.boolean(), zod_1.z.number()]).optional(),
|
|
26
|
+
minimum: zod_1.z.number().optional(),
|
|
27
|
+
exclusiveMinimum: zod_1.z.union([zod_1.z.boolean(), zod_1.z.number()]).optional(),
|
|
28
|
+
maxLength: zod_1.z.number().optional(),
|
|
29
|
+
minLength: zod_1.z.number().optional(),
|
|
30
|
+
pattern: zod_1.z.string().optional(),
|
|
31
|
+
maxItems: zod_1.z.number().optional(),
|
|
32
|
+
minItems: zod_1.z.number().optional(),
|
|
33
|
+
uniqueItems: zod_1.z.boolean().optional(),
|
|
34
|
+
maxProperties: zod_1.z.number().optional(),
|
|
35
|
+
minProperties: zod_1.z.number().optional(),
|
|
36
|
+
const: zod_1.z.any().optional(),
|
|
37
|
+
});
|
|
5
38
|
const emits = zod_1.z.array(zod_1.z.union([
|
|
6
39
|
zod_1.z.string(),
|
|
7
40
|
zod_1.z
|
|
@@ -30,7 +63,7 @@ const eventSchema = zod_1.z
|
|
|
30
63
|
subscribes: zod_1.z.array(zod_1.z.string()),
|
|
31
64
|
emits: emits,
|
|
32
65
|
virtualEmits: emits.optional(),
|
|
33
|
-
input: zod_1.z.
|
|
66
|
+
input: zod_1.z.union([jsonSchema, zod_1.z.null()]).optional(),
|
|
34
67
|
flows: zod_1.z.array(zod_1.z.string()).optional(),
|
|
35
68
|
})
|
|
36
69
|
.strict();
|
|
@@ -45,7 +78,7 @@ const apiSchema = zod_1.z
|
|
|
45
78
|
virtualEmits: emits.optional(),
|
|
46
79
|
virtualSubscribes: zod_1.z.array(zod_1.z.string()).optional(),
|
|
47
80
|
flows: zod_1.z.array(zod_1.z.string()).optional(),
|
|
48
|
-
bodySchema: zod_1.z.
|
|
81
|
+
bodySchema: zod_1.z.union([jsonSchema, zod_1.z.null()]).optional(),
|
|
49
82
|
})
|
|
50
83
|
.strict();
|
|
51
84
|
const cronSchema = zod_1.z
|
package/dist/src/types.d.ts
CHANGED
|
@@ -75,7 +75,8 @@ export type CronConfig = {
|
|
|
75
75
|
emits: Emit[];
|
|
76
76
|
flows?: string[];
|
|
77
77
|
};
|
|
78
|
-
export type
|
|
78
|
+
export type CronHandler = (ctx: FlowContext) => Promise<void>;
|
|
79
|
+
export type StepHandler<T> = T extends EventConfig<any> ? EventHandler<T['input']> : T extends ApiRouteConfig ? ApiRouteHandler : T extends CronConfig ? CronHandler : never;
|
|
79
80
|
export type Event<TData = unknown> = {
|
|
80
81
|
type: string;
|
|
81
82
|
data: TData;
|
package/dist/src/utils.js
CHANGED
|
@@ -10,6 +10,9 @@ const isAllowedToEmit = (step, emit) => {
|
|
|
10
10
|
if ((0, guards_1.isEventStep)(step)) {
|
|
11
11
|
return step.config.emits.map(toType).includes(emit);
|
|
12
12
|
}
|
|
13
|
+
if ((0, guards_1.isCronStep)(step)) {
|
|
14
|
+
return step.config.emits.map(toType).includes(emit);
|
|
15
|
+
}
|
|
13
16
|
return false;
|
|
14
17
|
};
|
|
15
18
|
exports.isAllowedToEmit = isAllowedToEmit;
|
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.24",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"body-parser": "^1.20.3",
|
|
7
7
|
"colors": "^1.4.0",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"typescript": "^5.7.2"
|
|
28
28
|
},
|
|
29
29
|
"scripts": {
|
|
30
|
-
"move:python": "cp src/python/*.py dist/src/python",
|
|
31
|
-
"move:rb": "cp src/ruby/*.rb dist/src/ruby",
|
|
30
|
+
"move:python": "mkdir -p dist/src/python && cp src/python/*.py dist/src/python",
|
|
31
|
+
"move:rb": "mkdir -p dist/src/ruby && cp src/ruby/*.rb dist/src/ruby",
|
|
32
32
|
"move:steps": "cp src/steps/*.ts dist/src/steps",
|
|
33
33
|
"build": "rm -rf dist && tsc && npm run move:python && npm run move:rb && npm run move:steps",
|
|
34
34
|
"lint": "eslint --config ../../eslint.config.js",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const getModuleExport: (filePath: string, exportName: string) => Promise<any>;
|
|
@@ -1,68 +0,0 @@
|
|
|
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
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
49
|
-
require('ts-node').register({
|
|
50
|
-
transpileOnly: true,
|
|
51
|
-
compilerOptions: { module: 'commonjs', baseUrl: absoluteBaseUrl, paths },
|
|
52
|
-
});
|
|
53
|
-
const getModuleExport = async (filePath, exportName) => {
|
|
54
|
-
try {
|
|
55
|
-
const resolvedFilePath = require.resolve(filePath);
|
|
56
|
-
if (resolvedFilePath in require.cache) {
|
|
57
|
-
delete require.cache[resolvedFilePath];
|
|
58
|
-
}
|
|
59
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
60
|
-
const module = require(resolvedFilePath);
|
|
61
|
-
return module[exportName];
|
|
62
|
-
}
|
|
63
|
-
catch (error) {
|
|
64
|
-
console.error(`Failed to extract ${exportName} from`, error);
|
|
65
|
-
return undefined;
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
exports.getModuleExport = getModuleExport;
|
|
@@ -1,34 +0,0 @@
|
|
|
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.getPythonConfig = void 0;
|
|
7
|
-
const child_process_1 = require("child_process");
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const logger_1 = require("../logger");
|
|
10
|
-
const getPythonConfig = (file) => {
|
|
11
|
-
const getConfig = path_1.default.join(__dirname, 'get-config.py');
|
|
12
|
-
return new Promise((resolve, reject) => {
|
|
13
|
-
let config = null;
|
|
14
|
-
const child = (0, child_process_1.spawn)('python', [getConfig, file], {
|
|
15
|
-
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
|
|
16
|
-
});
|
|
17
|
-
child.on('message', (message) => {
|
|
18
|
-
logger_1.globalLogger.debug('[Python Config] Read config', { config: message });
|
|
19
|
-
config = message;
|
|
20
|
-
});
|
|
21
|
-
child.on('close', (code) => {
|
|
22
|
-
if (code !== 0) {
|
|
23
|
-
reject(new Error(`Process exited with code ${code}`));
|
|
24
|
-
}
|
|
25
|
-
else if (!config) {
|
|
26
|
-
reject(new Error(`No config found for file ${file}`));
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
resolve(config);
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
};
|
|
34
|
-
exports.getPythonConfig = getPythonConfig;
|