@motiadev/core 0.0.28 → 0.0.30
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/LICENSE +21 -0
- package/dist/src/LoggerFactory.d.ts +14 -0
- package/dist/src/LoggerFactory.js +14 -0
- package/dist/src/call-step-file.js +11 -3
- package/dist/src/cron-handler.d.ts +2 -2
- package/dist/src/cron-handler.js +5 -5
- package/dist/src/event-manager.js +1 -1
- package/dist/src/flows-endpoint.d.ts +1 -1
- package/dist/src/flows-endpoint.js +6 -6
- package/dist/src/generate-trace-id.d.ts +2 -0
- package/dist/src/generate-trace-id.js +14 -0
- package/dist/src/get-step-config.js +10 -2
- package/dist/src/locked-data.d.ts +4 -1
- package/dist/src/locked-data.js +11 -0
- package/dist/src/logger.d.ts +5 -4
- package/dist/src/logger.js +31 -24
- package/dist/src/pretty-print.d.ts +1 -0
- package/dist/src/pretty-print.js +66 -0
- package/dist/src/printer.d.ts +22 -3
- package/dist/src/printer.js +25 -1
- package/dist/src/python/get-config.py +21 -5
- package/dist/src/python/python-runner.py +22 -15
- package/dist/src/server.d.ts +5 -1
- package/dist/src/server.js +8 -6
- package/dist/src/step-handlers.js +2 -5
- package/dist/src/step-validator.js +1 -1
- package/dist/src/steps/emit.step.js +5 -5
- package/dist/src/steps/emit.step.ts +5 -5
- package/dist/src/types.d.ts +3 -3
- package/dist/src/utils.js +4 -4
- package/package.json +1 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Motia
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Server } from 'socket.io';
|
|
2
|
+
import { Logger } from './logger';
|
|
3
|
+
type CreateLogger = {
|
|
4
|
+
traceId: string;
|
|
5
|
+
flows?: string[];
|
|
6
|
+
stepName: string;
|
|
7
|
+
};
|
|
8
|
+
export declare class LoggerFactory {
|
|
9
|
+
private readonly isVerbose;
|
|
10
|
+
private readonly socketServer;
|
|
11
|
+
constructor(isVerbose: boolean, socketServer: Server);
|
|
12
|
+
create({ stepName, traceId, flows }: CreateLogger): Logger;
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LoggerFactory = void 0;
|
|
4
|
+
const logger_1 = require("./logger");
|
|
5
|
+
class LoggerFactory {
|
|
6
|
+
constructor(isVerbose, socketServer) {
|
|
7
|
+
this.isVerbose = isVerbose;
|
|
8
|
+
this.socketServer = socketServer;
|
|
9
|
+
}
|
|
10
|
+
create({ stepName, traceId, flows }) {
|
|
11
|
+
return new logger_1.Logger(traceId, flows, stepName, this.isVerbose, this.socketServer);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.LoggerFactory = LoggerFactory;
|
|
@@ -52,8 +52,8 @@ const callStepFile = (options) => {
|
|
|
52
52
|
result = input;
|
|
53
53
|
});
|
|
54
54
|
rpcProcessor.handler('emit', async (input) => {
|
|
55
|
-
if (!(0, utils_1.isAllowedToEmit)(step, input.
|
|
56
|
-
return printer.printInvalidEmit(step, input.
|
|
55
|
+
if (!(0, utils_1.isAllowedToEmit)(step, input.topic)) {
|
|
56
|
+
return printer.printInvalidEmit(step, input.topic);
|
|
57
57
|
}
|
|
58
58
|
return eventManager.emit({ ...input, traceId, flows: step.config.flows, logger }, step.filePath);
|
|
59
59
|
});
|
|
@@ -70,12 +70,20 @@ const callStepFile = (options) => {
|
|
|
70
70
|
child.stderr?.on('data', (data) => logger.error(Buffer.from(data).toString()));
|
|
71
71
|
child.on('close', (code) => {
|
|
72
72
|
if (code !== 0 && code !== null) {
|
|
73
|
-
reject(
|
|
73
|
+
reject(`Process exited with code ${code}`);
|
|
74
74
|
}
|
|
75
75
|
else {
|
|
76
76
|
resolve(result);
|
|
77
77
|
}
|
|
78
78
|
});
|
|
79
|
+
child.on('error', (error) => {
|
|
80
|
+
if (error.code === 'ENOENT') {
|
|
81
|
+
reject(`Executable ${command} not found`);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
reject(error);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
79
87
|
});
|
|
80
88
|
};
|
|
81
89
|
exports.callStepFile = callStepFile;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { Server } from 'socket.io';
|
|
2
1
|
import { LockedData } from './locked-data';
|
|
3
2
|
import { StateAdapter } from './state/state-adapter';
|
|
4
3
|
import { CronConfig, EventManager, Step } from './types';
|
|
4
|
+
import { LoggerFactory } from './LoggerFactory';
|
|
5
5
|
export type CronManager = {
|
|
6
6
|
createCronJob: (step: Step<CronConfig>) => void;
|
|
7
7
|
removeCronJob: (step: Step<CronConfig>) => void;
|
|
8
8
|
close: () => void;
|
|
9
9
|
};
|
|
10
|
-
export declare const setupCronHandlers: (lockedData: LockedData, eventManager: EventManager, state: StateAdapter,
|
|
10
|
+
export declare const setupCronHandlers: (lockedData: LockedData, eventManager: EventManager, state: StateAdapter, loggerFactory: LoggerFactory) => {
|
|
11
11
|
createCronJob: (step: Step<CronConfig>) => void;
|
|
12
12
|
removeCronJob: (step: Step<CronConfig>) => void;
|
|
13
13
|
close: () => void;
|
package/dist/src/cron-handler.js
CHANGED
|
@@ -34,16 +34,16 @@ 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");
|
|
38
37
|
const cron = __importStar(require("node-cron"));
|
|
39
38
|
const call_step_file_1 = require("./call-step-file");
|
|
40
39
|
const logger_1 = require("./logger");
|
|
41
|
-
const
|
|
40
|
+
const generate_trace_id_1 = require("./generate-trace-id");
|
|
41
|
+
const setupCronHandlers = (lockedData, eventManager, state, loggerFactory) => {
|
|
42
42
|
const cronJobs = new Map();
|
|
43
43
|
const printer = lockedData.printer;
|
|
44
44
|
const createCronJob = (step) => {
|
|
45
45
|
const { config, filePath } = step;
|
|
46
|
-
const { cron: cronExpression, name: stepName } = config;
|
|
46
|
+
const { cron: cronExpression, name: stepName, flows } = config;
|
|
47
47
|
if (!cron.validate(cronExpression)) {
|
|
48
48
|
logger_1.globalLogger.error('[cron handler] invalid cron expression', {
|
|
49
49
|
expression: cronExpression,
|
|
@@ -57,8 +57,8 @@ const setupCronHandlers = (lockedData, eventManager, state, socketServer) => {
|
|
|
57
57
|
cron: cronExpression,
|
|
58
58
|
});
|
|
59
59
|
const task = cron.schedule(cronExpression, async () => {
|
|
60
|
-
const traceId = (0,
|
|
61
|
-
const logger =
|
|
60
|
+
const traceId = (0, generate_trace_id_1.generateTraceId)();
|
|
61
|
+
const logger = loggerFactory.create({ traceId, flows, stepName });
|
|
62
62
|
try {
|
|
63
63
|
await (0, call_step_file_1.callStepFile)({
|
|
64
64
|
contextInFirstArg: true,
|
|
@@ -5,7 +5,7 @@ const logger_1 = require("./logger");
|
|
|
5
5
|
const createEventManager = () => {
|
|
6
6
|
const handlers = {};
|
|
7
7
|
const emit = async (event, file) => {
|
|
8
|
-
const eventHandlers = handlers[event.
|
|
8
|
+
const eventHandlers = handlers[event.topic] ?? [];
|
|
9
9
|
const { logger, ...rest } = event;
|
|
10
10
|
logger.debug('[Flow Emit] Event emitted', { handlers: eventHandlers.length, data: rest, file });
|
|
11
11
|
eventHandlers.map((eventHandler) => eventHandler.handler(event));
|
|
@@ -36,21 +36,21 @@ const getNodeComponentPath = (filePath) => {
|
|
|
36
36
|
const tsxPath = filePathWithoutExtension + '.tsx';
|
|
37
37
|
return fs_1.default.existsSync(tsxPath) ? tsxPath : undefined;
|
|
38
38
|
};
|
|
39
|
-
const createEdge = (sourceId, targetId,
|
|
39
|
+
const createEdge = (sourceId, targetId, topic, label, variant, conditional) => ({
|
|
40
40
|
id: `${sourceId}-${targetId}`,
|
|
41
41
|
source: sourceId,
|
|
42
42
|
target: targetId,
|
|
43
43
|
data: {
|
|
44
44
|
variant,
|
|
45
45
|
label,
|
|
46
|
-
|
|
46
|
+
topic,
|
|
47
47
|
labelVariant: conditional ? 'conditional' : 'default',
|
|
48
48
|
},
|
|
49
49
|
});
|
|
50
50
|
const processEmit = (emit) => {
|
|
51
51
|
const isString = typeof emit === 'string';
|
|
52
52
|
return {
|
|
53
|
-
|
|
53
|
+
topic: isString ? emit : emit.topic,
|
|
54
54
|
label: isString ? undefined : emit.label,
|
|
55
55
|
conditional: isString ? undefined : emit.conditional,
|
|
56
56
|
};
|
|
@@ -58,10 +58,10 @@ const processEmit = (emit) => {
|
|
|
58
58
|
const createEdgesForEmits = (sourceStep, targetSteps, emits, variant) => {
|
|
59
59
|
const edges = [];
|
|
60
60
|
emits.forEach((emit) => {
|
|
61
|
-
const {
|
|
61
|
+
const { topic, label, conditional } = processEmit(emit);
|
|
62
62
|
targetSteps.forEach((targetStep) => {
|
|
63
|
-
if (targetStep.subscribes?.includes(
|
|
64
|
-
edges.push(createEdge(sourceStep.id, targetStep.id,
|
|
63
|
+
if (targetStep.subscribes?.includes(topic)) {
|
|
64
|
+
edges.push(createEdge(sourceStep.id, targetStep.id, topic, label, variant, conditional));
|
|
65
65
|
}
|
|
66
66
|
});
|
|
67
67
|
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateTraceId = exports.generateCode = void 0;
|
|
4
|
+
const generateCode = (length = 6) => {
|
|
5
|
+
const chars = 'ABCDEFGHJKMNPQRSTUVWXYZ123456789';
|
|
6
|
+
return Array.from({ length }, () => chars[Math.floor(Math.random() * chars.length)]).join('');
|
|
7
|
+
};
|
|
8
|
+
exports.generateCode = generateCode;
|
|
9
|
+
const generateTraceId = () => {
|
|
10
|
+
const datePart = String(Date.now()).slice(6);
|
|
11
|
+
const randomPart = (0, exports.generateCode)(5);
|
|
12
|
+
return `${randomPart}-${datePart}`;
|
|
13
|
+
};
|
|
14
|
+
exports.generateTraceId = generateTraceId;
|
|
@@ -47,10 +47,18 @@ const getStepConfig = (file) => {
|
|
|
47
47
|
return; // Config was already resolved
|
|
48
48
|
}
|
|
49
49
|
else if (code !== 0) {
|
|
50
|
-
reject(
|
|
50
|
+
reject(`Process exited with code ${code}`);
|
|
51
51
|
}
|
|
52
52
|
else if (!config) {
|
|
53
|
-
reject(
|
|
53
|
+
reject(`No config found for file ${file}`);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
child.on('error', (error) => {
|
|
57
|
+
if (error.code === 'ENOENT') {
|
|
58
|
+
reject(`Executable ${command} not found`);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
reject(error);
|
|
54
62
|
}
|
|
55
63
|
});
|
|
56
64
|
});
|
|
@@ -2,16 +2,19 @@ import { ZodObject } from 'zod';
|
|
|
2
2
|
import { ApiRouteConfig, CronConfig, EventConfig, Flow, Step } from './types';
|
|
3
3
|
import { Printer } from './printer';
|
|
4
4
|
type FlowEvent = 'flow-created' | 'flow-removed' | 'flow-updated';
|
|
5
|
+
type StepEvent = 'step-created' | 'step-removed' | 'step-updated';
|
|
5
6
|
export declare class LockedData {
|
|
6
7
|
readonly baseDir: string;
|
|
7
8
|
flows: Record<string, Flow>;
|
|
8
9
|
activeSteps: Step[];
|
|
9
10
|
devSteps: Step[];
|
|
10
|
-
|
|
11
|
+
printer: Printer;
|
|
11
12
|
private stepsMap;
|
|
12
13
|
private handlers;
|
|
14
|
+
private stepHandlers;
|
|
13
15
|
constructor(baseDir: string);
|
|
14
16
|
on(event: FlowEvent, handler: (flowName: string) => void): void;
|
|
17
|
+
onStep(event: StepEvent, handler: (step: Step) => void): void;
|
|
15
18
|
eventSteps(): Step<EventConfig<ZodObject<any>>>[];
|
|
16
19
|
apiSteps(): Step<ApiRouteConfig>[];
|
|
17
20
|
cronSteps(): Step<CronConfig>[];
|
package/dist/src/locked-data.js
CHANGED
|
@@ -17,10 +17,18 @@ class LockedData {
|
|
|
17
17
|
'flow-removed': [],
|
|
18
18
|
'flow-updated': [],
|
|
19
19
|
};
|
|
20
|
+
this.stepHandlers = {
|
|
21
|
+
'step-created': [],
|
|
22
|
+
'step-removed': [],
|
|
23
|
+
'step-updated': [],
|
|
24
|
+
};
|
|
20
25
|
}
|
|
21
26
|
on(event, handler) {
|
|
22
27
|
this.handlers[event].push(handler);
|
|
23
28
|
}
|
|
29
|
+
onStep(event, handler) {
|
|
30
|
+
this.stepHandlers[event].push(handler);
|
|
31
|
+
}
|
|
24
32
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
33
|
eventSteps() {
|
|
26
34
|
return this.activeSteps.filter(guards_1.isEventStep);
|
|
@@ -72,6 +80,7 @@ class LockedData {
|
|
|
72
80
|
}
|
|
73
81
|
}
|
|
74
82
|
savedStep.config = newStep.config;
|
|
83
|
+
this.stepHandlers['step-updated'].forEach((handler) => handler(newStep));
|
|
75
84
|
this.printer.printStepUpdated(newStep);
|
|
76
85
|
return true;
|
|
77
86
|
}
|
|
@@ -96,6 +105,7 @@ class LockedData {
|
|
|
96
105
|
this.onFlowUpdated(flowName);
|
|
97
106
|
}
|
|
98
107
|
}
|
|
108
|
+
this.stepHandlers['step-created'].forEach((handler) => handler(step));
|
|
99
109
|
this.printer.printStepCreated(step);
|
|
100
110
|
return true;
|
|
101
111
|
}
|
|
@@ -116,6 +126,7 @@ class LockedData {
|
|
|
116
126
|
this.onFlowUpdated(flowName);
|
|
117
127
|
}
|
|
118
128
|
}
|
|
129
|
+
this.stepHandlers['step-removed'].forEach((handler) => handler(step));
|
|
119
130
|
this.printer.printStepRemoved(step);
|
|
120
131
|
}
|
|
121
132
|
createFlow(flowName) {
|
package/dist/src/logger.d.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { Server } from 'socket.io';
|
|
2
2
|
export declare class BaseLogger {
|
|
3
|
+
readonly isVerbose: boolean;
|
|
3
4
|
private readonly meta;
|
|
4
|
-
|
|
5
|
-
constructor(meta?: Record<string, unknown>);
|
|
5
|
+
constructor(isVerbose?: boolean, meta?: Record<string, unknown>);
|
|
6
6
|
child(meta?: Record<string, unknown>): this;
|
|
7
|
+
private _log;
|
|
7
8
|
info(message: string, args?: unknown): void;
|
|
8
9
|
error(message: string, args?: unknown): void;
|
|
9
10
|
debug(message: string, args?: unknown): void;
|
|
10
11
|
warn(message: string, args?: unknown): void;
|
|
11
|
-
log(args:
|
|
12
|
+
log(args: any): void;
|
|
12
13
|
}
|
|
13
14
|
export declare class Logger extends BaseLogger {
|
|
14
15
|
private readonly traceId;
|
|
@@ -16,7 +17,7 @@ export declare class Logger extends BaseLogger {
|
|
|
16
17
|
private readonly step;
|
|
17
18
|
private readonly socketServer?;
|
|
18
19
|
private emitLog;
|
|
19
|
-
constructor(traceId: string, flows: string[] | undefined, step: string, socketServer?: Server | undefined);
|
|
20
|
+
constructor(traceId: string, flows: string[] | undefined, step: string, isVerbose: boolean, socketServer?: Server | undefined);
|
|
20
21
|
child(meta?: Record<string, unknown>): this;
|
|
21
22
|
log(message: any): void;
|
|
22
23
|
info: (message: string, args?: unknown) => void;
|
package/dist/src/logger.js
CHANGED
|
@@ -1,44 +1,51 @@
|
|
|
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.globalLogger = exports.Logger = exports.BaseLogger = void 0;
|
|
7
|
-
const
|
|
8
|
-
const
|
|
4
|
+
const pretty_print_1 = require("./pretty-print");
|
|
5
|
+
const logLevel = process.env.LOG_LEVEL ?? 'info';
|
|
6
|
+
const isDebugEnabled = logLevel === 'debug';
|
|
7
|
+
const isInfoEnabled = ['info', 'debug'].includes(logLevel);
|
|
8
|
+
const isWarnEnabled = ['warn', 'info', 'debug', 'trace'].includes(logLevel);
|
|
9
9
|
class BaseLogger {
|
|
10
|
-
constructor(meta = {}) {
|
|
10
|
+
constructor(isVerbose = false, meta = {}) {
|
|
11
|
+
this.isVerbose = isVerbose;
|
|
11
12
|
this.meta = meta;
|
|
12
|
-
this.logger = (0, pino_1.default)({
|
|
13
|
-
level: process.env.LOG_LEVEL || 'info',
|
|
14
|
-
formatters: { level: (level) => ({ level }) },
|
|
15
|
-
base: null,
|
|
16
|
-
mixin: () => meta,
|
|
17
|
-
});
|
|
18
13
|
}
|
|
19
14
|
child(meta = {}) {
|
|
20
|
-
return new BaseLogger({ ...this.meta, ...meta });
|
|
15
|
+
return new BaseLogger(this.isVerbose, { ...this.meta, ...meta });
|
|
16
|
+
}
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
+
_log(level, msg, args) {
|
|
19
|
+
const time = Date.now();
|
|
20
|
+
(0, pretty_print_1.prettyPrint)({ level, time, msg, ...this.meta, ...(args ?? {}) }, !this.isVerbose);
|
|
21
21
|
}
|
|
22
22
|
info(message, args) {
|
|
23
|
-
|
|
23
|
+
if (isInfoEnabled) {
|
|
24
|
+
this._log('info', message, args);
|
|
25
|
+
}
|
|
24
26
|
}
|
|
25
27
|
error(message, args) {
|
|
26
|
-
this.
|
|
28
|
+
this._log('error', message, args);
|
|
27
29
|
}
|
|
28
30
|
debug(message, args) {
|
|
29
|
-
|
|
31
|
+
if (isDebugEnabled) {
|
|
32
|
+
this._log('debug', message, args);
|
|
33
|
+
}
|
|
30
34
|
}
|
|
31
35
|
warn(message, args) {
|
|
32
|
-
|
|
36
|
+
if (isWarnEnabled) {
|
|
37
|
+
this._log('warn', message, args);
|
|
38
|
+
}
|
|
33
39
|
}
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34
41
|
log(args) {
|
|
35
|
-
this.
|
|
42
|
+
this._log('info', args.msg, args);
|
|
36
43
|
}
|
|
37
44
|
}
|
|
38
45
|
exports.BaseLogger = BaseLogger;
|
|
39
46
|
class Logger extends BaseLogger {
|
|
40
|
-
constructor(traceId, flows, step, socketServer) {
|
|
41
|
-
super({ traceId, flows, step });
|
|
47
|
+
constructor(traceId, flows, step, isVerbose, socketServer) {
|
|
48
|
+
super(isVerbose, { traceId, flows, step });
|
|
42
49
|
this.traceId = traceId;
|
|
43
50
|
this.flows = flows;
|
|
44
51
|
this.step = step;
|
|
@@ -52,8 +59,8 @@ class Logger extends BaseLogger {
|
|
|
52
59
|
this.emitLog('error', message, args);
|
|
53
60
|
};
|
|
54
61
|
this.debug = (message, args) => {
|
|
55
|
-
|
|
56
|
-
|
|
62
|
+
if (isDebugEnabled) {
|
|
63
|
+
super.debug(message, args);
|
|
57
64
|
this.emitLog('debug', message, args);
|
|
58
65
|
}
|
|
59
66
|
};
|
|
@@ -74,11 +81,11 @@ class Logger extends BaseLogger {
|
|
|
74
81
|
};
|
|
75
82
|
}
|
|
76
83
|
child(meta = {}) {
|
|
77
|
-
return new Logger(this.traceId, this.flows, meta.step, this.socketServer);
|
|
84
|
+
return new Logger(this.traceId, this.flows, meta.step, this.isVerbose, this.socketServer);
|
|
78
85
|
}
|
|
79
86
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
80
87
|
log(message) {
|
|
81
|
-
|
|
88
|
+
super.log(message);
|
|
82
89
|
this.emitLog(message.level, message.msg, message);
|
|
83
90
|
}
|
|
84
91
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const prettyPrint: (json: Record<string, any>, excludeDetails?: boolean) => void;
|
|
@@ -0,0 +1,66 @@
|
|
|
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.prettyPrint = void 0;
|
|
7
|
+
const colors_1 = __importDefault(require("colors"));
|
|
8
|
+
const stepTag = (step) => colors_1.default.bold(colors_1.default.cyan(step));
|
|
9
|
+
const timestampTag = (timestamp) => colors_1.default.gray(timestamp);
|
|
10
|
+
const traceIdTag = (traceId) => colors_1.default.gray(traceId);
|
|
11
|
+
const levelTags = {
|
|
12
|
+
error: colors_1.default.red('[ERROR]'),
|
|
13
|
+
info: colors_1.default.blue('[INFO]'),
|
|
14
|
+
warn: colors_1.default.yellow('[WARN]'),
|
|
15
|
+
debug: colors_1.default.gray('[DEBUG]'),
|
|
16
|
+
trace: colors_1.default.gray('[TRACE]'),
|
|
17
|
+
};
|
|
18
|
+
const numericTag = (value) => colors_1.default.green(value);
|
|
19
|
+
const stringTag = (value) => colors_1.default.cyan(value);
|
|
20
|
+
const booleanTag = (value) => colors_1.default.blue(value);
|
|
21
|
+
const arrayBrackets = ['[', ']'].map((s) => colors_1.default.gray(s));
|
|
22
|
+
const objectBrackets = ['{', '}'].map((s) => colors_1.default.gray(s));
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
24
|
+
const prettyPrintObject = (obj, depth = 0, parentIsLast = false, prefix = '') => {
|
|
25
|
+
const tab = prefix + (depth === 0 ? '' : parentIsLast ? '│ ' : '│ ');
|
|
26
|
+
if (depth > 2) {
|
|
27
|
+
return `${tab} └ ${colors_1.default.gray('[...]')}`;
|
|
28
|
+
}
|
|
29
|
+
const entries = Object.entries(obj);
|
|
30
|
+
return entries
|
|
31
|
+
.map(([key, value], index) => {
|
|
32
|
+
const isLast = index === entries.length - 1;
|
|
33
|
+
const isObject = typeof value === 'object' && value !== null;
|
|
34
|
+
const prefix = isLast && !isObject ? '└' : '├';
|
|
35
|
+
if (isObject) {
|
|
36
|
+
const subObject = prettyPrintObject(value, depth + 1, isLast, tab);
|
|
37
|
+
const [start, end] = Array.isArray(value) ? arrayBrackets : objectBrackets;
|
|
38
|
+
return `${tab}${prefix} ${key}: ${start}\n${subObject}\n${tab}${isLast ? '└' : '│'} ${end}`;
|
|
39
|
+
}
|
|
40
|
+
let printedValue = value;
|
|
41
|
+
if (typeof value === 'number') {
|
|
42
|
+
printedValue = numericTag(String(value));
|
|
43
|
+
}
|
|
44
|
+
else if (typeof value === 'boolean') {
|
|
45
|
+
printedValue = booleanTag(String(value));
|
|
46
|
+
}
|
|
47
|
+
else if (typeof value === 'string') {
|
|
48
|
+
printedValue = stringTag(value);
|
|
49
|
+
}
|
|
50
|
+
return `${tab}${prefix} ${key}: ${printedValue}`;
|
|
51
|
+
})
|
|
52
|
+
.join('\n');
|
|
53
|
+
};
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
55
|
+
const prettyPrint = (json, excludeDetails = false) => {
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
57
|
+
const { time, traceId, msg, flows, level, step, ...details } = json;
|
|
58
|
+
const levelTag = levelTags[level];
|
|
59
|
+
const timestamp = timestampTag(`[${new Date(time).toLocaleTimeString()}]`);
|
|
60
|
+
const objectHasKeys = Object.keys(details).length > 0;
|
|
61
|
+
console.log(`${timestamp} ${traceIdTag(traceId)} ${levelTag} ${stepTag(step)} ${msg}`);
|
|
62
|
+
if (objectHasKeys && !excludeDetails) {
|
|
63
|
+
console.log(prettyPrintObject(details));
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
exports.prettyPrint = prettyPrint;
|
package/dist/src/printer.d.ts
CHANGED
|
@@ -3,6 +3,13 @@ import { Step } from './types';
|
|
|
3
3
|
export declare class Printer {
|
|
4
4
|
private readonly baseDir;
|
|
5
5
|
constructor(baseDir: string);
|
|
6
|
+
stepTag: string;
|
|
7
|
+
flowTag: string;
|
|
8
|
+
created: string;
|
|
9
|
+
building: string;
|
|
10
|
+
built: string;
|
|
11
|
+
updated: string;
|
|
12
|
+
removed: string;
|
|
6
13
|
printInvalidEmit(step: Step, emit: string): void;
|
|
7
14
|
printStepCreated(step: Step): void;
|
|
8
15
|
printStepUpdated(step: Step): void;
|
|
@@ -11,7 +18,19 @@ export declare class Printer {
|
|
|
11
18
|
printFlowUpdated(flowName: string): void;
|
|
12
19
|
printFlowRemoved(flowName: string): void;
|
|
13
20
|
printValidationError(stepPath: string, validationError: ValidationError): void;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
getRelativePath(filePath: string): string;
|
|
22
|
+
getStepType(step: Step): string;
|
|
23
|
+
getStepPath(step: Step): string;
|
|
24
|
+
}
|
|
25
|
+
export declare class NoPrinter extends Printer {
|
|
26
|
+
constructor(baseDir: string);
|
|
27
|
+
printInvalidEmit(): void;
|
|
28
|
+
printStepCreated(): void;
|
|
29
|
+
printStepUpdated(): void;
|
|
30
|
+
printStepRemoved(): void;
|
|
31
|
+
printFlowCreated(): void;
|
|
32
|
+
printFlowUpdated(): void;
|
|
33
|
+
printFlowRemoved(): void;
|
|
34
|
+
printStepType(): void;
|
|
35
|
+
printStepPath(): void;
|
|
17
36
|
}
|
package/dist/src/printer.js
CHANGED
|
@@ -3,13 +3,15 @@ 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.Printer = void 0;
|
|
6
|
+
exports.NoPrinter = exports.Printer = void 0;
|
|
7
7
|
const colors_1 = __importDefault(require("colors"));
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const guards_1 = require("./guards");
|
|
10
10
|
const stepTag = colors_1.default.bold(colors_1.default.magenta('Step'));
|
|
11
11
|
const flowTag = colors_1.default.bold(colors_1.default.blue('Flow'));
|
|
12
12
|
const created = colors_1.default.green('➜ [CREATED]');
|
|
13
|
+
const building = colors_1.default.yellow('⚡ [BUILDING]');
|
|
14
|
+
const built = colors_1.default.green('✓ [BUILT]');
|
|
13
15
|
const updated = colors_1.default.yellow('➜ [UPDATED]');
|
|
14
16
|
const removed = colors_1.default.red('➜ [REMOVED]');
|
|
15
17
|
const invalidEmit = colors_1.default.red('➜ [INVALID EMIT]');
|
|
@@ -17,6 +19,13 @@ const error = colors_1.default.red('[ERROR]');
|
|
|
17
19
|
class Printer {
|
|
18
20
|
constructor(baseDir) {
|
|
19
21
|
this.baseDir = baseDir;
|
|
22
|
+
this.stepTag = stepTag;
|
|
23
|
+
this.flowTag = flowTag;
|
|
24
|
+
this.created = created;
|
|
25
|
+
this.building = building;
|
|
26
|
+
this.built = built;
|
|
27
|
+
this.updated = updated;
|
|
28
|
+
this.removed = removed;
|
|
20
29
|
}
|
|
21
30
|
printInvalidEmit(step, emit) {
|
|
22
31
|
console.log(`${invalidEmit} ${stepTag} ${this.getStepType(step)} ${this.getStepPath(step)} tried to emit an event not defined in the step config: ${colors_1.default.yellow(emit)}`);
|
|
@@ -72,3 +81,18 @@ class Printer {
|
|
|
72
81
|
}
|
|
73
82
|
}
|
|
74
83
|
exports.Printer = Printer;
|
|
84
|
+
class NoPrinter extends Printer {
|
|
85
|
+
constructor(baseDir) {
|
|
86
|
+
super(baseDir);
|
|
87
|
+
}
|
|
88
|
+
printInvalidEmit() { }
|
|
89
|
+
printStepCreated() { }
|
|
90
|
+
printStepUpdated() { }
|
|
91
|
+
printStepRemoved() { }
|
|
92
|
+
printFlowCreated() { }
|
|
93
|
+
printFlowUpdated() { }
|
|
94
|
+
printFlowRemoved() { }
|
|
95
|
+
printStepType() { }
|
|
96
|
+
printStepPath() { }
|
|
97
|
+
}
|
|
98
|
+
exports.NoPrinter = NoPrinter;
|
|
@@ -8,25 +8,41 @@ from typing import Any, Callable
|
|
|
8
8
|
NODEIPCFD = int(os.environ["NODE_CHANNEL_FD"])
|
|
9
9
|
|
|
10
10
|
def sendMessage(text):
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
'sends a Node IPC message to parent proccess'
|
|
12
|
+
# encode message as json string + newline in bytes
|
|
13
|
+
bytesMessage = (json.dumps(text) + "\n").encode('utf-8')
|
|
14
|
+
# send message
|
|
15
|
+
os.write(NODEIPCFD, bytesMessage)
|
|
16
16
|
|
|
17
17
|
async def run_python_module(file_path: str) -> None:
|
|
18
18
|
try:
|
|
19
|
+
# Get the directory containing the module file
|
|
20
|
+
module_dir = os.path.dirname(os.path.abspath(file_path))
|
|
21
|
+
|
|
22
|
+
# Add module directory to Python path
|
|
23
|
+
if module_dir not in sys.path:
|
|
24
|
+
sys.path.insert(0, module_dir)
|
|
25
|
+
|
|
26
|
+
# Get the flows directory (parent of steps)
|
|
27
|
+
flows_dir = os.path.dirname(module_dir)
|
|
28
|
+
if flows_dir not in sys.path:
|
|
29
|
+
sys.path.insert(0, flows_dir)
|
|
30
|
+
|
|
19
31
|
# Load the module dynamically
|
|
20
32
|
spec = importlib.util.spec_from_file_location("dynamic_module", file_path)
|
|
21
33
|
if spec is None or spec.loader is None:
|
|
22
34
|
raise ImportError(f"Could not load module from {file_path}")
|
|
23
35
|
|
|
24
36
|
module = importlib.util.module_from_spec(spec)
|
|
37
|
+
# Add module's directory as its __package__
|
|
38
|
+
module.__package__ = os.path.basename(module_dir)
|
|
25
39
|
spec.loader.exec_module(module)
|
|
26
40
|
|
|
27
41
|
# Print the config if it exists
|
|
28
42
|
if hasattr(module, 'config'):
|
|
29
43
|
sendMessage(module.config)
|
|
44
|
+
else:
|
|
45
|
+
raise AttributeError(f"No 'config' found in module {file_path}")
|
|
30
46
|
|
|
31
47
|
except Exception as error:
|
|
32
48
|
print('Error running Python module:', str(error), file=sys.stderr)
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
import json
|
|
3
3
|
import importlib.util
|
|
4
|
-
import traceback
|
|
5
|
-
import asyncio
|
|
6
4
|
import os
|
|
5
|
+
import asyncio
|
|
6
|
+
import traceback
|
|
7
7
|
from logger import Logger
|
|
8
8
|
from rpc import RpcSender
|
|
9
9
|
from rpc_state_manager import RpcStateManager
|
|
10
|
-
|
|
11
10
|
from typing import Any
|
|
12
11
|
|
|
13
12
|
def parse_args(arg: str) -> Any:
|
|
@@ -33,22 +32,33 @@ class Context:
|
|
|
33
32
|
|
|
34
33
|
async def run_python_module(file_path: str, rpc: RpcSender, args: Any) -> None:
|
|
35
34
|
try:
|
|
36
|
-
#
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
# Get the directory containing the module file
|
|
36
|
+
module_dir = os.path.dirname(os.path.abspath(file_path))
|
|
37
|
+
|
|
38
|
+
# Add module directory to Python path
|
|
39
|
+
if module_dir not in sys.path:
|
|
40
|
+
sys.path.insert(0, module_dir)
|
|
41
|
+
|
|
42
|
+
# Get the flows directory (parent of steps)
|
|
43
|
+
flows_dir = os.path.dirname(module_dir)
|
|
44
|
+
if flows_dir not in sys.path:
|
|
45
|
+
sys.path.insert(0, flows_dir)
|
|
46
|
+
|
|
39
47
|
contextInFirstArg = args.contextInFirstArg
|
|
40
48
|
|
|
41
49
|
# Load the module dynamically
|
|
42
|
-
spec = importlib.util.spec_from_file_location("dynamic_module",
|
|
50
|
+
spec = importlib.util.spec_from_file_location("dynamic_module", file_path)
|
|
43
51
|
if spec is None or spec.loader is None:
|
|
44
|
-
raise ImportError(f"Could not load module from {
|
|
52
|
+
raise ImportError(f"Could not load module from {file_path}")
|
|
45
53
|
|
|
46
54
|
module = importlib.util.module_from_spec(spec)
|
|
55
|
+
# Add module's directory as its __package__
|
|
56
|
+
module.__package__ = os.path.basename(module_dir)
|
|
47
57
|
spec.loader.exec_module(module)
|
|
48
58
|
|
|
49
59
|
# Check if the handler function exists
|
|
50
60
|
if not hasattr(module, 'handler'):
|
|
51
|
-
raise AttributeError(f"Function 'handler' not found in module {
|
|
61
|
+
raise AttributeError(f"Function 'handler' not found in module {file_path}")
|
|
52
62
|
|
|
53
63
|
context = Context(args, rpc)
|
|
54
64
|
|
|
@@ -57,13 +67,12 @@ async def run_python_module(file_path: str, rpc: RpcSender, args: Any) -> None:
|
|
|
57
67
|
else:
|
|
58
68
|
result = await module.handler(args.data, context)
|
|
59
69
|
|
|
60
|
-
if
|
|
70
|
+
if result:
|
|
61
71
|
await rpc.send('result', result)
|
|
62
72
|
|
|
63
73
|
rpc.close()
|
|
64
|
-
|
|
65
|
-
# We need this to close the process
|
|
66
74
|
rpc.send_no_wait('close', None)
|
|
75
|
+
|
|
67
76
|
except Exception as error:
|
|
68
77
|
print(f'Error running Python module: {error}', file=sys.stderr)
|
|
69
78
|
traceback.print_exc(file=sys.stderr)
|
|
@@ -79,7 +88,5 @@ if __name__ == "__main__":
|
|
|
79
88
|
|
|
80
89
|
rpc = RpcSender()
|
|
81
90
|
loop = asyncio.get_event_loop()
|
|
82
|
-
# Create and gather tasks
|
|
83
91
|
tasks = asyncio.gather(rpc.init(), run_python_module(file_path, rpc, parse_args(arg)))
|
|
84
|
-
|
|
85
|
-
loop.run_until_complete(tasks)
|
|
92
|
+
loop.run_until_complete(tasks)
|
package/dist/src/server.d.ts
CHANGED
|
@@ -14,4 +14,8 @@ export type MotiaServer = {
|
|
|
14
14
|
addRoute: (step: Step<ApiRouteConfig>) => void;
|
|
15
15
|
cronManager: CronManager;
|
|
16
16
|
};
|
|
17
|
-
|
|
17
|
+
type MotiaServerConfig = {
|
|
18
|
+
isVerbose: boolean;
|
|
19
|
+
};
|
|
20
|
+
export declare const createServer: (lockedData: LockedData, eventManager: EventManager, state: StateAdapter, config: MotiaServerConfig) => Promise<MotiaServer>;
|
|
21
|
+
export {};
|
package/dist/src/server.js
CHANGED
|
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.createServer = void 0;
|
|
7
7
|
const cron_handler_1 = require("./cron-handler");
|
|
8
8
|
const body_parser_1 = __importDefault(require("body-parser"));
|
|
9
|
-
const crypto_1 = require("crypto");
|
|
10
9
|
const express_1 = __importDefault(require("express"));
|
|
11
10
|
const http_1 = __importDefault(require("http"));
|
|
12
11
|
const socket_io_1 = require("socket.io");
|
|
@@ -15,18 +14,21 @@ const guards_1 = require("./guards");
|
|
|
15
14
|
const logger_1 = require("./logger");
|
|
16
15
|
const steps_1 = require("./steps");
|
|
17
16
|
const call_step_file_1 = require("./call-step-file");
|
|
18
|
-
const
|
|
17
|
+
const LoggerFactory_1 = require("./LoggerFactory");
|
|
18
|
+
const generate_trace_id_1 = require("./generate-trace-id");
|
|
19
|
+
const createServer = async (lockedData, eventManager, state, config) => {
|
|
19
20
|
const printer = lockedData.printer;
|
|
20
21
|
const app = (0, express_1.default)();
|
|
21
22
|
const server = http_1.default.createServer(app);
|
|
22
23
|
const io = new socket_io_1.Server(server);
|
|
24
|
+
const loggerFactory = new LoggerFactory_1.LoggerFactory(config.isVerbose, io);
|
|
23
25
|
const allSteps = [...steps_1.systemSteps, ...lockedData.activeSteps];
|
|
24
|
-
const cronManager = (0, cron_handler_1.setupCronHandlers)(lockedData, eventManager, state,
|
|
26
|
+
const cronManager = (0, cron_handler_1.setupCronHandlers)(lockedData, eventManager, state, loggerFactory);
|
|
25
27
|
const asyncHandler = (step) => {
|
|
26
28
|
return async (req, res) => {
|
|
27
|
-
const traceId = (0,
|
|
28
|
-
const { name, flows } = step.config;
|
|
29
|
-
const logger =
|
|
29
|
+
const traceId = (0, generate_trace_id_1.generateTraceId)();
|
|
30
|
+
const { name: stepName, flows } = step.config;
|
|
31
|
+
const logger = loggerFactory.create({ traceId, flows, stepName });
|
|
30
32
|
logger.debug('[API] Received request, processing step', { path: req.path });
|
|
31
33
|
const request = {
|
|
32
34
|
body: req.body,
|
|
@@ -38,11 +38,8 @@ const createStepHandlers = (lockedData, eventManager, state) => {
|
|
|
38
38
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
39
39
|
}
|
|
40
40
|
catch (error) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
filePath,
|
|
44
|
-
step: name,
|
|
45
|
-
});
|
|
41
|
+
const message = typeof error === 'string' ? error : error.message;
|
|
42
|
+
logger.error(message);
|
|
46
43
|
}
|
|
47
44
|
},
|
|
48
45
|
});
|
|
@@ -11,17 +11,17 @@ exports.config = {
|
|
|
11
11
|
emits: [], // Dynamic emissions
|
|
12
12
|
flows: ['_system'],
|
|
13
13
|
bodySchema: zod_1.z.object({
|
|
14
|
-
|
|
14
|
+
topic: zod_1.z.string(),
|
|
15
15
|
data: zod_1.z.record(zod_1.z.unknown()),
|
|
16
16
|
}),
|
|
17
17
|
};
|
|
18
18
|
const handler = async (req, { emit, logger }) => {
|
|
19
|
-
const {
|
|
20
|
-
logger.info('[Event Emitter] Emitting event', {
|
|
21
|
-
await emit({
|
|
19
|
+
const { topic, data } = req.body;
|
|
20
|
+
logger.info('[Event Emitter] Emitting event', { topic, data });
|
|
21
|
+
await emit({ topic, data });
|
|
22
22
|
return {
|
|
23
23
|
status: 200,
|
|
24
|
-
body: { success: true, emitted: {
|
|
24
|
+
body: { success: true, emitted: { topic, data } },
|
|
25
25
|
};
|
|
26
26
|
};
|
|
27
27
|
exports.handler = handler;
|
|
@@ -10,19 +10,19 @@ export const config: ApiRouteConfig = {
|
|
|
10
10
|
emits: [], // Dynamic emissions
|
|
11
11
|
flows: ['_system'],
|
|
12
12
|
bodySchema: z.object({
|
|
13
|
-
|
|
13
|
+
topic: z.string(),
|
|
14
14
|
data: z.record(z.unknown()),
|
|
15
15
|
}),
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export const handler: StepHandler<typeof config> = async (req, { emit, logger }) => {
|
|
19
|
-
const {
|
|
19
|
+
const { topic, data } = req.body
|
|
20
20
|
|
|
21
|
-
logger.info('[Event Emitter] Emitting event', {
|
|
22
|
-
await emit({
|
|
21
|
+
logger.info('[Event Emitter] Emitting event', { topic, data })
|
|
22
|
+
await emit({ topic, data })
|
|
23
23
|
|
|
24
24
|
return {
|
|
25
25
|
status: 200,
|
|
26
|
-
body: { success: true, emitted: {
|
|
26
|
+
body: { success: true, emitted: { topic, data } },
|
|
27
27
|
}
|
|
28
28
|
}
|
package/dist/src/types.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export type InternalStateManager = {
|
|
|
7
7
|
clear(traceId: string): Promise<void>;
|
|
8
8
|
};
|
|
9
9
|
export type EmitData = {
|
|
10
|
-
|
|
10
|
+
topic: string;
|
|
11
11
|
data: Record<string, unknown>;
|
|
12
12
|
};
|
|
13
13
|
export type Emitter = (event: EmitData) => Promise<void>;
|
|
@@ -19,7 +19,7 @@ export type FlowContext = {
|
|
|
19
19
|
};
|
|
20
20
|
export type EventHandler<TInput extends ZodObject<any>> = (input: z.infer<TInput>, ctx: FlowContext) => Promise<void>;
|
|
21
21
|
export type Emit = string | {
|
|
22
|
-
|
|
22
|
+
topic: string;
|
|
23
23
|
label?: string;
|
|
24
24
|
conditional?: boolean;
|
|
25
25
|
};
|
|
@@ -78,7 +78,7 @@ export type CronConfig = {
|
|
|
78
78
|
export type CronHandler = (ctx: FlowContext) => Promise<void>;
|
|
79
79
|
export type StepHandler<T> = T extends EventConfig<any> ? EventHandler<T['input']> : T extends ApiRouteConfig ? ApiRouteHandler : T extends CronConfig ? CronHandler : never;
|
|
80
80
|
export type Event<TData = unknown> = {
|
|
81
|
-
|
|
81
|
+
topic: string;
|
|
82
82
|
data: TData;
|
|
83
83
|
traceId: string;
|
|
84
84
|
flows?: string[];
|
package/dist/src/utils.js
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.isAllowedToEmit = void 0;
|
|
4
4
|
const guards_1 = require("./guards");
|
|
5
|
-
const
|
|
5
|
+
const toTopic = (emit) => (typeof emit === 'string' ? emit : emit.topic);
|
|
6
6
|
const isAllowedToEmit = (step, emit) => {
|
|
7
7
|
if ((0, guards_1.isApiStep)(step)) {
|
|
8
|
-
return step.config.emits.map(
|
|
8
|
+
return step.config.emits.map(toTopic).includes(emit);
|
|
9
9
|
}
|
|
10
10
|
if ((0, guards_1.isEventStep)(step)) {
|
|
11
|
-
return step.config.emits.map(
|
|
11
|
+
return step.config.emits.map(toTopic).includes(emit);
|
|
12
12
|
}
|
|
13
13
|
if ((0, guards_1.isCronStep)(step)) {
|
|
14
|
-
return step.config.emits.map(
|
|
14
|
+
return step.config.emits.map(toTopic).includes(emit);
|
|
15
15
|
}
|
|
16
16
|
return false;
|
|
17
17
|
};
|
package/package.json
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@motiadev/core",
|
|
3
3
|
"main": "dist/index.js",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.30",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"body-parser": "^1.20.3",
|
|
7
7
|
"colors": "^1.4.0",
|
|
8
8
|
"express": "^4.21.2",
|
|
9
9
|
"ioredis": "^5.4.2",
|
|
10
10
|
"node-cron": "^3.0.3",
|
|
11
|
-
"pino": "^9.6.0",
|
|
12
11
|
"socket.io": "^4.8.1",
|
|
13
12
|
"ts-node": "^10.9.2",
|
|
14
13
|
"tsconfig-paths": "^4.2.0",
|