@motiadev/core 0.17.0-beta.181 → 0.17.0-beta.182-326905
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/call-step-file.mjs +20 -20
- package/dist/src/call-step-file.mjs.map +1 -1
- package/dist/src/observability/create-trace.mjs +1 -5
- package/dist/src/observability/create-trace.mjs.map +1 -1
- package/dist/src/observability/stream-tracer.mjs +0 -23
- package/dist/src/observability/stream-tracer.mjs.map +1 -1
- package/dist/src/observability/trace-manager.mjs +0 -1
- package/dist/src/observability/trace-manager.mjs.map +1 -1
- package/dist/src/observability/tracer.mjs +3 -9
- package/dist/src/observability/tracer.mjs.map +1 -1
- package/dist/src/observability/types.d.mts.map +1 -1
- package/dist/src/python/can-access.py +2 -2
- package/dist/src/python/get-config.py +2 -2
- package/dist/src/python/python-runner.py +2 -2
- package/dist/src/server.mjs +4 -1
- package/dist/src/server.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -50,7 +50,7 @@ const callStepFile = (options, motia) => {
|
|
|
50
50
|
step: step.config.name,
|
|
51
51
|
timeout: timeoutSeconds
|
|
52
52
|
});
|
|
53
|
-
|
|
53
|
+
tracer.end({ message: errorMessage });
|
|
54
54
|
trackEvent("step_execution_timeout", {
|
|
55
55
|
stepName: step.config.name,
|
|
56
56
|
traceId,
|
|
@@ -68,22 +68,22 @@ const callStepFile = (options, motia) => {
|
|
|
68
68
|
traceId,
|
|
69
69
|
message: err.message
|
|
70
70
|
});
|
|
71
|
-
|
|
71
|
+
tracer.end({
|
|
72
72
|
message: err.message,
|
|
73
73
|
code: err.code,
|
|
74
74
|
stack: err.stack?.replace(/* @__PURE__ */ new RegExp(`${motia.lockedData.baseDir}/`), "")
|
|
75
75
|
});
|
|
76
76
|
reject(err ?? /* @__PURE__ */ new Error("Handler execution failed"));
|
|
77
|
-
} else
|
|
77
|
+
} else tracer.end();
|
|
78
78
|
processManager.kill();
|
|
79
79
|
});
|
|
80
80
|
processManager.handler("log", async (input) => logger.log(input));
|
|
81
81
|
processManager.handler("state.get", async (input) => {
|
|
82
|
-
|
|
82
|
+
tracer.stateOperation("get", input);
|
|
83
83
|
return motia.state.get(input.traceId, input.key);
|
|
84
84
|
});
|
|
85
85
|
processManager.handler("state.set", async (input) => {
|
|
86
|
-
|
|
86
|
+
tracer.stateOperation("set", {
|
|
87
87
|
traceId: input.traceId,
|
|
88
88
|
key: input.key,
|
|
89
89
|
value: input.value
|
|
@@ -91,15 +91,15 @@ const callStepFile = (options, motia) => {
|
|
|
91
91
|
return motia.state.set(input.traceId, input.key, input.value);
|
|
92
92
|
});
|
|
93
93
|
processManager.handler("state.delete", async (input) => {
|
|
94
|
-
|
|
94
|
+
tracer.stateOperation("delete", input);
|
|
95
95
|
return motia.state.delete(input.traceId, input.key);
|
|
96
96
|
});
|
|
97
97
|
processManager.handler("state.clear", async (input) => {
|
|
98
|
-
|
|
98
|
+
tracer.stateOperation("clear", input);
|
|
99
99
|
return motia.state.clear(input.traceId);
|
|
100
100
|
});
|
|
101
101
|
processManager.handler(`state.getGroup`, async (input) => {
|
|
102
|
-
|
|
102
|
+
tracer.stateOperation("getGroup", input);
|
|
103
103
|
return motia.state.getGroup(input.groupId);
|
|
104
104
|
});
|
|
105
105
|
processManager.handler("result", async (input) => {
|
|
@@ -110,10 +110,10 @@ const callStepFile = (options, motia) => {
|
|
|
110
110
|
processManager.handler("emit", async (input) => {
|
|
111
111
|
const flows$1 = step.config.flows;
|
|
112
112
|
if (!isAllowedToEmit(step, input.topic)) {
|
|
113
|
-
|
|
113
|
+
tracer.emitOperation(input.topic, input.data, false);
|
|
114
114
|
return motia.printer.printInvalidEmit(step, input.topic);
|
|
115
115
|
}
|
|
116
|
-
|
|
116
|
+
tracer.emitOperation(input.topic, input.data, true);
|
|
117
117
|
return motia.eventAdapter.emit({
|
|
118
118
|
...input,
|
|
119
119
|
traceId,
|
|
@@ -125,11 +125,11 @@ const callStepFile = (options, motia) => {
|
|
|
125
125
|
Object.entries(streamConfig).forEach(([name, streamFactory]) => {
|
|
126
126
|
const stateStream = streamFactory();
|
|
127
127
|
processManager.handler(`streams.${name}.get`, async (input) => {
|
|
128
|
-
|
|
128
|
+
tracer.streamOperation(name, "get", input);
|
|
129
129
|
return stateStream.get(input.groupId, input.id);
|
|
130
130
|
});
|
|
131
131
|
processManager.handler(`streams.${name}.set`, async (input) => {
|
|
132
|
-
|
|
132
|
+
tracer.streamOperation(name, "set", {
|
|
133
133
|
groupId: input.groupId,
|
|
134
134
|
id: input.id,
|
|
135
135
|
data: input.data
|
|
@@ -137,15 +137,15 @@ const callStepFile = (options, motia) => {
|
|
|
137
137
|
return stateStream.set(input.groupId, input.id, input.data);
|
|
138
138
|
});
|
|
139
139
|
processManager.handler(`streams.${name}.delete`, async (input) => {
|
|
140
|
-
|
|
140
|
+
tracer.streamOperation(name, "delete", input);
|
|
141
141
|
return stateStream.delete(input.groupId, input.id);
|
|
142
142
|
});
|
|
143
143
|
processManager.handler(`streams.${name}.getGroup`, async (input) => {
|
|
144
|
-
|
|
144
|
+
tracer.streamOperation(name, "getGroup", input);
|
|
145
145
|
return stateStream.getGroup(input.groupId);
|
|
146
146
|
});
|
|
147
147
|
processManager.handler(`streams.${name}.send`, async (input) => {
|
|
148
|
-
|
|
148
|
+
tracer.streamOperation(name, "send", input);
|
|
149
149
|
return stateStream.send(input.channel, input.event);
|
|
150
150
|
});
|
|
151
151
|
});
|
|
@@ -166,7 +166,7 @@ const callStepFile = (options, motia) => {
|
|
|
166
166
|
message: `Process exited with code ${code}`,
|
|
167
167
|
code
|
|
168
168
|
};
|
|
169
|
-
|
|
169
|
+
tracer.end(error);
|
|
170
170
|
trackEvent("step_execution_error", {
|
|
171
171
|
stepName: step.config.name,
|
|
172
172
|
traceId,
|
|
@@ -174,14 +174,14 @@ const callStepFile = (options, motia) => {
|
|
|
174
174
|
});
|
|
175
175
|
reject(`Process exited with code ${code}`);
|
|
176
176
|
} else {
|
|
177
|
-
|
|
177
|
+
tracer.end();
|
|
178
178
|
resolve(result);
|
|
179
179
|
}
|
|
180
180
|
});
|
|
181
181
|
processManager.onProcessError(async (error) => {
|
|
182
182
|
if (timeoutId) clearTimeout(timeoutId);
|
|
183
183
|
processManager.close();
|
|
184
|
-
|
|
184
|
+
tracer.end({
|
|
185
185
|
message: error.message,
|
|
186
186
|
code: error.code,
|
|
187
187
|
stack: error.stack
|
|
@@ -198,7 +198,7 @@ const callStepFile = (options, motia) => {
|
|
|
198
198
|
});
|
|
199
199
|
}).catch(async (error) => {
|
|
200
200
|
if (timeoutId) clearTimeout(timeoutId);
|
|
201
|
-
|
|
201
|
+
tracer.end({
|
|
202
202
|
message: error.message,
|
|
203
203
|
code: error.code,
|
|
204
204
|
stack: error.stack
|
|
@@ -214,7 +214,7 @@ const callStepFile = (options, motia) => {
|
|
|
214
214
|
});
|
|
215
215
|
} catch (error) {
|
|
216
216
|
const err = error;
|
|
217
|
-
|
|
217
|
+
tracer.end({
|
|
218
218
|
message: err.message,
|
|
219
219
|
code: err.code,
|
|
220
220
|
stack: err.stack
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"call-step-file.mjs","names":["result: TData | undefined","timeoutId: NodeJS.Timeout | undefined","flows","data","error: unknown"],"sources":["../../src/call-step-file.ts"],"sourcesContent":["import { trackEvent } from './analytics/utils'\nimport { getLanguageBasedRunner } from './language-runner'\nimport type { Logger } from './logger'\nimport type { Motia } from './motia'\nimport type { Tracer } from './observability'\nimport type { TraceError } from './observability/types'\nimport { ProcessManager } from './process-communication/process-manager'\nimport { compile } from './ts-compiler'\nimport type { Event, InfrastructureConfig, Step } from './types'\nimport type { BaseStreamItem, StateStreamEvent, StateStreamEventChannel } from './types-stream'\nimport { isAllowedToEmit } from './utils'\n\ntype StateGetInput = { traceId: string; key: string }\ntype StateSetInput = { traceId: string; key: string; value: unknown }\ntype StateDeleteInput = { traceId: string; key: string }\ntype StateClearInput = { traceId: string }\n\ntype StateStreamGetInput = { groupId: string; id: string }\ntype StateStreamSendInput = { channel: StateStreamEventChannel; event: StateStreamEvent<unknown> }\ntype StateStreamMutateInput = { groupId: string; id: string; data: BaseStreamItem }\n\ntype CallStepFileOptions = {\n step: Step\n traceId: string\n data?: unknown\n contextInFirstArg?: boolean\n logger: Logger\n tracer: Tracer\n infrastructure?: Partial<InfrastructureConfig>\n}\n\nexport const callStepFile = <TData>(options: CallStepFileOptions, motia: Motia): Promise<TData | undefined> => {\n const { step, traceId, data, tracer, logger, contextInFirstArg = false, infrastructure } = options\n\n const flows = step.config.flows\n\n return (async () => {\n try {\n const streamConfig = motia.lockedData.getStreams()\n const streams = Object.keys(streamConfig).map((name) => ({ name }))\n const jsonData = JSON.stringify({ data, flows, traceId, contextInFirstArg, streams })\n\n const filePathToExecute = step.filePath.endsWith('.ts')\n ? await compile(step.filePath, motia.lockedData.baseDir)\n : step.filePath\n\n const { runner, command, args } = getLanguageBasedRunner(step.filePath)\n let result: TData | undefined\n let timeoutId: NodeJS.Timeout | undefined\n\n return new Promise<TData | undefined>((resolve, reject) => {\n const processManager = new ProcessManager({\n command,\n args: [...args, runner, filePathToExecute, jsonData],\n logger,\n context: 'StepExecution',\n projectRoot: motia.lockedData.baseDir,\n })\n\n trackEvent('step_execution_started', {\n stepName: step.config.name,\n language: command,\n type: step.config.type,\n streams: streams.length,\n })\n\n const timeoutSeconds = infrastructure?.handler?.timeout\n if (timeoutSeconds) {\n timeoutId = setTimeout(async () => {\n processManager.kill()\n const errorMessage = `Step execution timed out after ${timeoutSeconds} seconds`\n logger.error(errorMessage, { step: step.config.name, timeout: timeoutSeconds })\n await tracer.end({ message: errorMessage })\n trackEvent('step_execution_timeout', {\n stepName: step.config.name,\n traceId,\n timeout: timeoutSeconds,\n })\n reject(new Error(errorMessage))\n }, timeoutSeconds * 1000)\n }\n\n processManager\n .spawn()\n .then(() => {\n processManager.handler<TraceError | undefined>('close', async (err) => {\n if (err) {\n if (timeoutId) clearTimeout(timeoutId)\n processManager.close()\n\n trackEvent('step_execution_error', {\n stepName: step.config.name,\n traceId,\n message: err.message,\n })\n\n await tracer.end({\n message: err.message,\n code: err.code,\n stack: err.stack?.replace(new RegExp(`${motia.lockedData.baseDir}/`), ''),\n })\n\n const error = err ?? new Error('Handler execution failed')\n\n reject(error)\n } else {\n await tracer.end()\n }\n\n processManager.kill()\n })\n processManager.handler<unknown>('log', async (input: unknown) => logger.log(input))\n\n processManager.handler<StateGetInput, unknown>('state.get', async (input) => {\n await tracer.stateOperation('get', input)\n return motia.state.get(input.traceId, input.key)\n })\n\n processManager.handler<StateSetInput, unknown>('state.set', async (input) => {\n await tracer.stateOperation('set', { traceId: input.traceId, key: input.key, value: input.value })\n return motia.state.set(input.traceId, input.key, input.value)\n })\n\n processManager.handler<StateDeleteInput, unknown>('state.delete', async (input) => {\n await tracer.stateOperation('delete', input)\n return motia.state.delete(input.traceId, input.key)\n })\n\n processManager.handler<StateClearInput, void>('state.clear', async (input) => {\n await tracer.stateOperation('clear', input)\n return motia.state.clear(input.traceId)\n })\n\n processManager.handler<StateStreamGetInput>(`state.getGroup`, async (input) => {\n await tracer.stateOperation('getGroup', input)\n return motia.state.getGroup(input.groupId)\n })\n\n processManager.handler<TData, void>('result', async (input) => {\n const inputWithBody = input as TData & { body?: { type?: string; data?: number[] } }\n\n if (inputWithBody.body && inputWithBody.body.type === 'Buffer') {\n inputWithBody.body = Buffer.from(inputWithBody.body.data || []) as unknown as typeof inputWithBody.body\n }\n result = inputWithBody as TData\n })\n\n processManager.handler<Event, unknown>('emit', async (input) => {\n const flows = step.config.flows\n\n if (!isAllowedToEmit(step, input.topic)) {\n await tracer.emitOperation(input.topic, input.data, false)\n return motia.printer.printInvalidEmit(step, input.topic)\n }\n\n await tracer.emitOperation(input.topic, input.data, true)\n return motia.eventAdapter.emit({ ...input, traceId, flows, logger, tracer })\n })\n\n Object.entries(streamConfig).forEach(([name, streamFactory]) => {\n const stateStream = streamFactory()\n\n processManager.handler<StateStreamGetInput>(`streams.${name}.get`, async (input) => {\n await tracer.streamOperation(name, 'get', input)\n return stateStream.get(input.groupId, input.id)\n })\n\n processManager.handler<StateStreamMutateInput>(`streams.${name}.set`, async (input) => {\n await tracer.streamOperation(name, 'set', { groupId: input.groupId, id: input.id, data: input.data })\n return stateStream.set(input.groupId, input.id, input.data)\n })\n\n processManager.handler<StateStreamGetInput>(`streams.${name}.delete`, async (input) => {\n await tracer.streamOperation(name, 'delete', input)\n return stateStream.delete(input.groupId, input.id)\n })\n\n processManager.handler<StateStreamGetInput>(`streams.${name}.getGroup`, async (input) => {\n await tracer.streamOperation(name, 'getGroup', input)\n return stateStream.getGroup(input.groupId)\n })\n\n processManager.handler<StateStreamSendInput>(`streams.${name}.send`, async (input) => {\n await tracer.streamOperation(name, 'send', input)\n return stateStream.send(input.channel, input.event)\n })\n })\n\n processManager.onStdout((data) => {\n try {\n const message = JSON.parse(data.toString())\n logger.log(message)\n } catch {\n logger.info(Buffer.from(data).toString())\n }\n })\n\n processManager.onStderr((data) => logger.error(Buffer.from(data).toString()))\n\n processManager.onProcessClose(async (code) => {\n if (timeoutId) clearTimeout(timeoutId)\n processManager.close()\n\n if (code !== 0 && code !== null) {\n const error = { message: `Process exited with code ${code}`, code }\n await tracer.end(error)\n trackEvent('step_execution_error', { stepName: step.config.name, traceId, code })\n reject(`Process exited with code ${code}`)\n } else {\n await tracer.end()\n resolve(result)\n }\n })\n\n processManager.onProcessError(async (error) => {\n if (timeoutId) clearTimeout(timeoutId)\n processManager.close()\n await tracer.end({\n message: error.message,\n code: error.code,\n stack: error.stack,\n })\n\n if (error.code === 'ENOENT') {\n trackEvent('step_execution_error', {\n stepName: step.config.name,\n traceId,\n code: error.code,\n message: error.message,\n })\n reject(`Executable ${command} not found`)\n } else {\n reject(error)\n }\n })\n })\n .catch(async (error) => {\n if (timeoutId) clearTimeout(timeoutId)\n await tracer.end({\n message: error.message,\n code: error.code,\n stack: error.stack,\n })\n\n trackEvent('step_execution_error', {\n stepName: step.config.name,\n traceId,\n code: error.code,\n message: error.message,\n })\n reject(`Failed to spawn process: ${error}`)\n })\n })\n } catch (error: unknown) {\n const err = error as Error & { code?: string }\n await tracer.end({\n message: err.message,\n code: err.code,\n stack: err.stack,\n })\n trackEvent('step_execution_error', {\n stepName: step.config.name,\n traceId,\n code: err.code,\n message: err.message,\n })\n throw err\n }\n })()\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"call-step-file.mjs","names":["result: TData | undefined","timeoutId: NodeJS.Timeout | undefined","flows","data","error: unknown"],"sources":["../../src/call-step-file.ts"],"sourcesContent":["import { trackEvent } from './analytics/utils'\nimport { getLanguageBasedRunner } from './language-runner'\nimport type { Logger } from './logger'\nimport type { Motia } from './motia'\nimport type { Tracer } from './observability'\nimport type { TraceError } from './observability/types'\nimport { ProcessManager } from './process-communication/process-manager'\nimport { compile } from './ts-compiler'\nimport type { Event, InfrastructureConfig, Step } from './types'\nimport type { BaseStreamItem, StateStreamEvent, StateStreamEventChannel } from './types-stream'\nimport { isAllowedToEmit } from './utils'\n\ntype StateGetInput = { traceId: string; key: string }\ntype StateSetInput = { traceId: string; key: string; value: unknown }\ntype StateDeleteInput = { traceId: string; key: string }\ntype StateClearInput = { traceId: string }\n\ntype StateStreamGetInput = { groupId: string; id: string }\ntype StateStreamSendInput = { channel: StateStreamEventChannel; event: StateStreamEvent<unknown> }\ntype StateStreamMutateInput = { groupId: string; id: string; data: BaseStreamItem }\n\ntype CallStepFileOptions = {\n step: Step\n traceId: string\n data?: unknown\n contextInFirstArg?: boolean\n logger: Logger\n tracer: Tracer\n infrastructure?: Partial<InfrastructureConfig>\n}\n\nexport const callStepFile = <TData>(options: CallStepFileOptions, motia: Motia): Promise<TData | undefined> => {\n const { step, traceId, data, tracer, logger, contextInFirstArg = false, infrastructure } = options\n\n const flows = step.config.flows\n\n return (async () => {\n try {\n const streamConfig = motia.lockedData.getStreams()\n const streams = Object.keys(streamConfig).map((name) => ({ name }))\n const jsonData = JSON.stringify({ data, flows, traceId, contextInFirstArg, streams })\n\n const filePathToExecute = step.filePath.endsWith('.ts')\n ? await compile(step.filePath, motia.lockedData.baseDir)\n : step.filePath\n\n const { runner, command, args } = getLanguageBasedRunner(step.filePath)\n let result: TData | undefined\n let timeoutId: NodeJS.Timeout | undefined\n\n return new Promise<TData | undefined>((resolve, reject) => {\n const processManager = new ProcessManager({\n command,\n args: [...args, runner, filePathToExecute, jsonData],\n logger,\n context: 'StepExecution',\n projectRoot: motia.lockedData.baseDir,\n })\n\n trackEvent('step_execution_started', {\n stepName: step.config.name,\n language: command,\n type: step.config.type,\n streams: streams.length,\n })\n\n const timeoutSeconds = infrastructure?.handler?.timeout\n if (timeoutSeconds) {\n timeoutId = setTimeout(async () => {\n processManager.kill()\n const errorMessage = `Step execution timed out after ${timeoutSeconds} seconds`\n logger.error(errorMessage, { step: step.config.name, timeout: timeoutSeconds })\n tracer.end({ message: errorMessage })\n trackEvent('step_execution_timeout', {\n stepName: step.config.name,\n traceId,\n timeout: timeoutSeconds,\n })\n reject(new Error(errorMessage))\n }, timeoutSeconds * 1000)\n }\n\n processManager\n .spawn()\n .then(() => {\n processManager.handler<TraceError | undefined>('close', async (err) => {\n if (err) {\n if (timeoutId) clearTimeout(timeoutId)\n processManager.close()\n\n trackEvent('step_execution_error', {\n stepName: step.config.name,\n traceId,\n message: err.message,\n })\n\n tracer.end({\n message: err.message,\n code: err.code,\n stack: err.stack?.replace(new RegExp(`${motia.lockedData.baseDir}/`), ''),\n })\n\n const error = err ?? new Error('Handler execution failed')\n\n reject(error)\n } else {\n tracer.end()\n }\n\n processManager.kill()\n })\n processManager.handler<unknown>('log', async (input: unknown) => logger.log(input))\n\n processManager.handler<StateGetInput, unknown>('state.get', async (input) => {\n tracer.stateOperation('get', input)\n return motia.state.get(input.traceId, input.key)\n })\n\n processManager.handler<StateSetInput, unknown>('state.set', async (input) => {\n tracer.stateOperation('set', { traceId: input.traceId, key: input.key, value: input.value })\n return motia.state.set(input.traceId, input.key, input.value)\n })\n\n processManager.handler<StateDeleteInput, unknown>('state.delete', async (input) => {\n tracer.stateOperation('delete', input)\n return motia.state.delete(input.traceId, input.key)\n })\n\n processManager.handler<StateClearInput, void>('state.clear', async (input) => {\n tracer.stateOperation('clear', input)\n return motia.state.clear(input.traceId)\n })\n\n processManager.handler<StateStreamGetInput>(`state.getGroup`, async (input) => {\n tracer.stateOperation('getGroup', input)\n return motia.state.getGroup(input.groupId)\n })\n\n processManager.handler<TData, void>('result', async (input) => {\n const inputWithBody = input as TData & { body?: { type?: string; data?: number[] } }\n\n if (inputWithBody.body && inputWithBody.body.type === 'Buffer') {\n inputWithBody.body = Buffer.from(inputWithBody.body.data || []) as unknown as typeof inputWithBody.body\n }\n result = inputWithBody as TData\n })\n\n processManager.handler<Event, unknown>('emit', async (input) => {\n const flows = step.config.flows\n\n if (!isAllowedToEmit(step, input.topic)) {\n tracer.emitOperation(input.topic, input.data, false)\n return motia.printer.printInvalidEmit(step, input.topic)\n }\n\n tracer.emitOperation(input.topic, input.data, true)\n return motia.eventAdapter.emit({ ...input, traceId, flows, logger, tracer })\n })\n\n Object.entries(streamConfig).forEach(([name, streamFactory]) => {\n const stateStream = streamFactory()\n\n processManager.handler<StateStreamGetInput>(`streams.${name}.get`, async (input) => {\n tracer.streamOperation(name, 'get', input)\n return stateStream.get(input.groupId, input.id)\n })\n\n processManager.handler<StateStreamMutateInput>(`streams.${name}.set`, async (input) => {\n tracer.streamOperation(name, 'set', { groupId: input.groupId, id: input.id, data: input.data })\n return stateStream.set(input.groupId, input.id, input.data)\n })\n\n processManager.handler<StateStreamGetInput>(`streams.${name}.delete`, async (input) => {\n tracer.streamOperation(name, 'delete', input)\n return stateStream.delete(input.groupId, input.id)\n })\n\n processManager.handler<StateStreamGetInput>(`streams.${name}.getGroup`, async (input) => {\n tracer.streamOperation(name, 'getGroup', input)\n return stateStream.getGroup(input.groupId)\n })\n\n processManager.handler<StateStreamSendInput>(`streams.${name}.send`, async (input) => {\n tracer.streamOperation(name, 'send', input)\n return stateStream.send(input.channel, input.event)\n })\n })\n\n processManager.onStdout((data) => {\n try {\n const message = JSON.parse(data.toString())\n logger.log(message)\n } catch {\n logger.info(Buffer.from(data).toString())\n }\n })\n\n processManager.onStderr((data) => logger.error(Buffer.from(data).toString()))\n\n processManager.onProcessClose(async (code) => {\n if (timeoutId) clearTimeout(timeoutId)\n processManager.close()\n\n if (code !== 0 && code !== null) {\n const error = { message: `Process exited with code ${code}`, code }\n tracer.end(error)\n trackEvent('step_execution_error', { stepName: step.config.name, traceId, code })\n reject(`Process exited with code ${code}`)\n } else {\n tracer.end()\n resolve(result)\n }\n })\n\n processManager.onProcessError(async (error) => {\n if (timeoutId) clearTimeout(timeoutId)\n processManager.close()\n tracer.end({\n message: error.message,\n code: error.code,\n stack: error.stack,\n })\n\n if (error.code === 'ENOENT') {\n trackEvent('step_execution_error', {\n stepName: step.config.name,\n traceId,\n code: error.code,\n message: error.message,\n })\n reject(`Executable ${command} not found`)\n } else {\n reject(error)\n }\n })\n })\n .catch(async (error) => {\n if (timeoutId) clearTimeout(timeoutId)\n tracer.end({\n message: error.message,\n code: error.code,\n stack: error.stack,\n })\n\n trackEvent('step_execution_error', {\n stepName: step.config.name,\n traceId,\n code: error.code,\n message: error.message,\n })\n reject(`Failed to spawn process: ${error}`)\n })\n })\n } catch (error: unknown) {\n const err = error as Error & { code?: string }\n tracer.end({\n message: err.message,\n code: err.code,\n stack: err.stack,\n })\n trackEvent('step_execution_error', {\n stepName: step.config.name,\n traceId,\n code: err.code,\n message: err.message,\n })\n throw err\n }\n })()\n}\n"],"mappings":"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"}
|
|
@@ -2,10 +2,9 @@ import { randomUUID } from "crypto";
|
|
|
2
2
|
|
|
3
3
|
//#region src/observability/create-trace.ts
|
|
4
4
|
const createTrace = (traceGroup, step) => {
|
|
5
|
-
|
|
5
|
+
return {
|
|
6
6
|
id: randomUUID(),
|
|
7
7
|
name: step.config.name,
|
|
8
|
-
correlationId: traceGroup.correlationId,
|
|
9
8
|
parentTraceId: traceGroup.id,
|
|
10
9
|
status: "running",
|
|
11
10
|
startTime: Date.now(),
|
|
@@ -16,9 +15,6 @@ const createTrace = (traceGroup, step) => {
|
|
|
16
15
|
},
|
|
17
16
|
events: []
|
|
18
17
|
};
|
|
19
|
-
traceGroup.metadata.totalSteps++;
|
|
20
|
-
traceGroup.metadata.activeSteps++;
|
|
21
|
-
return trace;
|
|
22
18
|
};
|
|
23
19
|
|
|
24
20
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-trace.mjs","names":[
|
|
1
|
+
{"version":3,"file":"create-trace.mjs","names":[],"sources":["../../../src/observability/create-trace.ts"],"sourcesContent":["import { randomUUID } from 'crypto'\nimport type { Step } from '../types'\nimport type { Trace, TraceGroup } from './types'\n\nexport const createTrace = (traceGroup: TraceGroup, step: Step) => {\n const id = randomUUID()\n const trace: Trace = {\n id,\n name: step.config.name,\n parentTraceId: traceGroup.id,\n status: 'running',\n startTime: Date.now(),\n endTime: undefined,\n entryPoint: { type: step.config.type, stepName: step.config.name },\n events: [],\n }\n\n return trace\n}\n"],"mappings":";;;AAIA,MAAa,eAAe,YAAwB,SAAe;AAajE,QAXqB;EACnB,IAFS,YAAY;EAGrB,MAAM,KAAK,OAAO;EAClB,eAAe,WAAW;EAC1B,QAAQ;EACR,WAAW,KAAK,KAAK;EACrB,SAAS;EACT,YAAY;GAAE,MAAM,KAAK,OAAO;GAAM,UAAU,KAAK,OAAO;GAAM;EAClE,QAAQ,EAAE;EACX"}
|
|
@@ -22,25 +22,6 @@ var StreamTracer = class StreamTracer {
|
|
|
22
22
|
this.trace.endTime = Date.now();
|
|
23
23
|
this.trace.error = err;
|
|
24
24
|
await this.manager.updateTrace();
|
|
25
|
-
await this.recomputeTraceGroupStatus();
|
|
26
|
-
await this.manager.updateTraceGroup();
|
|
27
|
-
}
|
|
28
|
-
async recomputeTraceGroupStatus() {
|
|
29
|
-
const allTracesFromStorage = await this.manager.getAllTracesForGroup();
|
|
30
|
-
const currentTraceIndex = allTracesFromStorage.findIndex((t) => t.id === this.trace.id);
|
|
31
|
-
const allTraces = [...allTracesFromStorage];
|
|
32
|
-
if (currentTraceIndex >= 0) allTraces[currentTraceIndex] = this.trace;
|
|
33
|
-
else allTraces.push(this.trace);
|
|
34
|
-
const completedCount = allTraces.filter((t) => t.status === "completed").length;
|
|
35
|
-
const failedCount = allTraces.filter((t) => t.status === "failed").length;
|
|
36
|
-
const runningCount = allTraces.filter((t) => t.status === "running").length;
|
|
37
|
-
this.traceGroup.metadata.completedSteps = completedCount;
|
|
38
|
-
this.traceGroup.metadata.activeSteps = runningCount;
|
|
39
|
-
if (failedCount > 0) this.traceGroup.status = "failed";
|
|
40
|
-
else if (runningCount === 0 && completedCount > 0) {
|
|
41
|
-
this.traceGroup.status = "completed";
|
|
42
|
-
if (!this.traceGroup.endTime) this.traceGroup.endTime = Date.now();
|
|
43
|
-
} else this.traceGroup.status = "running";
|
|
44
25
|
}
|
|
45
26
|
async stateOperation(operation, input) {
|
|
46
27
|
await this.addEvent({
|
|
@@ -66,9 +47,7 @@ var StreamTracer = class StreamTracer {
|
|
|
66
47
|
lastEvent.calls++;
|
|
67
48
|
lastEvent.data.data = input.data;
|
|
68
49
|
lastEvent.maxTimestamp = Date.now();
|
|
69
|
-
this.traceGroup.lastActivity = lastEvent.maxTimestamp;
|
|
70
50
|
await this.manager.updateTrace();
|
|
71
|
-
await this.manager.updateTraceGroup();
|
|
72
51
|
return;
|
|
73
52
|
}
|
|
74
53
|
}
|
|
@@ -87,9 +66,7 @@ var StreamTracer = class StreamTracer {
|
|
|
87
66
|
}
|
|
88
67
|
async addEvent(event) {
|
|
89
68
|
this.trace.events.push(event);
|
|
90
|
-
this.traceGroup.lastActivity = event.timestamp;
|
|
91
69
|
await this.manager.updateTrace();
|
|
92
|
-
await this.manager.updateTraceGroup();
|
|
93
70
|
}
|
|
94
71
|
};
|
|
95
72
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-tracer.mjs","names":["manager: TraceManager","traceGroup: TraceGroup","trace: Trace"],"sources":["../../../src/observability/stream-tracer.ts"],"sourcesContent":["import type { Logger } from '../logger'\nimport type { Step } from '../types'\nimport { createTrace } from './create-trace'\nimport type { Tracer } from './index'\nimport type { TraceManager } from './trace-manager'\nimport type { StateOperation, StreamOperation, Trace, TraceError, TraceEvent, TraceGroup } from './types'\n\nexport class StreamTracer implements Tracer {\n constructor(\n private readonly manager: TraceManager,\n private readonly traceGroup: TraceGroup,\n private readonly trace: Trace,\n logger: Logger,\n ) {\n logger.addListener(async (level, msg, args) => {\n await this.addEvent({\n type: 'log',\n timestamp: Date.now(),\n level,\n message: msg,\n metadata: args,\n })\n })\n }\n\n async end(err?: TraceError) {\n if (this.trace.endTime) {\n return\n }\n\n this.trace.status = err ? 'failed' : 'completed'\n this.trace.endTime = Date.now()\n this.trace.error = err\n\n await this.manager.updateTrace()\n
|
|
1
|
+
{"version":3,"file":"stream-tracer.mjs","names":["manager: TraceManager","traceGroup: TraceGroup","trace: Trace"],"sources":["../../../src/observability/stream-tracer.ts"],"sourcesContent":["import type { Logger } from '../logger'\nimport type { Step } from '../types'\nimport { createTrace } from './create-trace'\nimport type { Tracer } from './index'\nimport type { TraceManager } from './trace-manager'\nimport type { StateOperation, StreamOperation, Trace, TraceError, TraceEvent, TraceGroup } from './types'\n\nexport class StreamTracer implements Tracer {\n constructor(\n private readonly manager: TraceManager,\n private readonly traceGroup: TraceGroup,\n private readonly trace: Trace,\n logger: Logger,\n ) {\n logger.addListener(async (level, msg, args) => {\n await this.addEvent({\n type: 'log',\n timestamp: Date.now(),\n level,\n message: msg,\n metadata: args,\n })\n })\n }\n\n async end(err?: TraceError) {\n if (this.trace.endTime) {\n return\n }\n\n this.trace.status = err ? 'failed' : 'completed'\n this.trace.endTime = Date.now()\n this.trace.error = err\n\n await this.manager.updateTrace()\n }\n\n async stateOperation(operation: StateOperation, input: unknown) {\n await this.addEvent({\n type: 'state',\n timestamp: Date.now(),\n operation,\n data: input,\n })\n }\n\n async emitOperation(topic: string, data: unknown, success: boolean) {\n await this.addEvent({\n type: 'emit',\n timestamp: Date.now(),\n topic,\n success,\n data,\n })\n }\n\n async streamOperation(\n streamName: string,\n operation: StreamOperation,\n input: { groupId: string; id: string; data?: unknown },\n ) {\n if (operation === 'set') {\n const lastEvent = this.trace.events[this.trace.events.length - 1]\n\n if (\n lastEvent &&\n lastEvent.type === 'stream' &&\n lastEvent.streamName === streamName &&\n lastEvent.data.groupId === input.groupId &&\n lastEvent.data.id === input.id\n ) {\n lastEvent.calls++\n lastEvent.data.data = input.data\n lastEvent.maxTimestamp = Date.now()\n\n await this.manager.updateTrace()\n\n return\n }\n }\n\n await this.addEvent({\n type: 'stream',\n timestamp: Date.now(),\n operation,\n data: input,\n streamName,\n calls: 1,\n })\n }\n\n child(step: Step, logger: Logger) {\n const trace = createTrace(this.traceGroup, step)\n const manager = this.manager.child(trace)\n\n return new StreamTracer(manager, this.traceGroup, trace, logger)\n }\n\n private async addEvent(event: TraceEvent) {\n this.trace.events.push(event)\n\n await this.manager.updateTrace()\n }\n}\n"],"mappings":";;;AAOA,IAAa,eAAb,MAAa,aAA+B;CAC1C,YACE,AAAiBA,SACjB,AAAiBC,YACjB,AAAiBC,OACjB,QACA;EAJiB;EACA;EACA;AAGjB,SAAO,YAAY,OAAO,OAAO,KAAK,SAAS;AAC7C,SAAM,KAAK,SAAS;IAClB,MAAM;IACN,WAAW,KAAK,KAAK;IACrB;IACA,SAAS;IACT,UAAU;IACX,CAAC;IACF;;CAGJ,MAAM,IAAI,KAAkB;AAC1B,MAAI,KAAK,MAAM,QACb;AAGF,OAAK,MAAM,SAAS,MAAM,WAAW;AACrC,OAAK,MAAM,UAAU,KAAK,KAAK;AAC/B,OAAK,MAAM,QAAQ;AAEnB,QAAM,KAAK,QAAQ,aAAa;;CAGlC,MAAM,eAAe,WAA2B,OAAgB;AAC9D,QAAM,KAAK,SAAS;GAClB,MAAM;GACN,WAAW,KAAK,KAAK;GACrB;GACA,MAAM;GACP,CAAC;;CAGJ,MAAM,cAAc,OAAe,MAAe,SAAkB;AAClE,QAAM,KAAK,SAAS;GAClB,MAAM;GACN,WAAW,KAAK,KAAK;GACrB;GACA;GACA;GACD,CAAC;;CAGJ,MAAM,gBACJ,YACA,WACA,OACA;AACA,MAAI,cAAc,OAAO;GACvB,MAAM,YAAY,KAAK,MAAM,OAAO,KAAK,MAAM,OAAO,SAAS;AAE/D,OACE,aACA,UAAU,SAAS,YACnB,UAAU,eAAe,cACzB,UAAU,KAAK,YAAY,MAAM,WACjC,UAAU,KAAK,OAAO,MAAM,IAC5B;AACA,cAAU;AACV,cAAU,KAAK,OAAO,MAAM;AAC5B,cAAU,eAAe,KAAK,KAAK;AAEnC,UAAM,KAAK,QAAQ,aAAa;AAEhC;;;AAIJ,QAAM,KAAK,SAAS;GAClB,MAAM;GACN,WAAW,KAAK,KAAK;GACrB;GACA,MAAM;GACN;GACA,OAAO;GACR,CAAC;;CAGJ,MAAM,MAAY,QAAgB;EAChC,MAAM,QAAQ,YAAY,KAAK,YAAY,KAAK;AAGhD,SAAO,IAAI,aAFK,KAAK,QAAQ,MAAM,MAAM,EAER,KAAK,YAAY,OAAO,OAAO;;CAGlE,MAAc,SAAS,OAAmB;AACxC,OAAK,MAAM,OAAO,KAAK,MAAM;AAE7B,QAAM,KAAK,QAAQ,aAAa"}
|
|
@@ -6,7 +6,6 @@ var TraceManager = class TraceManager {
|
|
|
6
6
|
this.traceGroup = traceGroup;
|
|
7
7
|
this.trace = trace;
|
|
8
8
|
this.updateTrace().catch(() => {});
|
|
9
|
-
this.updateTraceGroup().catch(() => {});
|
|
10
9
|
}
|
|
11
10
|
async updateTrace() {
|
|
12
11
|
await this.traceStream.set(this.traceGroup.id, this.trace.id, this.trace);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trace-manager.mjs","names":["traceStream: MotiaStream<Trace>","traceGroupStream: MotiaStream<TraceGroup>","traceGroup: TraceGroup","trace: Trace"],"sources":["../../../src/observability/trace-manager.ts"],"sourcesContent":["import type { MotiaStream } from '../types-stream'\nimport type { Trace, TraceGroup } from './types'\n\nexport class TraceManager {\n constructor(\n private readonly traceStream: MotiaStream<Trace>,\n private readonly traceGroupStream: MotiaStream<TraceGroup>,\n private readonly traceGroup: TraceGroup,\n private readonly trace: Trace,\n ) {\n this.updateTrace().catch(() => {})\n
|
|
1
|
+
{"version":3,"file":"trace-manager.mjs","names":["traceStream: MotiaStream<Trace>","traceGroupStream: MotiaStream<TraceGroup>","traceGroup: TraceGroup","trace: Trace"],"sources":["../../../src/observability/trace-manager.ts"],"sourcesContent":["import type { MotiaStream } from '../types-stream'\nimport type { Trace, TraceGroup } from './types'\n\nexport class TraceManager {\n constructor(\n private readonly traceStream: MotiaStream<Trace>,\n private readonly traceGroupStream: MotiaStream<TraceGroup>,\n private readonly traceGroup: TraceGroup,\n private readonly trace: Trace,\n ) {\n this.updateTrace().catch(() => {})\n }\n\n async updateTrace() {\n await this.traceStream.set(this.traceGroup.id, this.trace.id, this.trace)\n }\n\n async updateTraceGroup() {\n await this.traceGroupStream.set('default', this.traceGroup.id, this.traceGroup)\n }\n\n async getAllTracesForGroup(): Promise<Trace[]> {\n return await this.traceStream.getGroup(this.traceGroup.id)\n }\n\n child(trace: Trace) {\n return new TraceManager(this.traceStream, this.traceGroupStream, this.traceGroup, trace)\n }\n}\n"],"mappings":";AAGA,IAAa,eAAb,MAAa,aAAa;CACxB,YACE,AAAiBA,aACjB,AAAiBC,kBACjB,AAAiBC,YACjB,AAAiBC,OACjB;EAJiB;EACA;EACA;EACA;AAEjB,OAAK,aAAa,CAAC,YAAY,GAAG;;CAGpC,MAAM,cAAc;AAClB,QAAM,KAAK,YAAY,IAAI,KAAK,WAAW,IAAI,KAAK,MAAM,IAAI,KAAK,MAAM;;CAG3E,MAAM,mBAAmB;AACvB,QAAM,KAAK,iBAAiB,IAAI,WAAW,KAAK,WAAW,IAAI,KAAK,WAAW;;CAGjF,MAAM,uBAAyC;AAC7C,SAAO,MAAM,KAAK,YAAY,SAAS,KAAK,WAAW,GAAG;;CAG5D,MAAM,OAAc;AAClB,SAAO,IAAI,aAAa,KAAK,aAAa,KAAK,kBAAkB,KAAK,YAAY,MAAM"}
|
|
@@ -25,18 +25,12 @@ var BaseTracerFactory = class {
|
|
|
25
25
|
const traceGroup = {
|
|
26
26
|
id: traceId,
|
|
27
27
|
name: step.config.name,
|
|
28
|
-
lastActivity: Date.now(),
|
|
29
|
-
metadata: {
|
|
30
|
-
completedSteps: 0,
|
|
31
|
-
activeSteps: 0,
|
|
32
|
-
totalSteps: 0
|
|
33
|
-
},
|
|
34
|
-
correlationId: void 0,
|
|
35
|
-
status: "running",
|
|
36
28
|
startTime: Date.now()
|
|
37
29
|
};
|
|
38
30
|
const trace = createTrace(traceGroup, step);
|
|
39
|
-
|
|
31
|
+
const manager = new TraceManager(this.traceStream, this.traceGroupStream, traceGroup, trace);
|
|
32
|
+
await manager.updateTraceGroup();
|
|
33
|
+
return new StreamTracer(manager, traceGroup, trace, logger);
|
|
40
34
|
}
|
|
41
35
|
async attachToTrace(traceId, step, logger) {
|
|
42
36
|
const existingGroup = await this.traceGroupStream.get("default", traceId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracer.mjs","names":["traceStream: MotiaStream<Trace>","traceGroupStream: MotiaStream<TraceGroup>","traceGroup: TraceGroup","traceStreamAdapter: MotiaStream<Trace>","traceGroupStreamAdapter: MotiaStream<TraceGroup>"],"sources":["../../../src/observability/tracer.ts"],"sourcesContent":["import type { LockedData } from '../locked-data'\nimport type { Logger } from '../logger'\nimport type { Step } from '../types'\nimport type { MotiaStream } from '../types-stream'\nimport { createTrace } from './create-trace'\nimport type { TracerFactory } from './index'\nimport { RedisTraceStreamAdapter } from './redis-trace-stream-adapter'\nimport { StreamTracer } from './stream-tracer'\nimport { TraceManager } from './trace-manager'\nimport type { Trace, TraceGroup } from './types'\n\nexport class BaseTracerFactory implements TracerFactory {\n constructor(\n private readonly traceStream: MotiaStream<Trace>,\n private readonly traceGroupStream: MotiaStream<TraceGroup>,\n ) {}\n\n private async getAllGroups() {\n return await this.traceGroupStream.getGroup('default')\n }\n\n private async deleteGroup(group: TraceGroup) {\n const traces = await this.traceStream.getGroup(group.id)\n\n for (const trace of traces) {\n await this.traceStream.delete(group.id, trace.id)\n }\n await this.traceGroupStream.delete('default', group.id)\n }\n\n async clear() {\n const groups = await this.getAllGroups()\n\n for (const group of groups) {\n await this.deleteGroup(group)\n }\n }\n\n async createTracer(traceId: string, step: Step, logger: Logger) {\n const traceGroup: TraceGroup = {\n id: traceId,\n name: step.config.name,\n
|
|
1
|
+
{"version":3,"file":"tracer.mjs","names":["traceStream: MotiaStream<Trace>","traceGroupStream: MotiaStream<TraceGroup>","traceGroup: TraceGroup","traceStreamAdapter: MotiaStream<Trace>","traceGroupStreamAdapter: MotiaStream<TraceGroup>"],"sources":["../../../src/observability/tracer.ts"],"sourcesContent":["import type { LockedData } from '../locked-data'\nimport type { Logger } from '../logger'\nimport type { Step } from '../types'\nimport type { MotiaStream } from '../types-stream'\nimport { createTrace } from './create-trace'\nimport type { TracerFactory } from './index'\nimport { RedisTraceStreamAdapter } from './redis-trace-stream-adapter'\nimport { StreamTracer } from './stream-tracer'\nimport { TraceManager } from './trace-manager'\nimport type { Trace, TraceGroup } from './types'\n\nexport class BaseTracerFactory implements TracerFactory {\n constructor(\n private readonly traceStream: MotiaStream<Trace>,\n private readonly traceGroupStream: MotiaStream<TraceGroup>,\n ) {}\n\n private async getAllGroups() {\n return await this.traceGroupStream.getGroup('default')\n }\n\n private async deleteGroup(group: TraceGroup) {\n const traces = await this.traceStream.getGroup(group.id)\n\n for (const trace of traces) {\n await this.traceStream.delete(group.id, trace.id)\n }\n await this.traceGroupStream.delete('default', group.id)\n }\n\n async clear() {\n const groups = await this.getAllGroups()\n\n for (const group of groups) {\n await this.deleteGroup(group)\n }\n }\n\n async createTracer(traceId: string, step: Step, logger: Logger) {\n const traceGroup: TraceGroup = {\n id: traceId,\n name: step.config.name,\n startTime: Date.now(),\n }\n\n const trace = createTrace(traceGroup, step)\n const manager = new TraceManager(this.traceStream, this.traceGroupStream, traceGroup, trace)\n\n await manager.updateTraceGroup()\n\n return new StreamTracer(manager, traceGroup, trace, logger)\n }\n\n async attachToTrace(traceId: string, step: Step, logger: Logger) {\n const existingGroup = await this.traceGroupStream.get('default', traceId)\n\n if (!existingGroup) {\n return this.createTracer(traceId, step, logger)\n }\n\n const trace = createTrace(existingGroup, step)\n const manager = new TraceManager(this.traceStream, this.traceGroupStream, existingGroup, trace)\n\n return new StreamTracer(manager, existingGroup, trace, logger)\n }\n}\n\nexport const createTracerFactory = (lockedData: LockedData): TracerFactory => {\n if (!lockedData.redisClient) {\n throw new Error(\n 'Redis client is required for tracer factory. Please provide a redisClient when creating LockedData.',\n )\n }\n\n const traceStreamName = 'motia-trace'\n const traceStreamAdapter: MotiaStream<Trace> = new RedisTraceStreamAdapter(traceStreamName, lockedData.redisClient)\n\n const traceStream = lockedData.createStream<Trace>({\n filePath: traceStreamName,\n hidden: true,\n config: {\n name: traceStreamName,\n baseConfig: { storageType: 'custom', factory: () => traceStreamAdapter },\n schema: null as never,\n },\n })()\n\n const traceGroupName = 'motia-trace-group'\n const traceGroupStreamAdapter: MotiaStream<TraceGroup> = new RedisTraceStreamAdapter(\n traceGroupName,\n lockedData.redisClient,\n )\n\n const traceGroupStream = lockedData.createStream<TraceGroup>({\n filePath: traceGroupName,\n hidden: true,\n config: {\n name: traceGroupName,\n baseConfig: { storageType: 'custom', factory: () => traceGroupStreamAdapter },\n schema: null as never,\n },\n })()\n\n return new BaseTracerFactory(traceStream, traceGroupStream)\n}\n"],"mappings":";;;;;;AAWA,IAAa,oBAAb,MAAwD;CACtD,YACE,AAAiBA,aACjB,AAAiBC,kBACjB;EAFiB;EACA;;CAGnB,MAAc,eAAe;AAC3B,SAAO,MAAM,KAAK,iBAAiB,SAAS,UAAU;;CAGxD,MAAc,YAAY,OAAmB;EAC3C,MAAM,SAAS,MAAM,KAAK,YAAY,SAAS,MAAM,GAAG;AAExD,OAAK,MAAM,SAAS,OAClB,OAAM,KAAK,YAAY,OAAO,MAAM,IAAI,MAAM,GAAG;AAEnD,QAAM,KAAK,iBAAiB,OAAO,WAAW,MAAM,GAAG;;CAGzD,MAAM,QAAQ;EACZ,MAAM,SAAS,MAAM,KAAK,cAAc;AAExC,OAAK,MAAM,SAAS,OAClB,OAAM,KAAK,YAAY,MAAM;;CAIjC,MAAM,aAAa,SAAiB,MAAY,QAAgB;EAC9D,MAAMC,aAAyB;GAC7B,IAAI;GACJ,MAAM,KAAK,OAAO;GAClB,WAAW,KAAK,KAAK;GACtB;EAED,MAAM,QAAQ,YAAY,YAAY,KAAK;EAC3C,MAAM,UAAU,IAAI,aAAa,KAAK,aAAa,KAAK,kBAAkB,YAAY,MAAM;AAE5F,QAAM,QAAQ,kBAAkB;AAEhC,SAAO,IAAI,aAAa,SAAS,YAAY,OAAO,OAAO;;CAG7D,MAAM,cAAc,SAAiB,MAAY,QAAgB;EAC/D,MAAM,gBAAgB,MAAM,KAAK,iBAAiB,IAAI,WAAW,QAAQ;AAEzE,MAAI,CAAC,cACH,QAAO,KAAK,aAAa,SAAS,MAAM,OAAO;EAGjD,MAAM,QAAQ,YAAY,eAAe,KAAK;AAG9C,SAAO,IAAI,aAFK,IAAI,aAAa,KAAK,aAAa,KAAK,kBAAkB,eAAe,MAAM,EAE9D,eAAe,OAAO,OAAO;;;AAIlE,MAAa,uBAAuB,eAA0C;AAC5E,KAAI,CAAC,WAAW,YACd,OAAM,IAAI,MACR,sGACD;CAGH,MAAM,kBAAkB;CACxB,MAAMC,qBAAyC,IAAI,wBAAwB,iBAAiB,WAAW,YAAY;CAEnH,MAAM,cAAc,WAAW,aAAoB;EACjD,UAAU;EACV,QAAQ;EACR,QAAQ;GACN,MAAM;GACN,YAAY;IAAE,aAAa;IAAU,eAAe;IAAoB;GACxE,QAAQ;GACT;EACF,CAAC,EAAE;CAEJ,MAAM,iBAAiB;CACvB,MAAMC,0BAAmD,IAAI,wBAC3D,gBACA,WAAW,YACZ;AAYD,QAAO,IAAI,kBAAkB,aAVJ,WAAW,aAAyB;EAC3D,UAAU;EACV,QAAQ;EACR,QAAQ;GACN,MAAM;GACN,YAAY;IAAE,aAAa;IAAU,eAAe;IAAyB;GAC7E,QAAQ;GACT;EACF,CAAC,EAAE,CAEuD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.mts","names":[],"sources":["../../../src/observability/types.ts"],"sourcesContent":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"types.d.mts","names":[],"sources":["../../../src/observability/types.ts"],"sourcesContent":[],"mappings":";;;;KAQY,UAAA;;;;;KAqBA,cAAA;KACA,eAAA"}
|
|
@@ -24,9 +24,9 @@ def get_can_access(config):
|
|
|
24
24
|
async def run_python_module(file_path: str, payload: dict) -> None:
|
|
25
25
|
try:
|
|
26
26
|
path = Path(file_path).resolve()
|
|
27
|
-
steps_dir = next((p for p in path.parents if p.name
|
|
27
|
+
steps_dir = next((p for p in path.parents if p.name in ("src", "steps")), None)
|
|
28
28
|
if steps_dir is None:
|
|
29
|
-
raise RuntimeError("Could not find 'steps' directory in path")
|
|
29
|
+
raise RuntimeError("Could not find 'src' or 'steps' directory in path")
|
|
30
30
|
|
|
31
31
|
project_root = steps_dir.parent
|
|
32
32
|
project_parent = project_root.parent
|
|
@@ -23,9 +23,9 @@ def sendMessage(text):
|
|
|
23
23
|
async def run_python_module(file_path: str) -> None:
|
|
24
24
|
try:
|
|
25
25
|
path = Path(file_path).resolve()
|
|
26
|
-
steps_dir = next((p for p in path.parents if p.name
|
|
26
|
+
steps_dir = next((p for p in path.parents if p.name in ("src", "steps")), None)
|
|
27
27
|
if steps_dir is None:
|
|
28
|
-
raise RuntimeError("Could not find 'steps' directory in path")
|
|
28
|
+
raise RuntimeError("Could not find 'src' or 'steps' directory in path")
|
|
29
29
|
|
|
30
30
|
project_root = steps_dir.parent
|
|
31
31
|
project_parent = project_root.parent
|
|
@@ -24,9 +24,9 @@ async def run_python_module(file_path: str, rpc: RpcSender, args: Dict) -> None:
|
|
|
24
24
|
"""Execute a Python module with the given arguments"""
|
|
25
25
|
try:
|
|
26
26
|
path = Path(file_path).resolve()
|
|
27
|
-
steps_dir = next((p for p in path.parents if p.name
|
|
27
|
+
steps_dir = next((p for p in path.parents if p.name in ("src", "steps")), None)
|
|
28
28
|
if steps_dir is None:
|
|
29
|
-
raise RuntimeError("Could not find 'steps' directory in path")
|
|
29
|
+
raise RuntimeError("Could not find 'src' or 'steps' directory in path")
|
|
30
30
|
|
|
31
31
|
project_root = steps_dir.parent
|
|
32
32
|
project_parent = project_root.parent
|
package/dist/src/server.mjs
CHANGED
|
@@ -327,7 +327,10 @@ const createServer = (lockedData, state, config, adapters, configureApp) => {
|
|
|
327
327
|
analyticsEndpoint(app, process.cwd());
|
|
328
328
|
stepEndpoint(app, lockedData);
|
|
329
329
|
server.on("error", (error) => {
|
|
330
|
-
console.error("Server error:", error);
|
|
330
|
+
if (error.code !== "EADDRINUSE") console.error("Server error:", error);
|
|
331
|
+
});
|
|
332
|
+
socketServer.on("error", (error) => {
|
|
333
|
+
if (error.code !== "EADDRINUSE") console.error("WebSocket server error:", error);
|
|
331
334
|
});
|
|
332
335
|
const close = async () => {
|
|
333
336
|
await cronManager.close();
|
package/dist/src/server.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.mjs","names":["accessContext: StreamSubscription","motia: Motia","data: ApiRequest","result: ApiResponse | undefined"],"sources":["../../src/server.ts"],"sourcesContent":["import bodyParser from 'body-parser'\nimport express, { type Express, type Request, type Response } from 'express'\nimport http from 'http'\nimport type { Server as WsServer } from 'ws'\nimport type { CronAdapter } from './adapters/interfaces/cron-adapter.interface'\nimport type { EventAdapter } from './adapters/interfaces/event-adapter.interface'\nimport type { StateAdapter } from './adapters/interfaces/state-adapter.interface'\nimport type { StreamAdapterManager } from './adapters/interfaces/stream-adapter-manager.interface'\nimport { trackEvent } from './analytics/utils'\nimport { callStepFile } from './call-step-file'\nimport { type CronManager, setupCronHandlers } from './cron-handler'\nimport { analyticsEndpoint } from './endpoints/analytics-endpoint'\nimport { flowsConfigEndpoint } from './endpoints/flows-config-endpoint'\nimport { flowsEndpoint } from './endpoints/flows-endpoint'\nimport { stepEndpoint } from './endpoints/step-endpoint'\nimport { generateTraceId } from './generate-trace-id'\nimport { isApiStep } from './guards'\nimport type { LockedData } from './locked-data'\nimport { globalLogger } from './logger'\nimport { BaseLoggerFactory } from './logger-factory'\nimport type { Motia } from './motia'\nimport type { Tracer } from './observability'\nimport { createTracerFactory } from './observability/tracer'\nimport { Printer } from './printer'\nimport { runStreamCanAccess } from './run-stream-can-access'\nimport { createSocketServer } from './socket-server'\nimport { createStepHandlers, type MotiaEventManager } from './step-handlers'\nimport { systemSteps } from './steps'\nimport { type Log, RedisLogsStream } from './streams/redis-logs-stream'\nimport type { ApiRequest, ApiResponse, ApiRouteConfig, ApiRouteMethod, EmitData, Step } from './types'\nimport type {\n BaseStreamItem,\n MotiaStream,\n StateStreamEvent,\n StateStreamEventChannel,\n StreamSubscription,\n} from './types-stream'\n\nexport type MotiaServer = {\n printer: Printer\n app: Express\n server: http.Server\n socketServer: WsServer\n close: () => Promise<void>\n removeRoute: (step: Step<ApiRouteConfig>) => void\n addRoute: (step: Step<ApiRouteConfig>) => void\n cronManager: CronManager\n motiaEventManager: MotiaEventManager\n motia: Motia\n}\n\ntype MotiaServerConfig = {\n isVerbose: boolean\n printer?: Printer\n}\n\ntype AdapterOptions = {\n eventAdapter: EventAdapter\n cronAdapter: CronAdapter\n streamAdapter?: StreamAdapterManager\n}\n\nexport const createServer = (\n lockedData: LockedData,\n state: StateAdapter,\n config: MotiaServerConfig,\n adapters: AdapterOptions,\n configureApp?: (app: Express) => void,\n): MotiaServer => {\n const printer = config.printer ?? new Printer(process.cwd())\n const app = express()\n if (configureApp) {\n configureApp(app)\n }\n const server = http.createServer(app)\n\n const streamAuth = lockedData.getStreamAuthConfig()\n\n const authorizeSubscription = async (\n subscription: { streamName: string; groupId: string; id?: string },\n authContext?: unknown,\n ): Promise<boolean> => {\n const stream = lockedData.getStreamByName(subscription.streamName)\n\n if (!stream) {\n throw new Error(`Stream ${subscription.streamName} not found`)\n }\n\n const accessContext: StreamSubscription = { groupId: subscription.groupId, id: subscription.id }\n\n if (typeof stream.config.canAccess === 'function') {\n try {\n const allowed = await stream.config.canAccess(accessContext, authContext)\n return Boolean(allowed)\n } catch (error) {\n globalLogger.error('[Streams] Inline canAccess evaluation failed', {\n streamName: subscription.streamName,\n groupId: subscription.groupId,\n error,\n })\n return false\n }\n }\n\n // @ts-expect-error - internal property, not part of the public API\n if (!stream.config.__motia_hasCanAccess) {\n globalLogger.debug('[Streams] No canAccess function found, allowing access', {\n streamName: subscription.streamName,\n groupId: subscription.groupId,\n })\n return true\n }\n\n try {\n const allowed = await runStreamCanAccess({\n file: stream.filePath,\n subscription: accessContext,\n authContext,\n projectRoot: lockedData.baseDir,\n })\n return Boolean(allowed)\n } catch (error) {\n globalLogger.error('[Streams] canAccess evaluation failed', {\n streamName: subscription.streamName,\n groupId: subscription.groupId,\n error,\n })\n return false\n }\n }\n\n const { pushEvent, socketServer } = createSocketServer({\n server,\n authenticate: streamAuth?.authenticate,\n authorize: authorizeSubscription,\n onJoin: async (streamName: string, groupId: string, id: string) => {\n const streams = lockedData.getStreams()\n const stream = streams[streamName]\n\n if (stream) {\n const result = await stream().get(groupId, id)\n delete result?.__motia // deleting because we don't need it in the socket\n return result\n }\n },\n onJoinGroup: async (streamName: string, groupId: string) => {\n const streams = lockedData.getStreams()\n const stream = streams[streamName]\n\n if (stream) {\n const result = stream ? await stream().getGroup(groupId) : []\n\n return result.map(({ __motia, ...rest }) => rest)\n }\n },\n })\n\n lockedData.applyStreamWrapper((streamName, stream) => {\n return (): MotiaStream<BaseStreamItem> => {\n const main = stream() as MotiaStream<BaseStreamItem>\n\n const wrapObject = (groupId: string, id: string, object: any) => {\n if (!object) {\n return null\n }\n\n return {\n ...object,\n __motia: { type: 'state-stream', streamName, groupId, id },\n }\n }\n\n const mainGetGroup = main.getGroup\n const mainGet = main.get\n const mainSet = main.set\n const mainDelete = main.delete\n\n main.send = async <T>(channel: StateStreamEventChannel, event: StateStreamEvent<T>) => {\n pushEvent({ streamName, ...channel, event: { type: 'event', event } })\n }\n\n main.getGroup = async (groupId: string) => {\n const result = await mainGetGroup.apply(main, [groupId])\n return result.map((object: BaseStreamItem) => wrapObject(groupId, object.id, object))\n }\n\n main.get = async (groupId: string, id: string) => {\n const result = await mainGet.apply(main, [groupId, id])\n return wrapObject(groupId, id, result)\n }\n\n main.set = async (groupId: string, id: string, data: BaseStreamItem) => {\n if (!data) {\n return null\n }\n\n const exists = await main.get(groupId, id)\n const updated = await mainSet.apply(main, [groupId, id, data])\n const result = updated ?? data\n const wrappedResult = wrapObject(groupId, id, result)\n\n const type = exists ? 'update' : 'create'\n pushEvent({ streamName, groupId, id, event: { type, data: result } })\n\n return wrappedResult\n }\n\n main.delete = async (groupId: string, id: string) => {\n const result = await mainDelete.apply(main, [groupId, id])\n\n pushEvent({ streamName, groupId, id, event: { type: 'delete', data: result } })\n\n return wrapObject(groupId, id, result)\n }\n\n return main\n }\n })\n\n const logStream = lockedData.createStream<Log>({\n filePath: '__motia.logs',\n hidden: true,\n config: {\n name: '__motia.logs',\n baseConfig: {\n storageType: 'custom',\n factory: () => {\n if (!lockedData.redisClient) {\n throw new Error(\n 'Redis client is required for server operation. Please provide a redisClient when creating LockedData.',\n )\n }\n return new RedisLogsStream(lockedData.redisClient)\n },\n },\n schema: null as never,\n },\n })()\n\n const allSteps = [...systemSteps, ...lockedData.activeSteps]\n const loggerFactory = new BaseLoggerFactory(config.isVerbose, logStream)\n const tracerFactory = createTracerFactory(lockedData)\n const motia: Motia = {\n loggerFactory,\n eventAdapter: adapters.eventAdapter,\n state,\n lockedData,\n printer,\n tracerFactory,\n app,\n stateAdapter: state,\n }\n\n const cronManager = setupCronHandlers(motia, adapters?.cronAdapter)\n const motiaEventManager = createStepHandlers(motia, adapters.eventAdapter)\n\n const asyncHandler = (step: Step<ApiRouteConfig>) => {\n return async (req: Request, res: Response) => {\n const traceId = generateTraceId()\n const { name: stepName, flows } = step.config\n const logger = loggerFactory.create({ traceId, flows, stepName })\n\n logger.debug('[API] Received request, processing step', { path: req.path })\n\n const rawBody = req.rawBody || ''\n\n const data: ApiRequest = {\n body: req.body,\n headers: req.headers as Record<string, string | string[]>,\n pathParams: req.params,\n queryParams: req.query as Record<string, string | string[]>,\n rawBody,\n }\n\n try {\n let result: ApiResponse | undefined\n\n if ('handler' in step && typeof step.handler === 'function') {\n const context = {\n traceId,\n flows,\n state: state,\n emit: async (event: EmitData) => {\n const eventObj = {\n ...event,\n traceId,\n flows,\n logger,\n tracer: null as unknown as Tracer,\n }\n await adapters.eventAdapter.emit(eventObj)\n },\n logger,\n streams: lockedData.getStreams(),\n }\n result = await step.handler(data, context)\n } else {\n const tracer = await motia.tracerFactory.createTracer(traceId, step, logger)\n result = await callStepFile<ApiResponse>({ data, step, logger, tracer, traceId }, motia)\n }\n\n trackEvent('api_call_success', { stepName })\n\n if (!result) {\n console.log('no result')\n res.status(500).json({ error: 'Internal server error' })\n return\n }\n\n if (result.headers) {\n Object.entries(result.headers).forEach(([key, value]) => res.setHeader(key, value))\n }\n\n res.status(result.status)\n\n // Handle different body types\n if (Buffer.isBuffer(result.body) || typeof result.body === 'string') {\n res.send(result.body)\n } else {\n res.json(result.body)\n }\n } catch (error) {\n trackEvent('api_call_error', {\n stepName,\n traceId,\n error: error instanceof Error ? error.message : 'Unknown error',\n })\n logger.error('[API] Internal server error', { error })\n console.log(error)\n res.status(500).json({ error: 'Internal server error' })\n }\n }\n }\n\n app.use((req, _, next) => {\n req.rawBody = ''\n next()\n })\n\n app.use(\n bodyParser.json({\n limit: '1gb',\n verify: (req, _, buf, encoding) => {\n req.rawBody = buf.toString((encoding as BufferEncoding) || 'utf8')\n },\n }),\n )\n\n app.use(\n bodyParser.urlencoded({\n extended: true,\n limit: '1gb',\n verify: (req, _, buf, encoding) => {\n req.rawBody = buf.toString((encoding as BufferEncoding) || 'utf8')\n },\n }),\n )\n\n app.use(\n bodyParser.text({\n limit: '1gb',\n verify: (req, _, buf, encoding) => {\n req.rawBody = buf.toString((encoding as BufferEncoding) || 'utf8')\n },\n }),\n )\n\n const router = express.Router()\n\n const addRoute = (step: Step<ApiRouteConfig>) => {\n const { method, path } = step.config\n globalLogger.debug('[API] Registering route', step.config)\n\n const handler = asyncHandler(step)\n const methods: Record<ApiRouteMethod, () => void> = {\n GET: () => router.get(path, handler),\n POST: () => router.post(path, handler),\n PUT: () => router.put(path, handler),\n DELETE: () => router.delete(path, handler),\n PATCH: () => router.patch(path, handler),\n OPTIONS: () => router.options(path, handler),\n HEAD: () => router.head(path, handler),\n }\n\n const methodHandler = methods[method]\n if (!methodHandler) {\n throw new Error(`Unsupported method: ${method}`)\n }\n\n methodHandler()\n }\n\n const removeRoute = (step: Step<ApiRouteConfig>) => {\n const { path, method } = step.config\n const routerStack = router.stack\n\n const filteredStack = routerStack.filter((layer: any) => {\n if (layer.route) {\n const match = layer.route.path === path && layer.route.methods[method.toLowerCase()]\n return !match\n }\n return true\n })\n router.stack = filteredStack\n }\n\n allSteps.filter(isApiStep).forEach(addRoute)\n\n app.options('*', (_req, res) => {\n res.header('Access-Control-Allow-Origin', '*')\n res.header('Access-Control-Allow-Methods', '*')\n res.header('Access-Control-Allow-Headers', '*')\n res.header('Access-Control-Max-Age', '600')\n res.header('Access-Control-Allow-Credentials', 'true')\n res.header('Access-Control-Allow-Private-Network', 'true')\n res.status(204).end()\n })\n app.use((_req, res, next) => {\n res.header('Access-Control-Allow-Origin', '*')\n res.header('Access-Control-Allow-Methods', '*')\n res.header('Access-Control-Allow-Headers', '*')\n res.header('Access-Control-Max-Age', '600')\n res.header('Access-Control-Allow-Credentials', 'true')\n res.header('Access-Control-Allow-Private-Network', 'true')\n next()\n })\n\n app.use(router)\n\n flowsEndpoint(lockedData)\n flowsConfigEndpoint(app, process.cwd(), lockedData)\n analyticsEndpoint(app, process.cwd())\n stepEndpoint(app, lockedData)\n\n server.on('error', (error) => {\n console.error('Server error:', error)\n })\n\n const close = async (): Promise<void> => {\n await cronManager.close()\n socketServer.close()\n if (adapters?.eventAdapter) {\n await adapters.eventAdapter.shutdown()\n }\n }\n\n return { app, server, socketServer, close, removeRoute, addRoute, cronManager, motiaEventManager, motia, printer }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server.mjs","names":["accessContext: StreamSubscription","motia: Motia","data: ApiRequest","result: ApiResponse | undefined"],"sources":["../../src/server.ts"],"sourcesContent":["import bodyParser from 'body-parser'\nimport express, { type Express, type Request, type Response } from 'express'\nimport http from 'http'\nimport type { Server as WsServer } from 'ws'\nimport type { CronAdapter } from './adapters/interfaces/cron-adapter.interface'\nimport type { EventAdapter } from './adapters/interfaces/event-adapter.interface'\nimport type { StateAdapter } from './adapters/interfaces/state-adapter.interface'\nimport type { StreamAdapterManager } from './adapters/interfaces/stream-adapter-manager.interface'\nimport { trackEvent } from './analytics/utils'\nimport { callStepFile } from './call-step-file'\nimport { type CronManager, setupCronHandlers } from './cron-handler'\nimport { analyticsEndpoint } from './endpoints/analytics-endpoint'\nimport { flowsConfigEndpoint } from './endpoints/flows-config-endpoint'\nimport { flowsEndpoint } from './endpoints/flows-endpoint'\nimport { stepEndpoint } from './endpoints/step-endpoint'\nimport { generateTraceId } from './generate-trace-id'\nimport { isApiStep } from './guards'\nimport type { LockedData } from './locked-data'\nimport { globalLogger } from './logger'\nimport { BaseLoggerFactory } from './logger-factory'\nimport type { Motia } from './motia'\nimport type { Tracer } from './observability'\nimport { createTracerFactory } from './observability/tracer'\nimport { Printer } from './printer'\nimport { runStreamCanAccess } from './run-stream-can-access'\nimport { createSocketServer } from './socket-server'\nimport { createStepHandlers, type MotiaEventManager } from './step-handlers'\nimport { systemSteps } from './steps'\nimport { type Log, RedisLogsStream } from './streams/redis-logs-stream'\nimport type { ApiRequest, ApiResponse, ApiRouteConfig, ApiRouteMethod, EmitData, Step } from './types'\nimport type {\n BaseStreamItem,\n MotiaStream,\n StateStreamEvent,\n StateStreamEventChannel,\n StreamSubscription,\n} from './types-stream'\n\nexport type MotiaServer = {\n printer: Printer\n app: Express\n server: http.Server\n socketServer: WsServer\n close: () => Promise<void>\n removeRoute: (step: Step<ApiRouteConfig>) => void\n addRoute: (step: Step<ApiRouteConfig>) => void\n cronManager: CronManager\n motiaEventManager: MotiaEventManager\n motia: Motia\n}\n\ntype MotiaServerConfig = {\n isVerbose: boolean\n printer?: Printer\n}\n\ntype AdapterOptions = {\n eventAdapter: EventAdapter\n cronAdapter: CronAdapter\n streamAdapter?: StreamAdapterManager\n}\n\nexport const createServer = (\n lockedData: LockedData,\n state: StateAdapter,\n config: MotiaServerConfig,\n adapters: AdapterOptions,\n configureApp?: (app: Express) => void,\n): MotiaServer => {\n const printer = config.printer ?? new Printer(process.cwd())\n const app = express()\n if (configureApp) {\n configureApp(app)\n }\n const server = http.createServer(app)\n\n const streamAuth = lockedData.getStreamAuthConfig()\n\n const authorizeSubscription = async (\n subscription: { streamName: string; groupId: string; id?: string },\n authContext?: unknown,\n ): Promise<boolean> => {\n const stream = lockedData.getStreamByName(subscription.streamName)\n\n if (!stream) {\n throw new Error(`Stream ${subscription.streamName} not found`)\n }\n\n const accessContext: StreamSubscription = { groupId: subscription.groupId, id: subscription.id }\n\n if (typeof stream.config.canAccess === 'function') {\n try {\n const allowed = await stream.config.canAccess(accessContext, authContext)\n return Boolean(allowed)\n } catch (error) {\n globalLogger.error('[Streams] Inline canAccess evaluation failed', {\n streamName: subscription.streamName,\n groupId: subscription.groupId,\n error,\n })\n return false\n }\n }\n\n // @ts-expect-error - internal property, not part of the public API\n if (!stream.config.__motia_hasCanAccess) {\n globalLogger.debug('[Streams] No canAccess function found, allowing access', {\n streamName: subscription.streamName,\n groupId: subscription.groupId,\n })\n return true\n }\n\n try {\n const allowed = await runStreamCanAccess({\n file: stream.filePath,\n subscription: accessContext,\n authContext,\n projectRoot: lockedData.baseDir,\n })\n return Boolean(allowed)\n } catch (error) {\n globalLogger.error('[Streams] canAccess evaluation failed', {\n streamName: subscription.streamName,\n groupId: subscription.groupId,\n error,\n })\n return false\n }\n }\n\n const { pushEvent, socketServer } = createSocketServer({\n server,\n authenticate: streamAuth?.authenticate,\n authorize: authorizeSubscription,\n onJoin: async (streamName: string, groupId: string, id: string) => {\n const streams = lockedData.getStreams()\n const stream = streams[streamName]\n\n if (stream) {\n const result = await stream().get(groupId, id)\n delete result?.__motia // deleting because we don't need it in the socket\n return result\n }\n },\n onJoinGroup: async (streamName: string, groupId: string) => {\n const streams = lockedData.getStreams()\n const stream = streams[streamName]\n\n if (stream) {\n const result = stream ? await stream().getGroup(groupId) : []\n\n return result.map(({ __motia, ...rest }) => rest)\n }\n },\n })\n\n lockedData.applyStreamWrapper((streamName, stream) => {\n return (): MotiaStream<BaseStreamItem> => {\n const main = stream() as MotiaStream<BaseStreamItem>\n\n const wrapObject = (groupId: string, id: string, object: any) => {\n if (!object) {\n return null\n }\n\n return {\n ...object,\n __motia: { type: 'state-stream', streamName, groupId, id },\n }\n }\n\n const mainGetGroup = main.getGroup\n const mainGet = main.get\n const mainSet = main.set\n const mainDelete = main.delete\n\n main.send = async <T>(channel: StateStreamEventChannel, event: StateStreamEvent<T>) => {\n pushEvent({ streamName, ...channel, event: { type: 'event', event } })\n }\n\n main.getGroup = async (groupId: string) => {\n const result = await mainGetGroup.apply(main, [groupId])\n return result.map((object: BaseStreamItem) => wrapObject(groupId, object.id, object))\n }\n\n main.get = async (groupId: string, id: string) => {\n const result = await mainGet.apply(main, [groupId, id])\n return wrapObject(groupId, id, result)\n }\n\n main.set = async (groupId: string, id: string, data: BaseStreamItem) => {\n if (!data) {\n return null\n }\n\n const exists = await main.get(groupId, id)\n const updated = await mainSet.apply(main, [groupId, id, data])\n const result = updated ?? data\n const wrappedResult = wrapObject(groupId, id, result)\n\n const type = exists ? 'update' : 'create'\n pushEvent({ streamName, groupId, id, event: { type, data: result } })\n\n return wrappedResult\n }\n\n main.delete = async (groupId: string, id: string) => {\n const result = await mainDelete.apply(main, [groupId, id])\n\n pushEvent({ streamName, groupId, id, event: { type: 'delete', data: result } })\n\n return wrapObject(groupId, id, result)\n }\n\n return main\n }\n })\n\n const logStream = lockedData.createStream<Log>({\n filePath: '__motia.logs',\n hidden: true,\n config: {\n name: '__motia.logs',\n baseConfig: {\n storageType: 'custom',\n factory: () => {\n if (!lockedData.redisClient) {\n throw new Error(\n 'Redis client is required for server operation. Please provide a redisClient when creating LockedData.',\n )\n }\n return new RedisLogsStream(lockedData.redisClient)\n },\n },\n schema: null as never,\n },\n })()\n\n const allSteps = [...systemSteps, ...lockedData.activeSteps]\n const loggerFactory = new BaseLoggerFactory(config.isVerbose, logStream)\n const tracerFactory = createTracerFactory(lockedData)\n const motia: Motia = {\n loggerFactory,\n eventAdapter: adapters.eventAdapter,\n state,\n lockedData,\n printer,\n tracerFactory,\n app,\n stateAdapter: state,\n }\n\n const cronManager = setupCronHandlers(motia, adapters?.cronAdapter)\n const motiaEventManager = createStepHandlers(motia, adapters.eventAdapter)\n\n const asyncHandler = (step: Step<ApiRouteConfig>) => {\n return async (req: Request, res: Response) => {\n const traceId = generateTraceId()\n const { name: stepName, flows } = step.config\n const logger = loggerFactory.create({ traceId, flows, stepName })\n\n logger.debug('[API] Received request, processing step', { path: req.path })\n\n const rawBody = req.rawBody || ''\n\n const data: ApiRequest = {\n body: req.body,\n headers: req.headers as Record<string, string | string[]>,\n pathParams: req.params,\n queryParams: req.query as Record<string, string | string[]>,\n rawBody,\n }\n\n try {\n let result: ApiResponse | undefined\n\n if ('handler' in step && typeof step.handler === 'function') {\n const context = {\n traceId,\n flows,\n state: state,\n emit: async (event: EmitData) => {\n const eventObj = {\n ...event,\n traceId,\n flows,\n logger,\n tracer: null as unknown as Tracer,\n }\n await adapters.eventAdapter.emit(eventObj)\n },\n logger,\n streams: lockedData.getStreams(),\n }\n result = await step.handler(data, context)\n } else {\n const tracer = await motia.tracerFactory.createTracer(traceId, step, logger)\n result = await callStepFile<ApiResponse>({ data, step, logger, tracer, traceId }, motia)\n }\n\n trackEvent('api_call_success', { stepName })\n\n if (!result) {\n console.log('no result')\n res.status(500).json({ error: 'Internal server error' })\n return\n }\n\n if (result.headers) {\n Object.entries(result.headers).forEach(([key, value]) => res.setHeader(key, value))\n }\n\n res.status(result.status)\n\n // Handle different body types\n if (Buffer.isBuffer(result.body) || typeof result.body === 'string') {\n res.send(result.body)\n } else {\n res.json(result.body)\n }\n } catch (error) {\n trackEvent('api_call_error', {\n stepName,\n traceId,\n error: error instanceof Error ? error.message : 'Unknown error',\n })\n logger.error('[API] Internal server error', { error })\n console.log(error)\n res.status(500).json({ error: 'Internal server error' })\n }\n }\n }\n\n app.use((req, _, next) => {\n req.rawBody = ''\n next()\n })\n\n app.use(\n bodyParser.json({\n limit: '1gb',\n verify: (req, _, buf, encoding) => {\n req.rawBody = buf.toString((encoding as BufferEncoding) || 'utf8')\n },\n }),\n )\n\n app.use(\n bodyParser.urlencoded({\n extended: true,\n limit: '1gb',\n verify: (req, _, buf, encoding) => {\n req.rawBody = buf.toString((encoding as BufferEncoding) || 'utf8')\n },\n }),\n )\n\n app.use(\n bodyParser.text({\n limit: '1gb',\n verify: (req, _, buf, encoding) => {\n req.rawBody = buf.toString((encoding as BufferEncoding) || 'utf8')\n },\n }),\n )\n\n const router = express.Router()\n\n const addRoute = (step: Step<ApiRouteConfig>) => {\n const { method, path } = step.config\n globalLogger.debug('[API] Registering route', step.config)\n\n const handler = asyncHandler(step)\n const methods: Record<ApiRouteMethod, () => void> = {\n GET: () => router.get(path, handler),\n POST: () => router.post(path, handler),\n PUT: () => router.put(path, handler),\n DELETE: () => router.delete(path, handler),\n PATCH: () => router.patch(path, handler),\n OPTIONS: () => router.options(path, handler),\n HEAD: () => router.head(path, handler),\n }\n\n const methodHandler = methods[method]\n if (!methodHandler) {\n throw new Error(`Unsupported method: ${method}`)\n }\n\n methodHandler()\n }\n\n const removeRoute = (step: Step<ApiRouteConfig>) => {\n const { path, method } = step.config\n const routerStack = router.stack\n\n const filteredStack = routerStack.filter((layer: any) => {\n if (layer.route) {\n const match = layer.route.path === path && layer.route.methods[method.toLowerCase()]\n return !match\n }\n return true\n })\n router.stack = filteredStack\n }\n\n allSteps.filter(isApiStep).forEach(addRoute)\n\n app.options('*', (_req, res) => {\n res.header('Access-Control-Allow-Origin', '*')\n res.header('Access-Control-Allow-Methods', '*')\n res.header('Access-Control-Allow-Headers', '*')\n res.header('Access-Control-Max-Age', '600')\n res.header('Access-Control-Allow-Credentials', 'true')\n res.header('Access-Control-Allow-Private-Network', 'true')\n res.status(204).end()\n })\n app.use((_req, res, next) => {\n res.header('Access-Control-Allow-Origin', '*')\n res.header('Access-Control-Allow-Methods', '*')\n res.header('Access-Control-Allow-Headers', '*')\n res.header('Access-Control-Max-Age', '600')\n res.header('Access-Control-Allow-Credentials', 'true')\n res.header('Access-Control-Allow-Private-Network', 'true')\n next()\n })\n\n app.use(router)\n\n flowsEndpoint(lockedData)\n flowsConfigEndpoint(app, process.cwd(), lockedData)\n analyticsEndpoint(app, process.cwd())\n stepEndpoint(app, lockedData)\n\n server.on('error', (error: NodeJS.ErrnoException) => {\n if (error.code !== 'EADDRINUSE') {\n console.error('Server error:', error)\n }\n })\n\n socketServer.on('error', (error: NodeJS.ErrnoException) => {\n if (error.code !== 'EADDRINUSE') {\n console.error('WebSocket server error:', error)\n }\n })\n\n const close = async (): Promise<void> => {\n await cronManager.close()\n socketServer.close()\n if (adapters?.eventAdapter) {\n await adapters.eventAdapter.shutdown()\n }\n }\n\n return { app, server, socketServer, close, removeRoute, addRoute, cronManager, motiaEventManager, motia, printer }\n}\n"],"mappings":"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"}
|