@motiadev/core 0.0.27 → 0.0.29

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 CHANGED
@@ -1,10 +1,11 @@
1
1
  export * from './src/types';
2
- export * from './src/server';
3
- export * from './src/step-handlers';
4
- export * from './src/event-manager';
5
- export * from './src/logger';
6
- export * from './src/state/create-state-adapter';
7
- export * from './src/cron-handler';
8
- export * from './src/guards';
9
- export * from './src/locked-data';
10
- export * from './src/get-step-config';
2
+ export { createServer, MotiaServer } from './src/server';
3
+ export { createStepHandlers, MotiaEventManager } from './src/step-handlers';
4
+ export { createEventManager } from './src/event-manager';
5
+ export { globalLogger, Logger } from './src/logger';
6
+ export { createStateAdapter } from './src/state/create-state-adapter';
7
+ export { setupCronHandlers, CronManager } from './src/cron-handler';
8
+ export { isApiStep, isCronStep, isEventStep, isNoopStep } from './src/guards';
9
+ export { LockedData } from './src/locked-data';
10
+ export { getStepConfig } from './src/get-step-config';
11
+ export { StateAdapter } from './src/state/state-adapter';
package/dist/index.js CHANGED
@@ -14,13 +14,27 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.getStepConfig = exports.LockedData = exports.isNoopStep = exports.isEventStep = exports.isCronStep = exports.isApiStep = exports.setupCronHandlers = exports.createStateAdapter = exports.Logger = exports.globalLogger = exports.createEventManager = exports.createStepHandlers = exports.createServer = void 0;
17
18
  __exportStar(require("./src/types"), exports);
