@motiadev/core 0.14.0-beta.165-275091 → 0.14.0-beta.165-557689
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.mts +1 -2
- package/dist/index.mjs +1 -2
- package/dist/src/call-step-file.mjs +178 -216
- package/dist/src/call-step-file.mjs.map +1 -1
- package/dist/src/get-step-config.d.mts +0 -1
- package/dist/src/get-step-config.d.mts.map +1 -1
- package/dist/src/get-step-config.mjs +12 -19
- package/dist/src/get-step-config.mjs.map +1 -1
- package/dist/src/language-runner.mjs +0 -6
- package/dist/src/language-runner.mjs.map +1 -1
- package/dist/src/logger.d.mts +0 -1
- package/dist/src/logger.d.mts.map +1 -1
- package/dist/src/logger.mjs +0 -8
- package/dist/src/logger.mjs.map +1 -1
- package/dist/src/node/node-runner.mjs +8 -23
- package/dist/src/node/node-runner.mjs.map +1 -1
- package/dist/src/observability/stream-tracer.mjs +2 -2
- package/dist/src/observability/stream-tracer.mjs.map +1 -1
- package/dist/src/observability/trace-manager.mjs +3 -24
- package/dist/src/observability/trace-manager.mjs.map +1 -1
- package/dist/src/process-communication/process-manager.mjs +1 -1
- package/dist/src/process-communication/process-manager.mjs.map +1 -1
- package/dist/src/step-handler-rpc-stdin-processor.mjs +1 -4
- package/dist/src/step-handler-rpc-stdin-processor.mjs.map +1 -1
- package/dist/src/types-stream.d.mts.map +1 -1
- package/package.json +1 -2
- package/dist/src/ts-compiler.d.mts +0 -5
- package/dist/src/ts-compiler.d.mts.map +0 -1
- package/dist/src/ts-compiler.mjs +0 -92
- package/dist/src/ts-compiler.mjs.map +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -25,7 +25,6 @@ import "./src/adapters/defaults/index.mjs";
|
|
|
25
25
|
import { getProjectIdentifier, getProjectName, getUserIdentifier, isAnalyticsEnabled, trackEvent } from "./src/analytics/utils.mjs";
|
|
26
26
|
import { config } from "./src/config.mjs";
|
|
27
27
|
import { CronManager, setupCronHandlers } from "./src/cron-handler.mjs";
|
|
28
|
-
import { invalidate } from "./src/ts-compiler.mjs";
|
|
29
28
|
import { getStepConfig, getStreamConfig } from "./src/get-step-config.mjs";
|
|
30
29
|
import { isApiStep, isCronStep, isEventStep, isNoopStep } from "./src/guards.mjs";
|
|
31
30
|
import { InfrastructureValidationError, InfrastructureValidationResult } from "./src/infrastructure-validator/types.mjs";
|
|
@@ -36,4 +35,4 @@ import { NoTracer } from "./src/observability/no-tracer.mjs";
|
|
|
36
35
|
import { MotiaEventManager, createStepHandlers } from "./src/step-handlers.mjs";
|
|
37
36
|
import { MotiaServer, createServer } from "./src/server.mjs";
|
|
38
37
|
import { createStateAdapter } from "./src/state/create-state-adapter.mjs";
|
|
39
|
-
export { type AdapterConfig, ApiMiddleware, ApiRequest, ApiResponse, ApiRouteConfig, ApiRouteHandler, ApiRouteMethod, type BaseStreamItem, type Config, type CronAdapter, type CronAdapterConfig, type CronConfig, CronHandler, type CronLock, type CronLockInfo, type CronManager, InMemoryCronAdapter as DefaultCronAdapter, InMemoryQueueEventAdapter as DefaultQueueEventAdapter, Emit, EmitData, Emitter, Event, type EventAdapter, EventConfig, EventHandler, FileStateAdapter, FileStreamAdapter, FileStreamAdapterManager, Flow, FlowContext, FlowContextStateStreams, Handler, HandlerConfig, Handlers, InfrastructureConfig, type InfrastructureValidationError, type InfrastructureValidationResult, InternalStateManager, JsonSchema, JsonSchemaError, LockedData, Logger, MemoryStateAdapter, MemoryStreamAdapter, MemoryStreamAdapterManager, type Metric, type Motia, type MotiaEventManager, MotiaPlugin, MotiaPluginBuilder, type MotiaPluginContext, type MotiaServer, type MotiaStream, NoPrinter, NoTracer, NoopConfig, type ObservabilityAdapter, PLUGIN_FLOW_ID, type PluginApiConfig, PluginStep, Printer, QueryParam, QueueConfig, QueueManager, type QueueMetrics, type StateAdapter, type StateFilter, type StateItem, type StateItemsInput, type StateStreamEvent, type StateStreamEventChannel, Step, StepConfig, StepHandler, StepSchemaInput, type Stream, StreamAdapter, type StreamAdapterManager, StreamAuthConfig, type StreamAuthRequest, type StreamConfig, type StreamQueryFilter, type StreamSubscription, SubscribeConfig, type SubscriptionHandle, type Tracer, type UnregisterMotiaPluginApi, UnsubscribeConfig, WorkbenchPlugin, ZodInput, config, createMermaidGenerator, createServer, createStateAdapter, createStepHandlers, getProjectIdentifier, getProjectName, getStepConfig, getStreamConfig, getUserIdentifier,
|
|
38
|
+
export { type AdapterConfig, ApiMiddleware, ApiRequest, ApiResponse, ApiRouteConfig, ApiRouteHandler, ApiRouteMethod, type BaseStreamItem, type Config, type CronAdapter, type CronAdapterConfig, type CronConfig, CronHandler, type CronLock, type CronLockInfo, type CronManager, InMemoryCronAdapter as DefaultCronAdapter, InMemoryQueueEventAdapter as DefaultQueueEventAdapter, Emit, EmitData, Emitter, Event, type EventAdapter, EventConfig, EventHandler, FileStateAdapter, FileStreamAdapter, FileStreamAdapterManager, Flow, FlowContext, FlowContextStateStreams, Handler, HandlerConfig, Handlers, InfrastructureConfig, type InfrastructureValidationError, type InfrastructureValidationResult, InternalStateManager, JsonSchema, JsonSchemaError, LockedData, Logger, MemoryStateAdapter, MemoryStreamAdapter, MemoryStreamAdapterManager, type Metric, type Motia, type MotiaEventManager, MotiaPlugin, MotiaPluginBuilder, type MotiaPluginContext, type MotiaServer, type MotiaStream, NoPrinter, NoTracer, NoopConfig, type ObservabilityAdapter, PLUGIN_FLOW_ID, type PluginApiConfig, PluginStep, Printer, QueryParam, QueueConfig, QueueManager, type QueueMetrics, type StateAdapter, type StateFilter, type StateItem, type StateItemsInput, type StateStreamEvent, type StateStreamEventChannel, Step, StepConfig, StepHandler, StepSchemaInput, type Stream, StreamAdapter, type StreamAdapterManager, StreamAuthConfig, type StreamAuthRequest, type StreamConfig, type StreamQueryFilter, type StreamSubscription, SubscribeConfig, type SubscriptionHandle, type Tracer, type UnregisterMotiaPluginApi, UnsubscribeConfig, WorkbenchPlugin, ZodInput, config, createMermaidGenerator, createServer, createStateAdapter, createStepHandlers, getProjectIdentifier, getProjectName, getStepConfig, getStreamConfig, getUserIdentifier, isAnalyticsEnabled, isAnyOf, isApiStep, isCronStep, isEventStep, isNoopStep, setupCronHandlers, trackEvent, validateInfrastructureConfig };
|
package/dist/index.mjs
CHANGED
|
@@ -12,7 +12,6 @@ import { MemoryStreamAdapterManager } from "./src/adapters/defaults/stream/memor
|
|
|
12
12
|
import "./src/adapters/defaults/index.mjs";
|
|
13
13
|
import { getProjectIdentifier, getProjectName, getUserIdentifier, isAnalyticsEnabled, trackEvent } from "./src/analytics/utils.mjs";
|
|
14
14
|
import { config } from "./src/config.mjs";
|
|
15
|
-
import { invalidate } from "./src/ts-compiler.mjs";
|
|
16
15
|
import { isApiStep, isCronStep, isEventStep, isNoopStep } from "./src/guards.mjs";
|
|
17
16
|
import { setupCronHandlers } from "./src/cron-handler.mjs";
|
|
18
17
|
import { getStepConfig, getStreamConfig } from "./src/get-step-config.mjs";
|
|
@@ -28,4 +27,4 @@ import { createStepHandlers } from "./src/step-handlers.mjs";
|
|
|
28
27
|
import { createServer } from "./src/server.mjs";
|
|
29
28
|
import { createStateAdapter } from "./src/state/create-state-adapter.mjs";
|
|
30
29
|
|
|
31
|
-
export { InMemoryCronAdapter as DefaultCronAdapter, InMemoryQueueEventAdapter as DefaultQueueEventAdapter, FileStateAdapter, FileStreamAdapter, FileStreamAdapterManager, JsonSchemaError, LockedData, Logger, MemoryStateAdapter, MemoryStreamAdapter, MemoryStreamAdapterManager, NoPrinter, NoTracer, PLUGIN_FLOW_ID, Printer, QueueManager, StreamAdapter, config, createMermaidGenerator, createServer, createStateAdapter, createStepHandlers, getProjectIdentifier, getProjectName, getStepConfig, getStreamConfig, getUserIdentifier,
|
|
30
|
+
export { InMemoryCronAdapter as DefaultCronAdapter, InMemoryQueueEventAdapter as DefaultQueueEventAdapter, FileStateAdapter, FileStreamAdapter, FileStreamAdapterManager, JsonSchemaError, LockedData, Logger, MemoryStateAdapter, MemoryStreamAdapter, MemoryStreamAdapterManager, NoPrinter, NoTracer, PLUGIN_FLOW_ID, Printer, QueueManager, StreamAdapter, config, createMermaidGenerator, createServer, createStateAdapter, createStepHandlers, getProjectIdentifier, getProjectName, getStepConfig, getStreamConfig, getUserIdentifier, isAnalyticsEnabled, isAnyOf, isApiStep, isCronStep, isEventStep, isNoopStep, setupCronHandlers, trackEvent, validateInfrastructureConfig };
|
|
@@ -1,251 +1,213 @@
|
|
|
1
1
|
import { trackEvent } from "./analytics/utils.mjs";
|
|
2
2
|
import { getLanguageBasedRunner } from "./language-runner.mjs";
|
|
3
3
|
import { ProcessManager } from "./process-communication/process-manager.mjs";
|
|
4
|
-
import { compile } from "./ts-compiler.mjs";
|
|
5
4
|
import { isAllowedToEmit } from "./utils.mjs";
|
|
6
5
|
|
|
7
6
|
//#region src/call-step-file.ts
|
|
8
7
|
const callStepFile = (options, motia) => {
|
|
9
8
|
const { step, traceId, data, tracer, logger, contextInFirstArg = false, infrastructure } = options;
|
|
10
9
|
const flows = step.config.flows;
|
|
11
|
-
return (
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
const streamConfig = motia.lockedData.getStreams();
|
|
12
|
+
const streams = Object.keys(streamConfig).map((name) => ({ name }));
|
|
13
|
+
const jsonData = JSON.stringify({
|
|
14
|
+
data,
|
|
15
|
+
flows,
|
|
16
|
+
traceId,
|
|
17
|
+
contextInFirstArg,
|
|
18
|
+
streams
|
|
19
|
+
});
|
|
20
|
+
const { runner, command, args } = getLanguageBasedRunner(step.filePath);
|
|
21
|
+
let result;
|
|
22
|
+
let timeoutId;
|
|
23
|
+
const processManager = new ProcessManager({
|
|
24
|
+
command,
|
|
25
|
+
args: [
|
|
26
|
+
...args,
|
|
27
|
+
runner,
|
|
28
|
+
step.filePath,
|
|
29
|
+
jsonData
|
|
30
|
+
],
|
|
31
|
+
logger,
|
|
32
|
+
context: "StepExecution",
|
|
33
|
+
projectRoot: motia.lockedData.baseDir
|
|
34
|
+
});
|
|
35
|
+
trackEvent("step_execution_started", {
|
|
36
|
+
stepName: step.config.name,
|
|
37
|
+
language: command,
|
|
38
|
+
type: step.config.type,
|
|
39
|
+
streams: streams.length
|
|
40
|
+
});
|
|
41
|
+
const timeoutSeconds = infrastructure?.handler?.timeout;
|
|
42
|
+
if (timeoutSeconds) timeoutId = setTimeout(async () => {
|
|
43
|
+
processManager.kill();
|
|
44
|
+
const errorMessage = `Step execution timed out after ${timeoutSeconds} seconds`;
|
|
45
|
+
logger.error(errorMessage, {
|
|
46
|
+
step: step.config.name,
|
|
47
|
+
timeout: timeoutSeconds
|
|
48
|
+
});
|
|
49
|
+
await tracer.end({ message: errorMessage });
|
|
50
|
+
trackEvent("step_execution_timeout", {
|
|
51
|
+
stepName: step.config.name,
|
|
18
52
|
traceId,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
53
|
+
timeout: timeoutSeconds
|
|
54
|
+
});
|
|
55
|
+
reject(new Error(errorMessage));
|
|
56
|
+
}, timeoutSeconds * 1e3);
|
|
57
|
+
processManager.spawn().then(() => {
|
|
58
|
+
processManager.handler("close", async (err) => {
|
|
59
|
+
if (err) {
|
|
60
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
61
|
+
processManager.close();
|
|
62
|
+
trackEvent("step_execution_error", {
|
|
63
|
+
stepName: step.config.name,
|
|
64
|
+
traceId,
|
|
65
|
+
message: err.message
|
|
66
|
+
});
|
|
67
|
+
await tracer.end({
|
|
68
|
+
message: err.message,
|
|
69
|
+
code: err.code,
|
|
70
|
+
stack: err.stack?.replace(/* @__PURE__ */ new RegExp(`${motia.lockedData.baseDir}/`), "")
|
|
71
|
+
});
|
|
72
|
+
reject(err ?? /* @__PURE__ */ new Error("Handler execution failed"));
|
|
73
|
+
} else await tracer.end();
|
|
74
|
+
processManager.kill();
|
|
75
|
+
});
|
|
76
|
+
processManager.handler("log", async (input) => logger.log(input));
|
|
77
|
+
processManager.handler("state.get", async (input) => {
|
|
78
|
+
await tracer.stateOperation("get", input);
|
|
79
|
+
return motia.state.get(input.traceId, input.key);
|
|
80
|
+
});
|
|
81
|
+
processManager.handler("state.set", async (input) => {
|
|
82
|
+
await tracer.stateOperation("set", {
|
|
83
|
+
traceId: input.traceId,
|
|
84
|
+
key: input.key,
|
|
85
|
+
value: input.value
|
|
32
86
|
});
|
|
33
|
-
|
|
34
|
-
|
|
87
|
+
return motia.state.set(input.traceId, input.key, input.value);
|
|
88
|
+
});
|
|
89
|
+
processManager.handler("state.delete", async (input) => {
|
|
90
|
+
await tracer.stateOperation("delete", input);
|
|
91
|
+
return motia.state.delete(input.traceId, input.key);
|
|
92
|
+
});
|
|
93
|
+
processManager.handler("state.clear", async (input) => {
|
|
94
|
+
await tracer.stateOperation("clear", input);
|
|
95
|
+
return motia.state.clear(input.traceId);
|
|
96
|
+
});
|
|
97
|
+
processManager.handler(`state.getGroup`, async (input) => {
|
|
98
|
+
await tracer.stateOperation("getGroup", input);
|
|
99
|
+
return motia.state.getGroup(input.groupId);
|
|
100
|
+
});
|
|
101
|
+
processManager.handler("result", async (input) => {
|
|
102
|
+
const anyInput = { ...input };
|
|
103
|
+
if (anyInput.body && anyInput.body.type === "Buffer") anyInput.body = Buffer.from(anyInput.body.data);
|
|
104
|
+
result = anyInput;
|
|
105
|
+
});
|
|
106
|
+
processManager.handler("emit", async (input) => {
|
|
107
|
+
const flows$1 = step.config.flows;
|
|
108
|
+
if (!isAllowedToEmit(step, input.topic)) {
|
|
109
|
+
await tracer.emitOperation(input.topic, input.data, false);
|
|
110
|
+
return motia.printer.printInvalidEmit(step, input.topic);
|
|
111
|
+
}
|
|
112
|
+
await tracer.emitOperation(input.topic, input.data, true);
|
|
113
|
+
return motia.eventAdapter.emit({
|
|
114
|
+
...input,
|
|
35
115
|
traceId,
|
|
36
|
-
|
|
37
|
-
message: error.message
|
|
38
|
-
});
|
|
39
|
-
throw new Error(`Failed to compile TypeScript file ${step.filePath}: ${error.message}`);
|
|
40
|
-
}
|
|
41
|
-
const { runner, command, args } = getLanguageBasedRunner(step.filePath);
|
|
42
|
-
let result;
|
|
43
|
-
let timeoutId;
|
|
44
|
-
return new Promise((resolve, reject) => {
|
|
45
|
-
const processManager = new ProcessManager({
|
|
46
|
-
command,
|
|
47
|
-
args: [
|
|
48
|
-
...args,
|
|
49
|
-
runner,
|
|
50
|
-
filePathToExecute,
|
|
51
|
-
jsonData
|
|
52
|
-
],
|
|
116
|
+
flows: flows$1,
|
|
53
117
|
logger,
|
|
54
|
-
|
|
55
|
-
projectRoot: motia.lockedData.baseDir
|
|
118
|
+
tracer
|
|
56
119
|
});
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
120
|
+
});
|
|
121
|
+
Object.entries(streamConfig).forEach(([name, streamFactory]) => {
|
|
122
|
+
const stateStream = streamFactory();
|
|
123
|
+
processManager.handler(`streams.${name}.get`, async (input) => {
|
|
124
|
+
await tracer.streamOperation(name, "get", input);
|
|
125
|
+
return stateStream.get(input.groupId, input.id);
|
|
62
126
|
});
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
step: step.config.name,
|
|
69
|
-
timeout: timeoutSeconds
|
|
127
|
+
processManager.handler(`streams.${name}.set`, async (input) => {
|
|
128
|
+
await tracer.streamOperation(name, "set", {
|
|
129
|
+
groupId: input.groupId,
|
|
130
|
+
id: input.id,
|
|
131
|
+
data: input.data
|
|
70
132
|
});
|
|
71
|
-
|
|
72
|
-
|
|
133
|
+
return stateStream.set(input.groupId, input.id, input.data);
|
|
134
|
+
});
|
|
135
|
+
processManager.handler(`streams.${name}.delete`, async (input) => {
|
|
136
|
+
await tracer.streamOperation(name, "delete", input);
|
|
137
|
+
return stateStream.delete(input.groupId, input.id);
|
|
138
|
+
});
|
|
139
|
+
processManager.handler(`streams.${name}.getGroup`, async (input) => {
|
|
140
|
+
await tracer.streamOperation(name, "getGroup", input);
|
|
141
|
+
return stateStream.getGroup(input.groupId);
|
|
142
|
+
});
|
|
143
|
+
processManager.handler(`streams.${name}.send`, async (input) => {
|
|
144
|
+
await tracer.streamOperation(name, "send", input);
|
|
145
|
+
return stateStream.send(input.channel, input.event);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
processManager.onStdout((data$1) => {
|
|
149
|
+
try {
|
|
150
|
+
const message = JSON.parse(data$1.toString());
|
|
151
|
+
logger.log(message);
|
|
152
|
+
} catch {
|
|
153
|
+
logger.info(Buffer.from(data$1).toString());
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
processManager.onStderr((data$1) => logger.error(Buffer.from(data$1).toString()));
|
|
157
|
+
processManager.onProcessClose(async (code) => {
|
|
158
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
159
|
+
processManager.close();
|
|
160
|
+
if (code !== 0 && code !== null) {
|
|
161
|
+
const error = {
|
|
162
|
+
message: `Process exited with code ${code}`,
|
|
163
|
+
code
|
|
164
|
+
};
|
|
165
|
+
await tracer.end(error);
|
|
166
|
+
trackEvent("step_execution_error", {
|
|
73
167
|
stepName: step.config.name,
|
|
74
168
|
traceId,
|
|
75
|
-
|
|
76
|
-
});
|
|
77
|
-
reject(new Error(errorMessage));
|
|
78
|
-
}, timeoutSeconds * 1e3);
|
|
79
|
-
processManager.spawn().then(() => {
|
|
80
|
-
processManager.handler("close", async (err) => {
|
|
81
|
-
if (err) {
|
|
82
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
83
|
-
processManager.close();
|
|
84
|
-
trackEvent("step_execution_error", {
|
|
85
|
-
stepName: step.config.name,
|
|
86
|
-
traceId,
|
|
87
|
-
message: err.message
|
|
88
|
-
});
|
|
89
|
-
await tracer.end({
|
|
90
|
-
message: err.message,
|
|
91
|
-
code: err.code,
|
|
92
|
-
stack: err.stack?.replace(/* @__PURE__ */ new RegExp(`${motia.lockedData.baseDir}/`), "")
|
|
93
|
-
});
|
|
94
|
-
reject(err ?? /* @__PURE__ */ new Error("Handler execution failed"));
|
|
95
|
-
} else await tracer.end();
|
|
96
|
-
processManager.kill();
|
|
97
|
-
});
|
|
98
|
-
processManager.handler("log", async (input) => logger.log(input));
|
|
99
|
-
processManager.handler("state.get", async (input) => {
|
|
100
|
-
await tracer.stateOperation("get", input);
|
|
101
|
-
return motia.state.get(input.traceId, input.key);
|
|
102
|
-
});
|
|
103
|
-
processManager.handler("state.set", async (input) => {
|
|
104
|
-
await tracer.stateOperation("set", {
|
|
105
|
-
traceId: input.traceId,
|
|
106
|
-
key: input.key,
|
|
107
|
-
value: input.value
|
|
108
|
-
});
|
|
109
|
-
return motia.state.set(input.traceId, input.key, input.value);
|
|
110
|
-
});
|
|
111
|
-
processManager.handler("state.delete", async (input) => {
|
|
112
|
-
await tracer.stateOperation("delete", input);
|
|
113
|
-
return motia.state.delete(input.traceId, input.key);
|
|
114
|
-
});
|
|
115
|
-
processManager.handler("state.clear", async (input) => {
|
|
116
|
-
await tracer.stateOperation("clear", input);
|
|
117
|
-
return motia.state.clear(input.traceId);
|
|
118
|
-
});
|
|
119
|
-
processManager.handler(`state.getGroup`, async (input) => {
|
|
120
|
-
await tracer.stateOperation("getGroup", input);
|
|
121
|
-
return motia.state.getGroup(input.groupId);
|
|
122
|
-
});
|
|
123
|
-
processManager.handler("result", async (input) => {
|
|
124
|
-
const inputWithBody = input;
|
|
125
|
-
if (inputWithBody.body && inputWithBody.body.type === "Buffer") inputWithBody.body = Buffer.from(inputWithBody.body.data || []);
|
|
126
|
-
result = inputWithBody;
|
|
127
|
-
});
|
|
128
|
-
processManager.handler("emit", async (input) => {
|
|
129
|
-
const flows$1 = step.config.flows;
|
|
130
|
-
if (!isAllowedToEmit(step, input.topic)) {
|
|
131
|
-
await tracer.emitOperation(input.topic, input.data, false);
|
|
132
|
-
return motia.printer.printInvalidEmit(step, input.topic);
|
|
133
|
-
}
|
|
134
|
-
await tracer.emitOperation(input.topic, input.data, true);
|
|
135
|
-
return motia.eventAdapter.emit({
|
|
136
|
-
...input,
|
|
137
|
-
traceId,
|
|
138
|
-
flows: flows$1,
|
|
139
|
-
logger,
|
|
140
|
-
tracer
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
Object.entries(streamConfig).forEach(([name, streamFactory]) => {
|
|
144
|
-
const stateStream = streamFactory();
|
|
145
|
-
processManager.handler(`streams.${name}.get`, async (input) => {
|
|
146
|
-
await tracer.streamOperation(name, "get", input);
|
|
147
|
-
return stateStream.get(input.groupId, input.id);
|
|
148
|
-
});
|
|
149
|
-
processManager.handler(`streams.${name}.set`, async (input) => {
|
|
150
|
-
await tracer.streamOperation(name, "set", {
|
|
151
|
-
groupId: input.groupId,
|
|
152
|
-
id: input.id,
|
|
153
|
-
data: input.data
|
|
154
|
-
});
|
|
155
|
-
return stateStream.set(input.groupId, input.id, input.data);
|
|
156
|
-
});
|
|
157
|
-
processManager.handler(`streams.${name}.delete`, async (input) => {
|
|
158
|
-
await tracer.streamOperation(name, "delete", input);
|
|
159
|
-
return stateStream.delete(input.groupId, input.id);
|
|
160
|
-
});
|
|
161
|
-
processManager.handler(`streams.${name}.getGroup`, async (input) => {
|
|
162
|
-
await tracer.streamOperation(name, "getGroup", input);
|
|
163
|
-
return stateStream.getGroup(input.groupId);
|
|
164
|
-
});
|
|
165
|
-
processManager.handler(`streams.${name}.send`, async (input) => {
|
|
166
|
-
await tracer.streamOperation(name, "send", input);
|
|
167
|
-
return stateStream.send(input.channel, input.event);
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
processManager.onStdout((data$1) => {
|
|
171
|
-
try {
|
|
172
|
-
const message = JSON.parse(data$1.toString());
|
|
173
|
-
logger.log(message);
|
|
174
|
-
} catch {
|
|
175
|
-
logger.info(Buffer.from(data$1).toString());
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
processManager.onStderr((data$1) => logger.error(Buffer.from(data$1).toString()));
|
|
179
|
-
processManager.onProcessClose(async (code) => {
|
|
180
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
181
|
-
processManager.close();
|
|
182
|
-
if (code !== 0 && code !== null) {
|
|
183
|
-
const error = {
|
|
184
|
-
message: `Process exited with code ${code}`,
|
|
185
|
-
code
|
|
186
|
-
};
|
|
187
|
-
await tracer.end(error);
|
|
188
|
-
trackEvent("step_execution_error", {
|
|
189
|
-
stepName: step.config.name,
|
|
190
|
-
traceId,
|
|
191
|
-
code
|
|
192
|
-
});
|
|
193
|
-
reject(`Process exited with code ${code}`);
|
|
194
|
-
} else {
|
|
195
|
-
await tracer.end();
|
|
196
|
-
resolve(result);
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
processManager.onProcessError(async (error) => {
|
|
200
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
201
|
-
processManager.close();
|
|
202
|
-
await tracer.end({
|
|
203
|
-
message: error.message,
|
|
204
|
-
code: error.code,
|
|
205
|
-
stack: error.stack
|
|
206
|
-
});
|
|
207
|
-
if (error.code === "ENOENT") {
|
|
208
|
-
trackEvent("step_execution_error", {
|
|
209
|
-
stepName: step.config.name,
|
|
210
|
-
traceId,
|
|
211
|
-
code: error.code,
|
|
212
|
-
message: error.message
|
|
213
|
-
});
|
|
214
|
-
reject(`Executable ${command} not found`);
|
|
215
|
-
} else reject(error);
|
|
216
|
-
});
|
|
217
|
-
}).catch(async (error) => {
|
|
218
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
219
|
-
await tracer.end({
|
|
220
|
-
message: error.message,
|
|
221
|
-
code: error.code,
|
|
222
|
-
stack: error.stack
|
|
169
|
+
code
|
|
223
170
|
});
|
|
171
|
+
reject(`Process exited with code ${code}`);
|
|
172
|
+
} else {
|
|
173
|
+
await tracer.end();
|
|
174
|
+
resolve(result);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
processManager.onProcessError(async (error) => {
|
|
178
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
179
|
+
processManager.close();
|
|
180
|
+
await tracer.end({
|
|
181
|
+
message: error.message,
|
|
182
|
+
code: error.code,
|
|
183
|
+
stack: error.stack
|
|
184
|
+
});
|
|
185
|
+
if (error.code === "ENOENT") {
|
|
224
186
|
trackEvent("step_execution_error", {
|
|
225
187
|
stepName: step.config.name,
|
|
226
188
|
traceId,
|
|
227
189
|
code: error.code,
|
|
228
190
|
message: error.message
|
|
229
191
|
});
|
|
230
|
-
reject(`
|
|
231
|
-
});
|
|
192
|
+
reject(`Executable ${command} not found`);
|
|
193
|
+
} else reject(error);
|
|
232
194
|
});
|
|
233
|
-
}
|
|
234
|
-
|
|
195
|
+
}).catch(async (error) => {
|
|
196
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
235
197
|
await tracer.end({
|
|
236
|
-
message:
|
|
237
|
-
code:
|
|
238
|
-
stack:
|
|
198
|
+
message: error.message,
|
|
199
|
+
code: error.code,
|
|
200
|
+
stack: error.stack
|
|
239
201
|
});
|
|
240
202
|
trackEvent("step_execution_error", {
|
|
241
203
|
stepName: step.config.name,
|
|
242
204
|
traceId,
|
|
243
|
-
code:
|
|
244
|
-
message:
|
|
205
|
+
code: error.code,
|
|
206
|
+
message: error.message
|
|
245
207
|
});
|
|
246
|
-
|
|
247
|
-
}
|
|
248
|
-
})
|
|
208
|
+
reject(`Failed to spawn process: ${error}`);
|
|
209
|
+
});
|
|
210
|
+
});
|
|
249
211
|
};
|
|
250
212
|
|
|
251
213
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"call-step-file.mjs","names":["compileError: unknown","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 let filePathToExecute = step.filePath\n if (step.filePath.endsWith('.ts')) {\n try {\n filePathToExecute = await compile(step.filePath, motia.lockedData.baseDir)\n } catch (compileError: unknown) {\n const error = compileError as Error & { code?: string }\n logger.error(`Failed to compile TypeScript file: ${step.filePath}`, { error })\n await tracer.end({\n message: `Compilation failed: ${error.message}`,\n code: error.code,\n stack: error.stack,\n })\n trackEvent('step_execution_error', {\n stepName: step.config.name,\n traceId,\n code: 'COMPILATION_ERROR',\n message: error.message,\n })\n throw new Error(`Failed to compile TypeScript file ${step.filePath}: ${error.message}`)\n }\n }\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","anyInput: any","flows","data"],"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 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 new Promise((resolve, reject) => {\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 const { runner, command, args } = getLanguageBasedRunner(step.filePath)\n let result: TData | undefined\n let timeoutId: NodeJS.Timeout | undefined\n\n const processManager = new ProcessManager({\n command,\n args: [...args, runner, step.filePath, 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 anyInput: any = { ...input }\n\n if (anyInput.body && anyInput.body.type === 'Buffer') {\n anyInput.body = Buffer.from(anyInput.body.data)\n }\n result = anyInput\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}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { StreamConfig } from "./types-stream.mjs";
|
|
2
2
|
import { StepConfig } from "./types.mjs";
|
|
3
|
-
import { invalidate } from "./ts-compiler.mjs";
|
|
4
3
|
|
|
5
4
|
//#region src/get-step-config.d.ts
|
|
6
5
|
declare const getStepConfig: (file: string, projectRoot?: string) => Promise<StepConfig | null>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-step-config.d.mts","names":[],"sources":["../../src/get-step-config.ts"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"get-step-config.d.mts","names":[],"sources":["../../src/get-step-config.ts"],"sourcesContent":[],"mappings":";;;;cA+Da,uDAAsD,QAAQ;cAI9D,yDAAwD,QAAQ"}
|
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
import { globalLogger } from "./logger.mjs";
|
|
2
2
|
import { getLanguageBasedRunner } from "./language-runner.mjs";
|
|
3
3
|
import { ProcessManager } from "./process-communication/process-manager.mjs";
|
|
4
|
-
import { compile, invalidate } from "./ts-compiler.mjs";
|
|
5
4
|
|
|
6
5
|
//#region src/get-step-config.ts
|
|
7
|
-
const getConfig =
|
|
8
|
-
let filePathToExecute = file;
|
|
9
|
-
if (file.endsWith(".ts")) try {
|
|
10
|
-
filePathToExecute = await compile(file, projectRoot || process.cwd());
|
|
11
|
-
} catch (error) {
|
|
12
|
-
throw new Error(`Failed to compile TypeScript file: ${error}`);
|
|
13
|
-
}
|
|
6
|
+
const getConfig = (file, projectRoot) => {
|
|
14
7
|
const { runner, command, args } = getLanguageBasedRunner(file, {
|
|
15
8
|
python: "get-config.py",
|
|
16
9
|
ruby: "get-config.rb",
|
|
@@ -19,19 +12,19 @@ const getConfig = async (file, projectRoot) => {
|
|
|
19
12
|
ts: "get-config.ts"
|
|
20
13
|
}
|
|
21
14
|
});
|
|
22
|
-
const processManager = new ProcessManager({
|
|
23
|
-
command,
|
|
24
|
-
args: [
|
|
25
|
-
...args,
|
|
26
|
-
runner,
|
|
27
|
-
filePathToExecute
|
|
28
|
-
],
|
|
29
|
-
logger: globalLogger,
|
|
30
|
-
context: "Config",
|
|
31
|
-
projectRoot
|
|
32
|
-
});
|
|
33
15
|
return new Promise((resolve, reject) => {
|
|
34
16
|
let config = null;
|
|
17
|
+
const processManager = new ProcessManager({
|
|
18
|
+
command,
|
|
19
|
+
args: [
|
|
20
|
+
...args,
|
|
21
|
+
runner,
|
|
22
|
+
file
|
|
23
|
+
],
|
|
24
|
+
logger: globalLogger,
|
|
25
|
+
context: "Config",
|
|
26
|
+
projectRoot
|
|
27
|
+
});
|
|
35
28
|
processManager.spawn().then(() => {
|
|
36
29
|
processManager.onMessage((message) => {
|
|
37
30
|
config = message;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-step-config.mjs","names":["config: T | null"],"sources":["../../src/get-step-config.ts"],"sourcesContent":["import { getLanguageBasedRunner } from './language-runner'\nimport { globalLogger } from './logger'\nimport { ProcessManager } from './process-communication/process-manager'\nimport
|
|
1
|
+
{"version":3,"file":"get-step-config.mjs","names":["config: T | null"],"sources":["../../src/get-step-config.ts"],"sourcesContent":["import { getLanguageBasedRunner } from './language-runner'\nimport { globalLogger } from './logger'\nimport { ProcessManager } from './process-communication/process-manager'\nimport type { StepConfig } from './types'\nimport type { StreamConfig } from './types-stream'\n\nconst getConfig = <T>(file: string, projectRoot?: string): Promise<T | null> => {\n const { runner, command, args } = getLanguageBasedRunner(file, {\n python: 'get-config.py',\n ruby: 'get-config.rb',\n node: { js: 'get-config.mjs', ts: 'get-config.ts' },\n })\n\n return new Promise((resolve, reject) => {\n let config: T | null = null\n\n const processManager = new ProcessManager({\n command,\n args: [...args, runner, file],\n logger: globalLogger,\n context: 'Config',\n projectRoot,\n })\n\n processManager\n .spawn()\n .then(() => {\n processManager.onMessage<T>((message) => {\n config = message\n globalLogger.debug(`[Config] Read config via ${processManager.commType?.toUpperCase()}`, {\n config,\n communicationType: processManager.commType,\n })\n resolve(config)\n processManager.kill()\n })\n\n processManager.onProcessClose((code) => {\n processManager.close()\n if (config) {\n return\n } else if (code !== 0) {\n reject(`Process exited with code ${code}`)\n } else if (!config) {\n reject(`No config found for file ${file}`)\n }\n })\n\n processManager.onProcessError((error) => {\n processManager.close()\n if (error.code === 'ENOENT') {\n reject(`Executable ${command} not found`)\n } else {\n reject(error)\n }\n })\n })\n .catch((error) => {\n reject(`Failed to spawn process: ${error}`)\n })\n })\n}\n\nexport const getStepConfig = (file: string, projectRoot?: string): Promise<StepConfig | null> => {\n return getConfig<StepConfig>(file, projectRoot)\n}\n\nexport const getStreamConfig = (file: string, projectRoot?: string): Promise<StreamConfig | null> => {\n return getConfig<StreamConfig>(file, projectRoot)\n}\n"],"mappings":";;;;;AAMA,MAAM,aAAgB,MAAc,gBAA4C;CAC9E,MAAM,EAAE,QAAQ,SAAS,SAAS,uBAAuB,MAAM;EAC7D,QAAQ;EACR,MAAM;EACN,MAAM;GAAE,IAAI;GAAkB,IAAI;GAAiB;EACpD,CAAC;AAEF,QAAO,IAAI,SAAS,SAAS,WAAW;EACtC,IAAIA,SAAmB;EAEvB,MAAM,iBAAiB,IAAI,eAAe;GACxC;GACA,MAAM;IAAC,GAAG;IAAM;IAAQ;IAAK;GAC7B,QAAQ;GACR,SAAS;GACT;GACD,CAAC;AAEF,iBACG,OAAO,CACP,WAAW;AACV,kBAAe,WAAc,YAAY;AACvC,aAAS;AACT,iBAAa,MAAM,4BAA4B,eAAe,UAAU,aAAa,IAAI;KACvF;KACA,mBAAmB,eAAe;KACnC,CAAC;AACF,YAAQ,OAAO;AACf,mBAAe,MAAM;KACrB;AAEF,kBAAe,gBAAgB,SAAS;AACtC,mBAAe,OAAO;AACtB,QAAI,OACF;aACS,SAAS,EAClB,QAAO,4BAA4B,OAAO;aACjC,CAAC,OACV,QAAO,4BAA4B,OAAO;KAE5C;AAEF,kBAAe,gBAAgB,UAAU;AACvC,mBAAe,OAAO;AACtB,QAAI,MAAM,SAAS,SACjB,QAAO,cAAc,QAAQ,YAAY;QAEzC,QAAO,MAAM;KAEf;IACF,CACD,OAAO,UAAU;AAChB,UAAO,4BAA4B,QAAQ;IAC3C;GACJ;;AAGJ,MAAa,iBAAiB,MAAc,gBAAqD;AAC/F,QAAO,UAAsB,MAAM,YAAY;;AAGjD,MAAa,mBAAmB,MAAc,gBAAuD;AACnG,QAAO,UAAwB,MAAM,YAAY"}
|
|
@@ -29,7 +29,6 @@ const getLanguageBasedRunner = (stepFilePath = "", overrides) => {
|
|
|
29
29
|
};
|
|
30
30
|
else if (isNode) {
|
|
31
31
|
const defaultNodeOverrides = overrides?.node;
|
|
32
|
-
const isTypeScript = stepFilePath.endsWith(".ts");
|
|
33
32
|
if (process.env._MOTIA_TEST_MODE === "true") {
|
|
34
33
|
const runnerFile = defaultNodeOverrides?.ts ?? "node-runner.ts";
|
|
35
34
|
return {
|
|
@@ -43,11 +42,6 @@ const getLanguageBasedRunner = (stepFilePath = "", overrides) => {
|
|
|
43
42
|
};
|
|
44
43
|
}
|
|
45
44
|
const jsRunner = path.join(__dirname, "node", defaultNodeOverrides?.js ?? "node-runner.mjs");
|
|
46
|
-
if (isTypeScript) return {
|
|
47
|
-
runner: jsRunner,
|
|
48
|
-
command: "node",
|
|
49
|
-
args: []
|
|
50
|
-
};
|
|
51
45
|
const tsxPath = getTsxPath();
|
|
52
46
|
if (tsxPath !== "tsx") return {
|
|
53
47
|
runner: jsRunner,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"language-runner.mjs","names":[],"sources":["../../src/language-runner.ts"],"sourcesContent":["import { createRequire } from 'module'\nimport path from 'path'\nimport { fileURLToPath } from 'url'\n\nexport type LanguageRunnerConfig = {\n command: string\n runner: string\n args: string[]\n}\n\nexport type LanguageRunnerOverrides = {\n python?: string\n ruby?: string\n node?: {\n js: string\n ts?: string\n }\n}\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\nconst require = createRequire(import.meta.url)\n\nconst getTsxPath = () => {\n try {\n const tsxModule = require.resolve('tsx/package.json')\n return path.join(path.dirname(tsxModule), 'dist', 'cli.mjs')\n } catch {\n return 'tsx'\n }\n}\n\nexport const getLanguageBasedRunner = (\n stepFilePath = '',\n overrides?: LanguageRunnerOverrides,\n): LanguageRunnerConfig => {\n const isPython = stepFilePath.endsWith('.py')\n const isRuby = stepFilePath.endsWith('.rb')\n const isNode = stepFilePath.endsWith('.js') || stepFilePath.endsWith('.ts')\n\n if (isPython) {\n const pythonRunner = path.join(__dirname, 'python', overrides?.python ?? 'python-runner.py')\n return { runner: pythonRunner, command: 'python', args: [] }\n } else if (isRuby) {\n const rubyRunner = path.join(__dirname, 'ruby', overrides?.ruby ?? 'ruby-runner.rb')\n return { runner: rubyRunner, command: 'ruby', args: [] }\n } else if (isNode) {\n const defaultNodeOverrides = overrides?.node\n
|
|
1
|
+
{"version":3,"file":"language-runner.mjs","names":[],"sources":["../../src/language-runner.ts"],"sourcesContent":["import { createRequire } from 'module'\nimport path from 'path'\nimport { fileURLToPath } from 'url'\n\nexport type LanguageRunnerConfig = {\n command: string\n runner: string\n args: string[]\n}\n\nexport type LanguageRunnerOverrides = {\n python?: string\n ruby?: string\n node?: {\n js: string\n ts?: string\n }\n}\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\nconst require = createRequire(import.meta.url)\n\nconst getTsxPath = () => {\n try {\n const tsxModule = require.resolve('tsx/package.json')\n return path.join(path.dirname(tsxModule), 'dist', 'cli.mjs')\n } catch {\n return 'tsx'\n }\n}\n\nexport const getLanguageBasedRunner = (\n stepFilePath = '',\n overrides?: LanguageRunnerOverrides,\n): LanguageRunnerConfig => {\n const isPython = stepFilePath.endsWith('.py')\n const isRuby = stepFilePath.endsWith('.rb')\n const isNode = stepFilePath.endsWith('.js') || stepFilePath.endsWith('.ts')\n\n if (isPython) {\n const pythonRunner = path.join(__dirname, 'python', overrides?.python ?? 'python-runner.py')\n return { runner: pythonRunner, command: 'python', args: [] }\n } else if (isRuby) {\n const rubyRunner = path.join(__dirname, 'ruby', overrides?.ruby ?? 'ruby-runner.rb')\n return { runner: rubyRunner, command: 'ruby', args: [] }\n } else if (isNode) {\n const defaultNodeOverrides = overrides?.node\n\n if (process.env._MOTIA_TEST_MODE === 'true') {\n const runnerFile = defaultNodeOverrides?.ts ?? 'node-runner.ts'\n return {\n runner: path.join(__dirname, 'node', runnerFile),\n command: 'node',\n args: ['--loader', 'ts-node/esm', '--no-warnings=ExperimentalWarning'],\n }\n }\n const jsRunner = path.join(__dirname, 'node', defaultNodeOverrides?.js ?? 'node-runner.mjs')\n const tsxPath = getTsxPath()\n // When tsx resolves to a file path, run it through node (tsx CLI is an .mjs file)\n // When tsx falls back to 'tsx' string, use it directly as a command (assumes tsx is in PATH)\n if (tsxPath !== 'tsx') {\n return { runner: jsRunner, command: 'node', args: [tsxPath] }\n }\n return { runner: jsRunner, command: tsxPath, args: [] }\n }\n\n throw Error(`Unsupported file extension ${stepFilePath}`)\n}\n"],"mappings":";;;;;AAmBA,MAAM,YAAY,KAAK,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;AAC9D,MAAM,UAAU,cAAc,OAAO,KAAK,IAAI;AAE9C,MAAM,mBAAmB;AACvB,KAAI;EACF,MAAM,YAAY,QAAQ,QAAQ,mBAAmB;AACrD,SAAO,KAAK,KAAK,KAAK,QAAQ,UAAU,EAAE,QAAQ,UAAU;SACtD;AACN,SAAO;;;AAIX,MAAa,0BACX,eAAe,IACf,cACyB;CACzB,MAAM,WAAW,aAAa,SAAS,MAAM;CAC7C,MAAM,SAAS,aAAa,SAAS,MAAM;CAC3C,MAAM,SAAS,aAAa,SAAS,MAAM,IAAI,aAAa,SAAS,MAAM;AAE3E,KAAI,SAEF,QAAO;EAAE,QADY,KAAK,KAAK,WAAW,UAAU,WAAW,UAAU,mBAAmB;EAC7D,SAAS;EAAU,MAAM,EAAE;EAAE;UACnD,OAET,QAAO;EAAE,QADU,KAAK,KAAK,WAAW,QAAQ,WAAW,QAAQ,iBAAiB;EACvD,SAAS;EAAQ,MAAM,EAAE;EAAE;UAC/C,QAAQ;EACjB,MAAM,uBAAuB,WAAW;AAExC,MAAI,QAAQ,IAAI,qBAAqB,QAAQ;GAC3C,MAAM,aAAa,sBAAsB,MAAM;AAC/C,UAAO;IACL,QAAQ,KAAK,KAAK,WAAW,QAAQ,WAAW;IAChD,SAAS;IACT,MAAM;KAAC;KAAY;KAAe;KAAoC;IACvE;;EAEH,MAAM,WAAW,KAAK,KAAK,WAAW,QAAQ,sBAAsB,MAAM,kBAAkB;EAC5F,MAAM,UAAU,YAAY;AAG5B,MAAI,YAAY,MACd,QAAO;GAAE,QAAQ;GAAU,SAAS;GAAQ,MAAM,CAAC,QAAQ;GAAE;AAE/D,SAAO;GAAE,QAAQ;GAAU,SAAS;GAAS,MAAM,EAAE;GAAE;;AAGzD,OAAM,MAAM,8BAA8B,eAAe"}
|
package/dist/src/logger.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.mts","names":[],"sources":["../../src/logger.ts"],"sourcesContent":[],"mappings":";KAQY,WAAA;AAAA,cAEC,MAAA,CAFU;EAEV,SAAM,SAAA,EAAA,OAAA;EAaQ,iBAAA,IAAA;EACS,iBAAA,aAAA;EAGtB;;;;;;;;;0CAJa,yCACS;cAGtB,0BAA0B;;;;;;;wBAuChB
|
|
1
|
+
{"version":3,"file":"logger.d.mts","names":[],"sources":["../../src/logger.ts"],"sourcesContent":[],"mappings":";KAQY,WAAA;AAAA,cAEC,MAAA,CAFU;EAEV,SAAM,SAAA,EAAA,OAAA;EAaQ,iBAAA,IAAA;EACS,iBAAA,aAAA;EAGtB;;;;;;;;;0CAJa,yCACS;cAGtB,0BAA0B;;;;;;;wBAuChB"}
|
package/dist/src/logger.mjs
CHANGED
|
@@ -56,14 +56,6 @@ var Logger = class Logger {
|
|
|
56
56
|
addListener(listener) {
|
|
57
57
|
this.listeners.push(listener);
|
|
58
58
|
}
|
|
59
|
-
removeListener(listener) {
|
|
60
|
-
const index = this.listeners.indexOf(listener);
|
|
61
|
-
if (index !== -1) {
|
|
62
|
-
this.listeners.splice(index, 1);
|
|
63
|
-
return true;
|
|
64
|
-
}
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
59
|
};
|
|
68
60
|
const globalLogger = new Logger();
|
|
69
61
|
|
package/dist/src/logger.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.mjs","names":["isVerbose: boolean","meta: Record<string, unknown>","coreListeners: LogListener[]"],"sources":["../../src/logger.ts"],"sourcesContent":["import { prettyPrint } from './pretty-print'\n\nconst logLevel = process.env.LOG_LEVEL ?? 'info'\n\nconst isDebugEnabled = logLevel === 'debug'\nconst isInfoEnabled = ['info', 'debug'].includes(logLevel)\nconst isWarnEnabled = ['warn', 'info', 'debug', 'trace'].includes(logLevel)\n\nexport type LogListener = (level: string, msg: string, args?: unknown) => void\n\nexport class Logger {\n /**\n * Why do we need two level of listeners?\n *\n * Core listeners pass along to children loggers.\n *\n * However, base listeners do not pass along to children loggers.\n * Those are specific to each logger in the hierarchy.\n */\n private readonly listeners: LogListener[] = []\n\n constructor(\n readonly isVerbose: boolean = false,\n private readonly meta: Record<string, unknown> = {},\n private readonly coreListeners: LogListener[] = [],\n ) {}\n\n child(meta: Record<string, unknown>): Logger {\n return new Logger(this.isVerbose, { ...this.meta, ...meta }, this.coreListeners)\n }\n\n private _log(level: string, msg: string, args?: any) {\n const time = Date.now()\n const meta = { ...this.meta, ...(args ?? {}) }\n prettyPrint({ level, time, msg, ...meta }, !this.isVerbose)\n\n this.coreListeners.forEach((listener) => listener(level, msg, meta))\n this.listeners.forEach((listener) => listener(level, msg, meta))\n }\n\n info(message: string, args?: unknown) {\n if (isInfoEnabled) {\n this._log('info', message, args)\n }\n }\n\n error(message: string, args?: unknown) {\n this._log('error', message, args)\n }\n\n debug(message: string, args?: unknown) {\n if (isDebugEnabled) {\n this._log('debug', message, args)\n }\n }\n\n warn(message: string, args?: unknown) {\n if (isWarnEnabled) {\n this._log('warn', message, args)\n }\n }\n\n log(args: any) {\n this._log(args.level ?? 'info', args.msg, args)\n }\n\n addListener(listener: LogListener) {\n this.listeners.push(listener)\n }\n
|
|
1
|
+
{"version":3,"file":"logger.mjs","names":["isVerbose: boolean","meta: Record<string, unknown>","coreListeners: LogListener[]"],"sources":["../../src/logger.ts"],"sourcesContent":["import { prettyPrint } from './pretty-print'\n\nconst logLevel = process.env.LOG_LEVEL ?? 'info'\n\nconst isDebugEnabled = logLevel === 'debug'\nconst isInfoEnabled = ['info', 'debug'].includes(logLevel)\nconst isWarnEnabled = ['warn', 'info', 'debug', 'trace'].includes(logLevel)\n\nexport type LogListener = (level: string, msg: string, args?: unknown) => void\n\nexport class Logger {\n /**\n * Why do we need two level of listeners?\n *\n * Core listeners pass along to children loggers.\n *\n * However, base listeners do not pass along to children loggers.\n * Those are specific to each logger in the hierarchy.\n */\n private readonly listeners: LogListener[] = []\n\n constructor(\n readonly isVerbose: boolean = false,\n private readonly meta: Record<string, unknown> = {},\n private readonly coreListeners: LogListener[] = [],\n ) {}\n\n child(meta: Record<string, unknown>): Logger {\n return new Logger(this.isVerbose, { ...this.meta, ...meta }, this.coreListeners)\n }\n\n private _log(level: string, msg: string, args?: any) {\n const time = Date.now()\n const meta = { ...this.meta, ...(args ?? {}) }\n prettyPrint({ level, time, msg, ...meta }, !this.isVerbose)\n\n this.coreListeners.forEach((listener) => listener(level, msg, meta))\n this.listeners.forEach((listener) => listener(level, msg, meta))\n }\n\n info(message: string, args?: unknown) {\n if (isInfoEnabled) {\n this._log('info', message, args)\n }\n }\n\n error(message: string, args?: unknown) {\n this._log('error', message, args)\n }\n\n debug(message: string, args?: unknown) {\n if (isDebugEnabled) {\n this._log('debug', message, args)\n }\n }\n\n warn(message: string, args?: unknown) {\n if (isWarnEnabled) {\n this._log('warn', message, args)\n }\n }\n\n log(args: any) {\n this._log(args.level ?? 'info', args.msg, args)\n }\n\n addListener(listener: LogListener) {\n this.listeners.push(listener)\n }\n}\n\nexport const globalLogger = new Logger()\n"],"mappings":";;;AAEA,MAAM,WAAW,QAAQ,IAAI,aAAa;AAE1C,MAAM,iBAAiB,aAAa;AACpC,MAAM,gBAAgB,CAAC,QAAQ,QAAQ,CAAC,SAAS,SAAS;AAC1D,MAAM,gBAAgB;CAAC;CAAQ;CAAQ;CAAS;CAAQ,CAAC,SAAS,SAAS;AAI3E,IAAa,SAAb,MAAa,OAAO;CAWlB,YACE,AAASA,YAAqB,OAC9B,AAAiBC,OAAgC,EAAE,EACnD,AAAiBC,gBAA+B,EAAE,EAClD;EAHS;EACQ;EACA;mBALyB,EAAE;;CAQ9C,MAAM,MAAuC;AAC3C,SAAO,IAAI,OAAO,KAAK,WAAW;GAAE,GAAG,KAAK;GAAM,GAAG;GAAM,EAAE,KAAK,cAAc;;CAGlF,AAAQ,KAAK,OAAe,KAAa,MAAY;EACnD,MAAM,OAAO,KAAK,KAAK;EACvB,MAAM,OAAO;GAAE,GAAG,KAAK;GAAM,GAAI,QAAQ,EAAE;GAAG;AAC9C,cAAY;GAAE;GAAO;GAAM;GAAK,GAAG;GAAM,EAAE,CAAC,KAAK,UAAU;AAE3D,OAAK,cAAc,SAAS,aAAa,SAAS,OAAO,KAAK,KAAK,CAAC;AACpE,OAAK,UAAU,SAAS,aAAa,SAAS,OAAO,KAAK,KAAK,CAAC;;CAGlE,KAAK,SAAiB,MAAgB;AACpC,MAAI,cACF,MAAK,KAAK,QAAQ,SAAS,KAAK;;CAIpC,MAAM,SAAiB,MAAgB;AACrC,OAAK,KAAK,SAAS,SAAS,KAAK;;CAGnC,MAAM,SAAiB,MAAgB;AACrC,MAAI,eACF,MAAK,KAAK,SAAS,SAAS,KAAK;;CAIrC,KAAK,SAAiB,MAAgB;AACpC,MAAI,cACF,MAAK,KAAK,QAAQ,SAAS,KAAK;;CAIpC,IAAI,MAAW;AACb,OAAK,KAAK,KAAK,SAAS,QAAQ,KAAK,KAAK,KAAK;;CAGjD,YAAY,UAAuB;AACjC,OAAK,UAAU,KAAK,SAAS;;;AAIjC,MAAa,eAAe,IAAI,QAAQ"}
|
|
@@ -18,21 +18,7 @@ function parseArgs(arg$1) {
|
|
|
18
18
|
async function runTypescriptModule(filePath$1, event) {
|
|
19
19
|
const sender = new RpcSender(process);
|
|
20
20
|
try {
|
|
21
|
-
|
|
22
|
-
let importedModule;
|
|
23
|
-
try {
|
|
24
|
-
importedModule = await import(pathToFileURL(path.resolve(filePath$1)).href);
|
|
25
|
-
} catch (importError) {
|
|
26
|
-
const err = importError;
|
|
27
|
-
const error = {
|
|
28
|
-
message: `Failed to import module ${filePath$1}: ${err.message}`,
|
|
29
|
-
code: err.code || "IMPORT_ERROR",
|
|
30
|
-
stack: err.stack || ""
|
|
31
|
-
};
|
|
32
|
-
sender.sendNoWait("close", error);
|
|
33
|
-
process.exit(1);
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
21
|
+
const importedModule = await import(pathToFileURL(path.resolve(filePath$1)).href);
|
|
36
22
|
const handler = importedModule.handler || importedModule.default?.handler;
|
|
37
23
|
const config = importedModule.config || importedModule.default?.config || {};
|
|
38
24
|
if (typeof handler !== "function") throw new Error(`Function handler not found in module ${filePath$1}`);
|
|
@@ -70,29 +56,28 @@ async function runTypescriptModule(filePath$1, event) {
|
|
|
70
56
|
return acc;
|
|
71
57
|
}, {})
|
|
72
58
|
};
|
|
59
|
+
sender.init();
|
|
73
60
|
const composedMiddleware = composeMiddleware(...Array.isArray(config.middleware) ? config.middleware : []);
|
|
74
61
|
const handlerFn = () => {
|
|
75
62
|
return contextInFirstArg ? handler(context) : handler(event.data, context);
|
|
76
63
|
};
|
|
77
64
|
const result = await composedMiddleware(event.data, context, handlerFn);
|
|
78
|
-
|
|
79
|
-
sender.sendNoWait("close", void 0);
|
|
65
|
+
await sender.send("result", result);
|
|
80
66
|
await sender.close();
|
|
81
67
|
process.exit(0);
|
|
82
68
|
} catch (err) {
|
|
83
|
-
const
|
|
84
|
-
const stack = error.stack?.split("\n") ?? [];
|
|
69
|
+
const stack = err.stack?.split("\n") ?? [];
|
|
85
70
|
if (stack) {
|
|
86
71
|
const index = stack.findIndex((line) => line.includes("src/node/node-runner"));
|
|
87
72
|
stack.splice(index, stack.length - index);
|
|
88
73
|
stack.splice(0, 1);
|
|
89
74
|
}
|
|
90
|
-
const
|
|
91
|
-
message:
|
|
92
|
-
code:
|
|
75
|
+
const error = {
|
|
76
|
+
message: err.message || "",
|
|
77
|
+
code: err.code || null,
|
|
93
78
|
stack: stack.join("\n")
|
|
94
79
|
};
|
|
95
|
-
sender.sendNoWait("close",
|
|
80
|
+
sender.sendNoWait("close", error);
|
|
96
81
|
}
|
|
97
82
|
}
|
|
98
83
|
const [, , filePath, arg] = process.argv;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-runner.mjs","names":["arg","
|
|
1
|
+
{"version":3,"file":"node-runner.mjs","names":["arg","filePath","err: any","stack: string[]"],"sources":["../../../src/node/node-runner.ts"],"sourcesContent":["import dotenv from 'dotenv'\nimport path from 'path'\nimport { pathToFileURL } from 'url'\nimport type { StateStreamEvent, StateStreamEventChannel, StreamConfig } from '../types-stream'\nimport { Logger } from './logger'\nimport { composeMiddleware } from './middleware-compose'\nimport { RpcSender } from './rpc'\nimport { RpcStateManager } from './rpc-state-manager'\n\ndotenv.config()\n\nfunction parseArgs(arg: string) {\n try {\n return JSON.parse(arg)\n } catch {\n return arg\n }\n}\n\nasync function runTypescriptModule(filePath: string, event: Record<string, unknown>) {\n const sender = new RpcSender(process)\n\n try {\n const importedModule = await import(pathToFileURL(path.resolve(filePath)).href)\n const handler = importedModule.handler || importedModule.default?.handler\n const config = importedModule.config || importedModule.default?.config || {}\n\n // Check if the specified function exists in the module\n if (typeof handler !== 'function') {\n throw new Error(`Function handler not found in module ${filePath}`)\n }\n\n const { traceId, flows, contextInFirstArg } = event\n\n const logger = new Logger(traceId as string, flows as string[], sender)\n const state = new RpcStateManager(sender)\n\n const emit = async (data: unknown) => sender.send('emit', data)\n const streamsConfig = event.streams as StreamConfig[]\n const streams = (streamsConfig ?? []).reduce(\n (acc, streams) => {\n acc[streams.name] = {\n get: (groupId: string, id: string) => sender.send(`streams.${streams.name}.get`, { groupId, id }),\n set: (groupId: string, id: string, data: unknown) =>\n sender.send(`streams.${streams.name}.set`, { groupId, id, data }),\n delete: (groupId: string, id: string) => sender.send(`streams.${streams.name}.delete`, { groupId, id }),\n getGroup: (groupId: string) => sender.send(`streams.${streams.name}.getGroup`, { groupId }),\n send: (channel: StateStreamEventChannel, event: StateStreamEvent<unknown>) =>\n sender.send(`streams.${streams.name}.send`, { channel, event }),\n }\n return acc\n },\n {} as Record<string, unknown>,\n )\n\n const context = { traceId, flows, logger, state, emit, streams }\n\n sender.init()\n\n const middlewares = Array.isArray(config.middleware) ? config.middleware : []\n\n const composedMiddleware = composeMiddleware(...middlewares)\n const handlerFn = () => {\n return contextInFirstArg ? handler(context) : handler(event.data, context)\n }\n\n const result = await composedMiddleware(event.data, context, handlerFn)\n\n await sender.send('result', result)\n await sender.close()\n\n process.exit(0)\n } catch (err: any) {\n const stack: string[] = err.stack?.split('\\n') ?? []\n\n if (stack) {\n const index = stack.findIndex((line) => line.includes('src/node/node-runner'))\n stack.splice(index, stack.length - index)\n stack.splice(0, 1) // remove first line which has the error message\n }\n\n const error = {\n message: err.message || '',\n code: err.code || null,\n stack: stack.join('\\n'),\n }\n sender.sendNoWait('close', error)\n }\n}\n\nconst [, , filePath, arg] = process.argv\n\nif (!filePath) {\n console.error('Usage: node node-runner.mjs <file-path> <arg>')\n process.exit(1)\n}\n\nrunTypescriptModule(filePath, parseArgs(arg)).catch((err) => {\n console.error('Error:', err)\n process.exit(1)\n})\n"],"mappings":";;;;;;;;;AASA,OAAO,QAAQ;AAEf,SAAS,UAAU,OAAa;AAC9B,KAAI;AACF,SAAO,KAAK,MAAMA,MAAI;SAChB;AACN,SAAOA;;;AAIX,eAAe,oBAAoB,YAAkB,OAAgC;CACnF,MAAM,SAAS,IAAI,UAAU,QAAQ;AAErC,KAAI;EACF,MAAM,iBAAiB,MAAM,OAAO,cAAc,KAAK,QAAQC,WAAS,CAAC,CAAC;EAC1E,MAAM,UAAU,eAAe,WAAW,eAAe,SAAS;EAClE,MAAM,SAAS,eAAe,UAAU,eAAe,SAAS,UAAU,EAAE;AAG5E,MAAI,OAAO,YAAY,WACrB,OAAM,IAAI,MAAM,wCAAwCA,aAAW;EAGrE,MAAM,EAAE,SAAS,OAAO,sBAAsB;EAE9C,MAAM,SAAS,IAAI,OAAO,SAAmB,OAAmB,OAAO;EACvE,MAAM,QAAQ,IAAI,gBAAgB,OAAO;EAEzC,MAAM,OAAO,OAAO,SAAkB,OAAO,KAAK,QAAQ,KAAK;EAkB/D,MAAM,UAAU;GAAE;GAAS;GAAO;GAAQ;GAAO;GAAM,UAjBjC,MAAM,WACM,EAAE,EAAE,QACnC,KAAK,YAAY;AAChB,QAAI,QAAQ,QAAQ;KAClB,MAAM,SAAiB,OAAe,OAAO,KAAK,WAAW,QAAQ,KAAK,OAAO;MAAE;MAAS;MAAI,CAAC;KACjG,MAAM,SAAiB,IAAY,SACjC,OAAO,KAAK,WAAW,QAAQ,KAAK,OAAO;MAAE;MAAS;MAAI;MAAM,CAAC;KACnE,SAAS,SAAiB,OAAe,OAAO,KAAK,WAAW,QAAQ,KAAK,UAAU;MAAE;MAAS;MAAI,CAAC;KACvG,WAAW,YAAoB,OAAO,KAAK,WAAW,QAAQ,KAAK,YAAY,EAAE,SAAS,CAAC;KAC3F,OAAO,SAAkC,YACvC,OAAO,KAAK,WAAW,QAAQ,KAAK,QAAQ;MAAE;MAAS;MAAO,CAAC;KAClE;AACD,WAAO;MAET,EAAE,CACH;GAE+D;AAEhE,SAAO,MAAM;EAIb,MAAM,qBAAqB,kBAAkB,GAFzB,MAAM,QAAQ,OAAO,WAAW,GAAG,OAAO,aAAa,EAAE,CAEjB;EAC5D,MAAM,kBAAkB;AACtB,UAAO,oBAAoB,QAAQ,QAAQ,GAAG,QAAQ,MAAM,MAAM,QAAQ;;EAG5E,MAAM,SAAS,MAAM,mBAAmB,MAAM,MAAM,SAAS,UAAU;AAEvE,QAAM,OAAO,KAAK,UAAU,OAAO;AACnC,QAAM,OAAO,OAAO;AAEpB,UAAQ,KAAK,EAAE;UACRC,KAAU;EACjB,MAAMC,QAAkB,IAAI,OAAO,MAAM,KAAK,IAAI,EAAE;AAEpD,MAAI,OAAO;GACT,MAAM,QAAQ,MAAM,WAAW,SAAS,KAAK,SAAS,uBAAuB,CAAC;AAC9E,SAAM,OAAO,OAAO,MAAM,SAAS,MAAM;AACzC,SAAM,OAAO,GAAG,EAAE;;EAGpB,MAAM,QAAQ;GACZ,SAAS,IAAI,WAAW;GACxB,MAAM,IAAI,QAAQ;GAClB,OAAO,MAAM,KAAK,KAAK;GACxB;AACD,SAAO,WAAW,SAAS,MAAM;;;AAIrC,MAAM,KAAK,UAAU,OAAO,QAAQ;AAEpC,IAAI,CAAC,UAAU;AACb,SAAQ,MAAM,gDAAgD;AAC9D,SAAQ,KAAK,EAAE;;AAGjB,oBAAoB,UAAU,UAAU,IAAI,CAAC,CAAC,OAAO,QAAQ;AAC3D,SAAQ,MAAM,UAAU,IAAI;AAC5B,SAAQ,KAAK,EAAE;EACf"}
|
|
@@ -21,9 +21,9 @@ var StreamTracer = class StreamTracer {
|
|
|
21
21
|
this.trace.status = err ? "failed" : "completed";
|
|
22
22
|
this.trace.endTime = Date.now();
|
|
23
23
|
this.trace.error = err;
|
|
24
|
-
await this.manager.
|
|
24
|
+
await this.manager.updateTrace();
|
|
25
25
|
await this.recomputeTraceGroupStatus();
|
|
26
|
-
await this.manager.
|
|
26
|
+
await this.manager.updateTraceGroup();
|
|
27
27
|
}
|
|
28
28
|
async recomputeTraceGroupStatus() {
|
|
29
29
|
const allTracesFromStorage = await this.manager.getAllTracesForGroup();
|
|
@@ -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 await this.manager.
|
|
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 await this.recomputeTraceGroupStatus()\n await this.manager.updateTraceGroup()\n }\n\n private async recomputeTraceGroupStatus() {\n const allTracesFromStorage = await this.manager.getAllTracesForGroup()\n\n const currentTraceIndex = allTracesFromStorage.findIndex((t) => t.id === this.trace.id)\n const allTraces = [...allTracesFromStorage]\n\n if (currentTraceIndex >= 0) {\n allTraces[currentTraceIndex] = this.trace\n } else {\n allTraces.push(this.trace)\n }\n\n const completedCount = allTraces.filter((t) => t.status === 'completed').length\n const failedCount = allTraces.filter((t) => t.status === 'failed').length\n const runningCount = allTraces.filter((t) => t.status === 'running').length\n\n this.traceGroup.metadata.completedSteps = completedCount\n this.traceGroup.metadata.activeSteps = runningCount\n\n if (failedCount > 0) {\n this.traceGroup.status = 'failed'\n } else if (runningCount === 0 && completedCount > 0) {\n this.traceGroup.status = 'completed'\n if (!this.traceGroup.endTime) {\n this.traceGroup.endTime = Date.now()\n }\n } else {\n this.traceGroup.status = 'running'\n }\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 this.traceGroup.lastActivity = lastEvent.maxTimestamp\n await this.manager.updateTrace()\n await this.manager.updateTraceGroup()\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 this.traceGroup.lastActivity = event.timestamp\n\n await this.manager.updateTrace()\n await this.manager.updateTraceGroup()\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;AAChC,QAAM,KAAK,2BAA2B;AACtC,QAAM,KAAK,QAAQ,kBAAkB;;CAGvC,MAAc,4BAA4B;EACxC,MAAM,uBAAuB,MAAM,KAAK,QAAQ,sBAAsB;EAEtE,MAAM,oBAAoB,qBAAqB,WAAW,MAAM,EAAE,OAAO,KAAK,MAAM,GAAG;EACvF,MAAM,YAAY,CAAC,GAAG,qBAAqB;AAE3C,MAAI,qBAAqB,EACvB,WAAU,qBAAqB,KAAK;MAEpC,WAAU,KAAK,KAAK,MAAM;EAG5B,MAAM,iBAAiB,UAAU,QAAQ,MAAM,EAAE,WAAW,YAAY,CAAC;EACzE,MAAM,cAAc,UAAU,QAAQ,MAAM,EAAE,WAAW,SAAS,CAAC;EACnE,MAAM,eAAe,UAAU,QAAQ,MAAM,EAAE,WAAW,UAAU,CAAC;AAErE,OAAK,WAAW,SAAS,iBAAiB;AAC1C,OAAK,WAAW,SAAS,cAAc;AAEvC,MAAI,cAAc,EAChB,MAAK,WAAW,SAAS;WAChB,iBAAiB,KAAK,iBAAiB,GAAG;AACnD,QAAK,WAAW,SAAS;AACzB,OAAI,CAAC,KAAK,WAAW,QACnB,MAAK,WAAW,UAAU,KAAK,KAAK;QAGtC,MAAK,WAAW,SAAS;;CAI7B,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,SAAK,WAAW,eAAe,UAAU;AACzC,UAAM,KAAK,QAAQ,aAAa;AAChC,UAAM,KAAK,QAAQ,kBAAkB;AAErC;;;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;AAC7B,OAAK,WAAW,eAAe,MAAM;AAErC,QAAM,KAAK,QAAQ,aAAa;AAChC,QAAM,KAAK,QAAQ,kBAAkB"}
|
|
@@ -1,40 +1,19 @@
|
|
|
1
1
|
//#region src/observability/trace-manager.ts
|
|
2
|
-
const DEBOUNCE_DELAY_MS = 500;
|
|
3
|
-
const noop = () => void 0;
|
|
4
2
|
var TraceManager = class TraceManager {
|
|
5
3
|
constructor(traceStream, traceGroupStream, traceGroup, trace) {
|
|
6
4
|
this.traceStream = traceStream;
|
|
7
5
|
this.traceGroupStream = traceGroupStream;
|
|
8
6
|
this.traceGroup = traceGroup;
|
|
9
7
|
this.trace = trace;
|
|
10
|
-
this.
|
|
11
|
-
this.
|
|
12
|
-
this.updateTraceGroup().catch(noop);
|
|
8
|
+
this.updateTrace().catch(() => {});
|
|
9
|
+
this.updateTraceGroup().catch(() => {});
|
|
13
10
|
}
|
|
14
11
|
async updateTrace() {
|
|
15
|
-
|
|
16
|
-
this.traceDebounceTimer = setTimeout(() => {
|
|
17
|
-
this.traceDebounceTimer = null;
|
|
18
|
-
this.traceStream.set(this.traceGroup.id, this.trace.id, this.trace).catch(noop);
|
|
19
|
-
}, DEBOUNCE_DELAY_MS);
|
|
12
|
+
await this.traceStream.set(this.traceGroup.id, this.trace.id, this.trace);
|
|
20
13
|
}
|
|
21
14
|
async updateTraceGroup() {
|
|
22
15
|
await this.traceGroupStream.set("default", this.traceGroup.id, this.traceGroup);
|
|
23
16
|
}
|
|
24
|
-
async flushTrace() {
|
|
25
|
-
if (this.traceDebounceTimer) {
|
|
26
|
-
clearTimeout(this.traceDebounceTimer);
|
|
27
|
-
this.traceDebounceTimer = null;
|
|
28
|
-
}
|
|
29
|
-
await this.traceStream.set(this.traceGroup.id, this.trace.id, this.trace);
|
|
30
|
-
}
|
|
31
|
-
async flush() {
|
|
32
|
-
if (this.traceDebounceTimer) {
|
|
33
|
-
clearTimeout(this.traceDebounceTimer);
|
|
34
|
-
this.traceDebounceTimer = null;
|
|
35
|
-
}
|
|
36
|
-
await Promise.all([this.traceStream.set(this.traceGroup.id, this.trace.id, this.trace), this.traceGroupStream.set("default", this.traceGroup.id, this.traceGroup)]);
|
|
37
|
-
}
|
|
38
17
|
async getAllTracesForGroup() {
|
|
39
18
|
return await this.traceStream.getGroup(this.traceGroup.id);
|
|
40
19
|
}
|
|
@@ -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\
|
|
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 this.updateTraceGroup().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;AAClC,OAAK,kBAAkB,CAAC,YAAY,GAAG;;CAGzC,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"}
|
|
@@ -48,11 +48,11 @@ var ProcessManager = class {
|
|
|
48
48
|
}
|
|
49
49
|
kill() {
|
|
50
50
|
if (this.child) this.child.kill("SIGKILL");
|
|
51
|
-
this.child = void 0;
|
|
52
51
|
}
|
|
53
52
|
close() {
|
|
54
53
|
if (this.processor) this.processor.close();
|
|
55
54
|
this.processor = void 0;
|
|
55
|
+
this.child = void 0;
|
|
56
56
|
}
|
|
57
57
|
get process() {
|
|
58
58
|
return this.child;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-manager.mjs","names":["options: ProcessManagerOptions"],"sources":["../../../src/process-communication/process-manager.ts"],"sourcesContent":["import { type ChildProcess, spawn } from 'child_process'\nimport type { Logger } from '../logger'\nimport { RpcProcessor } from '../step-handler-rpc-processor'\nimport { RpcStdinProcessor } from '../step-handler-rpc-stdin-processor'\nimport { type CommunicationType, createCommunicationConfig } from './communication-config'\nimport type { MessageCallback, RpcHandler, RpcProcessorInterface } from './rpc-processor-interface'\n\nexport interface ProcessManagerOptions {\n command: string\n args: string[]\n logger: Logger\n context?: string\n projectRoot?: string\n}\n\nexport class ProcessManager {\n private child?: ChildProcess\n private processor?: RpcProcessorInterface\n private communicationType?: CommunicationType\n\n constructor(private options: ProcessManagerOptions) {}\n\n async spawn(): Promise<ChildProcess> {\n const { command, args, logger, context = 'Process', projectRoot } = this.options\n\n // Get communication configuration\n const commConfig = createCommunicationConfig(command, projectRoot)\n this.communicationType = commConfig.type\n\n logger.debug(`[${context}] Spawning process`, {\n command,\n args,\n communicationType: this.communicationType,\n })\n\n // Spawn the process\n this.child = spawn(command, args, commConfig.spawnOptions)\n\n // Create appropriate processor based on communication type\n this.processor = this.communicationType === 'rpc' ? new RpcStdinProcessor(this.child) : new RpcProcessor(this.child)\n\n // Initialize the processor\n await this.processor.init()\n\n return this.child\n }\n\n handler<TInput, TOutput = unknown>(method: string, handler: RpcHandler<TInput, TOutput>): void {\n if (!this.processor) {\n throw new Error('Process not spawned yet. Call spawn() first.')\n }\n this.processor.handler(method, handler)\n }\n\n onMessage<T = unknown>(callback: MessageCallback<T>): void {\n if (!this.processor) {\n throw new Error('Process not spawned yet. Call spawn() first.')\n }\n this.processor.onMessage(callback)\n }\n\n onProcessClose(callback: (code: number | null) => void): void {\n if (!this.child) {\n throw new Error('Process not spawned yet. Call spawn() first.')\n }\n this.child.on('close', callback)\n }\n\n onProcessError(callback: (error: Error & { code?: string }) => void): void {\n if (!this.child) {\n throw new Error('Process not spawned yet. Call spawn() first.')\n }\n this.child.on('error', callback)\n }\n\n onStderr(callback: (data: Buffer) => void): void {\n if (!this.child) {\n throw new Error('Process not spawned yet. Call spawn() first.')\n }\n this.child.stderr?.on('data', callback)\n }\n\n onStdout(callback: (data: Buffer) => void): void {\n if (!this.child) {\n throw new Error('Process not spawned yet. Call spawn() first.')\n }\n // Only for non-RPC mode (in RPC mode, stdout is used for communication)\n if (this.communicationType !== 'rpc') {\n this.child.stdout?.on('data', callback)\n }\n }\n\n kill(): void {\n if (this.child) {\n this.child.kill('SIGKILL')\n }\n
|
|
1
|
+
{"version":3,"file":"process-manager.mjs","names":["options: ProcessManagerOptions"],"sources":["../../../src/process-communication/process-manager.ts"],"sourcesContent":["import { type ChildProcess, spawn } from 'child_process'\nimport type { Logger } from '../logger'\nimport { RpcProcessor } from '../step-handler-rpc-processor'\nimport { RpcStdinProcessor } from '../step-handler-rpc-stdin-processor'\nimport { type CommunicationType, createCommunicationConfig } from './communication-config'\nimport type { MessageCallback, RpcHandler, RpcProcessorInterface } from './rpc-processor-interface'\n\nexport interface ProcessManagerOptions {\n command: string\n args: string[]\n logger: Logger\n context?: string\n projectRoot?: string\n}\n\nexport class ProcessManager {\n private child?: ChildProcess\n private processor?: RpcProcessorInterface\n private communicationType?: CommunicationType\n\n constructor(private options: ProcessManagerOptions) {}\n\n async spawn(): Promise<ChildProcess> {\n const { command, args, logger, context = 'Process', projectRoot } = this.options\n\n // Get communication configuration\n const commConfig = createCommunicationConfig(command, projectRoot)\n this.communicationType = commConfig.type\n\n logger.debug(`[${context}] Spawning process`, {\n command,\n args,\n communicationType: this.communicationType,\n })\n\n // Spawn the process\n this.child = spawn(command, args, commConfig.spawnOptions)\n\n // Create appropriate processor based on communication type\n this.processor = this.communicationType === 'rpc' ? new RpcStdinProcessor(this.child) : new RpcProcessor(this.child)\n\n // Initialize the processor\n await this.processor.init()\n\n return this.child\n }\n\n handler<TInput, TOutput = unknown>(method: string, handler: RpcHandler<TInput, TOutput>): void {\n if (!this.processor) {\n throw new Error('Process not spawned yet. Call spawn() first.')\n }\n this.processor.handler(method, handler)\n }\n\n onMessage<T = unknown>(callback: MessageCallback<T>): void {\n if (!this.processor) {\n throw new Error('Process not spawned yet. Call spawn() first.')\n }\n this.processor.onMessage(callback)\n }\n\n onProcessClose(callback: (code: number | null) => void): void {\n if (!this.child) {\n throw new Error('Process not spawned yet. Call spawn() first.')\n }\n this.child.on('close', callback)\n }\n\n onProcessError(callback: (error: Error & { code?: string }) => void): void {\n if (!this.child) {\n throw new Error('Process not spawned yet. Call spawn() first.')\n }\n this.child.on('error', callback)\n }\n\n onStderr(callback: (data: Buffer) => void): void {\n if (!this.child) {\n throw new Error('Process not spawned yet. Call spawn() first.')\n }\n this.child.stderr?.on('data', callback)\n }\n\n onStdout(callback: (data: Buffer) => void): void {\n if (!this.child) {\n throw new Error('Process not spawned yet. Call spawn() first.')\n }\n // Only for non-RPC mode (in RPC mode, stdout is used for communication)\n if (this.communicationType !== 'rpc') {\n this.child.stdout?.on('data', callback)\n }\n }\n\n kill(): void {\n if (this.child) {\n this.child.kill('SIGKILL')\n }\n }\n\n close(): void {\n if (this.processor) {\n this.processor.close()\n }\n this.processor = undefined\n this.child = undefined\n }\n\n get process(): ChildProcess | undefined {\n return this.child\n }\n\n get commType(): CommunicationType | undefined {\n return this.communicationType\n }\n}\n"],"mappings":";;;;;;AAeA,IAAa,iBAAb,MAA4B;CAK1B,YAAY,AAAQA,SAAgC;EAAhC;;CAEpB,MAAM,QAA+B;EACnC,MAAM,EAAE,SAAS,MAAM,QAAQ,UAAU,WAAW,gBAAgB,KAAK;EAGzE,MAAM,aAAa,0BAA0B,SAAS,YAAY;AAClE,OAAK,oBAAoB,WAAW;AAEpC,SAAO,MAAM,IAAI,QAAQ,qBAAqB;GAC5C;GACA;GACA,mBAAmB,KAAK;GACzB,CAAC;AAGF,OAAK,QAAQ,MAAM,SAAS,MAAM,WAAW,aAAa;AAG1D,OAAK,YAAY,KAAK,sBAAsB,QAAQ,IAAI,kBAAkB,KAAK,MAAM,GAAG,IAAI,aAAa,KAAK,MAAM;AAGpH,QAAM,KAAK,UAAU,MAAM;AAE3B,SAAO,KAAK;;CAGd,QAAmC,QAAgB,SAA4C;AAC7F,MAAI,CAAC,KAAK,UACR,OAAM,IAAI,MAAM,+CAA+C;AAEjE,OAAK,UAAU,QAAQ,QAAQ,QAAQ;;CAGzC,UAAuB,UAAoC;AACzD,MAAI,CAAC,KAAK,UACR,OAAM,IAAI,MAAM,+CAA+C;AAEjE,OAAK,UAAU,UAAU,SAAS;;CAGpC,eAAe,UAA+C;AAC5D,MAAI,CAAC,KAAK,MACR,OAAM,IAAI,MAAM,+CAA+C;AAEjE,OAAK,MAAM,GAAG,SAAS,SAAS;;CAGlC,eAAe,UAA4D;AACzE,MAAI,CAAC,KAAK,MACR,OAAM,IAAI,MAAM,+CAA+C;AAEjE,OAAK,MAAM,GAAG,SAAS,SAAS;;CAGlC,SAAS,UAAwC;AAC/C,MAAI,CAAC,KAAK,MACR,OAAM,IAAI,MAAM,+CAA+C;AAEjE,OAAK,MAAM,QAAQ,GAAG,QAAQ,SAAS;;CAGzC,SAAS,UAAwC;AAC/C,MAAI,CAAC,KAAK,MACR,OAAM,IAAI,MAAM,+CAA+C;AAGjE,MAAI,KAAK,sBAAsB,MAC7B,MAAK,MAAM,QAAQ,GAAG,QAAQ,SAAS;;CAI3C,OAAa;AACX,MAAI,KAAK,MACP,MAAK,MAAM,KAAK,UAAU;;CAI9B,QAAc;AACZ,MAAI,KAAK,UACP,MAAK,UAAU,OAAO;AAExB,OAAK,YAAY;AACjB,OAAK,QAAQ;;CAGf,IAAI,UAAoC;AACtC,SAAO,KAAK;;CAGd,IAAI,WAA0C;AAC5C,SAAO,KAAK"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"step-handler-rpc-stdin-processor.mjs","names":["child: ChildProcess"],"sources":["../../src/step-handler-rpc-stdin-processor.ts"],"sourcesContent":["import type { ChildProcess } from 'child_process'\nimport readline from 'readline'\nimport type {\n MessageCallback,\n RpcHandler,\n RpcProcessorInterface,\n} from './process-communication/rpc-processor-interface'\n\nexport type RpcMessage = {\n type: 'rpc_request'\n id: string | undefined\n method: string\n args: unknown\n}\n\nexport class RpcStdinProcessor implements RpcProcessorInterface {\n private handlers: Record<string, RpcHandler<any, any>> = {}\n\n private messageCallback?: MessageCallback<any>\n private isClosed = false\n private rl?: readline.Interface\n\n constructor(private child: ChildProcess) {}\n\n handler<TInput, TOutput = unknown>(method: string, handler: RpcHandler<TInput, TOutput>) {\n this.handlers[method] = handler\n }\n\n onMessage<T = unknown>(callback: MessageCallback<T>): void {\n this.messageCallback = callback\n }\n\n async handle(method: string, input: unknown) {\n const handler = this.handlers[method]\n if (!handler) {\n throw new Error(`Handler for method ${method} not found`)\n }\n return handler(input)\n }\n\n private response(id: string | undefined, result: unknown, error: unknown) {\n if (id && !this.isClosed && this.child.stdin && !this.child.killed) {\n const responseMessage = {\n type: 'rpc_response',\n id,\n result: error ? undefined : result,\n error: error ? String(error) : undefined,\n }\n const messageStr = JSON.stringify(responseMessage)\n this.child.stdin.write(messageStr + '\\n')\n }\n }\n\n async init() {\n if (this.child.stdout) {\n this.rl = readline.createInterface({\n input: this.child.stdout,\n crlfDelay: Infinity,\n })\n\n this.rl.on('line', (line) => {\n try {\n const msg = JSON.parse(line.trim())\n\n // Call generic message callback if registered\n if (this.messageCallback) {\n this.messageCallback(msg)\n }\n\n // Handle RPC requests specifically\n if (msg && msg.type === 'rpc_request') {\n const { id, method, args } = msg as RpcMessage\n this.handle(method, args)\n .then((result) => this.response(id, result, null))\n .catch((error) => this.response(id, null, error))\n }\n } catch (error) {\n console.error('Failed to parse RPC message:', error, 'Raw line:', line)\n }\n })\n\n this.rl.on('close', () => {\n this.isClosed = true\n })\n }\n\n this.child.on('exit', () => {\n this.isClosed = true\n })\n this.child.on('close', () => {\n this.isClosed = true\n })\n }\n\n close() {\n this.isClosed = true\n this.messageCallback = undefined\n if (this.rl) {\n this.rl.
|
|
1
|
+
{"version":3,"file":"step-handler-rpc-stdin-processor.mjs","names":["child: ChildProcess"],"sources":["../../src/step-handler-rpc-stdin-processor.ts"],"sourcesContent":["import type { ChildProcess } from 'child_process'\nimport readline from 'readline'\nimport type {\n MessageCallback,\n RpcHandler,\n RpcProcessorInterface,\n} from './process-communication/rpc-processor-interface'\n\nexport type RpcMessage = {\n type: 'rpc_request'\n id: string | undefined\n method: string\n args: unknown\n}\n\nexport class RpcStdinProcessor implements RpcProcessorInterface {\n private handlers: Record<string, RpcHandler<any, any>> = {}\n\n private messageCallback?: MessageCallback<any>\n private isClosed = false\n private rl?: readline.Interface\n\n constructor(private child: ChildProcess) {}\n\n handler<TInput, TOutput = unknown>(method: string, handler: RpcHandler<TInput, TOutput>) {\n this.handlers[method] = handler\n }\n\n onMessage<T = unknown>(callback: MessageCallback<T>): void {\n this.messageCallback = callback\n }\n\n async handle(method: string, input: unknown) {\n const handler = this.handlers[method]\n if (!handler) {\n throw new Error(`Handler for method ${method} not found`)\n }\n return handler(input)\n }\n\n private response(id: string | undefined, result: unknown, error: unknown) {\n if (id && !this.isClosed && this.child.stdin && !this.child.killed) {\n const responseMessage = {\n type: 'rpc_response',\n id,\n result: error ? undefined : result,\n error: error ? String(error) : undefined,\n }\n const messageStr = JSON.stringify(responseMessage)\n this.child.stdin.write(messageStr + '\\n')\n }\n }\n\n async init() {\n if (this.child.stdout) {\n this.rl = readline.createInterface({\n input: this.child.stdout,\n crlfDelay: Infinity,\n })\n\n this.rl.on('line', (line) => {\n try {\n const msg = JSON.parse(line.trim())\n\n // Call generic message callback if registered\n if (this.messageCallback) {\n this.messageCallback(msg)\n }\n\n // Handle RPC requests specifically\n if (msg && msg.type === 'rpc_request') {\n const { id, method, args } = msg as RpcMessage\n this.handle(method, args)\n .then((result) => this.response(id, result, null))\n .catch((error) => this.response(id, null, error))\n }\n } catch (error) {\n console.error('Failed to parse RPC message:', error, 'Raw line:', line)\n }\n })\n\n this.rl.on('close', () => {\n this.isClosed = true\n })\n }\n\n this.child.on('exit', () => {\n this.isClosed = true\n })\n this.child.on('close', () => {\n this.isClosed = true\n })\n }\n\n close() {\n this.isClosed = true\n this.messageCallback = undefined\n if (this.rl) {\n this.rl.close()\n }\n }\n}\n"],"mappings":";;;AAeA,IAAa,oBAAb,MAAgE;CAO9D,YAAY,AAAQA,OAAqB;EAArB;kBANqC,EAAE;kBAGxC;;CAKnB,QAAmC,QAAgB,SAAsC;AACvF,OAAK,SAAS,UAAU;;CAG1B,UAAuB,UAAoC;AACzD,OAAK,kBAAkB;;CAGzB,MAAM,OAAO,QAAgB,OAAgB;EAC3C,MAAM,UAAU,KAAK,SAAS;AAC9B,MAAI,CAAC,QACH,OAAM,IAAI,MAAM,sBAAsB,OAAO,YAAY;AAE3D,SAAO,QAAQ,MAAM;;CAGvB,AAAQ,SAAS,IAAwB,QAAiB,OAAgB;AACxE,MAAI,MAAM,CAAC,KAAK,YAAY,KAAK,MAAM,SAAS,CAAC,KAAK,MAAM,QAAQ;GAClE,MAAM,kBAAkB;IACtB,MAAM;IACN;IACA,QAAQ,QAAQ,SAAY;IAC5B,OAAO,QAAQ,OAAO,MAAM,GAAG;IAChC;GACD,MAAM,aAAa,KAAK,UAAU,gBAAgB;AAClD,QAAK,MAAM,MAAM,MAAM,aAAa,KAAK;;;CAI7C,MAAM,OAAO;AACX,MAAI,KAAK,MAAM,QAAQ;AACrB,QAAK,KAAK,SAAS,gBAAgB;IACjC,OAAO,KAAK,MAAM;IAClB,WAAW;IACZ,CAAC;AAEF,QAAK,GAAG,GAAG,SAAS,SAAS;AAC3B,QAAI;KACF,MAAM,MAAM,KAAK,MAAM,KAAK,MAAM,CAAC;AAGnC,SAAI,KAAK,gBACP,MAAK,gBAAgB,IAAI;AAI3B,SAAI,OAAO,IAAI,SAAS,eAAe;MACrC,MAAM,EAAE,IAAI,QAAQ,SAAS;AAC7B,WAAK,OAAO,QAAQ,KAAK,CACtB,MAAM,WAAW,KAAK,SAAS,IAAI,QAAQ,KAAK,CAAC,CACjD,OAAO,UAAU,KAAK,SAAS,IAAI,MAAM,MAAM,CAAC;;aAE9C,OAAO;AACd,aAAQ,MAAM,gCAAgC,OAAO,aAAa,KAAK;;KAEzE;AAEF,QAAK,GAAG,GAAG,eAAe;AACxB,SAAK,WAAW;KAChB;;AAGJ,OAAK,MAAM,GAAG,cAAc;AAC1B,QAAK,WAAW;IAChB;AACF,OAAK,MAAM,GAAG,eAAe;AAC3B,QAAK,WAAW;IAChB;;CAGJ,QAAQ;AACN,OAAK,WAAW;AAChB,OAAK,kBAAkB;AACvB,MAAI,KAAK,GACP,MAAK,GAAG,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types-stream.d.mts","names":[],"sources":["../../src/types-stream.ts"],"sourcesContent":[],"mappings":";;;;KAGY,kBAAA;;EAAA,EAAA,CAAA,EAAA,MAAA;AAEZ,CAAA;AAEU,UAFO,YAAA,CAEP;EACyE,IAAA,EAAA,MAAA;EACtD,MAAA,EAFnB,eAEmB;EAAmD,UAAA,EAAA;IAAO,WAAA,EAAA,SAAA;EAG3E,CAAA,GAAA;IACA,WAAA,EAAA,QAAgB;IAEhB,OAAA,EAAA,GAAA,GAPuE,WAOzD,CAAA,
|
|
1
|
+
{"version":3,"file":"types-stream.d.mts","names":[],"sources":["../../src/types-stream.ts"],"sourcesContent":[],"mappings":";;;;KAGY,kBAAA;;EAAA,EAAA,CAAA,EAAA,MAAA;AAEZ,CAAA;AAEU,UAFO,YAAA,CAEP;EACyE,IAAA,EAAA,MAAA;EACtD,MAAA,EAFnB,eAEmB;EAAmD,UAAA,EAAA;IAAO,WAAA,EAAA,SAAA;EAG3E,CAAA,GAAA;IACA,WAAA,EAAA,QAAgB;IAEhB,OAAA,EAAA,GAAA,GAPuE,WAOzD,CAAA,GAAoB,CAAA;EAElC,CAAA;EAAuB,SAAA,CAAA,EAAA,CAAA,YAAA,EARN,kBAQM,EAAA,WAAA,EAAA,GAAA,EAAA,GAAA,OAAA,GAR6C,OAQ7C,CAAA,OAAA,CAAA;;AAEzB,KAPE,uBAAA,GAOF;EAEC,OAAA,EAAA,MAAA;EAAa,EAAA,CAAA,EAAA,MAAA;AAGxB,CAAA;AAC2D,KAZ/C,gBAY+C,CAAA,KAAA,CAAA,GAAA;EAAf,IAAA,EAAA,MAAA;EAAR,IAAA,EAZwB,KAYxB;CACK;AAA+B,KAX5D,cAW4D,CAAA,QAAA,OAAA,CAAA,GAX1B,KAW0B,GAAA;EAAf,EAAA,EAAA,MAAA;CAAR;AACa,KAVlD,MAUkD,CAAA,gBAV3B,YAU2B,GAVZ,YAUY,CAAA,GAAA;EAAf,QAAA,EAAA,MAAA;EAAR,MAAA,EAR7B,OAQ6B;EACa,MAAA,CAAA,EAAA,OAAA;EAAf,OAAA,EAP1B,aAO0B,CAAA,OAAA,CAAA;CAAR;AAEV,UANF,WAME,CAAA,KAAA,CAAA,CAAA;EAAiD,GAAA,CAAA,OAAA,EAAA,MAAA,EAAA,EAAA,EAAA,MAAA,CAAA,EALhC,OAKgC,CALxB,cAKwB,CALT,KAKS,CAAA,GAAA,IAAA,CAAA;EAAjB,GAAA,CAAA,OAAA,EAAA,MAAA,EAAA,EAAA,EAAA,MAAA,EAAA,IAAA,EAJV,KAIU,CAAA,EAJF,OAIE,CAJM,cAIN,CAJqB,KAIrB,CAAA,CAAA;EAAsB,MAAA,CAAA,OAAA,EAAA,MAAA,EAAA,EAAA,EAAA,MAAA,CAAA,EAHlC,OAGkC,CAH1B,cAG0B,CAHX,KAGW,CAAA,GAAA,IAAA,CAAA;EAAO,QAAA,CAAA,OAAA,EAAA,MAAA,CAAA,EAFnD,OAEmD,CAF3C,cAE2C,CAF5B,KAE4B,CAAA,EAAA,CAAA;mBAA7D,gCAAgC,iBAAiB,KAAK"}
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"import": "./dist/index.mjs"
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
|
-
"version": "0.14.0-beta.165-
|
|
14
|
+
"version": "0.14.0-beta.165-557689",
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@amplitude/analytics-node": "^1.5.26",
|
|
17
17
|
"@standard-schema/spec": "^1.0.0",
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
"body-parser": "^1.20.3",
|
|
20
20
|
"picocolors": "^1.1.1",
|
|
21
21
|
"dotenv": "^16.4.7",
|
|
22
|
-
"esbuild": "^0.25.0",
|
|
23
22
|
"express": "^4.21.2",
|
|
24
23
|
"tsx": "^4.20.6",
|
|
25
24
|
"node-cron": "^3.0.3",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ts-compiler.d.mts","names":[],"sources":["../../src/ts-compiler.ts"],"sourcesContent":[],"mappings":";AA+HgB,iBAAA,UAAA,CAAU,UAAA,EAAA,MAAA,CAAA,EAAA,IAAA"}
|
package/dist/src/ts-compiler.mjs
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, statSync, writeFileSync } from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import * as esbuild from "esbuild";
|
|
4
|
-
|
|
5
|
-
//#region src/ts-compiler.ts
|
|
6
|
-
const COMPILED_DIR = ".motia/compiled";
|
|
7
|
-
const cache = /* @__PURE__ */ new Map();
|
|
8
|
-
function getCompiledPath(tsFilePath, projectRoot) {
|
|
9
|
-
const compiledRelativePath = path.relative(projectRoot, tsFilePath).replace(/\.ts$/, ".js");
|
|
10
|
-
return path.join(projectRoot, COMPILED_DIR, compiledRelativePath);
|
|
11
|
-
}
|
|
12
|
-
function getSourceMtime(filePath) {
|
|
13
|
-
try {
|
|
14
|
-
return statSync(filePath).mtimeMs;
|
|
15
|
-
} catch {
|
|
16
|
-
return 0;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
function ensureCompiledDir(compiledPath) {
|
|
20
|
-
const dir = path.dirname(compiledPath);
|
|
21
|
-
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
22
|
-
}
|
|
23
|
-
async function compile(tsFilePath, projectRoot) {
|
|
24
|
-
const cached = cache.get(tsFilePath);
|
|
25
|
-
const sourceMtime = getSourceMtime(tsFilePath);
|
|
26
|
-
const compiledPath = getCompiledPath(tsFilePath, projectRoot);
|
|
27
|
-
if (cached && cached.sourceMtime === sourceMtime && existsSync(cached.compiledPath)) return cached.compiledPath;
|
|
28
|
-
ensureCompiledDir(compiledPath);
|
|
29
|
-
const result = await esbuild.build({
|
|
30
|
-
entryPoints: [tsFilePath],
|
|
31
|
-
bundle: false,
|
|
32
|
-
format: "esm",
|
|
33
|
-
target: "node18",
|
|
34
|
-
platform: "node",
|
|
35
|
-
outfile: compiledPath,
|
|
36
|
-
sourcemap: "inline",
|
|
37
|
-
write: false,
|
|
38
|
-
resolveExtensions: [
|
|
39
|
-
".ts",
|
|
40
|
-
".tsx",
|
|
41
|
-
".js",
|
|
42
|
-
".jsx",
|
|
43
|
-
".json"
|
|
44
|
-
],
|
|
45
|
-
packages: "external"
|
|
46
|
-
});
|
|
47
|
-
if (result.outputFiles && result.outputFiles.length > 0) {
|
|
48
|
-
let compiledCode = result.outputFiles[0].text;
|
|
49
|
-
const dir = path.dirname(tsFilePath);
|
|
50
|
-
const relativeImports = [];
|
|
51
|
-
compiledCode = compiledCode.replace(/from\s+['"](\.\/?[^'"]+)['"]/g, (match, importPath) => {
|
|
52
|
-
if (!importPath.startsWith(".")) return match;
|
|
53
|
-
if (importPath.endsWith(".js") || importPath.endsWith(".json")) return match;
|
|
54
|
-
const fullImportPath = path.resolve(dir, importPath);
|
|
55
|
-
for (const ext of [
|
|
56
|
-
".ts",
|
|
57
|
-
".tsx",
|
|
58
|
-
".stream.ts",
|
|
59
|
-
".stream"
|
|
60
|
-
]) {
|
|
61
|
-
const testPath = fullImportPath + (ext.startsWith(".") ? ext : `.${ext}`);
|
|
62
|
-
if (existsSync(testPath)) {
|
|
63
|
-
let compiledFileName = path.relative(projectRoot, testPath);
|
|
64
|
-
if (compiledFileName.endsWith(".stream.ts")) compiledFileName = compiledFileName.replace(/\.stream\.ts$/, ".stream.js");
|
|
65
|
-
else if (compiledFileName.endsWith(".tsx")) compiledFileName = compiledFileName.replace(/\.tsx$/, ".js");
|
|
66
|
-
else if (compiledFileName.endsWith(".ts")) compiledFileName = compiledFileName.replace(/\.ts$/, ".js");
|
|
67
|
-
else if (compiledFileName.endsWith(".stream")) compiledFileName = compiledFileName.replace(/\.stream$/, ".stream.js");
|
|
68
|
-
const compiledImportPath = path.join(COMPILED_DIR, compiledFileName);
|
|
69
|
-
const relativeCompiledPath = path.relative(path.dirname(compiledPath), path.join(projectRoot, compiledImportPath)).replace(/\\/g, "/");
|
|
70
|
-
relativeImports.push(testPath);
|
|
71
|
-
return match.replace(importPath, relativeCompiledPath.startsWith(".") ? relativeCompiledPath : `./${relativeCompiledPath}`);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
if (!importPath.match(/\.(ts|tsx|js|jsx|json|stream)$/)) return match.replace(importPath, `${importPath}.js`);
|
|
75
|
-
return match.replace(importPath, importPath.replace(/\.(ts|tsx|stream\.ts|stream)$/, ".js"));
|
|
76
|
-
});
|
|
77
|
-
for (const importPath of relativeImports) if (importPath.endsWith(".ts") || importPath.endsWith(".tsx") || importPath.endsWith(".stream.ts")) await compile(importPath, projectRoot);
|
|
78
|
-
writeFileSync(compiledPath, compiledCode, "utf-8");
|
|
79
|
-
} else throw new Error(`Failed to compile ${tsFilePath}`);
|
|
80
|
-
cache.set(tsFilePath, {
|
|
81
|
-
compiledPath,
|
|
82
|
-
sourceMtime
|
|
83
|
-
});
|
|
84
|
-
return compiledPath;
|
|
85
|
-
}
|
|
86
|
-
function invalidate(tsFilePath) {
|
|
87
|
-
cache.delete(tsFilePath);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
//#endregion
|
|
91
|
-
export { compile, invalidate };
|
|
92
|
-
//# sourceMappingURL=ts-compiler.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ts-compiler.mjs","names":["relativeImports: string[]"],"sources":["../../src/ts-compiler.ts"],"sourcesContent":["import * as esbuild from 'esbuild'\nimport { existsSync, mkdirSync, statSync, writeFileSync } from 'fs'\nimport path from 'path'\n\nconst COMPILED_DIR = '.motia/compiled'\n\ninterface CompileCache {\n compiledPath: string\n sourceMtime: number\n}\n\nconst cache = new Map<string, CompileCache>()\n\nfunction getCompiledPath(tsFilePath: string, projectRoot: string): string {\n const relativePath = path.relative(projectRoot, tsFilePath)\n const compiledRelativePath = relativePath.replace(/\\.ts$/, '.js')\n return path.join(projectRoot, COMPILED_DIR, compiledRelativePath)\n}\n\nfunction getSourceMtime(filePath: string): number {\n try {\n return statSync(filePath).mtimeMs\n } catch {\n return 0\n }\n}\n\nfunction ensureCompiledDir(compiledPath: string): void {\n const dir = path.dirname(compiledPath)\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n}\n\nexport async function compile(tsFilePath: string, projectRoot: string): Promise<string> {\n const cached = cache.get(tsFilePath)\n const sourceMtime = getSourceMtime(tsFilePath)\n const compiledPath = getCompiledPath(tsFilePath, projectRoot)\n\n if (cached && cached.sourceMtime === sourceMtime && existsSync(cached.compiledPath)) {\n return cached.compiledPath\n }\n\n ensureCompiledDir(compiledPath)\n\n const result = await esbuild.build({\n entryPoints: [tsFilePath],\n bundle: false,\n format: 'esm',\n target: 'node18',\n platform: 'node',\n outfile: compiledPath,\n sourcemap: 'inline',\n write: false,\n resolveExtensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],\n packages: 'external',\n })\n\n if (result.outputFiles && result.outputFiles.length > 0) {\n let compiledCode = result.outputFiles[0].text\n\n const dir = path.dirname(tsFilePath)\n const relativeImports: string[] = []\n\n compiledCode = compiledCode.replace(/from\\s+['\"](\\.\\/?[^'\"]+)['\"]/g, (match, importPath) => {\n if (!importPath.startsWith('.')) {\n return match\n }\n if (importPath.endsWith('.js') || importPath.endsWith('.json')) {\n return match\n }\n\n const fullImportPath = path.resolve(dir, importPath)\n const possibleExtensions = ['.ts', '.tsx', '.stream.ts', '.stream']\n\n for (const ext of possibleExtensions) {\n const testPath = fullImportPath + (ext.startsWith('.') ? ext : `.${ext}`)\n if (existsSync(testPath)) {\n const relativeToProject = path.relative(projectRoot, testPath)\n let compiledFileName = relativeToProject\n if (compiledFileName.endsWith('.stream.ts')) {\n compiledFileName = compiledFileName.replace(/\\.stream\\.ts$/, '.stream.js')\n } else if (compiledFileName.endsWith('.tsx')) {\n compiledFileName = compiledFileName.replace(/\\.tsx$/, '.js')\n } else if (compiledFileName.endsWith('.ts')) {\n compiledFileName = compiledFileName.replace(/\\.ts$/, '.js')\n } else if (compiledFileName.endsWith('.stream')) {\n compiledFileName = compiledFileName.replace(/\\.stream$/, '.stream.js')\n }\n const compiledImportPath = path.join(COMPILED_DIR, compiledFileName)\n const relativeCompiledPath = path\n .relative(path.dirname(compiledPath), path.join(projectRoot, compiledImportPath))\n .replace(/\\\\/g, '/')\n relativeImports.push(testPath)\n return match.replace(\n importPath,\n relativeCompiledPath.startsWith('.') ? relativeCompiledPath : `./${relativeCompiledPath}`,\n )\n }\n }\n\n if (!importPath.match(/\\.(ts|tsx|js|jsx|json|stream)$/)) {\n return match.replace(importPath, `${importPath}.js`)\n }\n\n return match.replace(importPath, importPath.replace(/\\.(ts|tsx|stream\\.ts|stream)$/, '.js'))\n })\n\n for (const importPath of relativeImports) {\n if (importPath.endsWith('.ts') || importPath.endsWith('.tsx') || importPath.endsWith('.stream.ts')) {\n await compile(importPath, projectRoot)\n }\n }\n\n writeFileSync(compiledPath, compiledCode, 'utf-8')\n } else {\n throw new Error(`Failed to compile ${tsFilePath}`)\n }\n\n cache.set(tsFilePath, {\n compiledPath,\n sourceMtime,\n })\n\n return compiledPath\n}\n\nexport function invalidate(tsFilePath: string): void {\n cache.delete(tsFilePath)\n}\n\nexport function invalidateAll(): void {\n cache.clear()\n}\n"],"mappings":"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"}
|