@motiadev/core 0.14.0-beta.165-142851 → 0.14.0-beta.165-868490

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.
Files changed (31) hide show
  1. package/dist/index.d.mts +2 -1
  2. package/dist/index.mjs +2 -1
  3. package/dist/src/adapters/interfaces/state-adapter.interface.d.mts.map +1 -1
  4. package/dist/src/call-step-file.mjs +216 -178
  5. package/dist/src/call-step-file.mjs.map +1 -1
  6. package/dist/src/get-step-config.d.mts +1 -0
  7. package/dist/src/get-step-config.d.mts.map +1 -1
  8. package/dist/src/get-step-config.mjs +19 -12
  9. package/dist/src/get-step-config.mjs.map +1 -1
  10. package/dist/src/language-runner.mjs +6 -0
  11. package/dist/src/language-runner.mjs.map +1 -1
  12. package/dist/src/logger.d.mts +1 -0
  13. package/dist/src/logger.d.mts.map +1 -1
  14. package/dist/src/logger.mjs +8 -0
  15. package/dist/src/logger.mjs.map +1 -1
  16. package/dist/src/node/node-runner.mjs +23 -8
  17. package/dist/src/node/node-runner.mjs.map +1 -1
  18. package/dist/src/observability/stream-tracer.mjs +2 -2
  19. package/dist/src/observability/stream-tracer.mjs.map +1 -1
  20. package/dist/src/observability/trace-manager.mjs +24 -3
  21. package/dist/src/observability/trace-manager.mjs.map +1 -1
  22. package/dist/src/process-communication/process-manager.mjs +1 -1
  23. package/dist/src/process-communication/process-manager.mjs.map +1 -1
  24. package/dist/src/step-handler-rpc-stdin-processor.mjs +4 -1
  25. package/dist/src/step-handler-rpc-stdin-processor.mjs.map +1 -1
  26. package/dist/src/ts-compiler.d.mts +5 -0
  27. package/dist/src/ts-compiler.d.mts.map +1 -0
  28. package/dist/src/ts-compiler.mjs +92 -0
  29. package/dist/src/ts-compiler.mjs.map +1 -0
  30. package/dist/src/types-stream.d.mts.map +1 -1
  31. package/package.json +2 -1
package/dist/index.d.mts CHANGED
@@ -25,6 +25,7 @@ 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";
28
29
  import { getStepConfig, getStreamConfig } from "./src/get-step-config.mjs";
29
30
  import { isApiStep, isCronStep, isEventStep, isNoopStep } from "./src/guards.mjs";
30
31
  import { InfrastructureValidationError, InfrastructureValidationResult } from "./src/infrastructure-validator/types.mjs";
@@ -35,4 +36,4 @@ import { NoTracer } from "./src/observability/no-tracer.mjs";
35
36
  import { MotiaEventManager, createStepHandlers } from "./src/step-handlers.mjs";
36
37
  import { MotiaServer, createServer } from "./src/server.mjs";
37
38
  import { createStateAdapter } from "./src/state/create-state-adapter.mjs";
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 };
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, invalidate, isAnalyticsEnabled, isAnyOf, isApiStep, isCronStep, isEventStep, isNoopStep, setupCronHandlers, trackEvent, validateInfrastructureConfig };
package/dist/index.mjs CHANGED
@@ -12,6 +12,7 @@ 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";
15
16
  import { isApiStep, isCronStep, isEventStep, isNoopStep } from "./src/guards.mjs";
16
17
  import { setupCronHandlers } from "./src/cron-handler.mjs";
17
18
  import { getStepConfig, getStreamConfig } from "./src/get-step-config.mjs";
@@ -27,4 +28,4 @@ import { createStepHandlers } from "./src/step-handlers.mjs";
27
28
  import { createServer } from "./src/server.mjs";
28
29
  import { createStateAdapter } from "./src/state/create-state-adapter.mjs";
