@motiadev/core 0.0.9 → 0.0.11
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 -0
- package/dist/index.js +2 -0
- package/dist/src/cron-handler.d.ts +3 -0
- package/dist/src/cron-handler.js +95 -0
- package/dist/src/flows-endpoint.d.ts +2 -1
- package/dist/src/flows-endpoint.js +13 -0
- package/dist/src/guards.d.ts +2 -1
- package/dist/src/guards.js +3 -1
- package/dist/src/node/rpc.js +9 -2
- package/dist/src/server.d.ts +1 -0
- package/dist/src/server.js +10 -1
- package/dist/src/state/adapters/memory-state-adapter.d.ts +11 -0
- package/dist/src/state/adapters/memory-state-adapter.js +38 -0
- package/dist/src/state/create-state-adapter.d.ts +2 -1
- package/dist/src/state/create-state-adapter.js +3 -0
- package/dist/src/types.d.ts +11 -2
- package/package.json +3 -1
- package/tsconfig.json +0 -20
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -23,3 +23,5 @@ __exportStar(require("./src/state/create-state-adapter"), exports);
|
|
|
23
23
|
__exportStar(require("./src/python/get-python-config"), exports);
|
|
24
24
|
__exportStar(require("./src/ruby/get-ruby-config"), exports);
|
|
25
25
|
__exportStar(require("./src/node/get-config"), exports);
|
|
26
|
+
__exportStar(require("./src/cron-handler"), exports);
|
|
27
|
+
__exportStar(require("./src/guards"), exports);
|
|
@@ -0,0 +1,95 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.setupCronHandlers = void 0;
|
|
37
|
+
const logger_1 = require("./logger");
|
|
38
|
+
const cron = __importStar(require("node-cron"));
|
|
39
|
+
const guards_1 = require("./guards");
|
|
40
|
+
const get_module_export_1 = require("./node/get-module-export");
|
|
41
|
+
const cronJobs = new Map();
|
|
42
|
+
const setupCronHandlers = (steps, eventManager, socketServer) => {
|
|
43
|
+
steps.filter(guards_1.isCronStep).forEach(async (step) => {
|
|
44
|
+
const { config, filePath } = step;
|
|
45
|
+
const { cron: cronExpression } = config;
|
|
46
|
+
if (!cron.validate(cronExpression)) {
|
|
47
|
+
logger_1.globalLogger.error('[cron handler] invalid cron expression', {
|
|
48
|
+
expression: cronExpression,
|
|
49
|
+
step: step.config.name
|
|
50
|
+
});
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
logger_1.globalLogger.debug('[cron handler] setting up cron job', {
|
|
54
|
+
filePath,
|
|
55
|
+
step: step.config.name,
|
|
56
|
+
cron: cronExpression
|
|
57
|
+
});
|
|
58
|
+
const task = cron.schedule(cronExpression, async () => {
|
|
59
|
+
const traceId = Math.random().toString(36).substring(7);
|
|
60
|
+
const logger = new logger_1.Logger(traceId, config.flows, step.config.name, socketServer);
|
|
61
|
+
try {
|
|
62
|
+
const handler = await (0, get_module_export_1.getModuleExport)(filePath, 'handler');
|
|
63
|
+
const emit = async (event) => {
|
|
64
|
+
await eventManager.emit({
|
|
65
|
+
...event,
|
|
66
|
+
traceId,
|
|
67
|
+
flows: config.flows,
|
|
68
|
+
logger
|
|
69
|
+
}, filePath);
|
|
70
|
+
};
|
|
71
|
+
if (handler) {
|
|
72
|
+
await handler({ emit, logger, traceId });
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
await emit({
|
|
76
|
+
type: config.emits[0],
|
|
77
|
+
data: { timestamp: Date.now() }
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
logger.error('[cron handler] error executing cron job', {
|
|
83
|
+
error: error.message,
|
|
84
|
+
step: step.config.name
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
cronJobs.set(step.config.name, task);
|
|
89
|
+
});
|
|
90
|
+
return () => {
|
|
91
|
+
cronJobs.forEach((task) => task.stop());
|
|
92
|
+
cronJobs.clear();
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
exports.setupCronHandlers = setupCronHandlers;
|
|
@@ -18,7 +18,7 @@ type FlowEdge = {
|
|
|
18
18
|
type FlowStepResponse = {
|
|
19
19
|
id: string;
|
|
20
20
|
name: string;
|
|
21
|
-
type: 'event' | 'api' | 'noop';
|
|
21
|
+
type: 'event' | 'api' | 'noop' | 'cron';
|
|
22
22
|
description?: string;
|
|
23
23
|
subscribes?: string[];
|
|
24
24
|
emits: Emit[];
|
|
@@ -28,6 +28,7 @@ type FlowStepResponse = {
|
|
|
28
28
|
bodySchema?: any;
|
|
29
29
|
language?: string;
|
|
30
30
|
nodeComponentPath?: string;
|
|
31
|
+
cronExpression?: string;
|
|
31
32
|
};
|
|
32
33
|
type FlowResponse = FlowListResponse & {
|
|
33
34
|
steps: FlowStepResponse[];
|
|
@@ -107,6 +107,17 @@ const createNoopStepResponse = (step, id) => {
|
|
|
107
107
|
subscribes: step.config.virtualSubscribes,
|
|
108
108
|
};
|
|
109
109
|
};
|
|
110
|
+
const createCronStepResponse = (step, id) => {
|
|
111
|
+
if (!(0, guards_1.isCronStep)(step)) {
|
|
112
|
+
throw new Error('Attempted to create Cron step response with non-Cron step');
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
...createBaseStepResponse(step, id),
|
|
116
|
+
type: 'cron',
|
|
117
|
+
emits: step.config.emits,
|
|
118
|
+
cronExpression: step.config.cron
|
|
119
|
+
};
|
|
120
|
+
};
|
|
110
121
|
const createStepResponse = (step) => {
|
|
111
122
|
const id = (0, crypto_1.randomUUID)();
|
|
112
123
|
if ((0, guards_1.isApiStep)(step))
|
|
@@ -115,6 +126,8 @@ const createStepResponse = (step) => {
|
|
|
115
126
|
return createEventStepResponse(step, id);
|
|
116
127
|
if ((0, guards_1.isNoopStep)(step))
|
|
117
128
|
return createNoopStepResponse(step, id);
|
|
129
|
+
if ((0, guards_1.isCronStep)(step))
|
|
130
|
+
return createCronStepResponse(step, id);
|
|
118
131
|
throw new Error(`Unknown step type for step: ${step.config.name}`);
|
|
119
132
|
};
|
|
120
133
|
const createEdgesForStep = (sourceStep, allSteps) => {
|
package/dist/src/guards.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { ApiRouteConfig, EventConfig, NoopConfig, Step } from './types';
|
|
1
|
+
import { ApiRouteConfig, EventConfig, NoopConfig, Step, CronConfig } from './types';
|
|
2
2
|
export declare const isApiStep: (step: Step) => step is Step<ApiRouteConfig>;
|
|
3
3
|
export declare const isEventStep: (step: Step) => step is Step<EventConfig<any>>;
|
|
4
4
|
export declare const isNoopStep: (step: Step) => step is Step<NoopConfig>;
|
|
5
|
+
export declare const isCronStep: (step: Step) => step is Step<CronConfig>;
|
package/dist/src/guards.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isNoopStep = exports.isEventStep = exports.isApiStep = void 0;
|
|
3
|
+
exports.isCronStep = exports.isNoopStep = exports.isEventStep = exports.isApiStep = void 0;
|
|
4
4
|
const isApiStep = (step) => step.config.type === 'api';
|
|
5
5
|
exports.isApiStep = isApiStep;
|
|
6
6
|
const isEventStep = (step) => step.config.type === 'event';
|
|
7
7
|
exports.isEventStep = isEventStep;
|
|
8
8
|
const isNoopStep = (step) => step.config.type === 'noop';
|
|
9
9
|
exports.isNoopStep = isNoopStep;
|
|
10
|
+
const isCronStep = (step) => step.config.type === 'cron';
|
|
11
|
+
exports.isCronStep = isCronStep;
|
package/dist/src/node/rpc.js
CHANGED
|
@@ -22,8 +22,15 @@ class RpcSender {
|
|
|
22
22
|
if (msg.type === 'rpc_response') {
|
|
23
23
|
const { id, result, error } = msg;
|
|
24
24
|
const callbacks = this.pendingRequests[id];
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
if (!callbacks) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
else if (error) {
|
|
29
|
+
callbacks.reject(error);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
callbacks.resolve(result);
|
|
33
|
+
}
|
|
27
34
|
delete this.pendingRequests[id];
|
|
28
35
|
}
|
|
29
36
|
});
|
package/dist/src/server.d.ts
CHANGED
package/dist/src/server.js
CHANGED
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.createServer = void 0;
|
|
7
|
+
const cron_handler_1 = require("./cron-handler");
|
|
7
8
|
const body_parser_1 = __importDefault(require("body-parser"));
|
|
8
9
|
const crypto_1 = require("crypto");
|
|
9
10
|
const express_1 = __importDefault(require("express"));
|
|
@@ -18,6 +19,8 @@ const createServer = async (options) => {
|
|
|
18
19
|
const app = (0, express_1.default)();
|
|
19
20
|
const server = http_1.default.createServer(app);
|
|
20
21
|
const io = new socket_io_1.Server(server);
|
|
22
|
+
// Setup cron handlers with socket server
|
|
23
|
+
const cleanupCronJobs = (0, cron_handler_1.setupCronHandlers)(steps, eventManager, io);
|
|
21
24
|
const asyncHandler = (step, flows) => {
|
|
22
25
|
return async (req, res) => {
|
|
23
26
|
const traceId = (0, crypto_1.randomUUID)();
|
|
@@ -67,7 +70,13 @@ const createServer = async (options) => {
|
|
|
67
70
|
(0, flows_endpoint_1.flowsEndpoint)(flows, app);
|
|
68
71
|
server.on('error', (error) => {
|
|
69
72
|
console.error('Server error:', error);
|
|
73
|
+
cleanupCronJobs();
|
|
70
74
|
});
|
|
71
|
-
|
|
75
|
+
const close = async () => {
|
|
76
|
+
cleanupCronJobs();
|
|
77
|
+
await io.close();
|
|
78
|
+
server.close();
|
|
79
|
+
};
|
|
80
|
+
return { app, server, socketServer: io, close };
|
|
72
81
|
};
|
|
73
82
|
exports.createServer = createServer;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { StateAdapter } from '../state-adapter';
|
|
2
|
+
export declare class MemoryStateAdapter implements StateAdapter {
|
|
3
|
+
private state;
|
|
4
|
+
init(): Promise<void>;
|
|
5
|
+
get(traceId: string, key: string): Promise<any>;
|
|
6
|
+
set(traceId: string, key: string, value: any): Promise<void>;
|
|
7
|
+
delete(traceId: string, key: string): Promise<void>;
|
|
8
|
+
clear(traceId: string): Promise<void>;
|
|
9
|
+
cleanup(): Promise<void>;
|
|
10
|
+
private _makeKey;
|
|
11
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MemoryStateAdapter = void 0;
|
|
4
|
+
class MemoryStateAdapter {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.state = {};
|
|
7
|
+
}
|
|
8
|
+
async init() {
|
|
9
|
+
this.state = {};
|
|
10
|
+
}
|
|
11
|
+
async get(traceId, key) {
|
|
12
|
+
const fullKey = this._makeKey(traceId, key);
|
|
13
|
+
return this.state[fullKey] ? this.state[fullKey] : null;
|
|
14
|
+
}
|
|
15
|
+
async set(traceId, key, value) {
|
|
16
|
+
const fullKey = this._makeKey(traceId, key);
|
|
17
|
+
this.state[fullKey] = value;
|
|
18
|
+
}
|
|
19
|
+
async delete(traceId, key) {
|
|
20
|
+
const fullKey = this._makeKey(traceId, key);
|
|
21
|
+
delete this.state[fullKey];
|
|
22
|
+
}
|
|
23
|
+
async clear(traceId) {
|
|
24
|
+
const pattern = this._makeKey(traceId, '');
|
|
25
|
+
for (const key in this.state) {
|
|
26
|
+
if (key.startsWith(pattern)) {
|
|
27
|
+
delete this.state[key];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async cleanup() {
|
|
32
|
+
// No cleanup needed for file system
|
|
33
|
+
}
|
|
34
|
+
_makeKey(traceId, key) {
|
|
35
|
+
return `${traceId}:${key}`;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.MemoryStateAdapter = MemoryStateAdapter;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { FileStateAdapter } from './adapters/default-state-adapter';
|
|
2
|
+
import { MemoryStateAdapter } from './adapters/memory-state-adapter';
|
|
2
3
|
import { RedisAdapterConfig, RedisStateAdapter } from './adapters/redis-state-adapter';
|
|
3
4
|
type BaseConfig = {
|
|
4
5
|
adapter: 'default' | 'redis';
|
|
5
6
|
};
|
|
6
7
|
export type AdapterConfig = (BaseConfig & RedisAdapterConfig) | Record<string, unknown>;
|
|
7
|
-
export declare function createStateAdapter(config: Record<string, unknown>): FileStateAdapter | RedisStateAdapter;
|
|
8
|
+
export declare function createStateAdapter(config: Record<string, unknown>): FileStateAdapter | MemoryStateAdapter | RedisStateAdapter;
|
|
8
9
|
export {};
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createStateAdapter = createStateAdapter;
|
|
4
4
|
const default_state_adapter_1 = require("./adapters/default-state-adapter");
|
|
5
|
+
const memory_state_adapter_1 = require("./adapters/memory-state-adapter");
|
|
5
6
|
const redis_state_adapter_1 = require("./adapters/redis-state-adapter");
|
|
6
7
|
function createStateAdapter(config) {
|
|
7
8
|
const { adapter = 'redis', ...adapterConfig } = config;
|
|
@@ -10,6 +11,8 @@ function createStateAdapter(config) {
|
|
|
10
11
|
return new redis_state_adapter_1.RedisStateAdapter(adapterConfig);
|
|
11
12
|
case 'default':
|
|
12
13
|
return new default_state_adapter_1.FileStateAdapter(adapterConfig);
|
|
14
|
+
case 'memory':
|
|
15
|
+
return new memory_state_adapter_1.MemoryStateAdapter();
|
|
13
16
|
default:
|
|
14
17
|
throw new Error(`Unknown state adapter type: ${adapter}`);
|
|
15
18
|
}
|
package/dist/src/types.d.ts
CHANGED
|
@@ -68,7 +68,16 @@ export type ApiResponse = {
|
|
|
68
68
|
body: string | Buffer | Record<string, any>;
|
|
69
69
|
};
|
|
70
70
|
export type ApiRouteHandler = (req: ApiRequest, ctx: FlowContext) => Promise<ApiResponse>;
|
|
71
|
-
export type
|
|
71
|
+
export type CronConfig = {
|
|
72
|
+
type: 'cron';
|
|
73
|
+
name: string;
|
|
74
|
+
description?: string;
|
|
75
|
+
cron: string;
|
|
76
|
+
virtualEmits?: Emit[];
|
|
77
|
+
emits: string[];
|
|
78
|
+
flows: string[];
|
|
79
|
+
};
|
|
80
|
+
export type StepHandler<T> = T extends EventConfig<any> ? EventHandler<T['input']> : T extends ApiRouteConfig ? ApiRouteHandler : T extends CronConfig ? never : never;
|
|
72
81
|
export type MotiaServer = Server<any>;
|
|
73
82
|
export type MotiaSocketServer = SocketIOServer;
|
|
74
83
|
export type Event<TData = unknown> = {
|
|
@@ -83,7 +92,7 @@ export type EventManager = {
|
|
|
83
92
|
emit: <TData>(event: Event<TData>, file?: string) => Promise<void>;
|
|
84
93
|
subscribe: <TData>(event: string, handlerName: string, handler: Handler<TData>) => void;
|
|
85
94
|
};
|
|
86
|
-
export type StepConfig = EventConfig<ZodObject<any>> | NoopConfig | ApiRouteConfig;
|
|
95
|
+
export type StepConfig = EventConfig<ZodObject<any>> | NoopConfig | ApiRouteConfig | CronConfig;
|
|
87
96
|
export type Step<TConfig extends StepConfig = StepConfig> = {
|
|
88
97
|
filePath: string;
|
|
89
98
|
version: string;
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@motiadev/core",
|
|
3
3
|
"main": "dist/index.js",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.11",
|
|
5
5
|
"dependencies": {
|
|
6
|
+
"node-cron": "^3.0.3",
|
|
6
7
|
"body-parser": "^1.20.3",
|
|
7
8
|
"express": "^4.21.2",
|
|
8
9
|
"ioredis": "^5.4.2",
|
|
@@ -15,6 +16,7 @@
|
|
|
15
16
|
"zod-to-json-schema": "^3.24.1"
|
|
16
17
|
},
|
|
17
18
|
"devDependencies": {
|
|
19
|
+
"@types/node-cron": "^3.0.11",
|
|
18
20
|
"@types/body-parser": "^1.19.5",
|
|
19
21
|
"@types/express": "^5.0.0",
|
|
20
22
|
"@types/jest": "^29.5.14",
|
package/tsconfig.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"module": "CommonJS",
|
|
5
|
-
"moduleResolution": "Node",
|
|
6
|
-
"esModuleInterop": true,
|
|
7
|
-
"strict": true,
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
"forceConsistentCasingInFileNames": true,
|
|
10
|
-
"resolveJsonModule": true,
|
|
11
|
-
"allowJs": true,
|
|
12
|
-
"outDir": "./dist",
|
|
13
|
-
"rootDir": ".",
|
|
14
|
-
"baseUrl": ".",
|
|
15
|
-
"declaration": true,
|
|
16
|
-
"jsx": "react-jsx",
|
|
17
|
-
},
|
|
18
|
-
"include": ["**/*.ts", "**/*.js"],
|
|
19
|
-
"exclude": ["node_modules", "dist"]
|
|
20
|
-
}
|