@motiadev/core 0.0.19 → 0.0.21
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 +2 -3
- package/dist/index.js +2 -3
- package/dist/src/call-step-file.d.ts +3 -2
- package/dist/src/call-step-file.js +13 -9
- package/dist/src/cron-handler.d.ts +12 -2
- package/dist/src/cron-handler.js +23 -18
- package/dist/src/event-manager.js +9 -4
- package/dist/src/flows-endpoint.d.ts +4 -3
- package/dist/src/flows-endpoint.js +5 -4
- package/dist/src/get-step-config.d.ts +2 -0
- package/dist/src/get-step-config.js +22 -0
- package/dist/src/guards.d.ts +1 -1
- package/dist/src/guards.js +0 -1
- package/dist/src/locked-data.d.ts +26 -0
- package/dist/src/locked-data.js +144 -0
- package/dist/src/logger.d.ts +1 -1
- package/dist/src/node/get-module-export.js +5 -2
- package/dist/src/node/logger.d.ts +11 -6
- package/dist/src/node/logger.js +29 -16
- package/dist/src/node/node-runner.js +3 -4
- package/dist/src/node/rpc.d.ts +2 -0
- package/dist/src/node/rpc.js +11 -1
- package/dist/src/printer.d.ts +17 -0
- package/dist/src/printer.js +74 -0
- package/dist/src/python/logger.py +3 -3
- package/dist/src/python/python-runner.py +21 -16
- package/dist/src/python/rpc.py +26 -15
- package/dist/src/python/rpc_state_manager.py +12 -11
- package/dist/src/ruby/get_config.rb +12 -22
- package/dist/src/ruby/logger.rb +23 -16
- package/dist/src/ruby/rpc.rb +123 -0
- package/dist/src/ruby/rpc_state_manager.rb +25 -0
- package/dist/src/ruby/ruby_runner.rb +42 -31
- package/dist/src/server.d.ts +8 -10
- package/dist/src/server.js +31 -13
- package/dist/src/step-handler-rpc-processor.d.ts +1 -0
- package/dist/src/step-handler-rpc-processor.js +11 -1
- package/dist/src/step-handlers.d.ts +8 -2
- package/dist/src/step-handlers.js +34 -20
- package/dist/src/step-validator.d.ts +14 -0
- package/dist/src/step-validator.js +99 -0
- package/dist/src/types.d.ts +20 -26
- package/dist/src/utils.d.ts +2 -0
- package/dist/src/utils.js +15 -0
- package/package.json +2 -1
- package/dist/src/ruby/state_adapter.rb +0 -62
package/dist/src/server.d.ts
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
+
import { CronManager } from './cron-handler';
|
|
1
2
|
import { Express } from 'express';
|
|
2
3
|
import http from 'http';
|
|
3
4
|
import { Server as SocketIOServer } from 'socket.io';
|
|
4
5
|
import { StateAdapter } from './state/state-adapter';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
flows: LockedData['flows'];
|
|
9
|
-
eventManager: EventManager;
|
|
10
|
-
state: StateAdapter;
|
|
11
|
-
};
|
|
12
|
-
type ServerOutput = {
|
|
6
|
+
import { ApiRouteConfig, EventManager, Step } from './types';
|
|
7
|
+
import { LockedData } from './locked-data';
|
|
8
|
+
export type MotiaServer = {
|
|
13
9
|
app: Express;
|
|
14
10
|
server: http.Server;
|
|
15
11
|
socketServer: SocketIOServer;
|
|
16
12
|
close: () => Promise<void>;
|
|
13
|
+
removeRoute: (step: Step<ApiRouteConfig>) => void;
|
|
14
|
+
addRoute: (step: Step<ApiRouteConfig>) => void;
|
|
15
|
+
cronManager: CronManager;
|
|
17
16
|
};
|
|
18
|
-
export declare const createServer: (
|
|
19
|
-
export {};
|
|
17
|
+
export declare const createServer: (lockedData: LockedData, eventManager: EventManager, state: StateAdapter) => Promise<MotiaServer>;
|
package/dist/src/server.js
CHANGED
|
@@ -15,13 +15,13 @@ const guards_1 = require("./guards");
|
|
|
15
15
|
const logger_1 = require("./logger");
|
|
16
16
|
const get_module_export_1 = require("./node/get-module-export");
|
|
17
17
|
const steps_1 = require("./steps");
|
|
18
|
-
const
|
|
19
|
-
|
|
18
|
+
const utils_1 = require("./utils");
|
|
19
|
+
const createServer = async (lockedData, eventManager, state) => {
|
|
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
|
-
const allSteps = [...steps_1.systemSteps, ...
|
|
24
|
-
const
|
|
23
|
+
const allSteps = [...steps_1.systemSteps, ...lockedData.activeSteps];
|
|
24
|
+
const cronManager = (0, cron_handler_1.setupCronHandlers)(lockedData, eventManager, io);
|
|
25
25
|
const asyncHandler = (step, flows) => {
|
|
26
26
|
return async (req, res) => {
|
|
27
27
|
const traceId = (0, crypto_1.randomUUID)();
|
|
@@ -35,6 +35,10 @@ const createServer = async (options) => {
|
|
|
35
35
|
queryParams: req.query,
|
|
36
36
|
};
|
|
37
37
|
const emit = async ({ data, type }) => {
|
|
38
|
+
if (!(0, utils_1.isAllowedToEmit)(step, type)) {
|
|
39
|
+
lockedData.printer.printInvalidEmit(step, type);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
38
42
|
await eventManager.emit({ data, type, traceId, flows, logger }, step.filePath);
|
|
39
43
|
};
|
|
40
44
|
try {
|
|
@@ -54,30 +58,44 @@ const createServer = async (options) => {
|
|
|
54
58
|
};
|
|
55
59
|
app.use(body_parser_1.default.json());
|
|
56
60
|
app.use(body_parser_1.default.urlencoded({ extended: true }));
|
|
57
|
-
const
|
|
58
|
-
|
|
61
|
+
const router = express_1.default.Router();
|
|
62
|
+
const addRoute = (step) => {
|
|
59
63
|
const { method, flows, path } = step.config;
|
|
60
64
|
logger_1.globalLogger.debug('[API] Registering route', step.config);
|
|
61
65
|
if (method === 'POST') {
|
|
62
|
-
|
|
66
|
+
router.post(path, asyncHandler(step, flows));
|
|
63
67
|
}
|
|
64
68
|
else if (method === 'GET') {
|
|
65
|
-
|
|
69
|
+
router.get(path, asyncHandler(step, flows));
|
|
66
70
|
}
|
|
67
71
|
else {
|
|
68
72
|
throw new Error(`Unsupported method: ${method}`);
|
|
69
73
|
}
|
|
70
|
-
}
|
|
71
|
-
(
|
|
74
|
+
};
|
|
75
|
+
const removeRoute = (step) => {
|
|
76
|
+
const { path, method } = step.config;
|
|
77
|
+
const routerStack = router.stack;
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
79
|
+
const filteredStack = routerStack.filter((layer) => {
|
|
80
|
+
if (layer.route) {
|
|
81
|
+
const match = layer.route.path === path && layer.route.methods[method.toLowerCase()];
|
|
82
|
+
return !match;
|
|
83
|
+
}
|
|
84
|
+
return true;
|
|
85
|
+
});
|
|
86
|
+
router.stack = filteredStack;
|
|
87
|
+
};
|
|
88
|
+
allSteps.filter(guards_1.isApiStep).forEach(addRoute);
|
|
89
|
+
app.use(router);
|
|
90
|
+
(0, flows_endpoint_1.flowsEndpoint)(lockedData, app);
|
|
72
91
|
server.on('error', (error) => {
|
|
73
92
|
console.error('Server error:', error);
|
|
74
|
-
cleanupCronJobs();
|
|
75
93
|
});
|
|
76
94
|
const close = async () => {
|
|
77
|
-
|
|
95
|
+
cronManager.close();
|
|
78
96
|
await io.close();
|
|
79
97
|
server.close();
|
|
80
98
|
};
|
|
81
|
-
return { app, server, socketServer: io, close };
|
|
99
|
+
return { app, server, socketServer: io, close, removeRoute, addRoute, cronManager };
|
|
82
100
|
};
|
|
83
101
|
exports.createServer = createServer;
|
|
@@ -9,6 +9,7 @@ export type RpcMessage = {
|
|
|
9
9
|
export declare class RpcProcessor {
|
|
10
10
|
private child;
|
|
11
11
|
private handlers;
|
|
12
|
+
private isClosed;
|
|
12
13
|
constructor(child: ChildProcess);
|
|
13
14
|
handler<TInput, TOutput = unknown>(method: string, handler: RpcHandler<TInput, TOutput>): void;
|
|
14
15
|
handle(method: string, input: unknown): Promise<any>;
|
|
@@ -6,6 +6,7 @@ class RpcProcessor {
|
|
|
6
6
|
this.child = child;
|
|
7
7
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
8
|
this.handlers = {};
|
|
9
|
+
this.isClosed = false;
|
|
9
10
|
}
|
|
10
11
|
handler(method, handler) {
|
|
11
12
|
this.handlers[method] = handler;
|
|
@@ -18,7 +19,7 @@ class RpcProcessor {
|
|
|
18
19
|
return handler(input);
|
|
19
20
|
}
|
|
20
21
|
response(id, result, error) {
|
|
21
|
-
if (id) {
|
|
22
|
+
if (id && !this.isClosed && this.child.connected && !this.child.killed) {
|
|
22
23
|
this.child.send?.({ type: 'rpc_response', id, result, error });
|
|
23
24
|
}
|
|
24
25
|
}
|
|
@@ -31,6 +32,15 @@ class RpcProcessor {
|
|
|
31
32
|
.catch((error) => this.response(id, null, error));
|
|
32
33
|
}
|
|
33
34
|
});
|
|
35
|
+
this.child.on('exit', () => {
|
|
36
|
+
this.isClosed = true;
|
|
37
|
+
});
|
|
38
|
+
this.child.on('close', () => {
|
|
39
|
+
this.isClosed = true;
|
|
40
|
+
});
|
|
41
|
+
this.child.on('disconnect', () => {
|
|
42
|
+
this.isClosed = true;
|
|
43
|
+
});
|
|
34
44
|
}
|
|
35
45
|
}
|
|
36
46
|
exports.RpcProcessor = RpcProcessor;
|
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { EventConfig, EventManager, Step } from './types';
|
|
2
|
+
import { LockedData } from './locked-data';
|
|
3
|
+
import { StateAdapter } from './state/state-adapter';
|
|
4
|
+
export type MotiaEventManager = {
|
|
5
|
+
createHandler: (step: Step<EventConfig>) => void;
|
|
6
|
+
removeHandler: (step: Step<EventConfig>) => void;
|
|
7
|
+
};
|
|
8
|
+
export declare const createStepHandlers: (lockedData: LockedData, eventManager: EventManager, state: StateAdapter) => MotiaEventManager;
|
|
@@ -2,32 +2,46 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createStepHandlers = void 0;
|
|
4
4
|
const logger_1 = require("./logger");
|
|
5
|
-
const guards_1 = require("./guards");
|
|
6
5
|
const call_step_file_1 = require("./call-step-file");
|
|
7
|
-
const createStepHandlers = (
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
const createStepHandlers = (lockedData, eventManager, state) => {
|
|
7
|
+
const eventSteps = lockedData.eventSteps();
|
|
8
|
+
logger_1.globalLogger.debug(`[step handler] creating step handlers for ${eventSteps.length} steps`);
|
|
9
|
+
const createHandler = (step) => {
|
|
10
10
|
const { config, filePath } = step;
|
|
11
11
|
const { subscribes } = config;
|
|
12
12
|
logger_1.globalLogger.debug('[step handler] establishing step subscriptions', { filePath, step: step.config.name });
|
|
13
13
|
subscribes.forEach((subscribe) => {
|
|
14
|
-
eventManager.subscribe(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
14
|
+
eventManager.subscribe({
|
|
15
|
+
filePath,
|
|
16
|
+
event: subscribe,
|
|
17
|
+
handlerName: step.config.name,
|
|
18
|
+
handler: async (event) => {
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
20
|
+
const { logger, ...rest } = event;
|
|
21
|
+
logger_1.globalLogger.debug('[step handler] received event', { event: rest, step: step.config.name });
|
|
22
|
+
try {
|
|
23
|
+
await (0, call_step_file_1.callStepFile)(step, lockedData, event, eventManager, state);
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
logger_1.globalLogger.error(`[step handler] error calling step`, {
|
|
28
|
+
error: error.message,
|
|
29
|
+
filePath,
|
|
30
|
+
step: step.config.name,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
},
|
|
29
34
|
});
|
|
30
35
|
});
|
|
31
|
-
}
|
|
36
|
+
};
|
|
37
|
+
const removeHandler = (step) => {
|
|
38
|
+
const { config, filePath } = step;
|
|
39
|
+
const { subscribes } = config;
|
|
40
|
+
subscribes.forEach((subscribe) => {
|
|
41
|
+
eventManager.unsubscribe({ filePath, event: subscribe });
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
eventSteps.forEach(createHandler);
|
|
45
|
+
return { removeHandler, createHandler };
|
|
32
46
|
};
|
|
33
47
|
exports.createStepHandlers = createStepHandlers;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Step } from './types';
|
|
2
|
+
export type ValidationSuccess = {
|
|
3
|
+
success: true;
|
|
4
|
+
};
|
|
5
|
+
export type ValidationError = {
|
|
6
|
+
success: false;
|
|
7
|
+
error: string;
|
|
8
|
+
errors?: Array<{
|
|
9
|
+
path: string;
|
|
10
|
+
message: string;
|
|
11
|
+
}>;
|
|
12
|
+
};
|
|
13
|
+
export type ValidationResult = ValidationSuccess | ValidationError;
|
|
14
|
+
export declare const validateStep: (step: Step) => ValidationResult;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateStep = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const emits = zod_1.z.array(zod_1.z.union([
|
|
6
|
+
zod_1.z.string(),
|
|
7
|
+
zod_1.z
|
|
8
|
+
.object({
|
|
9
|
+
type: zod_1.z.string(),
|
|
10
|
+
label: zod_1.z.string().optional(),
|
|
11
|
+
conditional: zod_1.z.boolean().optional(),
|
|
12
|
+
})
|
|
13
|
+
.strict(),
|
|
14
|
+
]));
|
|
15
|
+
const noopSchema = zod_1.z
|
|
16
|
+
.object({
|
|
17
|
+
type: zod_1.z.literal('noop'),
|
|
18
|
+
name: zod_1.z.string(),
|
|
19
|
+
description: zod_1.z.string().optional(),
|
|
20
|
+
virtualEmits: emits,
|
|
21
|
+
virtualSubscribes: zod_1.z.array(zod_1.z.string()),
|
|
22
|
+
flows: zod_1.z.array(zod_1.z.string()).optional(),
|
|
23
|
+
})
|
|
24
|
+
.strict();
|
|
25
|
+
const eventSchema = zod_1.z
|
|
26
|
+
.object({
|
|
27
|
+
type: zod_1.z.literal('event'),
|
|
28
|
+
name: zod_1.z.string(),
|
|
29
|
+
description: zod_1.z.string().optional(),
|
|
30
|
+
subscribes: zod_1.z.array(zod_1.z.string()),
|
|
31
|
+
emits: emits,
|
|
32
|
+
virtualEmits: emits.optional(),
|
|
33
|
+
input: zod_1.z.any(),
|
|
34
|
+
flows: zod_1.z.array(zod_1.z.string()).optional(),
|
|
35
|
+
})
|
|
36
|
+
.strict();
|
|
37
|
+
const apiSchema = zod_1.z
|
|
38
|
+
.object({
|
|
39
|
+
type: zod_1.z.literal('api'),
|
|
40
|
+
name: zod_1.z.string(),
|
|
41
|
+
description: zod_1.z.string().optional(),
|
|
42
|
+
path: zod_1.z.string(),
|
|
43
|
+
method: zod_1.z.string(),
|
|
44
|
+
emits: emits,
|
|
45
|
+
virtualEmits: emits.optional(),
|
|
46
|
+
virtualSubscribes: zod_1.z.array(zod_1.z.string()).optional(),
|
|
47
|
+
flows: zod_1.z.array(zod_1.z.string()).optional(),
|
|
48
|
+
bodySchema: zod_1.z.instanceof(zod_1.z.ZodObject).optional(),
|
|
49
|
+
})
|
|
50
|
+
.strict();
|
|
51
|
+
const cronSchema = zod_1.z
|
|
52
|
+
.object({
|
|
53
|
+
type: zod_1.z.literal('cron'),
|
|
54
|
+
name: zod_1.z.string(),
|
|
55
|
+
description: zod_1.z.string().optional(),
|
|
56
|
+
cron: zod_1.z.string(),
|
|
57
|
+
virtualEmits: emits.optional(),
|
|
58
|
+
emits: emits,
|
|
59
|
+
flows: zod_1.z.array(zod_1.z.string()).optional(),
|
|
60
|
+
})
|
|
61
|
+
.strict();
|
|
62
|
+
const validateStep = (step) => {
|
|
63
|
+
try {
|
|
64
|
+
if (step.config.type === 'noop') {
|
|
65
|
+
noopSchema.parse(step.config);
|
|
66
|
+
}
|
|
67
|
+
else if (step.config.type === 'event') {
|
|
68
|
+
eventSchema.parse(step.config);
|
|
69
|
+
}
|
|
70
|
+
else if (step.config.type === 'api') {
|
|
71
|
+
apiSchema.parse(step.config);
|
|
72
|
+
}
|
|
73
|
+
else if (step.config.type === 'cron') {
|
|
74
|
+
cronSchema.parse(step.config);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
return {
|
|
78
|
+
success: false,
|
|
79
|
+
error: 'Invalid step type',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return { success: true };
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
if (error instanceof zod_1.z.ZodError) {
|
|
86
|
+
return {
|
|
87
|
+
success: false,
|
|
88
|
+
error: 'Invalid step configuration',
|
|
89
|
+
errors: error.errors.map((err) => ({ path: err.path.join('.'), message: err.message })),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Handle unexpected errors
|
|
93
|
+
return {
|
|
94
|
+
success: false,
|
|
95
|
+
error: 'Unexpected validation error occurred',
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
exports.validateStep = validateStep;
|
package/dist/src/types.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { z, ZodObject } from 'zod';
|
|
2
|
-
import { Server } from 'http';
|
|
3
|
-
import { Server as SocketIOServer } from 'socket.io';
|
|
4
2
|
import { Logger } from './logger';
|
|
5
3
|
export type InternalStateManager = {
|
|
6
4
|
get<T>(traceId: string, key: string): Promise<T | null>;
|
|
@@ -25,7 +23,7 @@ export type Emit = string | {
|
|
|
25
23
|
label?: string;
|
|
26
24
|
conditional?: boolean;
|
|
27
25
|
};
|
|
28
|
-
export type EventConfig<TInput extends ZodObject<any
|
|
26
|
+
export type EventConfig<TInput extends ZodObject<any> = any> = {
|
|
29
27
|
type: 'event';
|
|
30
28
|
name: string;
|
|
31
29
|
description?: string;
|
|
@@ -33,7 +31,7 @@ export type EventConfig<TInput extends ZodObject<any>> = {
|
|
|
33
31
|
emits: Emit[];
|
|
34
32
|
virtualEmits?: Emit[];
|
|
35
33
|
input: TInput;
|
|
36
|
-
flows
|
|
34
|
+
flows?: string[];
|
|
37
35
|
};
|
|
38
36
|
export type NoopConfig = {
|
|
39
37
|
type: 'noop';
|
|
@@ -41,7 +39,7 @@ export type NoopConfig = {
|
|
|
41
39
|
description?: string;
|
|
42
40
|
virtualEmits: Emit[];
|
|
43
41
|
virtualSubscribes: string[];
|
|
44
|
-
flows
|
|
42
|
+
flows?: string[];
|
|
45
43
|
};
|
|
46
44
|
export type ApiRouteMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'HEAD';
|
|
47
45
|
export type ApiRouteConfig = {
|
|
@@ -50,10 +48,10 @@ export type ApiRouteConfig = {
|
|
|
50
48
|
description?: string;
|
|
51
49
|
path: string;
|
|
52
50
|
method: ApiRouteMethod;
|
|
53
|
-
emits:
|
|
51
|
+
emits: Emit[];
|
|
54
52
|
virtualEmits?: Emit[];
|
|
55
53
|
virtualSubscribes?: string[];
|
|
56
|
-
flows
|
|
54
|
+
flows?: string[];
|
|
57
55
|
bodySchema?: ZodObject<any>;
|
|
58
56
|
};
|
|
59
57
|
export type ApiRequest = {
|
|
@@ -74,23 +72,32 @@ export type CronConfig = {
|
|
|
74
72
|
description?: string;
|
|
75
73
|
cron: string;
|
|
76
74
|
virtualEmits?: Emit[];
|
|
77
|
-
emits:
|
|
78
|
-
flows
|
|
75
|
+
emits: Emit[];
|
|
76
|
+
flows?: string[];
|
|
79
77
|
};
|
|
80
78
|
export type StepHandler<T> = T extends EventConfig<any> ? EventHandler<T['input']> : T extends ApiRouteConfig ? ApiRouteHandler : T extends CronConfig ? never : never;
|
|
81
|
-
export type MotiaServer = Server;
|
|
82
|
-
export type MotiaSocketServer = SocketIOServer;
|
|
83
79
|
export type Event<TData = unknown> = {
|
|
84
80
|
type: string;
|
|
85
81
|
data: TData;
|
|
86
82
|
traceId: string;
|
|
87
|
-
flows
|
|
83
|
+
flows?: string[];
|
|
88
84
|
logger: Logger;
|
|
89
85
|
};
|
|
90
86
|
export type Handler<TData = unknown> = (event: Event<TData>) => Promise<void>;
|
|
87
|
+
export type SubscribeConfig<TData> = {
|
|
88
|
+
event: string;
|
|
89
|
+
handlerName: string;
|
|
90
|
+
filePath: string;
|
|
91
|
+
handler: Handler<TData>;
|
|
92
|
+
};
|
|
93
|
+
export type UnsubscribeConfig = {
|
|
94
|
+
filePath: string;
|
|
95
|
+
event: string;
|
|
96
|
+
};
|
|
91
97
|
export type EventManager = {
|
|
92
98
|
emit: <TData>(event: Event<TData>, file?: string) => Promise<void>;
|
|
93
|
-
subscribe: <TData>(
|
|
99
|
+
subscribe: <TData>(config: SubscribeConfig<TData>) => void;
|
|
100
|
+
unsubscribe: (config: UnsubscribeConfig) => void;
|
|
94
101
|
};
|
|
95
102
|
export type StepConfig = EventConfig<ZodObject<any>> | NoopConfig | ApiRouteConfig | CronConfig;
|
|
96
103
|
export type Step<TConfig extends StepConfig = StepConfig> = {
|
|
@@ -103,16 +110,3 @@ export type Flow = {
|
|
|
103
110
|
description?: string;
|
|
104
111
|
steps: Step[];
|
|
105
112
|
};
|
|
106
|
-
export type LockedData = {
|
|
107
|
-
baseDir: string;
|
|
108
|
-
steps: {
|
|
109
|
-
active: Step[];
|
|
110
|
-
dev: Step[];
|
|
111
|
-
};
|
|
112
|
-
flows: Record<string, Flow>;
|
|
113
|
-
state: {
|
|
114
|
-
adapter: string;
|
|
115
|
-
host: string;
|
|
116
|
-
port: number;
|
|
117
|
-
};
|
|
118
|
-
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isAllowedToEmit = void 0;
|
|
4
|
+
const guards_1 = require("./guards");
|
|
5
|
+
const toType = (emit) => (typeof emit === 'string' ? emit : emit.type);
|
|
6
|
+
const isAllowedToEmit = (step, emit) => {
|
|
7
|
+
if ((0, guards_1.isApiStep)(step)) {
|
|
8
|
+
return step.config.emits.map(toType).includes(emit);
|
|
9
|
+
}
|
|
10
|
+
if ((0, guards_1.isEventStep)(step)) {
|
|
11
|
+
return step.config.emits.map(toType).includes(emit);
|
|
12
|
+
}
|
|
13
|
+
return false;
|
|
14
|
+
};
|
|
15
|
+
exports.isAllowedToEmit = isAllowedToEmit;
|
package/package.json
CHANGED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
require 'net/http'
|
|
2
|
-
require 'json'
|
|
3
|
-
require 'uri'
|
|
4
|
-
require 'logger'
|
|
5
|
-
|
|
6
|
-
class StateManagerError < StandardError; end
|
|
7
|
-
|
|
8
|
-
LOGGER = Logger.new($stdout)
|
|
9
|
-
|
|
10
|
-
def get_state_manager_handler(state_manager_url)
|
|
11
|
-
lambda do |action, payload|
|
|
12
|
-
begin
|
|
13
|
-
uri = URI("#{state_manager_url}/#{action}")
|
|
14
|
-
request = Net::HTTP::Post.new(uri)
|
|
15
|
-
request['Content-Type'] = 'application/json'
|
|
16
|
-
request['x-trace-id'] = payload[:traceId]
|
|
17
|
-
# TODO: Add internal auth token for security
|
|
18
|
-
# TODO: Encrypt the payload for security
|
|
19
|
-
request.body = payload.to_json
|
|
20
|
-
|
|
21
|
-
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
|
22
|
-
http.request(request)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
unless response.is_a?(Net::HTTPSuccess)
|
|
26
|
-
error_message = "Failed posting state change: #{response.code} - #{response.message}"
|
|
27
|
-
LOGGER.error(error_message)
|
|
28
|
-
raise StateManagerError, error_message
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
if action == 'get'
|
|
32
|
-
result = JSON.parse(response.body, object_class: OpenStruct)
|
|
33
|
-
return result.data
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
nil
|
|
37
|
-
rescue StandardError => error
|
|
38
|
-
LOGGER.error("[internal state manager] failed posting state change: #{error.message}")
|
|
39
|
-
raise StateManagerError, "Failed posting state change: #{error.message}"
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def create_internal_state_manager(state_manager_url:)
|
|
45
|
-
handler = get_state_manager_handler(state_manager_url)
|
|
46
|
-
|
|
47
|
-
{
|
|
48
|
-
get: ->(trace_id, key) {
|
|
49
|
-
result = handler.call('get', { traceId: trace_id, key: key })
|
|
50
|
-
{ data: result }
|
|
51
|
-
},
|
|
52
|
-
set: ->(trace_id, key, value) {
|
|
53
|
-
handler.call('set', { traceId: trace_id, key: key, value: value })
|
|
54
|
-
},
|
|
55
|
-
delete: ->(trace_id, key) {
|
|
56
|
-
handler.call('delete', { traceId: trace_id, key: key })
|
|
57
|
-
},
|
|
58
|
-
clear: ->(trace_id) {
|
|
59
|
-
handler.call('clear', { traceId: trace_id })
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
end
|