29
30
 
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 };
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, invalidate, isAnalyticsEnabled, isAnyOf, isApiStep, isCronStep, isEventStep, isNoopStep, setupCronHandlers, trackEvent, validateInfrastructureConfig };
@@ -1 +1 @@
1
- {"version":3,"file":"state-adapter.interface.d.mts","names":[],"sources":["../../../../src/adapters/interfaces/state-adapter.interface.ts"],"sourcesContent":[],"mappings":";;;UAEiB,SAAA;;EAAA,GAAA,EAAA,MAAA;EAOA,IAAA,EAAA,QAAW,GAAA,QAAA,GAAA,SAAA,GAAA,QAAA,GAAA,OAAA,GAAA,MAAA;EAkBX,KAAA,EAAA,MAAA,GAAA,MAAe,GAAA,OAErB,GAAA,MAAA,GAAW,OAAA,EAAA,GAAA,IAAA;AAGtB;AAC0B,UAxBT,WAAA,CAwBS;EACb,QAAA,EAAA,MAAA;EAEY,SAAA,EAAA,IAAA,GAAA,KAAA,GAAA,IAAA,GAAA,KAAA,GAAA,IAAA,GAAA,KAAA,GAAA,UAAA,GAAA,aAAA,GAAA,YAAA,GAAA,UAAA,GAAA,WAAA,GAAA,QAAA;EACX,KAAA,EAAA,MAAA;;AAE2B,UAZxB,eAAA,CAYwB;EAAR,OAAA,CAAA,EAAA,MAAA;EAPK,MAAA,CAAA,EAH3B,WAG2B,EAAA;;UAArB,YAAA,SAAqB;0BACZ;aACb;yBAEY;cACX;eAEC,kBAAkB,QAAQ"}
1
+ {"version":3,"file":"state-adapter.interface.d.mts","names":[],"sources":["../../../../src/adapters/interfaces/state-adapter.interface.ts"],"sourcesContent":[],"mappings":";;;UAEiB,SAAA;;EAAA,GAAA,EAAA,MAAA;EAOA,IAAA,EAAA,QAAW,GAAA,QAAA,GAAA,SAAA,GAAA,QAAA,GAAA,OAAA,GAAA,MAAA;EAkBX,KAAA,EAAA,MAAA,GAAA,MAAe,GAAA,OAErB,GAAA,MAAW,GAAA,OAAA,EAAA,GAAA,IAAA;AAGtB;AAC0B,UAxBT,WAAA,CAwBS;EACb,QAAA,EAAA,MAAA;EAEY,SAAA,EAAA,IAAA,GAAA,KAAA,GAAA,IAAA,GAAA,KAAA,GAAA,IAAA,GAAA,KAAA,GAAA,UAAA,GAAA,aAAA,GAAA,YAAA,GAAA,UAAA,GAAA,WAAA,GAAA,QAAA;EACX,KAAA,EAAA,MAAA;;AAE2B,UAZxB,eAAA,CAYwB;EAAR,OAAA,CAAA,EAAA,MAAA;EAPK,MAAA,CAAA,EAH3B,WAG2B,EAAA;;UAArB,YAAA,SAAqB;0BACZ;aACb;yBAEY;cACX;eAEC,kBAAkB,QAAQ"}
@@ -1,213 +1,251 @@
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";
4
5
  import { isAllowedToEmit } from "./utils.mjs";
5
6
 
6
7
  //#region src/call-step-file.ts
7
8
  const callStepFile = (options, motia) => {
8
9
  const { step, traceId, data, tracer, logger, contextInFirstArg = false, infrastructure } = options;
9
10
  const flows = step.config.flows;
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,
11
+ return (async () => {
12
+ try {
13
+ const streamConfig = motia.lockedData.getStreams();
14
+ const streams = Object.keys(streamConfig).map((name) => ({ name }));
15
+ const jsonData = JSON.stringify({
16
+ data,
17
+ flows,
52
18
  traceId,
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
19
+ contextInFirstArg,
20
+ streams
21
+ });
22
+ let filePathToExecute = step.filePath;
23
+ if (step.filePath.endsWith(".ts")) try {
24
+ filePathToExecute = await compile(step.filePath, motia.lockedData.baseDir);
25
+ } catch (compileError) {
26
+ const error = compileError;
27
+ logger.error(`Failed to compile TypeScript file: ${step.filePath}`, { error });
28
+ await tracer.end({
29
+ message: `Compilation failed: ${error.message}`,
30
+ code: error.code,
31
+ stack: error.stack
86
32
  });
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,
33
+ trackEvent("step_execution_error", {
34
+ stepName: step.config.name,
115
35
  traceId,
116
- flows: flows$1,
36
+ code: "COMPILATION_ERROR",
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
+ ],
117
53
  logger,
118
- tracer
54
+ context: "StepExecution",
55
+ projectRoot: motia.lockedData.baseDir
119
56
  });
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);
57
+ trackEvent("step_execution_started", {
58
+ stepName: step.config.name,
59
+ language: command,
60
+ type: step.config.type,
61
+ streams: streams.length
126
62
  });
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
63
+ const timeoutSeconds = infrastructure?.handler?.timeout;
64
+ if (timeoutSeconds) timeoutId = setTimeout(async () => {
65
+ processManager.kill();
66
+ const errorMessage = `Step execution timed out after ${timeoutSeconds} seconds`;
67
+ logger.error(errorMessage, {
68
+ step: step.config.name,
69
+ timeout: timeoutSeconds
132
70
  });
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", {
71
+ await tracer.end({ message: errorMessage });
72
+ trackEvent("step_execution_timeout", {
167
73
  stepName: step.config.name,
168
74
  traceId,
169
- code
75
+ timeout: timeoutSeconds
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
170
223
  });
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") {
186
224
  trackEvent("step_execution_error", {
187
225
  stepName: step.config.name,
188
226
  traceId,
189
227
  code: error.code,
190
228
  message: error.message
191
229
  });
192
- reject(`Executable ${command} not found`);
193
- } else reject(error);
230
+ reject(`Failed to spawn process: ${error}`);
231
+ });
194
232
  });
