inngest 4.1.2 → 4.2.0

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 (93) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/api/api.cjs +30 -1
  3. package/api/api.cjs.map +1 -1
  4. package/api/api.d.cts +19 -0
  5. package/api/api.d.cts.map +1 -1
  6. package/api/api.d.ts +19 -0
  7. package/api/api.d.ts.map +1 -1
  8. package/api/api.js +30 -1
  9. package/api/api.js.map +1 -1
  10. package/components/InngestCommHandler.cjs +9 -1
  11. package/components/InngestCommHandler.cjs.map +1 -1
  12. package/components/InngestCommHandler.d.cts.map +1 -1
  13. package/components/InngestCommHandler.d.ts.map +1 -1
  14. package/components/InngestCommHandler.js +9 -1
  15. package/components/InngestCommHandler.js.map +1 -1
  16. package/components/StreamTools.cjs +241 -0
  17. package/components/StreamTools.cjs.map +1 -0
  18. package/components/StreamTools.d.cts +161 -0
  19. package/components/StreamTools.d.cts.map +1 -0
  20. package/components/StreamTools.d.ts +161 -0
  21. package/components/StreamTools.d.ts.map +1 -0
  22. package/components/StreamTools.js +240 -0
  23. package/components/StreamTools.js.map +1 -0
  24. package/components/createWebApiCommHandler.cjs +46 -0
  25. package/components/createWebApiCommHandler.cjs.map +1 -0
  26. package/components/createWebApiCommHandler.js +46 -0
  27. package/components/createWebApiCommHandler.js.map +1 -0
  28. package/components/execution/InngestExecution.cjs.map +1 -1
  29. package/components/execution/InngestExecution.d.cts +6 -0
  30. package/components/execution/InngestExecution.d.cts.map +1 -1
  31. package/components/execution/InngestExecution.d.ts +6 -0
  32. package/components/execution/InngestExecution.d.ts.map +1 -1
  33. package/components/execution/InngestExecution.js.map +1 -1
  34. package/components/execution/als.cjs.map +1 -1
  35. package/components/execution/als.d.cts +9 -1
  36. package/components/execution/als.d.cts.map +1 -1
  37. package/components/execution/als.d.ts +9 -1
  38. package/components/execution/als.d.ts.map +1 -1
  39. package/components/execution/als.js.map +1 -1
  40. package/components/execution/engine.cjs +334 -26
  41. package/components/execution/engine.cjs.map +1 -1
  42. package/components/execution/engine.d.cts +1 -0
  43. package/components/execution/engine.d.cts.map +1 -1
  44. package/components/execution/engine.d.ts +1 -0
  45. package/components/execution/engine.d.ts.map +1 -1
  46. package/components/execution/engine.js +334 -26
  47. package/components/execution/engine.js.map +1 -1
  48. package/components/execution/streaming.cjs +208 -0
  49. package/components/execution/streaming.cjs.map +1 -0
  50. package/components/execution/streaming.d.cts +12 -0
  51. package/components/execution/streaming.d.cts.map +1 -0
  52. package/components/execution/streaming.d.ts +12 -0
  53. package/components/execution/streaming.d.ts.map +1 -0
  54. package/components/execution/streaming.js +198 -0
  55. package/components/execution/streaming.js.map +1 -0
  56. package/edge.cjs +19 -32
  57. package/edge.cjs.map +1 -1
  58. package/edge.d.cts +1 -1
  59. package/edge.d.cts.map +1 -1
  60. package/edge.d.ts +1 -1
  61. package/edge.d.ts.map +1 -1
  62. package/edge.js +19 -32
  63. package/edge.js.map +1 -1
  64. package/experimental/durable-endpoints/client.cjs +114 -0
  65. package/experimental/durable-endpoints/client.cjs.map +1 -0
  66. package/experimental/durable-endpoints/client.d.cts +49 -0
  67. package/experimental/durable-endpoints/client.d.cts.map +1 -0
  68. package/experimental/durable-endpoints/client.d.ts +49 -0
  69. package/experimental/durable-endpoints/client.d.ts.map +1 -0
  70. package/experimental/durable-endpoints/client.js +114 -0
  71. package/experimental/durable-endpoints/client.js.map +1 -0
  72. package/experimental/durable-endpoints/index.cjs +3 -0
  73. package/experimental/durable-endpoints/index.d.cts +2 -0
  74. package/experimental/durable-endpoints/index.d.ts +2 -0
  75. package/experimental/durable-endpoints/index.js +3 -0
  76. package/helpers/promises.cjs.map +1 -1
  77. package/helpers/promises.js.map +1 -1
  78. package/node.cjs +97 -0
  79. package/node.cjs.map +1 -1
  80. package/node.d.cts +34 -2
  81. package/node.d.cts.map +1 -1
  82. package/node.d.ts +34 -2
  83. package/node.d.ts.map +1 -1
  84. package/node.js +95 -2
  85. package/node.js.map +1 -1
  86. package/package.json +17 -1
  87. package/react.d.cts.map +1 -1
  88. package/version.cjs +1 -1
  89. package/version.cjs.map +1 -1
  90. package/version.d.cts +1 -1
  91. package/version.d.ts +1 -1
  92. package/version.js +1 -1
  93. package/version.js.map +1 -1