18
- __exportStar(require("./src/server"), exports);
19
- __exportStar(require("./src/step-handlers"), exports);
20
- __exportStar(require("./src/event-manager"), exports);
21
- __exportStar(require("./src/logger"), exports);
22
- __exportStar(require("./src/state/create-state-adapter"), exports);
23
- __exportStar(require("./src/cron-handler"), exports);
24
- __exportStar(require("./src/guards"), exports);
25
- __exportStar(require("./src/locked-data"), exports);
26
- __exportStar(require("./src/get-step-config"), exports);
19
+ var server_1 = require("./src/server");
20
+ Object.defineProperty(exports, "createServer", { enumerable: true, get: function () { return server_1.createServer; } });
21
+ var step_handlers_1 = require("./src/step-handlers");
22
+ Object.defineProperty(exports, "createStepHandlers", { enumerable: true, get: function () { return step_handlers_1.createStepHandlers; } });
23
+ var event_manager_1 = require("./src/event-manager");
24
+ Object.defineProperty(exports, "createEventManager", { enumerable: true, get: function () { return event_manager_1.createEventManager; } });
25
+ var logger_1 = require("./src/logger");
26
+ Object.defineProperty(exports, "globalLogger", { enumerable: true, get: function () { return logger_1.globalLogger; } });
27
+ Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return logger_1.Logger; } });
28
+ var create_state_adapter_1 = require("./src/state/create-state-adapter");
29
+ Object.defineProperty(exports, "createStateAdapter", { enumerable: true, get: function () { return create_state_adapter_1.createStateAdapter; } });
30
+ var cron_handler_1 = require("./src/cron-handler");
31
+ Object.defineProperty(exports, "setupCronHandlers", { enumerable: true, get: function () { return cron_handler_1.setupCronHandlers; } });
32
+ var guards_1 = require("./src/guards");
33
+ Object.defineProperty(exports, "isApiStep", { enumerable: true, get: function () { return guards_1.isApiStep; } });
34
+ Object.defineProperty(exports, "isCronStep", { enumerable: true, get: function () { return guards_1.isCronStep; } });
35
+ Object.defineProperty(exports, "isEventStep", { enumerable: true, get: function () { return guards_1.isEventStep; } });
36
+ Object.defineProperty(exports, "isNoopStep", { enumerable: true, get: function () { return guards_1.isNoopStep; } });
37
+ var locked_data_1 = require("./src/locked-data");
38
+ Object.defineProperty(exports, "LockedData", { enumerable: true, get: function () { return locked_data_1.LockedData; } });
39
+ var get_step_config_1 = require("./src/get-step-config");
40
+ Object.defineProperty(exports, "getStepConfig", { enumerable: true, get: function () { return get_step_config_1.getStepConfig; } });
@@ -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;
@@ -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(new Error(`Process exited with code ${code}`));
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, socketServer: Server) => {
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;
@@ -38,12 +38,12 @@ const crypto_1 = require("crypto");
38
38
  const cron = __importStar(require("node-cron"));
39
39
  const call_step_file_1 = require("./call-step-file");
40
40
  const logger_1 = require("./logger");
41
- const setupCronHandlers = (lockedData, eventManager, state, socketServer) => {
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,
@@ -58,7 +58,7 @@ const setupCronHandlers = (lockedData, eventManager, state, socketServer) => {
58
58
  });
59
59
  const task = cron.schedule(cronExpression, async () => {
60
60
  const traceId = (0, crypto_1.randomUUID)();
61
- const logger = new logger_1.Logger(traceId, config.flows, stepName, socketServer);
61
+ const logger = loggerFactory.create({ traceId, flows, stepName });
62
62
  try {
63
63
  await (0, call_step_file_1.callStepFile)({
64
64
  contextInFirstArg: true,
@@ -47,10 +47,18 @@ const getStepConfig = (file) => {
47
47
  return; // Config was already resolved
48
48
  }
49
49
  else if (code !== 0) {
50
- reject(new Error(`Process exited with code ${code}`));
50
+ reject(`Process exited with code ${code}`);
51
51
  }
52
52
  else if (!config) {
53
- reject(new Error(`No config found for file ${file}`));
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
  });
@@ -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
- private logger;
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: unknown): void;
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;
@@ -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 pino_1 = __importDefault(require("pino"));
8
- const isDebugEnabled = () => process.env.LOG_LEVEL === 'debug';
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
- this.logger.info(args, message);
23
+ if (isInfoEnabled) {
24
+ this._log('info', message, args);
25
+ }
24
26
  }
25
27
  error(message, args) {
26
- this.logger.error(args, message);
28
+ this._log('error', message, args);
27
29
  }
28
30
  debug(message, args) {
29
- this.logger.debug(args, message);
31
+ if (isDebugEnabled) {
32
+ this._log('debug', message, args);
33
+ }
30
34
  }
31
35
  warn(message, args) {
32
- this.logger.warn(args, message);
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.logger.info(args);
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
- super.debug(message, args);
56
- if (isDebugEnabled()) {
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
- console.log(JSON.stringify(message));
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;
@@ -14,4 +14,8 @@ export type MotiaServer = {
14
14
  addRoute: (step: Step<ApiRouteConfig>) => void;
15
15
  cronManager: CronManager;
16
16
  };
17
- export declare const createServer: (lockedData: LockedData, eventManager: EventManager, state: StateAdapter) => Promise<MotiaServer>;
17
+ type MotiaServerConfig = {
18
+ isVerbose: boolean;
19
+ };
20
+ export declare const createServer: (lockedData: LockedData, eventManager: EventManager, state: StateAdapter, config: MotiaServerConfig) => Promise<MotiaServer>;
21
+ export {};
@@ -15,18 +15,20 @@ const guards_1 = require("./guards");
15
15
  const logger_1 = require("./logger");
16
16
  const steps_1 = require("./steps");
17
17
  const call_step_file_1 = require("./call-step-file");
18
- const createServer = async (lockedData, eventManager, state) => {
18
+ const LoggerFactory_1 = require("./LoggerFactory");
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, io);
26
+ const cronManager = (0, cron_handler_1.setupCronHandlers)(lockedData, eventManager, state, loggerFactory);
25
27
  const asyncHandler = (step) => {
26
28
  return async (req, res) => {
27
29
  const traceId = (0, crypto_1.randomUUID)();
28
- const { name, flows } = step.config;
29
- const logger = new logger_1.Logger(traceId, flows, name, io);
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,
@@ -69,15 +71,21 @@ const createServer = async (lockedData, eventManager, state) => {
69
71
  const addRoute = (step) => {
70
72
  const { method, path } = step.config;
71
73
  logger_1.globalLogger.debug('[API] Registering route', step.config);
72
- if (method === 'POST') {
73
- router.post(path, asyncHandler(step));
74
- }
75
- else if (method === 'GET') {
76
- router.get(path, asyncHandler(step));
77
- }
78
- else {
74
+ const handler = asyncHandler(step);
75
+ const methods = {
76
+ GET: () => router.get(path, handler),
77
+ POST: () => router.post(path, handler),
78
+ PUT: () => router.put(path, handler),
79
+ DELETE: () => router.delete(path, handler),
80
+ PATCH: () => router.patch(path, handler),
81
+ OPTIONS: () => router.options(path, handler),
82
+ HEAD: () => router.head(path, handler),
83
+ };
84
+ const methodHandler = methods[method];
85
+ if (!methodHandler) {
79
86
  throw new Error(`Unsupported method: ${method}`);
80
87
  }
88
+ methodHandler();
81
89
  };
82
90
  const removeRoute = (step) => {
83
91
  const { path, method } = step.config;
@@ -10,6 +10,8 @@ export declare class FileStateAdapter implements StateAdapter {
10
10
  set<T>(traceId: string, key: string, value: T): Promise<void>;
11
11
  delete(traceId: string, key: string): Promise<void>;
12
12
  clear(traceId: string): Promise<void>;
13
+ keys(traceId: string): Promise<string[]>;
14
+ traceIds(): Promise<string[]>;
13
15
  cleanup(): Promise<void>;
14
16
  private _makeKey;
15
17
  private _readFile;
@@ -59,31 +59,43 @@ class FileStateAdapter {
59
59
  }
60
60
  }
61
61
  async get(traceId, key) {
62
- const data = await this._readFile();
62
+ const data = this._readFile();
63
63
  const fullKey = this._makeKey(traceId, key);
64
64
  return data[fullKey] ? JSON.parse(data[fullKey]) : null;
65
65
  }
66
66
  async set(traceId, key, value) {
67
- const data = await this._readFile();
67
+ const data = this._readFile();
68
68
  const fullKey = this._makeKey(traceId, key);
69
69
  data[fullKey] = JSON.stringify(value);
70
- await this._writeFile(data);
70
+ this._writeFile(data);
71
71
  }
72
72
  async delete(traceId, key) {
73
- const data = await this._readFile();
73
+ const data = this._readFile();
74
74
  const fullKey = this._makeKey(traceId, key);
75
75
  delete data[fullKey];
76
- await this._writeFile(data);
76
+ this._writeFile(data);
77
77
  }
78
78
  async clear(traceId) {
79
- const data = await this._readFile();
79
+ const data = this._readFile();
80
80
  const pattern = this._makeKey(traceId, '');
81
81
  for (const key in data) {
82
82
  if (key.startsWith(pattern)) {
83
83
  delete data[key];
84
84
  }
85
85
  }
86
- await this._writeFile(data);
86
+ this._writeFile(data);
87
+ }
88
+ async keys(traceId) {
89
+ const data = this._readFile();
90
+ return Object.keys(data)
91
+ .filter((key) => key.startsWith(this._makeKey(traceId, '')))
92
+ .map((key) => key.replace(this._makeKey(traceId, ''), ''));
93
+ }
94
+ async traceIds() {
95
+ const data = this._readFile();
96
+ const traceIds = new Set();
97
+ Object.keys(data).forEach((key) => traceIds.add(key.split(':')[0]));
98
+ return Array.from(traceIds);
87
99
  }
88
100
  async cleanup() {
89
101
  // No cleanup needed for file system
@@ -91,11 +103,11 @@ class FileStateAdapter {
91
103
  _makeKey(traceId, key) {
92
104
  return `${traceId}:${key}`;
93
105
  }
94
- async _readFile() {
106
+ _readFile() {
95
107
  const content = fs_1.default.readFileSync(this.filePath, 'utf-8');
96
108
  return JSON.parse(content);
97
109
  }
98
- async _writeFile(data) {
110
+ _writeFile(data) {
99
111
  fs_1.default.writeFileSync(this.filePath, JSON.stringify(data, null, 2), 'utf-8');
100
112
  }
101
113
  }
@@ -6,6 +6,8 @@ export declare class MemoryStateAdapter implements StateAdapter {
6
6
  set<T>(traceId: string, key: string, value: T): Promise<void>;
7
7
  delete(traceId: string, key: string): Promise<void>;
8
8
  clear(traceId: string): Promise<void>;
9
+ keys(traceId: string): Promise<string[]>;
10
+ traceIds(): Promise<string[]>;
9
11
  cleanup(): Promise<void>;
10
12
  private _makeKey;
11
13
  }
@@ -28,6 +28,16 @@ class MemoryStateAdapter {
28
28
  }
29
29
  }
30
30
  }
31
+ async keys(traceId) {
32
+ return Object.keys(this.state)
33
+ .filter((key) => key.startsWith(this._makeKey(traceId, '')))
34
+ .map((key) => key.replace(this._makeKey(traceId, ''), ''));
35
+ }
36
+ async traceIds() {
37
+ const traceIds = new Set();
38
+ Object.keys(this.state).forEach((key) => traceIds.add(key.split(':')[0]));
39
+ return Array.from(traceIds);
40
+ }
31
41
  async cleanup() {
32
42
  // No cleanup needed for file system
33
43
  }
@@ -14,6 +14,8 @@ export declare class RedisStateAdapter implements StateAdapter {
14
14
  set<T>(traceId: string, key: string, value: T): Promise<void>;
15
15
  delete(traceId: string, key: string): Promise<void>;
16
16
  clear(traceId: string): Promise<void>;
17
+ keys(traceId: string): Promise<string[]>;
18
+ traceIds(): Promise<string[]>;
17
19
  cleanup(): Promise<void>;
18
20
  _makeKey(traceId: string, key: string): string;
19
21
  }
@@ -34,6 +34,16 @@ class RedisStateAdapter {
34
34
  await this.client.del(keys);
35
35
  }
36
36
  }
37
+ async keys(traceId) {
38
+ const pattern = this._makeKey(traceId, '*');
39
+ const keys = await this.client.keys(pattern);
40
+ return keys.map((key) => key.replace(this._makeKey(traceId, ''), ''));
41
+ }
42
+ async traceIds() {
43
+ const pattern = `${this.prefix}:*`;
44
+ const keys = await this.client.keys(pattern);
45
+ return keys.map((key) => key.split(':')[1]);
46
+ }
37
47
  async cleanup() {
38
48
  await this.client.quit();
39
49
  }
@@ -7,4 +7,6 @@ export interface StateAdapter {
7
7
  delete(traceId: string, key: string): Promise<void>;
8
8
  clear(traceId: string): Promise<void>;
9
9
  cleanup(): Promise<void>;
10
+ keys(traceId: string): Promise<string[]>;
11
+ traceIds(): Promise<string[]>;
10
12
  }
@@ -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
- logger_1.globalLogger.error(`[step handler] error calling step`, {
42
- error: error.message,
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
  });
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.27",
4
+ "version": "0.0.29",
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",