195
- }).catch(async (error) => {
196
- if (timeoutId) clearTimeout(timeoutId);
233
+ } catch (error) {
234
+ const err = error;
197
235
  await tracer.end({
198
- message: error.message,
199
- code: error.code,
200
- stack: error.stack
236
+ message: err.message,
237
+ code: err.code,
238
+ stack: err.stack
201
239
  });
202
240
  trackEvent("step_execution_error", {
203
241
  stepName: step.config.name,
204
242
  traceId,
205
- code: error.code,
206
- message: error.message
243
+ code: err.code,
244
+ message: err.message
207
245
  });
208
- reject(`Failed to spawn process: ${error}`);
209
- });
210
- });
246
+ throw err;
247
+ }
248
+ })();
211
249
  };
212
250
 
213
251
  //#endregion
@@ -1 +1 @@
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
+ {"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,5 +1,6 @@
1
1
  import { StreamConfig } from "./types-stream.mjs";
2
2
  import { StepConfig } from "./types.mjs";
3
+ import { invalidate } from "./ts-compiler.mjs";
3
4
 
4
5
  //#region src/get-step-config.d.ts
5
6
  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":";;;;cA+Da,uDAAsD,QAAQ;cAI9D,yDAAwD,QAAQ"}
1
+ {"version":3,"file":"get-step-config.d.mts","names":[],"sources":["../../src/get-step-config.ts"],"sourcesContent":[],"mappings":";;;;;cAyEa,uDAAsD,QAAQ;cAI9D,yDAAwD,QAAQ"}
@@ -1,9 +1,16 @@
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";
4
5
 
5
6
  //#region src/get-step-config.ts
6
- const getConfig = (file, projectRoot) => {
7
+ const getConfig = async (file, projectRoot) => {
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
+ }
7
14
  const { runner, command, args } = getLanguageBasedRunner(file, {
8
15
  python: "get-config.py",
9
16
  ruby: "get-config.rb",
@@ -12,19 +19,19 @@ const getConfig = (file, projectRoot) => {
12
19
  ts: "get-config.ts"
13
20
  }
14
21
  });
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
+ });
15
33
  return new Promise((resolve, reject) => {
16
34
  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
- });
28
35
  processManager.spawn().then(() => {
29
36
  processManager.onMessage((message) => {
30
37
  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 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"}
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 { compile } from './ts-compiler'\nimport type { StepConfig } from './types'\nimport type { StreamConfig } from './types-stream'\n\nconst getConfig = async <T>(file: string, projectRoot?: string): Promise<T | null> => {\n let filePathToExecute = file\n if (file.endsWith('.ts')) {\n try {\n filePathToExecute = await compile(file, projectRoot || process.cwd())\n } catch (error) {\n throw new Error(`Failed to compile TypeScript file: ${error}`)\n }\n }\n\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 const processManager = new ProcessManager({\n command,\n args: [...args, runner, filePathToExecute],\n logger: globalLogger,\n context: 'Config',\n projectRoot,\n })\n\n return new Promise((resolve, reject) => {\n let config: T | null = null\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\nexport { invalidate } from './ts-compiler'\n"],"mappings":";;;;;;AAOA,MAAM,YAAY,OAAU,MAAc,gBAA4C;CACpF,IAAI,oBAAoB;AACxB,KAAI,KAAK,SAAS,MAAM,CACtB,KAAI;AACF,sBAAoB,MAAM,QAAQ,MAAM,eAAe,QAAQ,KAAK,CAAC;UAC9D,OAAO;AACd,QAAM,IAAI,MAAM,sCAAsC,QAAQ;;CAIlE,MAAM,EAAE,QAAQ,SAAS,SAAS,uBAAuB,MAAM;EAC7D,QAAQ;EACR,MAAM;EACN,MAAM;GAAE,IAAI;GAAkB,IAAI;GAAiB;EACpD,CAAC;CAEF,MAAM,iBAAiB,IAAI,eAAe;EACxC;EACA,MAAM;GAAC,GAAG;GAAM;GAAQ;GAAkB;EAC1C,QAAQ;EACR,SAAS;EACT;EACD,CAAC;AAEF,QAAO,IAAI,SAAS,SAAS,WAAW;EACtC,IAAIA,SAAmB;AAEvB,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,6 +29,7 @@ const getLanguageBasedRunner = (stepFilePath = "", overrides) => {
29
29
  };
30
30
  else if (isNode) {
31
31
  const defaultNodeOverrides = overrides?.node;
32
+ const isTypeScript = stepFilePath.endsWith(".ts");
32
33
  if (process.env._MOTIA_TEST_MODE === "true") {
33
34
  const runnerFile = defaultNodeOverrides?.ts ?? "node-runner.ts";
34
35
  return {
@@ -42,6 +43,11 @@ const getLanguageBasedRunner = (stepFilePath = "", overrides) => {
42
43
  };
43
44
  }
44
45
  const jsRunner = path.join(__dirname, "node", defaultNodeOverrides?.js ?? "node-runner.mjs");
46
+ if (isTypeScript) return {
47
+ runner: jsRunner,
48
+ command: "node",
49
+ args: []
50
+ };
45
51
  const tsxPath = getTsxPath();
46
52
  if (tsxPath !== "tsx") return {
47
53
  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\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"}
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 const isTypeScript = stepFilePath.endsWith('.ts')\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\n if (isTypeScript) {\n return { runner: jsRunner, command: 'node', args: [] }\n }\n\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;EACxC,MAAM,eAAe,aAAa,SAAS,MAAM;AAEjD,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;AAE5F,MAAI,aACF,QAAO;GAAE,QAAQ;GAAU,SAAS;GAAQ,MAAM,EAAE;GAAE;EAGxD,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"}
@@ -22,6 +22,7 @@ declare class Logger {
22
22
  warn(message: string, args?: unknown): void;
23
23
  log(args: any): void;
24
24
  addListener(listener: LogListener): void;
25
+ removeListener(listener: LogListener): boolean;
25
26
  }
26
27
  //#endregion
27
28
  export { Logger };
@@ -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;2BAIG"}
@@ -56,6 +56,14 @@ 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
+ }
59
67
  };
60
68
  const globalLogger = new Logger();
61
69
 
@@ -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}\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"}
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 removeListener(listener: LogListener): boolean {\n const index = this.listeners.indexOf(listener)\n if (index !== -1) {\n this.listeners.splice(index, 1)\n return true\n }\n return false\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;;CAG/B,eAAe,UAAgC;EAC7C,MAAM,QAAQ,KAAK,UAAU,QAAQ,SAAS;AAC9C,MAAI,UAAU,IAAI;AAChB,QAAK,UAAU,OAAO,OAAO,EAAE;AAC/B,UAAO;;AAET,SAAO;;;AAIX,MAAa,eAAe,IAAI,QAAQ"}
@@ -18,7 +18,21 @@ function parseArgs(arg$1) {
18
18
  async function runTypescriptModule(filePath$1, event) {
19
19
  const sender = new RpcSender(process);
20
20
  try {
21
- const importedModule = await import(pathToFileURL(path.resolve(filePath$1)).href);
21
+ sender.init();
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
+ }
22
36
  const handler = importedModule.handler || importedModule.default?.handler;
23
37
  const config = importedModule.config || importedModule.default?.config || {};
24
38
  if (typeof handler !== "function") throw new Error(`Function handler not found in module ${filePath$1}`);
@@ -56,28 +70,29 @@ async function runTypescriptModule(filePath$1, event) {
56
70
  return acc;
57
71
  }, {})
58
72
  };
59
- sender.init();
60
73
  const composedMiddleware = composeMiddleware(...Array.isArray(config.middleware) ? config.middleware : []);
61
74
  const handlerFn = () => {
62
75
  return contextInFirstArg ? handler(context) : handler(event.data, context);
63
76
  };
64
77
  const result = await composedMiddleware(event.data, context, handlerFn);
65
- await sender.send("result", result);
78
+ if (result !== void 0 && result !== null) await sender.send("result", result);
79
+ sender.sendNoWait("close", void 0);
66
80
  await sender.close();
67
81
  process.exit(0);
68
82
  } catch (err) {
69
- const stack = err.stack?.split("\n") ?? [];
83
+ const error = err;
84
+ const stack = error.stack?.split("\n") ?? [];
70
85
  if (stack) {
71
86
  const index = stack.findIndex((line) => line.includes("src/node/node-runner"));
72
87
  stack.splice(index, stack.length - index);
73
88
  stack.splice(0, 1);
74
89
  }
75
- const error = {
76
- message: err.message || "",
77
- code: err.code || null,
90
+ const errorObj = {
91
+ message: error.message || "",
92
+ code: error.code || null,
78
93
  stack: stack.join("\n")
79
94
  };
80
- sender.sendNoWait("close", error);
95
+ sender.sendNoWait("close", errorObj);
81
96
  }
82
97
  }
83
98
  const [, , filePath, arg] = process.argv;
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"node-runner.mjs","names":["arg","importedModule: { handler?: unknown; default?: { handler?: unknown; config?: unknown }; config?: unknown }","filePath","importError: unknown","err: unknown","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 sender.init()\n\n let importedModule: { handler?: unknown; default?: { handler?: unknown; config?: unknown }; config?: unknown }\n try {\n importedModule = await import(pathToFileURL(path.resolve(filePath)).href)\n } catch (importError: unknown) {\n const err = importError as Error & { code?: string }\n const error = {\n message: `Failed to import module ${filePath}: ${err.message}`,\n code: err.code || 'IMPORT_ERROR',\n stack: err.stack || '',\n }\n sender.sendNoWait('close', error)\n process.exit(1)\n return\n }\n\n const handler = importedModule.handler || importedModule.default?.handler\n const config = (importedModule.config || importedModule.default?.config || {}) as { middleware?: unknown[] }\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 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 if (result !== undefined && result !== null) {\n await sender.send('result', result)\n }\n\n sender.sendNoWait('close', undefined)\n await sender.close()\n process.exit(0)\n } catch (err: unknown) {\n const error = err as Error & { code?: string }\n const stack: string[] = error.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)\n }\n\n const errorObj = {\n message: error.message || '',\n code: error.code || null,\n stack: stack.join('\\n'),\n }\n sender.sendNoWait('close', errorObj)\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;AACF,SAAO,MAAM;EAEb,IAAIC;AACJ,MAAI;AACF,oBAAiB,MAAM,OAAO,cAAc,KAAK,QAAQC,WAAS,CAAC,CAAC;WAC7DC,aAAsB;GAC7B,MAAM,MAAM;GACZ,MAAM,QAAQ;IACZ,SAAS,2BAA2BD,WAAS,IAAI,IAAI;IACrD,MAAM,IAAI,QAAQ;IAClB,OAAO,IAAI,SAAS;IACrB;AACD,UAAO,WAAW,SAAS,MAAM;AACjC,WAAQ,KAAK,EAAE;AACf;;EAGF,MAAM,UAAU,eAAe,WAAW,eAAe,SAAS;EAClE,MAAM,SAAU,eAAe,UAAU,eAAe,SAAS,UAAU,EAAE;AAG7E,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;EAIhE,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,MAAI,WAAW,UAAa,WAAW,KACrC,OAAM,OAAO,KAAK,UAAU,OAAO;AAGrC,SAAO,WAAW,SAAS,OAAU;AACrC,QAAM,OAAO,OAAO;AACpB,UAAQ,KAAK,EAAE;UACRE,KAAc;EACrB,MAAM,QAAQ;EACd,MAAMC,QAAkB,MAAM,OAAO,MAAM,KAAK,IAAI,EAAE;AAEtD,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,WAAW;GACf,SAAS,MAAM,WAAW;GAC1B,MAAM,MAAM,QAAQ;GACpB,OAAO,MAAM,KAAK,KAAK;GACxB;AACD,SAAO,WAAW,SAAS,SAAS;;;AAIxC,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.updateTrace();
24
+ await this.manager.flushTrace();
25
25
  await this.recomputeTraceGroupStatus();
26
- await this.manager.updateTraceGroup();
26
+ await this.manager.flush();
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\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
+ {"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.flushTrace()\n await this.recomputeTraceGroupStatus()\n await this.manager.flush()\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;AACnB,QAAM,KAAK,QAAQ,YAAY;AAC/B,QAAM,KAAK,2BAA2B;AACtC,QAAM,KAAK,QAAQ,OAAO;;CAG5B,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,19 +1,40 @@
1
1
  //#region src/observability/trace-manager.ts
2
+ const DEBOUNCE_DELAY_MS = 500;
3
+ const noop = () => void 0;
2
4
  var TraceManager = class TraceManager {
3
5
  constructor(traceStream, traceGroupStream, traceGroup, trace) {
4
6
  this.traceStream = traceStream;
5
7
  this.traceGroupStream = traceGroupStream;
6
8
  this.traceGroup = traceGroup;
7
9
  this.trace = trace;
8
- this.updateTrace().catch(() => {});
9
- this.updateTraceGroup().catch(() => {});
10
+ this.traceDebounceTimer = null;
11
+ this.updateTrace().catch(noop);
12
+ this.updateTraceGroup().catch(noop);
10
13
  }
11
14
  async updateTrace() {
12
- await this.traceStream.set(this.traceGroup.id, this.trace.id, this.trace);
15
+ if (this.traceDebounceTimer) clearTimeout(this.traceDebounceTimer);
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);
13
20
  }
14
21
  async updateTraceGroup() {
15
22
  await this.traceGroupStream.set("default", this.traceGroup.id, this.traceGroup);
16
23
  }
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
+ }
17
38
  async getAllTracesForGroup() {
18
39
  return await this.traceStream.getGroup(this.traceGroup.id);
19
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"trace-manager.mjs","names":["traceStream: MotiaStream<Trace>","traceGroupStream: MotiaStream<TraceGroup>","traceGroup: TraceGroup","trace: Trace"],"sources":["../../../src/observability/trace-manager.ts"],"sourcesContent":["import type { MotiaStream } from '../types-stream'\nimport type { Trace, TraceGroup } from './types'\n\nexport class TraceManager {\n constructor(\n private readonly traceStream: MotiaStream<Trace>,\n private readonly traceGroupStream: MotiaStream<TraceGroup>,\n private readonly traceGroup: TraceGroup,\n private readonly trace: Trace,\n ) {\n this.updateTrace().catch(() => {})\n 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"}
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\nconst DEBOUNCE_DELAY_MS = 500\n\nconst noop = () => undefined\n\nexport class TraceManager {\n private traceDebounceTimer: NodeJS.Timeout | null = null\n\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(noop)\n this.updateTraceGroup().catch(noop)\n }\n\n async updateTrace() {\n if (this.traceDebounceTimer) {\n clearTimeout(this.traceDebounceTimer)\n }\n\n this.traceDebounceTimer = setTimeout(() => {\n this.traceDebounceTimer = null\n this.traceStream.set(this.traceGroup.id, this.trace.id, this.trace).catch(noop)\n }, DEBOUNCE_DELAY_MS)\n }\n\n async updateTraceGroup() {\n await this.traceGroupStream.set('default', this.traceGroup.id, this.traceGroup)\n }\n\n async flushTrace() {\n if (this.traceDebounceTimer) {\n clearTimeout(this.traceDebounceTimer)\n this.traceDebounceTimer = null\n }\n\n await this.traceStream.set(this.traceGroup.id, this.trace.id, this.trace)\n }\n\n async flush() {\n if (this.traceDebounceTimer) {\n clearTimeout(this.traceDebounceTimer)\n this.traceDebounceTimer = null\n }\n\n await Promise.all([\n this.traceStream.set(this.traceGroup.id, this.trace.id, this.trace),\n this.traceGroupStream.set('default', this.traceGroup.id, this.traceGroup),\n ])\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,MAAM,oBAAoB;AAE1B,MAAM,aAAa;AAEnB,IAAa,eAAb,MAAa,aAAa;CAGxB,YACE,AAAiBA,aACjB,AAAiBC,kBACjB,AAAiBC,YACjB,AAAiBC,OACjB;EAJiB;EACA;EACA;EACA;4BANiC;AAQlD,OAAK,aAAa,CAAC,MAAM,KAAK;AAC9B,OAAK,kBAAkB,CAAC,MAAM,KAAK;;CAGrC,MAAM,cAAc;AAClB,MAAI,KAAK,mBACP,cAAa,KAAK,mBAAmB;AAGvC,OAAK,qBAAqB,iBAAiB;AACzC,QAAK,qBAAqB;AAC1B,QAAK,YAAY,IAAI,KAAK,WAAW,IAAI,KAAK,MAAM,IAAI,KAAK,MAAM,CAAC,MAAM,KAAK;KAC9E,kBAAkB;;CAGvB,MAAM,mBAAmB;AACvB,QAAM,KAAK,iBAAiB,IAAI,WAAW,KAAK,WAAW,IAAI,KAAK,WAAW;;CAGjF,MAAM,aAAa;AACjB,MAAI,KAAK,oBAAoB;AAC3B,gBAAa,KAAK,mBAAmB;AACrC,QAAK,qBAAqB;;AAG5B,QAAM,KAAK,YAAY,IAAI,KAAK,WAAW,IAAI,KAAK,MAAM,IAAI,KAAK,MAAM;;CAG3E,MAAM,QAAQ;AACZ,MAAI,KAAK,oBAAoB;AAC3B,gBAAa,KAAK,mBAAmB;AACrC,QAAK,qBAAqB;;AAG5B,QAAM,QAAQ,IAAI,CAChB,KAAK,YAAY,IAAI,KAAK,WAAW,IAAI,KAAK,MAAM,IAAI,KAAK,MAAM,EACnE,KAAK,iBAAiB,IAAI,WAAW,KAAK,WAAW,IAAI,KAAK,WAAW,CAC1E,CAAC;;CAGJ,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;
51
52
  }
52
53
  close() {
53
54
  if (this.processor) this.processor.close();
54
55
  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 }\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
+ {"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 this.child = undefined\n }\n\n close(): void {\n if (this.processor) {\n this.processor.close()\n }\n this.processor = 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;AAE5B,OAAK,QAAQ;;CAGf,QAAc;AACZ,MAAI,KAAK,UACP,MAAK,UAAU,OAAO;AAExB,OAAK,YAAY;;CAGnB,IAAI,UAAoC;AACtC,SAAO,KAAK;;CAGd,IAAI,WAA0C;AAC5C,SAAO,KAAK"}
@@ -62,7 +62,10 @@ var RpcStdinProcessor = class {
62
62
  close() {
63
63
  this.isClosed = true;
64
64
  this.messageCallback = void 0;
65
- if (this.rl) this.rl.close();
65
+ if (this.rl) {
66
+ this.rl.removeAllListeners();
67
+ this.rl.close();
68
+ }
66
69
  }
67
70
  };
68
71
 
@@ -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.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
+ {"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.removeAllListeners()\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,IAAI;AACX,QAAK,GAAG,oBAAoB;AAC5B,QAAK,GAAG,OAAO"}
@@ -0,0 +1,5 @@
1
+ //#region src/ts-compiler.d.ts
2
+ declare function invalidate(tsFilePath: string): void;
3
+ //#endregion
4
+ export { invalidate };
5
+ //# sourceMappingURL=ts-compiler.d.mts.map
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,92 @@
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
@@ -0,0 +1 @@
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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"}
@@ -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,GAAA,CAAoB;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"}
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-142851",
14
+ "version": "0.14.0-beta.165-868490",
15
15
  "dependencies": {
16
16
  "@amplitude/analytics-node": "^1.5.26",
17
17
  "@standard-schema/spec": "^1.0.0",
@@ -19,6 +19,7 @@
19
19
  "body-parser": "^1.20.3",
20
20
  "picocolors": "^1.1.1",
21
21
  "dotenv": "^16.4.7",
22
+ "esbuild": "^0.25.0",
22
23
  "express": "^4.21.2",
23
24
  "tsx": "^4.20.6",
24
25
  "node-cron": "^3.0.3",