@workflow/core 4.0.1-beta.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 (143) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +3 -0
  3. package/dist/builtins.d.ts +4 -0
  4. package/dist/builtins.d.ts.map +1 -0
  5. package/dist/builtins.js +13 -0
  6. package/dist/builtins.js.map +1 -0
  7. package/dist/create-hook.d.ts +123 -0
  8. package/dist/create-hook.d.ts.map +1 -0
  9. package/dist/create-hook.js +32 -0
  10. package/dist/create-hook.js.map +1 -0
  11. package/dist/define-hook.d.ts +53 -0
  12. package/dist/define-hook.d.ts.map +1 -0
  13. package/dist/define-hook.js +59 -0
  14. package/dist/define-hook.js.map +1 -0
  15. package/dist/events-consumer.d.ts +35 -0
  16. package/dist/events-consumer.d.ts.map +1 -0
  17. package/dist/events-consumer.js +72 -0
  18. package/dist/events-consumer.js.map +1 -0
  19. package/dist/global.d.ts +29 -0
  20. package/dist/global.d.ts.map +1 -0
  21. package/dist/global.js +50 -0
  22. package/dist/global.js.map +1 -0
  23. package/dist/index.d.ts +18 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +18 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/logger.d.ts +31 -0
  28. package/dist/logger.d.ts.map +1 -0
  29. package/dist/logger.js +32 -0
  30. package/dist/logger.js.map +1 -0
  31. package/dist/observability.d.ts +24 -0
  32. package/dist/observability.d.ts.map +1 -0
  33. package/dist/observability.js +126 -0
  34. package/dist/observability.js.map +1 -0
  35. package/dist/parse-name.d.ts +25 -0
  36. package/dist/parse-name.d.ts.map +1 -0
  37. package/dist/parse-name.js +40 -0
  38. package/dist/parse-name.js.map +1 -0
  39. package/dist/private.d.ts +26 -0
  40. package/dist/private.d.ts.map +1 -0
  41. package/dist/private.js +17 -0
  42. package/dist/private.js.map +1 -0
  43. package/dist/runtime/resume-hook.d.ts +71 -0
  44. package/dist/runtime/resume-hook.d.ts.map +1 -0
  45. package/dist/runtime/resume-hook.js +180 -0
  46. package/dist/runtime/resume-hook.js.map +1 -0
  47. package/dist/runtime/start.d.ts +28 -0
  48. package/dist/runtime/start.d.ts.map +1 -0
  49. package/dist/runtime/start.js +57 -0
  50. package/dist/runtime/start.js.map +1 -0
  51. package/dist/runtime/world.d.ts +24 -0
  52. package/dist/runtime/world.d.ts.map +1 -0
  53. package/dist/runtime/world.js +84 -0
  54. package/dist/runtime/world.js.map +1 -0
  55. package/dist/runtime.d.ts +121 -0
  56. package/dist/runtime.d.ts.map +1 -0
  57. package/dist/runtime.js +554 -0
  58. package/dist/runtime.js.map +1 -0
  59. package/dist/schemas.d.ts +29 -0
  60. package/dist/schemas.d.ts.map +1 -0
  61. package/dist/schemas.js +15 -0
  62. package/dist/schemas.js.map +1 -0
  63. package/dist/serialization.d.ts +188 -0
  64. package/dist/serialization.d.ts.map +1 -0
  65. package/dist/serialization.js +725 -0
  66. package/dist/serialization.js.map +1 -0
  67. package/dist/step/context-storage.d.ts +8 -0
  68. package/dist/step/context-storage.d.ts.map +1 -0
  69. package/dist/step/context-storage.js +3 -0
  70. package/dist/step/context-storage.js.map +1 -0
  71. package/dist/step/get-step-metadata.d.ts +38 -0
  72. package/dist/step/get-step-metadata.d.ts.map +1 -0
  73. package/dist/step/get-step-metadata.js +14 -0
  74. package/dist/step/get-step-metadata.js.map +1 -0
  75. package/dist/step/get-workflow-metadata.d.ts +7 -0
  76. package/dist/step/get-workflow-metadata.d.ts.map +1 -0
  77. package/dist/step/get-workflow-metadata.js +12 -0
  78. package/dist/step/get-workflow-metadata.js.map +1 -0
  79. package/dist/step.d.ts +4 -0
  80. package/dist/step.d.ts.map +1 -0
  81. package/dist/step.js +92 -0
  82. package/dist/step.js.map +1 -0
  83. package/dist/symbols.d.ts +9 -0
  84. package/dist/symbols.d.ts.map +1 -0
  85. package/dist/symbols.js +9 -0
  86. package/dist/symbols.js.map +1 -0
  87. package/dist/telemetry/semantic-conventions.d.ts +175 -0
  88. package/dist/telemetry/semantic-conventions.d.ts.map +1 -0
  89. package/dist/telemetry/semantic-conventions.js +121 -0
  90. package/dist/telemetry/semantic-conventions.js.map +1 -0
  91. package/dist/telemetry.d.ts +24 -0
  92. package/dist/telemetry.d.ts.map +1 -0
  93. package/dist/telemetry.js +121 -0
  94. package/dist/telemetry.js.map +1 -0
  95. package/dist/types.d.ts +10 -0
  96. package/dist/types.d.ts.map +1 -0
  97. package/dist/types.js +39 -0
  98. package/dist/types.js.map +1 -0
  99. package/dist/util.d.ts +43 -0
  100. package/dist/util.d.ts.map +1 -0
  101. package/dist/util.js +76 -0
  102. package/dist/util.js.map +1 -0
  103. package/dist/vm/index.d.ts +17 -0
  104. package/dist/vm/index.d.ts.map +1 -0
  105. package/dist/vm/index.js +93 -0
  106. package/dist/vm/index.js.map +1 -0
  107. package/dist/vm/uuid.d.ts +10 -0
  108. package/dist/vm/uuid.d.ts.map +1 -0
  109. package/dist/vm/uuid.js +30 -0
  110. package/dist/vm/uuid.js.map +1 -0
  111. package/dist/workflow/create-hook.d.ts +7 -0
  112. package/dist/workflow/create-hook.d.ts.map +1 -0
  113. package/dist/workflow/create-hook.js +22 -0
  114. package/dist/workflow/create-hook.js.map +1 -0
  115. package/dist/workflow/define-hook.d.ts +10 -0
  116. package/dist/workflow/define-hook.d.ts.map +1 -0
  117. package/dist/workflow/define-hook.js +15 -0
  118. package/dist/workflow/define-hook.js.map +1 -0
  119. package/dist/workflow/get-workflow-metadata.d.ts +17 -0
  120. package/dist/workflow/get-workflow-metadata.d.ts.map +1 -0
  121. package/dist/workflow/get-workflow-metadata.js +11 -0
  122. package/dist/workflow/get-workflow-metadata.js.map +1 -0
  123. package/dist/workflow/hook.d.ts +4 -0
  124. package/dist/workflow/hook.d.ts.map +1 -0
  125. package/dist/workflow/hook.js +101 -0
  126. package/dist/workflow/hook.js.map +1 -0
  127. package/dist/workflow/index.d.ts +10 -0
  128. package/dist/workflow/index.d.ts.map +1 -0
  129. package/dist/workflow/index.js +14 -0
  130. package/dist/workflow/index.js.map +1 -0
  131. package/dist/workflow/writable-stream.d.ts +3 -0
  132. package/dist/workflow/writable-stream.d.ts.map +1 -0
  133. package/dist/workflow/writable-stream.js +12 -0
  134. package/dist/workflow/writable-stream.js.map +1 -0
  135. package/dist/workflow.d.ts +3 -0
  136. package/dist/workflow.d.ts.map +1 -0
  137. package/dist/workflow.js +454 -0
  138. package/dist/workflow.js.map +1 -0
  139. package/dist/writable-stream.d.ts +22 -0
  140. package/dist/writable-stream.d.ts.map +1 -0
  141. package/dist/writable-stream.js +16 -0
  142. package/dist/writable-stream.js.map +1 -0
  143. package/package.json +73 -0