@@ -0,0 +1,241 @@
1
+ const require_als = require('./execution/als.cjs');
2
+ const require_streaming = require('./execution/streaming.cjs');
3
+
4
+ //#region src/components/StreamTools.ts
5
+ /**
6
+ * Wraps a `TransformStream<Uint8Array>` to provide push/pipe SSE streaming
7
+ * capabilities within an Inngest execution.
8
+ *
9
+ * @internal
10
+ */
11
+ var Stream = class {
12
+ transform;
13
+ writer;
14
+ encoder = new TextEncoder();
15
+ _activated = false;
16
+ _errored = false;
17
+ writeChain = Promise.resolve();
18
+ /**
19
+ * Optional callback invoked the first time `push` or `pipe` is called.
20
+ * Used by the execution engine to fire a checkpoint that returns the SSE
21
+ * Response to the client immediately.
22
+ */
23
+ onActivated;
24
+ /**
25
+ * Optional callback invoked when a write to the underlying stream fails
26
+ * (e.g. the client disconnected or the transform stream errored). Used by
27
+ * the execution engine to emit diagnostic logs.
28
+ */
29
+ onWriteError;
30
+ constructor(opts) {
31
+ this.onActivated = opts?.onActivated;
32
+ this.onWriteError = opts?.onWriteError;
33
+ this.transform = new TransformStream(void 0, void 0, new CountQueuingStrategy({ highWaterMark: 1024 }));
34
+ this.writer = this.transform.writable.getWriter();
35
+ }
36
+ /**
37
+ * Whether `push` or `pipe` has been called at least once.
38
+ */
39
+ get activated() {
40
+ return this._activated;
41
+ }
42
+ /**
43
+ * The readable side of the underlying transform stream. Consumers (i.e. the
44
+ * HTTP response) read SSE events from here.
45
+ */
46
+ get readable() {
47
+ return this.transform.readable;
48
+ }
49
+ /**
50
+ * Resolve the current hashed step ID for stream events. Returns the
51
+ * executing step's hashed ID (read from ALS), or undefined if outside a step.
52
+ */
53
+ currentHashedStepId() {
54
+ return require_als.getAsyncCtxSync()?.execution?.executingStep?.hashedId;
55
+ }
56
+ activate() {
57
+ if (!this._activated) {
58
+ this._activated = true;
59
+ this.onActivated?.();
60
+ }
61
+ }
62
+ /**
63
+ * Encode and write an SSE event string to the underlying writer.
64
+ */
65
+ writeEncoded(sseEvent) {
66
+ return this.writer.write(this.encoder.encode(sseEvent));
67
+ }
68
+ /**
69
+ * Enqueue a pre-built SSE event string onto the write chain.
70
+ */
71
+ enqueue(sseEvent) {
72
+ if (this._errored) return;
73
+ this.writeChain = this.writeChain.then(() => this.writeEncoded(sseEvent)).catch((err) => {
74
+ this._errored = true;
75
+ this.onWriteError?.(err);
76
+ });
77
+ }
78
+ /**
79
+ * Emit an `inngest.commit` SSE event indicating that uncommitted streamed data
80
+ * should be committed (i.e. will not be rolled back). Internal use only.
81
+ */
82
+ commit(hashedStepId) {
83
+ this.enqueue(require_streaming.buildSseCommitEvent(hashedStepId));
84
+ }
85
+ /**
86
+ * Emit an `inngest.rollback` SSE event indicating the uncommitted streamed
87
+ * data should be discarded (e.g. step errored). Internal use only.
88
+ */
89
+ rollback(hashedStepId) {
90
+ this.enqueue(require_streaming.buildSseRollbackEvent(hashedStepId));
91
+ }
92
+ /**
93
+ * Serialize `data` into an SSE stream event and enqueue it. Returns `false`
94
+ * if serialization fails (e.g. circular reference) so callers can skip.
95
+ */
96
+ enqueueStreamEvent(data, hashedStepId) {
97
+ let sseEvent;
98
+ try {
99
+ sseEvent = require_streaming.buildSseStreamEvent(data, hashedStepId);
100
+ } catch {
101
+ return false;
102
+ }
103
+ this.enqueue(sseEvent);
104
+ return true;
105
+ }
106
+ /**
107
+ * Write a single SSE stream event containing `data`. The current step's
108
+ * hashed ID is automatically included as stepId for rollback tracking.
109
+ */
110
+ push(data) {
111
+ this.activate();
112
+ this.enqueueStreamEvent(data, this.currentHashedStepId());
113
+ }
114
+ /**
115
+ * Pipe a source to the client, writing each chunk as an SSE stream event.
116
+ * Returns the concatenated content of all chunks.
117
+ */
118
+ async pipe(source) {
119
+ this.activate();
120
+ let iterable;
121
+ if (source instanceof ReadableStream) iterable = this.readableToAsyncIterable(source);
122
+ else if (typeof source === "function") iterable = source();
123
+ else iterable = source;
124
+ return this.pipeIterable(iterable);
125
+ }
126
+ /**
127
+ * Adapt a ReadableStream into an AsyncIterable<string>. TypeScript's
128
+ * ReadableStream type doesn't declare Symbol.asyncIterator, so we use the
129
+ * reader API for type safety.
130
+ */
131
+ async *readableToAsyncIterable(readable) {
132
+ const reader = readable.getReader();
133
+ const decoder = new TextDecoder();
134
+ try {
135
+ while (true) {
136
+ const { done, value } = await reader.read();
137
+ if (done) break;
138
+ yield typeof value === "string" ? value : decoder.decode(value, { stream: true });
139
+ }
140
+ const final = decoder.decode();
141
+ if (final) yield final;
142
+ } finally {
143
+ reader.releaseLock();
144
+ }
145
+ }
146
+ /**
147
+ * Core pipe loop: iterate an async iterable, writing each chunk as an SSE
148
+ * stream event and collecting the concatenated result.
149
+ */
150
+ async pipeIterable(source) {
151
+ const hashedStepId = this.currentHashedStepId();
152
+ const chunks = [];
153
+ for await (const chunk of source) {
154
+ if (this._errored) break;
155
+ chunks.push(chunk);
156
+ if (!this.enqueueStreamEvent(chunk, hashedStepId)) continue;
157
+ await this.writeChain;
158
+ }
159
+ return chunks.join("");
160
+ }
161
+ /**
162
+ * Write a redirect info event. Tells the client where to reconnect if the
163
+ * durable endpoint goes async. Does NOT close the writer — more stream
164
+ * events may follow before the durable endpoint actually switches to async
165
+ * mode. Internal use only.
166
+ */
167
+ sendRedirectInfo(data) {
168
+ this.enqueue(require_streaming.buildSseRedirectEvent(data));
169
+ }
170
+ /**
171
+ * Write a succeeded result event and close the writer. Internal use only.
172
+ */
173
+ closeSucceeded(response) {
174
+ let sseEvent;
175
+ try {
176
+ sseEvent = require_streaming.buildSseSucceededEvent(response);
177
+ } catch {
178
+ sseEvent = require_streaming.buildSseFailedEvent("Failed to serialize result");
179
+ }
180
+ this.closeWriter(sseEvent);
181
+ }
182
+ /**
183
+ * Write a failed result event and close the writer. Internal use only.
184
+ */
185
+ closeFailed(error) {
186
+ this.closeWriter(require_streaming.buildSseFailedEvent(error));
187
+ }
188
+ /**
189
+ * Optionally write a final SSE event, then close the writer.
190
+ */
191
+ closeWriter(finalEvent) {
192
+ this.writeChain = this.writeChain.then(async () => {
193
+ if (finalEvent) await this.writeEncoded(finalEvent);
194
+ await this.writer.close();
195
+ }).catch((err) => {
196
+ this.onWriteError?.(err);
197
+ });
198
+ }
199
+ /**
200
+ * Close the writer without writing a result event. Used when the durable endpoint goes
201
+ * async and the real result will arrive on the redirected stream.
202
+ */
203
+ end() {
204
+ this.closeWriter();
205
+ }
206
+ };
207
+ /** Synchronous ALS lookup for the stream tools (fast path). */
208
+ const getStreamToolsSync = () => {
209
+ return require_als.getAsyncCtxSync()?.execution?.stream;
210
+ };
211
+ const getDeferredStreamTooling = async () => {
212
+ return (await require_als.getAsyncCtx())?.execution?.stream;
213
+ };
214
+ /**
215
+ * Stream tools that use ALS to resolve the current execution context.
216
+ * Outside an Inngest execution, `push()` is a no-op and `pipe()` resolves immediately.
217
+ */
218
+ const stream = {
219
+ push: (data) => {
220
+ const syncStream = getStreamToolsSync();
221
+ if (syncStream) {
222
+ syncStream.push(data);
223
+ return;
224
+ }
225
+ getDeferredStreamTooling().then((s) => {
226
+ s?.push(data);
227
+ }).catch(() => {});
228
+ },
229
+ pipe: async (source) => {
230
+ const syncStream = getStreamToolsSync();
231
+ if (syncStream) return syncStream.pipe(source);
232
+ const s = await getDeferredStreamTooling();
233
+ if (s) return s.pipe(source);
234
+ return "";
235
+ }
236
+ };
237
+
238
+ //#endregion
239
+ exports.Stream = Stream;
240
+ exports.stream = stream;
241
+ //# sourceMappingURL=StreamTools.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StreamTools.cjs","names":["getAsyncCtxSync","buildSseCommitEvent","buildSseRollbackEvent","sseEvent: string","buildSseStreamEvent","iterable: AsyncIterable<string>","chunks: string[]","buildSseRedirectEvent","buildSseSucceededEvent","buildSseFailedEvent","getAsyncCtx","stream: StreamTools"],"sources":["../../src/components/StreamTools.ts"],"sourcesContent":["import { getAsyncCtx, getAsyncCtxSync } from \"./execution/als.ts\";\nimport {\n buildSseCommitEvent,\n buildSseFailedEvent,\n buildSseRedirectEvent,\n buildSseRollbackEvent,\n buildSseStreamEvent,\n buildSseSucceededEvent,\n type SseResponse,\n} from \"./execution/streaming.ts\";\n\n/**\n * Accepted source types for `stream.pipe()`.\n *\n * - `ReadableStream` — piped directly\n * - `AsyncIterable<string>` — iterated; each yielded value becomes a chunk\n * - `() => AsyncIterable<string>` — factory invoked lazily, then iterated\n */\nexport type PipeSource =\n | ReadableStream\n | AsyncIterable<string>\n | (() => AsyncIterable<string>);\n\n/**\n * The public interface for stream tools available to user code.\n */\nexport interface StreamTools {\n /**\n * Push data to the client as an SSE stream event. Fire-and-forget from the\n * caller's perspective.\n *\n * Outside of an Inngest execution context this is a silent no-op (graceful\n * degradation).\n */\n push(data: unknown): void;\n\n /**\n * Pipe a source to the client, writing each chunk as an SSE stream event.\n * Resolves with the concatenated content of all chunks when the source is\n * fully consumed.\n *\n * Accepts a `ReadableStream`, an `AsyncIterable<string>`, or a factory\n * function that returns an `AsyncIterable<string>` (e.g. an async\n * generator function).\n *\n * Outside of an Inngest execution context this resolves with an empty string.\n */\n pipe(source: PipeSource): Promise<string>;\n}\n\n/**\n * Wraps a `TransformStream<Uint8Array>` to provide push/pipe SSE streaming\n * capabilities within an Inngest execution.\n *\n * @internal\n */\nexport class Stream implements StreamTools {\n private transform: TransformStream<Uint8Array, Uint8Array>;\n private writer: WritableStreamDefaultWriter<Uint8Array>;\n private encoder = new TextEncoder();\n private _activated = false;\n private _errored = false;\n private writeChain: Promise<void> = Promise.resolve();\n\n /**\n * Optional callback invoked the first time `push` or `pipe` is called.\n * Used by the execution engine to fire a checkpoint that returns the SSE\n * Response to the client immediately.\n */\n private onActivated?: () => void;\n\n /**\n * Optional callback invoked when a write to the underlying stream fails\n * (e.g. the client disconnected or the transform stream errored). Used by\n * the execution engine to emit diagnostic logs.\n */\n private onWriteError?: (err: unknown) => void;\n\n constructor(opts?: {\n onActivated?: () => void;\n onWriteError?: (err: unknown) => void;\n }) {\n this.onActivated = opts?.onActivated;\n this.onWriteError = opts?.onWriteError;\n this.transform = new TransformStream<Uint8Array, Uint8Array>(\n undefined,\n undefined,\n // Use a generous high water mark on the readable side so that writes\n // don't block due to backpressure before the consumer reads.\n new CountQueuingStrategy({ highWaterMark: 1024 }),\n );\n this.writer = this.transform.writable.getWriter();\n }\n\n /**\n * Whether `push` or `pipe` has been called at least once.\n */\n get activated(): boolean {\n return this._activated;\n }\n\n /**\n * The readable side of the underlying transform stream. Consumers (i.e. the\n * HTTP response) read SSE events from here.\n */\n get readable(): ReadableStream<Uint8Array> {\n return this.transform.readable;\n }\n\n /**\n * Resolve the current hashed step ID for stream events. Returns the\n * executing step's hashed ID (read from ALS), or undefined if outside a step.\n */\n private currentHashedStepId(): string | undefined {\n return getAsyncCtxSync()?.execution?.executingStep?.hashedId;\n }\n\n private activate(): void {\n if (!this._activated) {\n this._activated = true;\n this.onActivated?.();\n }\n }\n\n /**\n * Encode and write an SSE event string to the underlying writer.\n */\n private writeEncoded(sseEvent: string): Promise<void> {\n return this.writer.write(this.encoder.encode(sseEvent));\n }\n\n /**\n * Enqueue a pre-built SSE event string onto the write chain.\n */\n private enqueue(sseEvent: string): void {\n if (this._errored) return;\n\n this.writeChain = this.writeChain\n .then(() => this.writeEncoded(sseEvent))\n .catch((err) => {\n // Writer errored (e.g. stream closed) — swallow so the chain\n // doesn't break and subsequent writes fail gracefully.\n this._errored = true;\n this.onWriteError?.(err);\n });\n }\n\n /**\n * Emit an `inngest.commit` SSE event indicating that uncommitted streamed data\n * should be committed (i.e. will not be rolled back). Internal use only.\n */\n commit(hashedStepId: string | null): void {\n this.enqueue(buildSseCommitEvent(hashedStepId));\n }\n\n /**\n * Emit an `inngest.rollback` SSE event indicating the uncommitted streamed\n * data should be discarded (e.g. step errored). Internal use only.\n */\n rollback(hashedStepId: string | null): void {\n this.enqueue(buildSseRollbackEvent(hashedStepId));\n }\n\n /**\n * Serialize `data` into an SSE stream event and enqueue it. Returns `false`\n * if serialization fails (e.g. circular reference) so callers can skip.\n */\n private enqueueStreamEvent(data: unknown, hashedStepId?: string): boolean {\n let sseEvent: string;\n try {\n sseEvent = buildSseStreamEvent(data, hashedStepId);\n } catch {\n return false;\n }\n\n this.enqueue(sseEvent);\n return true;\n }\n\n /**\n * Write a single SSE stream event containing `data`. The current step's\n * hashed ID is automatically included as stepId for rollback tracking.\n */\n push(data: unknown): void {\n this.activate();\n this.enqueueStreamEvent(data, this.currentHashedStepId());\n }\n\n /**\n * Pipe a source to the client, writing each chunk as an SSE stream event.\n * Returns the concatenated content of all chunks.\n */\n async pipe(source: PipeSource): Promise<string> {\n this.activate();\n\n let iterable: AsyncIterable<string>;\n if (source instanceof ReadableStream) {\n iterable = this.readableToAsyncIterable(source);\n } else if (typeof source === \"function\") {\n iterable = source();\n } else {\n iterable = source;\n }\n\n return this.pipeIterable(iterable);\n }\n\n /**\n * Adapt a ReadableStream into an AsyncIterable<string>. TypeScript's\n * ReadableStream type doesn't declare Symbol.asyncIterator, so we use the\n * reader API for type safety.\n */\n private async *readableToAsyncIterable(\n readable: ReadableStream,\n ): AsyncIterable<string> {\n const reader = readable.getReader();\n const decoder = new TextDecoder();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n yield typeof value === \"string\"\n ? value\n : decoder.decode(value, { stream: true });\n }\n // flush any partially buffered multibyte characters from the decoder\n const final = decoder.decode();\n if (final) yield final;\n } finally {\n reader.releaseLock();\n }\n }\n\n /**\n * Core pipe loop: iterate an async iterable, writing each chunk as an SSE\n * stream event and collecting the concatenated result.\n */\n private async pipeIterable(source: AsyncIterable<string>): Promise<string> {\n const hashedStepId = this.currentHashedStepId();\n const chunks: string[] = [];\n\n for await (const chunk of source) {\n if (this._errored) break;\n\n chunks.push(chunk);\n\n if (!this.enqueueStreamEvent(chunk, hashedStepId)) {\n continue;\n }\n\n await this.writeChain;\n }\n\n return chunks.join(\"\");\n }\n\n /**\n * Write a redirect info event. Tells the client where to reconnect if the\n * durable endpoint goes async. Does NOT close the writer — more stream\n * events may follow before the durable endpoint actually switches to async\n * mode. Internal use only.\n */\n sendRedirectInfo(data: { runId: string; url: string }): void {\n this.enqueue(buildSseRedirectEvent(data));\n }\n\n /**\n * Write a succeeded result event and close the writer. Internal use only.\n */\n closeSucceeded(response: SseResponse): void {\n let sseEvent: string;\n try {\n sseEvent = buildSseSucceededEvent(response);\n } catch {\n sseEvent = buildSseFailedEvent(\"Failed to serialize result\");\n }\n this.closeWriter(sseEvent);\n }\n\n /**\n * Write a failed result event and close the writer. Internal use only.\n */\n closeFailed(error: string): void {\n this.closeWriter(buildSseFailedEvent(error));\n }\n\n /**\n * Optionally write a final SSE event, then close the writer.\n */\n private closeWriter(finalEvent?: string): void {\n this.writeChain = this.writeChain\n .then(async () => {\n if (finalEvent) {\n await this.writeEncoded(finalEvent);\n }\n await this.writer.close();\n })\n .catch((err) => {\n this.onWriteError?.(err);\n });\n }\n\n /**\n * Close the writer without writing a result event. Used when the durable endpoint goes\n * async and the real result will arrive on the redirected stream.\n */\n end(): void {\n this.closeWriter();\n }\n}\n\n/** Synchronous ALS lookup for the stream tools (fast path). */\nconst getStreamToolsSync = (): Stream | undefined => {\n const ctx = getAsyncCtxSync();\n return ctx?.execution?.stream;\n};\n\nconst getDeferredStreamTooling = async (): Promise<Stream | undefined> => {\n const ctx = await getAsyncCtx();\n return ctx?.execution?.stream;\n};\n\n/**\n * Stream tools that use ALS to resolve the current execution context.\n * Outside an Inngest execution, `push()` is a no-op and `pipe()` resolves immediately.\n */\nexport const stream: StreamTools = {\n push: (data) => {\n // Sync fast path: activate the stream before the next microtask tick.\n const syncStream = getStreamToolsSync();\n if (syncStream) {\n syncStream.push(data);\n return;\n }\n\n // Fallback: ALS not yet initialized (first import still resolving).\n void getDeferredStreamTooling()\n .then((s) => {\n s?.push(data);\n })\n .catch(() => {\n // ALS initialization failure — already warned in als.ts.\n // push() is best-effort, so silently degrade.\n });\n },\n pipe: async (source) => {\n const syncStream = getStreamToolsSync();\n if (syncStream) {\n return syncStream.pipe(source);\n }\n\n const s = await getDeferredStreamTooling();\n if (s) {\n return s.pipe(source);\n }\n return \"\";\n },\n};\n"],"mappings":"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"}
@@ -0,0 +1,161 @@
1
+ import { SseResponse } from "./execution/streaming.cjs";
2
+
3
+ //#region src/components/StreamTools.d.ts
4
+
5
+ /**
6
+ * Accepted source types for `stream.pipe()`.
7
+ *
8
+ * - `ReadableStream` — piped directly
9
+ * - `AsyncIterable<string>` — iterated; each yielded value becomes a chunk
10
+ * - `() => AsyncIterable<string>` — factory invoked lazily, then iterated
11
+ */
12
+ type PipeSource = ReadableStream | AsyncIterable<string> | (() => AsyncIterable<string>);
13
+ /**
14
+ * The public interface for stream tools available to user code.
15
+ */
16
+ interface StreamTools {
17
+ /**
18
+ * Push data to the client as an SSE stream event. Fire-and-forget from the
19
+ * caller's perspective.
20
+ *
21
+ * Outside of an Inngest execution context this is a silent no-op (graceful
22
+ * degradation).
23
+ */
24
+ push(data: unknown): void;
25
+ /**
26
+ * Pipe a source to the client, writing each chunk as an SSE stream event.
27
+ * Resolves with the concatenated content of all chunks when the source is
28
+ * fully consumed.
29
+ *
30
+ * Accepts a `ReadableStream`, an `AsyncIterable<string>`, or a factory
31
+ * function that returns an `AsyncIterable<string>` (e.g. an async
32
+ * generator function).
33
+ *
34
+ * Outside of an Inngest execution context this resolves with an empty string.
35
+ */
36
+ pipe(source: PipeSource): Promise<string>;
37
+ }
38
+ /**
39
+ * Wraps a `TransformStream<Uint8Array>` to provide push/pipe SSE streaming
40
+ * capabilities within an Inngest execution.
41
+ *
42
+ * @internal
43
+ */
44
+ declare class Stream implements StreamTools {
45
+ private transform;
46
+ private writer;
47
+ private encoder;
48
+ private _activated;
49
+ private _errored;
50
+ private writeChain;
51
+ /**
52
+ * Optional callback invoked the first time `push` or `pipe` is called.
53
+ * Used by the execution engine to fire a checkpoint that returns the SSE
54
+ * Response to the client immediately.
55
+ */
56
+ private onActivated?;
57
+ /**
58
+ * Optional callback invoked when a write to the underlying stream fails
59
+ * (e.g. the client disconnected or the transform stream errored). Used by
60
+ * the execution engine to emit diagnostic logs.
61
+ */
62
+ private onWriteError?;
63
+ constructor(opts?: {
64
+ onActivated?: () => void;
65
+ onWriteError?: (err: unknown) => void;
66
+ });
67
+ /**
68
+ * Whether `push` or `pipe` has been called at least once.
69
+ */
70
+ get activated(): boolean;
71
+ /**
72
+ * The readable side of the underlying transform stream. Consumers (i.e. the
73
+ * HTTP response) read SSE events from here.
74
+ */
75
+ get readable(): ReadableStream<Uint8Array>;
76
+ /**
77
+ * Resolve the current hashed step ID for stream events. Returns the
78
+ * executing step's hashed ID (read from ALS), or undefined if outside a step.
79
+ */
80
+ private currentHashedStepId;
81
+ private activate;
82
+ /**
83
+ * Encode and write an SSE event string to the underlying writer.
84
+ */
85
+ private writeEncoded;
86
+ /**
87
+ * Enqueue a pre-built SSE event string onto the write chain.
88
+ */
89
+ private enqueue;
90
+ /**
91
+ * Emit an `inngest.commit` SSE event indicating that uncommitted streamed data
92
+ * should be committed (i.e. will not be rolled back). Internal use only.
93
+ */
94
+ commit(hashedStepId: string | null): void;
95
+ /**
96
+ * Emit an `inngest.rollback` SSE event indicating the uncommitted streamed
97
+ * data should be discarded (e.g. step errored). Internal use only.
98
+ */
99
+ rollback(hashedStepId: string | null): void;
100
+ /**
101
+ * Serialize `data` into an SSE stream event and enqueue it. Returns `false`
102
+ * if serialization fails (e.g. circular reference) so callers can skip.
103
+ */
104
+ private enqueueStreamEvent;
105
+ /**
106
+ * Write a single SSE stream event containing `data`. The current step's
107
+ * hashed ID is automatically included as stepId for rollback tracking.
108
+ */
109
+ push(data: unknown): void;
110
+ /**
111
+ * Pipe a source to the client, writing each chunk as an SSE stream event.
112
+ * Returns the concatenated content of all chunks.
113
+ */
114
+ pipe(source: PipeSource): Promise<string>;
115
+ /**
116
+ * Adapt a ReadableStream into an AsyncIterable<string>. TypeScript's
117
+ * ReadableStream type doesn't declare Symbol.asyncIterator, so we use the
118
+ * reader API for type safety.
119
+ */
120
+ private readableToAsyncIterable;
121
+ /**
122
+ * Core pipe loop: iterate an async iterable, writing each chunk as an SSE
123
+ * stream event and collecting the concatenated result.
124
+ */
125
+ private pipeIterable;
126
+ /**
127
+ * Write a redirect info event. Tells the client where to reconnect if the
128
+ * durable endpoint goes async. Does NOT close the writer — more stream
129
+ * events may follow before the durable endpoint actually switches to async
130
+ * mode. Internal use only.
131
+ */
132
+ sendRedirectInfo(data: {
133
+ runId: string;
134
+ url: string;
135
+ }): void;
136
+ /**
137
+ * Write a succeeded result event and close the writer. Internal use only.
138
+ */
139
+ closeSucceeded(response: SseResponse): void;
140
+ /**
141
+ * Write a failed result event and close the writer. Internal use only.
142
+ */
143
+ closeFailed(error: string): void;
144
+ /**
145
+ * Optionally write a final SSE event, then close the writer.
146
+ */
147
+ private closeWriter;
148
+ /**
149
+ * Close the writer without writing a result event. Used when the durable endpoint goes
150
+ * async and the real result will arrive on the redirected stream.
151
+ */
152
+ end(): void;
153
+ }
154
+ /**
155
+ * Stream tools that use ALS to resolve the current execution context.
156
+ * Outside an Inngest execution, `push()` is a no-op and `pipe()` resolves immediately.
157
+ */
158
+ declare const stream: StreamTools;
159
+ //#endregion
160
+ export { Stream, stream };
161
+ //# sourceMappingURL=StreamTools.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StreamTools.d.cts","names":[],"sources":["../../src/components/StreamTools.ts"],"sourcesContent":[],"mappings":";;;;;;AAkBA;;;;;AAGwB,KAHZ,UAAA,GACR,cAEoB,GADpB,aACoB,CAAA,MAAA,CAAA,GAAA,CAAA,GAAA,GAAb,aAAa,CAAA,MAAA,CAAA,CAAA;AAKxB;;;AAqB4B,UArBX,WAAA,CAqBW;EAAO;AASnC;;;;;;MAqN2B,CAAA,IAAA,EAAA,OAAA,CAAA,EAAA,IAAA;;;AAyD3B;;;;;;;;;eAvRe,aAAa;;;;;;;;cASf,MAAA,YAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAiDb,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAuFZ,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;2BA6EP;;;;;;;;;;;;;;;;;;;cAyDd,QAAQ"}
@@ -0,0 +1,161 @@
1
+ import { SseResponse } from "./execution/streaming.js";
2
+
3
+ //#region src/components/StreamTools.d.ts
4
+
5
+ /**
6
+ * Accepted source types for `stream.pipe()`.
7
+ *
8
+ * - `ReadableStream` — piped directly
9
+ * - `AsyncIterable<string>` — iterated; each yielded value becomes a chunk
10
+ * - `() => AsyncIterable<string>` — factory invoked lazily, then iterated
11
+ */
12
+ type PipeSource = ReadableStream | AsyncIterable<string> | (() => AsyncIterable<string>);
13
+ /**
14
+ * The public interface for stream tools available to user code.
15
+ */
16
+ interface StreamTools {
17
+ /**
18
+ * Push data to the client as an SSE stream event. Fire-and-forget from the
19
+ * caller's perspective.
20
+ *
21
+ * Outside of an Inngest execution context this is a silent no-op (graceful
22
+ * degradation).
23
+ */
24
+ push(data: unknown): void;
25
+ /**
26
+ * Pipe a source to the client, writing each chunk as an SSE stream event.
27
+ * Resolves with the concatenated content of all chunks when the source is
28
+ * fully consumed.
29
+ *
30
+ * Accepts a `ReadableStream`, an `AsyncIterable<string>`, or a factory
31
+ * function that returns an `AsyncIterable<string>` (e.g. an async
32
+ * generator function).
33
+ *
34
+ * Outside of an Inngest execution context this resolves with an empty string.
35
+ */
36
+ pipe(source: PipeSource): Promise<string>;
37
+ }
38
+ /**
39
+ * Wraps a `TransformStream<Uint8Array>` to provide push/pipe SSE streaming
40
+ * capabilities within an Inngest execution.
41
+ *
42
+ * @internal
43
+ */
44
+ declare class Stream implements StreamTools {
45
+ private transform;
46
+ private writer;
47
+ private encoder;
48
+ private _activated;
49
+ private _errored;
50
+ private writeChain;
51
+ /**
52
+ * Optional callback invoked the first time `push` or `pipe` is called.
53
+ * Used by the execution engine to fire a checkpoint that returns the SSE
54
+ * Response to the client immediately.
55
+ */
56
+ private onActivated?;
57
+ /**
58
+ * Optional callback invoked when a write to the underlying stream fails
59
+ * (e.g. the client disconnected or the transform stream errored). Used by
60
+ * the execution engine to emit diagnostic logs.
61
+ */
62
+ private onWriteError?;
63
+ constructor(opts?: {
64
+ onActivated?: () => void;
65
+ onWriteError?: (err: unknown) => void;
66
+ });
67
+ /**
68
+ * Whether `push` or `pipe` has been called at least once.
69
+ */
70
+ get activated(): boolean;
71
+ /**
72
+ * The readable side of the underlying transform stream. Consumers (i.e. the
73
+ * HTTP response) read SSE events from here.
74
+ */
75
+ get readable(): ReadableStream<Uint8Array>;
76
+ /**
77
+ * Resolve the current hashed step ID for stream events. Returns the
78
+ * executing step's hashed ID (read from ALS), or undefined if outside a step.
79
+ */
80
+ private currentHashedStepId;
81
+ private activate;
82
+ /**
83
+ * Encode and write an SSE event string to the underlying writer.
84
+ */
85
+ private writeEncoded;
86
+ /**
87
+ * Enqueue a pre-built SSE event string onto the write chain.
88
+ */
89
+ private enqueue;
90
+ /**
91
+ * Emit an `inngest.commit` SSE event indicating that uncommitted streamed data
92
+ * should be committed (i.e. will not be rolled back). Internal use only.
93
+ */
94
+ commit(hashedStepId: string | null): void;
95
+ /**
96
+ * Emit an `inngest.rollback` SSE event indicating the uncommitted streamed
97
+ * data should be discarded (e.g. step errored). Internal use only.
98
+ */
99
+ rollback(hashedStepId: string | null): void;
100
+ /**
101
+ * Serialize `data` into an SSE stream event and enqueue it. Returns `false`
102
+ * if serialization fails (e.g. circular reference) so callers can skip.
103
+ */
104
+ private enqueueStreamEvent;
105
+ /**
106
+ * Write a single SSE stream event containing `data`. The current step's
107
+ * hashed ID is automatically included as stepId for rollback tracking.
108
+ */
109
+ push(data: unknown): void;
110
+ /**
111
+ * Pipe a source to the client, writing each chunk as an SSE stream event.
112
+ * Returns the concatenated content of all chunks.
113
+ */
114
+ pipe(source: PipeSource): Promise<string>;
115
+ /**
116
+ * Adapt a ReadableStream into an AsyncIterable<string>. TypeScript's
117
+ * ReadableStream type doesn't declare Symbol.asyncIterator, so we use the
118
+ * reader API for type safety.
119
+ */
120
+ private readableToAsyncIterable;
121
+ /**
122
+ * Core pipe loop: iterate an async iterable, writing each chunk as an SSE
123
+ * stream event and collecting the concatenated result.
124
+ */
125
+ private pipeIterable;
126
+ /**
127
+ * Write a redirect info event. Tells the client where to reconnect if the
128
+ * durable endpoint goes async. Does NOT close the writer — more stream
129
+ * events may follow before the durable endpoint actually switches to async
130
+ * mode. Internal use only.
131
+ */
132
+ sendRedirectInfo(data: {
133
+ runId: string;
134
+ url: string;
135
+ }): void;
136
+ /**
137
+ * Write a succeeded result event and close the writer. Internal use only.
138
+ */
139
+ closeSucceeded(response: SseResponse): void;
140
+ /**
141
+ * Write a failed result event and close the writer. Internal use only.
142
+ */
143
+ closeFailed(error: string): void;
144
+ /**
145
+ * Optionally write a final SSE event, then close the writer.
146
+ */
147
+ private closeWriter;
148
+ /**
149
+ * Close the writer without writing a result event. Used when the durable endpoint goes
150
+ * async and the real result will arrive on the redirected stream.
151
+ */
152
+ end(): void;
153
+ }
154
+ /**
155
+ * Stream tools that use ALS to resolve the current execution context.
156
+ * Outside an Inngest execution, `push()` is a no-op and `pipe()` resolves immediately.
157
+ */
158
+ declare const stream: StreamTools;
159
+ //#endregion
160
+ export { Stream, stream };
161
+ //# sourceMappingURL=StreamTools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StreamTools.d.ts","names":[],"sources":["../../src/components/StreamTools.ts"],"sourcesContent":[],"mappings":";;;;;;AAkBA;;;;;AAGwB,KAHZ,UAAA,GACR,cAEoB,GADpB,aACoB,CAAA,MAAA,CAAA,GAAA,CAAA,GAAA,GAAb,aAAa,CAAA,MAAA,CAAA,CAAA;AAKxB;;;AAqB4B,UArBX,WAAA,CAqBW;EAAO;AASnC;;;;;;MAqN2B,CAAA,IAAA,EAAA,OAAA,CAAA,EAAA,IAAA;;;AAyD3B;;;;;;;;;eAvRe,aAAa;;;;;;;;cASf,MAAA,YAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAiDb,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAuFZ,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;2BA6EP;;;;;;;;;;;;;;;;;;;cAyDd,QAAQ"}