@@ -0,0 +1,725 @@
1
+ import { WorkflowRuntimeError } from '@workflow/errors';
2
+ import * as devalue from 'devalue';
3
+ import { getWorld } from './runtime/world.js';
4
+ import { BODY_INIT_SYMBOL, STREAM_NAME_SYMBOL, STREAM_TYPE_SYMBOL, WEBHOOK_RESPONSE_WRITABLE, } from './symbols.js';
5
+ /**
6
+ * Detect if a readable stream is a byte stream.
7
+ *
8
+ * @param stream
9
+ * @returns `"bytes"` if the stream is a byte stream, `undefined` otherwise
10
+ */
11
+ export function getStreamType(stream) {
12
+ try {
13
+ const reader = stream.getReader({ mode: 'byob' });
14
+ reader.releaseLock();
15
+ return 'bytes';
16
+ }
17
+ catch { }
18
+ }
19
+ export function getSerializeStream(reducers) {
20
+ const encoder = new TextEncoder();
21
+ const stream = new TransformStream({
22
+ transform(chunk, controller) {
23
+ try {
24
+ const serialized = devalue.stringify(chunk, reducers);
25
+ controller.enqueue(encoder.encode(`${serialized}\n`));
26
+ }
27
+ catch (error) {
28
+ controller.error(new WorkflowRuntimeError("Failed to serialize stream chunk. Ensure you're passing serializable types (plain objects, arrays, primitives, Date, RegExp, Map, Set).", { slug: 'serialization-failed', cause: error }));
29
+ }
30
+ },
31
+ });
32
+ return stream;
33
+ }
34
+ export function getDeserializeStream(revivers) {
35
+ const decoder = new TextDecoder();
36
+ let buffer = '';
37
+ const stream = new TransformStream({
38
+ transform(chunk, controller) {
39
+ // Append new chunk to buffer
40
+ buffer += decoder.decode(chunk, { stream: true });
41
+ // Process all complete lines
42
+ while (true) {
43
+ const newlineIndex = buffer.indexOf('\n');
44
+ if (newlineIndex === -1)
45
+ break;
46
+ const line = buffer.slice(0, newlineIndex);
47
+ buffer = buffer.slice(newlineIndex + 1);
48
+ if (line.length > 0) {
49
+ const obj = devalue.parse(line, revivers);
50
+ controller.enqueue(obj);
51
+ }
52
+ }
53
+ },
54
+ flush(controller) {
55
+ // Process any remaining data in the buffer at the end of the stream
56
+ if (buffer && buffer.length > 0) {
57
+ const obj = devalue.parse(buffer, revivers);
58
+ controller.enqueue(obj);
59
+ }
60
+ },
61
+ });
62
+ return stream;
63
+ }
64
+ export class WorkflowServerReadableStream extends ReadableStream {
65
+ #reader;
66
+ constructor(name, startIndex) {
67
+ if (typeof name !== 'string' || name.length === 0) {
68
+ throw new Error(`"name" is required, got "${name}"`);
69
+ }
70
+ super({
71
+ // @ts-expect-error Not sure why TypeScript is complaining about this
72
+ type: 'bytes',
73
+ pull: async (controller) => {
74
+ let reader = this.#reader;
75
+ if (!reader) {
76
+ const world = getWorld();
77
+ const stream = await world.readFromStream(name, startIndex);
78
+ reader = this.#reader = stream.getReader();
79
+ }
80
+ if (!reader) {
81
+ controller.error(new Error('Failed to get reader'));
82
+ return;
83
+ }
84
+ const result = await reader.read();
85
+ if (result.done) {
86
+ this.#reader = undefined;
87
+ controller.close();
88
+ }
89
+ else {
90
+ controller.enqueue(result.value);
91
+ }
92
+ },
93
+ });
94
+ }
95
+ }
96
+ export class WorkflowServerWritableStream extends WritableStream {
97
+ constructor(name) {
98
+ if (typeof name !== 'string' || name.length === 0) {
99
+ throw new Error(`"name" is required, got "${name}"`);
100
+ }
101
+ const world = getWorld();
102
+ super({
103
+ write: async (chunk) => {
104
+ await world.writeToStream(name, chunk);
105
+ },
106
+ close: async () => {
107
+ await world.closeStream(name);
108
+ },
109
+ });
110
+ }
111
+ }
112
+ function revive(str) {
113
+ // biome-ignore lint/security/noGlobalEval: Eval is safe here - we are only passing value from `devalue.stringify()`
114
+ // biome-ignore lint/complexity/noCommaOperator: This is how you do global scope eval
115
+ return (0, eval)(`(${str})`);
116
+ }
117
+ function getCommonReducers(global = globalThis) {
118
+ const abToBase64 = (value, offset, length) => {
119
+ // Avoid returning falsy value for zero-length buffers
120
+ if (length === 0)
121
+ return '.';
122
+ return Buffer.from(value, offset, length).toString('base64');
123
+ };
124
+ const viewToBase64 = (value) => abToBase64(value.buffer, value.byteOffset, value.byteLength);
125
+ return {
126
+ ArrayBuffer: (value) => value instanceof global.ArrayBuffer &&
127
+ abToBase64(value, 0, value.byteLength),
128
+ BigInt64Array: (value) => value instanceof global.BigInt64Array && viewToBase64(value),
129
+ BigUint64Array: (value) => value instanceof global.BigUint64Array && viewToBase64(value),
130
+ Date: (value) => {
131
+ if (!(value instanceof global.Date))
132
+ return false;
133
+ const valid = !Number.isNaN(value.getDate());
134
+ // Note: "." is to avoid returning a falsy value when the date is invalid
135
+ return valid ? value.toISOString() : '.';
136
+ },
137
+ Error: (value) => {
138
+ if (!(value instanceof global.Error))
139
+ return false;
140
+ return {
141
+ name: value.name,
142
+ message: value.message,
143
+ stack: value.stack,
144
+ };
145
+ },
146
+ Float32Array: (value) => value instanceof global.Float32Array && viewToBase64(value),
147
+ Float64Array: (value) => value instanceof global.Float64Array && viewToBase64(value),
148
+ Headers: (value) => value instanceof global.Headers && Array.from(value),
149
+ Int8Array: (value) => value instanceof global.Int8Array && viewToBase64(value),
150
+ Int16Array: (value) => value instanceof global.Int16Array && viewToBase64(value),
151
+ Int32Array: (value) => value instanceof global.Int32Array && viewToBase64(value),
152
+ Map: (value) => value instanceof global.Map && Array.from(value),
153
+ RegExp: (value) => value instanceof global.RegExp && {
154
+ source: value.source,
155
+ flags: value.flags,
156
+ },
157
+ Request: (value) => {
158
+ if (!(value instanceof global.Request))
159
+ return false;
160
+ const data = {
161
+ method: value.method,
162
+ url: value.url,
163
+ headers: value.headers,
164
+ body: value.body,
165
+ duplex: value.duplex,
166
+ };
167
+ const responseWritable = value[WEBHOOK_RESPONSE_WRITABLE];
168
+ if (responseWritable) {
169
+ data.responseWritable = responseWritable;
170
+ }
171
+ return data;
172
+ },
173
+ Response: (value) => {
174
+ if (!(value instanceof global.Response))
175
+ return false;
176
+ return {
177
+ type: value.type,
178
+ url: value.url,
179
+ status: value.status,
180
+ statusText: value.statusText,
181
+ headers: value.headers,
182
+ body: value.body,
183
+ redirected: value.redirected,
184
+ };
185
+ },
186
+ Set: (value) => value instanceof global.Set && Array.from(value),
187
+ URL: (value) => value instanceof global.URL && value.href,
188
+ URLSearchParams: (value) => {
189
+ if (!(value instanceof global.URLSearchParams))
190
+ return false;
191
+ // Avoid returning a falsy value when the URLSearchParams is empty
192
+ if (value.size === 0)
193
+ return '.';
194
+ return String(value);
195
+ },
196
+ Uint8Array: (value) => value instanceof global.Uint8Array && viewToBase64(value),
197
+ Uint8ClampedArray: (value) => value instanceof global.Uint8ClampedArray && viewToBase64(value),
198
+ Uint16Array: (value) => value instanceof global.Uint16Array && viewToBase64(value),
199
+ Uint32Array: (value) => value instanceof global.Uint32Array && viewToBase64(value),
200
+ };
201
+ }
202
+ /**
203
+ * Reducers for serialization boundary from the client side, passing arguments
204
+ * to the workflow handler.
205
+ *
206
+ * @param global
207
+ * @param ops
208
+ * @returns
209
+ */
210
+ export function getExternalReducers(global = globalThis, ops) {
211
+ return {
212
+ ...getCommonReducers(global),
213
+ ReadableStream: (value) => {
214
+ if (!(value instanceof global.ReadableStream))
215
+ return false;
216
+ // Stream must not be locked when passing across execution boundary
217
+ if (value.locked) {
218
+ throw new Error('ReadableStream is locked');
219
+ }
220
+ const name = global.crypto.randomUUID();
221
+ const type = getStreamType(value);
222
+ const writable = new WorkflowServerWritableStream(name);
223
+ if (type === 'bytes') {
224
+ ops.push(value.pipeTo(writable));
225
+ }
226
+ else {
227
+ ops.push(value
228
+ .pipeThrough(getSerializeStream(getExternalReducers(global, ops)))
229
+ .pipeTo(writable));
230
+ }
231
+ const s = { name };
232
+ if (type)
233
+ s.type = type;
234
+ return s;
235
+ },
236
+ WritableStream: (value) => {
237
+ if (!(value instanceof global.WritableStream))
238
+ return false;
239
+ const name = global.crypto.randomUUID();
240
+ ops.push(new WorkflowServerReadableStream(name)
241
+ .pipeThrough(getDeserializeStream(getExternalRevivers(global, ops)))
242
+ .pipeTo(value));
243
+ return { name };
244
+ },
245
+ };
246
+ }
247
+ /**
248
+ * Reducers for serialization boundary from within the workflow execution
249
+ * environment, passing return value to the client side and into step arguments.
250
+ *
251
+ * @param global
252
+ * @returns
253
+ */
254
+ export function getWorkflowReducers(global = globalThis) {
255
+ return {
256
+ ...getCommonReducers(global),
257
+ // Readable/Writable streams from within the workflow execution environment
258
+ // are simply "handles" that can be passed around to other steps.
259
+ ReadableStream: (value) => {
260
+ if (!(value instanceof global.ReadableStream))
261
+ return false;
262
+ // Check if this is a fake stream storing BodyInit from Request/Response constructor
263
+ const bodyInit = value[BODY_INIT_SYMBOL];
264
+ if (bodyInit !== undefined) {
265
+ // This is a fake stream - serialize the BodyInit directly
266
+ // devalue will handle serializing strings, Uint8Array, etc.
267
+ return { bodyInit };
268
+ }
269
+ const name = value[STREAM_NAME_SYMBOL];
270
+ if (!name) {
271
+ throw new Error('ReadableStream `name` is not set');
272
+ }
273
+ const s = { name };
274
+ const type = value[STREAM_TYPE_SYMBOL];
275
+ if (type)
276
+ s.type = type;
277
+ return s;
278
+ },
279
+ WritableStream: (value) => {
280
+ if (!(value instanceof global.WritableStream))
281
+ return false;
282
+ const name = value[STREAM_NAME_SYMBOL];
283
+ if (!name) {
284
+ throw new Error('WritableStream `name` is not set');
285
+ }
286
+ return { name };
287
+ },
288
+ };
289
+ }
290
+ /**
291
+ * Reducers for serialization boundary from within the step execution
292
+ * environment, passing return value to the workflow handler.
293
+ *
294
+ * @param global
295
+ * @param ops
296
+ * @returns
297
+ */
298
+ function getStepReducers(global = globalThis, ops) {
299
+ return {
300
+ ...getCommonReducers(global),
301
+ ReadableStream: (value) => {
302
+ if (!(value instanceof global.ReadableStream))
303
+ return false;
304
+ // Stream must not be locked when passing across execution boundary
305
+ if (value.locked) {
306
+ throw new Error('ReadableStream is locked');
307
+ }
308
+ // Check if the stream already has the name symbol set, in which case
309
+ // it's already being sunk to the server and we can just return the
310
+ // name and type.
311
+ let name = value[STREAM_NAME_SYMBOL];
312
+ let type = value[STREAM_TYPE_SYMBOL];
313
+ if (!name) {
314
+ name = global.crypto.randomUUID();
315
+ type = getStreamType(value);
316
+ const writable = new WorkflowServerWritableStream(name);
317
+ if (type === 'bytes') {
318
+ ops.push(value.pipeTo(writable));
319
+ }
320
+ else {
321
+ ops.push(value
322
+ .pipeThrough(getSerializeStream(getStepReducers(global, ops)))
323
+ .pipeTo(writable));
324
+ }
325
+ }
326
+ const s = { name };
327
+ if (type)
328
+ s.type = type;
329
+ return s;
330
+ },
331
+ WritableStream: (value) => {
332
+ if (!(value instanceof global.WritableStream))
333
+ return false;
334
+ let name = value[STREAM_NAME_SYMBOL];
335
+ if (!name) {
336
+ name = global.crypto.randomUUID();
337
+ ops.push(new WorkflowServerReadableStream(name)
338
+ .pipeThrough(getDeserializeStream(getStepRevivers(global, ops)))
339
+ .pipeTo(value));
340
+ }
341
+ return { name };
342
+ },
343
+ };
344
+ }
345
+ function getCommonRevivers(global = globalThis) {
346
+ function reviveArrayBuffer(value) {
347
+ // Handle sentinel value for zero-length buffers
348
+ const base64 = value === '.' ? '' : value;
349
+ const buffer = Buffer.from(base64, 'base64');
350
+ const arrayBuffer = new global.ArrayBuffer(buffer.length);
351
+ const uint8Array = new global.Uint8Array(arrayBuffer);
352
+ uint8Array.set(buffer);
353
+ return arrayBuffer;
354
+ }
355
+ return {
356
+ ArrayBuffer: reviveArrayBuffer,
357
+ BigInt64Array: (value) => {
358
+ const ab = reviveArrayBuffer(value);
359
+ return new global.BigInt64Array(ab);
360
+ },
361
+ BigUint64Array: (value) => {
362
+ const ab = reviveArrayBuffer(value);
363
+ return new global.BigUint64Array(ab);
364
+ },
365
+ Date: (value) => new global.Date(value),
366
+ Error: (value) => {
367
+ const error = new global.Error(value.message);
368
+ error.name = value.name;
369
+ error.stack = value.stack;
370
+ return error;
371
+ },
372
+ Float32Array: (value) => {
373
+ const ab = reviveArrayBuffer(value);
374
+ return new global.Float32Array(ab);
375
+ },
376
+ Float64Array: (value) => {
377
+ const ab = reviveArrayBuffer(value);
378
+ return new global.Float64Array(ab);
379
+ },
380
+ Headers: (value) => new global.Headers(value),
381
+ Int8Array: (value) => {
382
+ const ab = reviveArrayBuffer(value);
383
+ return new global.Int8Array(ab);
384
+ },
385
+ Int16Array: (value) => {
386
+ const ab = reviveArrayBuffer(value);
387
+ return new global.Int16Array(ab);
388
+ },
389
+ Int32Array: (value) => {
390
+ const ab = reviveArrayBuffer(value);
391
+ return new global.Int32Array(ab);
392
+ },
393
+ Map: (value) => new global.Map(value),
394
+ RegExp: (value) => new global.RegExp(value.source, value.flags),
395
+ Set: (value) => new global.Set(value),
396
+ URL: (value) => new global.URL(value),
397
+ URLSearchParams: (value) => new global.URLSearchParams(value === '.' ? '' : value),
398
+ Uint8Array: (value) => {
399
+ const ab = reviveArrayBuffer(value);
400
+ return new global.Uint8Array(ab);
401
+ },
402
+ Uint8ClampedArray: (value) => {
403
+ const ab = reviveArrayBuffer(value);
404
+ return new global.Uint8ClampedArray(ab);
405
+ },
406
+ Uint16Array: (value) => {
407
+ const ab = reviveArrayBuffer(value);
408
+ return new global.Uint16Array(ab);
409
+ },
410
+ Uint32Array: (value) => {
411
+ const ab = reviveArrayBuffer(value);
412
+ return new global.Uint32Array(ab);
413
+ },
414
+ };
415
+ }
416
+ /**
417
+ * Revivers for deserialization boundary from the client side,
418
+ * receiving the return value from the workflow handler.
419
+ *
420
+ * @param global
421
+ * @param ops
422
+ */
423
+ export function getExternalRevivers(global = globalThis, ops) {
424
+ return {
425
+ ...getCommonRevivers(global),
426
+ Request: (value) => {
427
+ return new global.Request(value.url, {
428
+ method: value.method,
429
+ headers: new global.Headers(value.headers),
430
+ body: value.body,
431
+ duplex: value.duplex,
432
+ });
433
+ },
434
+ Response: (value) => {
435
+ // Note: Response constructor only accepts status, statusText, and headers
436
+ // The type, url, and redirected properties are read-only and set by the constructor
437
+ return new global.Response(value.body, {
438
+ status: value.status,
439
+ statusText: value.statusText,
440
+ headers: new global.Headers(value.headers),
441
+ });
442
+ },
443
+ ReadableStream: (value) => {
444
+ // If this has bodyInit, it came from a Response constructor
445
+ // Convert it to a REAL stream now that we're outside the workflow
446
+ if ('bodyInit' in value) {
447
+ const bodyInit = value.bodyInit;
448
+ // Use the native Response constructor to properly convert BodyInit to ReadableStream
449
+ const response = new global.Response(bodyInit);
450
+ return response.body;
451
+ }
452
+ const readable = new WorkflowServerReadableStream(value.name, value.startIndex);
453
+ if (value.type === 'bytes') {
454
+ return readable;
455
+ }
456
+ else {
457
+ const transform = getDeserializeStream(getExternalRevivers(global, ops));
458
+ ops.push(readable.pipeTo(transform.writable));
459
+ return transform.readable;
460
+ }
461
+ },
462
+ WritableStream: (value) => {
463
+ const serialize = getSerializeStream(getExternalReducers(global, ops));
464
+ ops.push(serialize.readable.pipeTo(new WorkflowServerWritableStream(value.name)));
465
+ return serialize.writable;
466
+ },
467
+ };
468
+ }
469
+ /**
470
+ * Revivers for deserialization boundary from within the workflow execution
471
+ * environment, receiving arguments from the client side, and return values
472
+ * from the steps.
473
+ *
474
+ * @param global
475
+ * @returns
476
+ */
477
+ export function getWorkflowRevivers(global = globalThis) {
478
+ return {
479
+ ...getCommonRevivers(global),
480
+ Request: (value) => {
481
+ Object.setPrototypeOf(value, global.Request.prototype);
482
+ const responseWritable = value.responseWritable;
483
+ if (responseWritable) {
484
+ value[WEBHOOK_RESPONSE_WRITABLE] = responseWritable;
485
+ delete value.responseWritable;
486
+ value.respondWith = () => {
487
+ throw new Error('`respondWith()` must be called from within a step function');
488
+ };
489
+ }
490
+ return value;
491
+ },
492
+ Response: (value) => {
493
+ Object.setPrototypeOf(value, global.Response.prototype);
494
+ return value;
495
+ },
496
+ ReadableStream: (value) => {
497
+ // Check if this is a BodyInit that should be wrapped in a fake stream
498
+ if ('bodyInit' in value) {
499
+ // Recreate the fake stream with the BodyInit
500
+ return Object.create(global.ReadableStream.prototype, {
501
+ [BODY_INIT_SYMBOL]: {
502
+ value: value.bodyInit,
503
+ writable: false,
504
+ },
505
+ });
506
+ }
507
+ // Regular stream handling
508
+ return Object.create(global.ReadableStream.prototype, {
509
+ [STREAM_NAME_SYMBOL]: {
510
+ value: value.name,
511
+ writable: false,
512
+ },
513
+ [STREAM_TYPE_SYMBOL]: {
514
+ value: value.type,
515
+ writable: false,
516
+ },
517
+ });
518
+ },
519
+ WritableStream: (value) => {
520
+ return Object.create(global.WritableStream.prototype, {
521
+ [STREAM_NAME_SYMBOL]: {
522
+ value: value.name,
523
+ writable: false,
524
+ },
525
+ });
526
+ },
527
+ };
528
+ }
529
+ /**
530
+ * Revivers for deserialization boundary from within the step execution
531
+ * environment, receiving arguments from the workflow handler.
532
+ *
533
+ * @param global
534
+ * @param ops
535
+ * @returns
536
+ */
537
+ function getStepRevivers(global = globalThis, ops) {
538
+ return {
539
+ ...getCommonRevivers(global),
540
+ Request: (value) => {
541
+ const responseWritable = value.responseWritable;
542
+ const request = new global.Request(value.url, {
543
+ method: value.method,
544
+ headers: new global.Headers(value.headers),
545
+ body: value.body,
546
+ duplex: value.duplex,
547
+ });
548
+ if (responseWritable) {
549
+ request.respondWith = async (response) => {
550
+ const writer = responseWritable.getWriter();
551
+ await writer.write(response);
552
+ await writer.close();
553
+ };
554
+ }
555
+ return request;
556
+ },
557
+ Response: (value) => {
558
+ // Note: Response constructor only accepts status, statusText, and headers
559
+ // The type, url, and redirected properties are read-only and set by the constructor
560
+ return new global.Response(value.body, {
561
+ status: value.status,
562
+ statusText: value.statusText,
563
+ headers: new global.Headers(value.headers),
564
+ });
565
+ },
566
+ ReadableStream: (value) => {
567
+ // If this has bodyInit, it came from a Response constructor
568
+ // Convert it to a REAL stream now that we're in the step environment
569
+ if ('bodyInit' in value) {
570
+ const bodyInit = value.bodyInit;
571
+ // Use the native Response constructor to properly convert BodyInit to ReadableStream
572
+ const response = new global.Response(bodyInit);
573
+ return response.body;
574
+ }
575
+ const readable = new WorkflowServerReadableStream(value.name);
576
+ if (value.type === 'bytes') {
577
+ return readable;
578
+ }
579
+ else {
580
+ const transform = getDeserializeStream(getStepRevivers(global, ops));
581
+ ops.push(readable.pipeTo(transform.writable));
582
+ return transform.readable;
583
+ }
584
+ },
585
+ WritableStream: (value) => {
586
+ const serialize = getSerializeStream(getStepReducers(global, ops));
587
+ ops.push(serialize.readable.pipeTo(new WorkflowServerWritableStream(value.name)));
588
+ return serialize.writable;
589
+ },
590
+ };
591
+ }
592
+ /**
593
+ * Called from the `start()` function to serialize the workflow arguments
594
+ * into a format that can be saved to the database and then hydrated from
595
+ * within the workflow execution environment.
596
+ *
597
+ * @param value
598
+ * @param global
599
+ * @returns The dehydrated value, ready to be inserted into the database
600
+ */
601
+ export function dehydrateWorkflowArguments(value, ops, global = globalThis) {
602
+ try {
603
+ const str = devalue.stringify(value, getExternalReducers(global, ops));
604
+ return revive(str);
605
+ }
606
+ catch (error) {
607
+ throw new WorkflowRuntimeError(`Failed to serialize workflow arguments. Ensure you're passing serializable types (plain objects, arrays, primitives, Date, RegExp, Map, Set).`, { slug: 'serialization-failed', cause: error });
608
+ }
609
+ }
610
+ /**
611
+ * Called from workflow execution environment to hydrate the workflow
612
+ * arguments from the database at the start of workflow execution.
613
+ *
614
+ * @param value
615
+ * @param ops
616
+ * @param global
617
+ * @returns The hydrated value
618
+ */
619
+ export function hydrateWorkflowArguments(value, global = globalThis, extraRevivers = {}) {
620
+ const obj = devalue.unflatten(value, {
621
+ ...getWorkflowRevivers(global),
622
+ ...extraRevivers,
623
+ });
624
+ return obj;
625
+ }
626
+ /**
627
+ * Called at the end of a completed workflow execution to serialize the
628
+ * return value into a format that can be saved to the database.
629
+ *
630
+ * @param value
631
+ * @param global
632
+ * @returns The dehydrated value, ready to be inserted into the database
633
+ */
634
+ export function dehydrateWorkflowReturnValue(value, global = globalThis) {
635
+ try {
636
+ const str = devalue.stringify(value, getWorkflowReducers(global));
637
+ return revive(str);
638
+ }
639
+ catch (error) {
640
+ throw new WorkflowRuntimeError(`Failed to serialize workflow return value. Ensure you're returning serializable types (plain objects, arrays, primitives, Date, RegExp, Map, Set).`, { slug: 'serialization-failed', cause: error });
641
+ }
642
+ }
643
+ /**
644
+ * Called from the client side (i.e. the execution environment where
645
+ * the workflow run was initiated from) to hydrate the workflow
646
+ * return value of a completed workflow run.
647
+ *
648
+ * @param value
649
+ * @param global
650
+ * @returns The hydrated return value, ready to be consumed by the client
651
+ */
652
+ export function hydrateWorkflowReturnValue(value, ops, global = globalThis, extraRevivers = {}) {
653
+ const obj = devalue.unflatten(value, {
654
+ ...getExternalRevivers(global, ops),
655
+ ...extraRevivers,
656
+ });
657
+ return obj;
658
+ }
659
+ /**
660
+ * Called from the workflow handler when a step is being created.
661
+ * Dehydrates values from within the workflow execution environment
662
+ * into a format that can be saved to the database.
663
+ *
664
+ * @param value
665
+ * @param global
666
+ * @returns The dehydrated value, ready to be inserted into the database
667
+ */
668
+ export function dehydrateStepArguments(value, global) {
669
+ try {
670
+ const str = devalue.stringify(value, getWorkflowReducers(global));
671
+ return revive(str);
672
+ }
673
+ catch (error) {
674
+ throw new WorkflowRuntimeError(`Failed to serialize step arguments. Ensure you're passing serializable types (plain objects, arrays, primitives, Date, RegExp, Map, Set).`, { slug: 'serialization-failed', cause: error });
675
+ }
676
+ }
677
+ /**
678
+ * Called from the step handler to hydrate the arguments of a step
679
+ * from the database at the start of the step execution.
680
+ *
681
+ * @param value
682
+ * @param global
683
+ * @returns The hydrated value, ready to be consumed by the step user-code function
684
+ */
685
+ export function hydrateStepArguments(value, ops, global = globalThis, extraRevivers = {}) {
686
+ const obj = devalue.unflatten(value, {
687
+ ...getStepRevivers(global, ops),
688
+ ...extraRevivers,
689
+ });
690
+ return obj;
691
+ }
692
+ /**
693
+ * Called from the step handler when a step has completed.
694
+ * Dehydrates values from within the step execution environment
695
+ * into a format that can be saved to the database.
696
+ *
697
+ * @param value
698
+ * @param global
699
+ * @returns The dehydrated value, ready to be inserted into the database
700
+ */
701
+ export function dehydrateStepReturnValue(value, ops, global = globalThis) {
702
+ try {
703
+ const str = devalue.stringify(value, getStepReducers(global, ops));
704
+ return revive(str);
705
+ }
706
+ catch (error) {
707
+ throw new WorkflowRuntimeError(`Failed to serialize step return value. Ensure you're returning serializable types (plain objects, arrays, primitives, Date, RegExp, Map, Set).`, { slug: 'serialization-failed', cause: error });
708
+ }
709
+ }
710
+ /**
711
+ * Called from the workflow handler when replaying the event log of a `step_completed` event.
712
+ * Hydrates the return value of a step from the database.
713
+ *
714
+ * @param value
715
+ * @param global
716
+ * @returns The hydrated return value of a step, ready to be consumed by the workflow handler
717
+ */
718
+ export function hydrateStepReturnValue(value, global = globalThis, extraRevivers = {}) {
719
+ const obj = devalue.unflatten(value, {
720
+ ...getWorkflowRevivers(global),
721
+ ...extraRevivers,
722
+ });
723
+ return obj;
724
+ }
725
+ //# sourceMappingURL=serialization.js.map