@requence/service 0.7.1 → 0.8.2-edge.1149

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 (91) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +15 -0
  3. package/build/chunk-974rc2jy.js +200 -0
  4. package/build/chunk-974rc2jy.js.map +12 -0
  5. package/build/cli.js +17 -7
  6. package/build/cli.js.map +3 -3
  7. package/build/index.js +1416 -452
  8. package/build/index.js.map +29 -14
  9. package/build/types/helpers/src/index.d.ts +8 -2
  10. package/build/types/helpers/src/index.d.ts.map +1 -1
  11. package/build/types/helpers/src/jsonschema/validate.d.ts +1 -5
  12. package/build/types/helpers/src/jsonschema/validate.d.ts.map +1 -1
  13. package/build/types/helpers/src/jsonschema/zod.d.ts +11 -1
  14. package/build/types/helpers/src/jsonschema/zod.d.ts.map +1 -1
  15. package/build/types/helpers/src/protocol/NodeTree.d.ts +532 -148
  16. package/build/types/helpers/src/protocol/NodeTree.d.ts.map +1 -1
  17. package/build/types/helpers/src/protocol/clientProperties.d.ts +66 -0
  18. package/build/types/helpers/src/protocol/clientProperties.d.ts.map +1 -0
  19. package/build/types/helpers/src/protocol/command.d.ts +372 -142
  20. package/build/types/helpers/src/protocol/command.d.ts.map +1 -1
  21. package/build/types/helpers/src/protocol/configurationScript.d.ts +10 -0
  22. package/build/types/helpers/src/protocol/configurationScript.d.ts.map +1 -0
  23. package/build/types/helpers/src/protocol/helpers.d.ts.map +1 -1
  24. package/build/types/helpers/src/protocol/index.d.ts +5 -0
  25. package/build/types/helpers/src/protocol/index.d.ts.map +1 -1
  26. package/build/types/helpers/src/protocol/logicLanguages.d.ts +19 -0
  27. package/build/types/helpers/src/protocol/logicLanguages.d.ts.map +1 -0
  28. package/build/types/helpers/src/protocol/loopDetection.d.ts +23 -0
  29. package/build/types/helpers/src/protocol/loopDetection.d.ts.map +1 -0
  30. package/build/types/helpers/src/protocol/nodeType.d.ts +81 -27
  31. package/build/types/helpers/src/protocol/nodeType.d.ts.map +1 -1
  32. package/build/types/helpers/src/protocol/taskOptions.d.ts +4 -1
  33. package/build/types/helpers/src/protocol/taskOptions.d.ts.map +1 -1
  34. package/build/types/helpers/src/protocol/templateNodeTypes.d.ts +36 -20
  35. package/build/types/helpers/src/protocol/templateNodeTypes.d.ts.map +1 -1
  36. package/build/types/helpers/src/protocol/treeNodes.d.ts +508 -164
  37. package/build/types/helpers/src/protocol/treeNodes.d.ts.map +1 -1
  38. package/build/types/helpers/src/protocol/update.d.ts +40 -24
  39. package/build/types/helpers/src/protocol/update.d.ts.map +1 -1
  40. package/build/types/helpers/src/protocol/validateTreeStructure.d.ts +22 -0
  41. package/build/types/helpers/src/protocol/validateTreeStructure.d.ts.map +1 -0
  42. package/build/types/helpers/src/utils/amqpHeartbeat.d.ts +3 -0
  43. package/build/types/helpers/src/utils/amqpHeartbeat.d.ts.map +1 -0
  44. package/build/types/helpers/src/utils/amqpPublishRetry.d.ts +45 -0
  45. package/build/types/helpers/src/utils/amqpPublishRetry.d.ts.map +1 -0
  46. package/build/types/helpers/src/utils/claimCheckObject.d.ts +40 -0
  47. package/build/types/helpers/src/utils/claimCheckObject.d.ts.map +1 -0
  48. package/build/types/helpers/src/utils/debounce.d.ts.map +1 -1
  49. package/build/types/helpers/src/{files → utils}/fileObject.d.ts.map +1 -1
  50. package/build/types/helpers/src/{files → utils}/isValidMimeType.d.ts.map +1 -1
  51. package/build/types/helpers/src/utils/mapData.d.ts +1 -1
  52. package/build/types/helpers/src/utils/mapData.d.ts.map +1 -1
  53. package/build/types/helpers/src/{files → utils}/streamObject.d.ts.map +1 -1
  54. package/build/types/helpers/src/utils/variableRef.d.ts +19 -0
  55. package/build/types/helpers/src/utils/variableRef.d.ts.map +1 -0
  56. package/build/types/helpers/src/utils/variableScriptPatterns.d.ts +125 -0
  57. package/build/types/helpers/src/utils/variableScriptPatterns.d.ts.map +1 -0
  58. package/build/types/service/src/boundary.d.ts +87 -0
  59. package/build/types/service/src/boundary.d.ts.map +1 -0
  60. package/build/types/service/src/createAmqpConnection.d.ts +29 -4
  61. package/build/types/service/src/createAmqpConnection.d.ts.map +1 -1
  62. package/build/types/service/src/errors.d.ts +45 -0
  63. package/build/types/service/src/errors.d.ts.map +1 -1
  64. package/build/types/service/src/helpers.d.ts +59 -56
  65. package/build/types/service/src/helpers.d.ts.map +1 -1
  66. package/build/types/service/src/index.d.ts +25 -3
  67. package/build/types/service/src/index.d.ts.map +1 -1
  68. package/build/types/service/src/transformer.d.ts +16 -0
  69. package/build/types/service/src/transformer.d.ts.map +1 -0
  70. package/package.json +7 -3
  71. package/build/chunk-6w7td62p.js +0 -56
  72. package/build/chunk-6w7td62p.js.map +0 -10
  73. package/build/types/helpers/src/files/RequenceFile.d.ts +0 -40
  74. package/build/types/helpers/src/files/RequenceFile.d.ts.map +0 -1
  75. package/build/types/helpers/src/files/RequenceStream.d.ts +0 -32
  76. package/build/types/helpers/src/files/RequenceStream.d.ts.map +0 -1
  77. package/build/types/helpers/src/files/index.d.ts +0 -7
  78. package/build/types/helpers/src/files/index.d.ts.map +0 -1
  79. package/build/types/helpers/src/files/mapOutput.d.ts +0 -10
  80. package/build/types/helpers/src/files/mapOutput.d.ts.map +0 -1
  81. package/build/types/helpers/src/files/types.d.ts +0 -4
  82. package/build/types/helpers/src/files/types.d.ts.map +0 -1
  83. package/build/types/helpers/src/utils/createObjectProxy.d.ts +0 -2
  84. package/build/types/helpers/src/utils/createObjectProxy.d.ts.map +0 -1
  85. package/build/types/helpers/src/utils/resolveRequenceTypes.d.ts +0 -8
  86. package/build/types/helpers/src/utils/resolveRequenceTypes.d.ts.map +0 -1
  87. package/build/types/service/src/mapInput.d.ts +0 -2
  88. package/build/types/service/src/mapInput.d.ts.map +0 -1
  89. /package/build/types/helpers/src/{files → utils}/fileObject.d.ts +0 -0
  90. /package/build/types/helpers/src/{files → utils}/isValidMimeType.d.ts +0 -0
  91. /package/build/types/helpers/src/{files → utils}/streamObject.d.ts +0 -0
package/build/index.js CHANGED
@@ -1,7 +1,19 @@
1
1
  import {
2
+ CAPABILITY_HEADER_KEYS,
3
+ PayloadTooLargeError,
4
+ RequenceConnectionError,
5
+ RequenceUnreachableError,
6
+ UnsupportedCapabilityError,
7
+ assertReachable,
8
+ buildServiceClientProperties,
9
+ buildServiceIdentityHeaders,
2
10
  deobfuscate,
3
- obfuscate
4
- } from "./chunk-6w7td62p.js";
11
+ isUnreachableStatus,
12
+ obfuscate,
13
+ reachableFetch,
14
+ readRequiredCapabilities,
15
+ unsupportedCapabilities
16
+ } from "./chunk-974rc2jy.js";
5
17
 
6
18
  // src/index.ts
7
19
  import fs from "node:fs";
@@ -49,7 +61,8 @@ function mapData(data, visitors) {
49
61
  if (data2 === null) {
50
62
  return notUndefined(visitors.Null?.(data2, path), data2);
51
63
  }
52
- if (typeof Buffer !== "undefined" && Buffer.isBuffer(data2)) {
64
+ const runtimeBuffer = globalThis.Buffer;
65
+ if (runtimeBuffer?.isBuffer(data2)) {
53
66
  return notUndefined(visitors.Buffer?.(data2, path), data2);
54
67
  }
55
68
  if (typeof data2 === "string") {
@@ -65,7 +78,7 @@ function mapData(data, visitors) {
65
78
  return notUndefined(visitors.Function?.(data2, path), data2);
66
79
  }
67
80
  if (isRecord(data2)) {
68
- return resolve(visitors.Object?.(structuredClone(data2), path), (resolvedData) => {
81
+ return resolve(visitors.Object?.({ ...data2 }, path), (resolvedData) => {
69
82
  const nextData = resolvedData ?? data2;
70
83
  if (!isRecord(nextData)) {
71
84
  return nextData;
@@ -98,14 +111,66 @@ mapData.abort = () => {
98
111
  throw new AbortMapData;
99
112
  };
100
113
 
101
- // ../helpers/src/utils/requenceCallback.ts
114
+ // ../helpers/src/utils/fileObject.ts
102
115
  import { z as z2 } from "zod/v4";
103
- var callbackObjectSchema = z2.object({
104
- sourceId: z2.string(),
105
- outputName: z2.string().nullable(),
106
- propertyPath: z2.array(z2.union([z2.string(), z2.int()])),
107
- callbackId: z2.uuid(),
108
- __REQUENCE_type: z2.literal("RequenceCallback")
116
+ var fileObjectSchema = z2.object({
117
+ size: z2.int().positive(),
118
+ mime: z2.string(),
119
+ url: z2.url(),
120
+ __REQUENCE_type: z2.literal("RequenceFile")
121
+ });
122
+ function toFileObject(fileInfo) {
123
+ return {
124
+ ...fileInfo,
125
+ __REQUENCE_type: "RequenceFile"
126
+ };
127
+ }
128
+ function isFileObject(data) {
129
+ return fileObjectSchema.safeParse(data).success;
130
+ }
131
+
132
+ // ../helpers/src/utils/streamObject.ts
133
+ import { z as z3 } from "zod/v4";
134
+ var streamObjectSchema = z3.object({
135
+ mime: z3.string(),
136
+ url: z3.string().url(),
137
+ __REQUENCE_type: z3.literal("RequenceStream")
138
+ });
139
+ function isStreamObject(data) {
140
+ return streamObjectSchema.safeParse(data).success;
141
+ }
142
+ function toStreamObject(streamInfo) {
143
+ return {
144
+ ...streamInfo,
145
+ __REQUENCE_type: "RequenceStream"
146
+ };
147
+ }
148
+
149
+ // ../helpers/src/utils/claimCheckObject.ts
150
+ import { z as z4 } from "zod/v4";
151
+ var claimCheckObjectSchema = z4.object({
152
+ url: z4.url(),
153
+ size: z4.int().positive(),
154
+ __REQUENCE_type: z4.literal("ClaimCheck")
155
+ });
156
+ function toClaimCheckObject(info) {
157
+ return {
158
+ ...info,
159
+ __REQUENCE_type: "ClaimCheck"
160
+ };
161
+ }
162
+ function isClaimCheckObject(data) {
163
+ return claimCheckObjectSchema.safeParse(data).success;
164
+ }
165
+
166
+ // ../helpers/src/utils/requenceCallback.ts
167
+ import { z as z5 } from "zod/v4";
168
+ var callbackObjectSchema = z5.object({
169
+ sourceId: z5.string(),
170
+ outputName: z5.string().nullable(),
171
+ propertyPath: z5.array(z5.union([z5.string(), z5.int()])),
172
+ callbackId: z5.uuid(),
173
+ __REQUENCE_type: z5.literal("RequenceCallback")
109
174
  });
110
175
  function isCallbackObject(data) {
111
176
  return callbackObjectSchema.safeParse(data).success;
@@ -123,36 +188,270 @@ function createCallback(callback) {
123
188
  });
124
189
  }
125
190
 
126
- // ../helpers/src/files/fileObject.ts
127
- import { z as z3 } from "zod/v4";
128
- var fileObjectSchema = z3.object({
129
- size: z3.int().positive(),
130
- mime: z3.string(),
131
- url: z3.url(),
132
- __REQUENCE_type: z3.literal("RequenceFile")
191
+ // ../helpers/src/utils/amqpHeartbeat.ts
192
+ var DEFAULT_AMQP_HEARTBEAT_SECONDS = 30;
193
+
194
+ // ../helpers/src/msgpack/index.ts
195
+ import { Buffer as Buffer2 } from "node:buffer";
196
+ import { Packr, addExtension } from "msgpackr";
197
+ var MSGPACK_EXTENSION_IDS = {
198
+ referenceCounter: 1,
199
+ nodeTree: 2,
200
+ url: 3
201
+ };
202
+ var packingForWire = false;
203
+ addExtension({
204
+ Class: URL,
205
+ get type() {
206
+ return packingForWire ? undefined : MSGPACK_EXTENSION_IDS.url;
207
+ },
208
+ write: (v) => v.href,
209
+ read: (href) => new URL(href)
133
210
  });
134
- function toFileObject(fileInfo) {
211
+ var packr = new Packr({ structuredClone: true });
212
+ var wirePackr = new Packr({
213
+ useRecords: false,
214
+ structuredClone: false,
215
+ encodeUndefinedAsNil: true,
216
+ mapAsEmptyObject: true,
217
+ setAsEmptyObject: true,
218
+ int64AsType: "number"
219
+ });
220
+ function packWire(value) {
221
+ packingForWire = true;
222
+ try {
223
+ return wirePackr.pack(value);
224
+ } finally {
225
+ packingForWire = false;
226
+ }
227
+ }
228
+ function unpackWire(buffer) {
229
+ return wirePackr.unpack(buffer);
230
+ }
231
+ function wireByteLength(value) {
232
+ return wirePackr.pack(value).length;
233
+ }
234
+ var WIRE_CONTENT_TYPES = {
235
+ json: "application/json",
236
+ msgpack: "application/msgpack"
237
+ };
238
+ function wireCodecFromContentType(contentType) {
239
+ return contentType === WIRE_CONTENT_TYPES.msgpack ? "msgpack" : "json";
240
+ }
241
+ function encodeWireBody(value, codec) {
135
242
  return {
136
- ...fileInfo,
137
- __REQUENCE_type: "RequenceFile"
243
+ body: codec === "msgpack" ? packWire(value) : Buffer2.from(JSON.stringify(value ?? null)),
244
+ contentType: WIRE_CONTENT_TYPES[codec]
138
245
  };
139
246
  }
140
- function isFileObject(data) {
141
- return fileObjectSchema.safeParse(data).success;
247
+ function decodeWireBody(content, contentType) {
248
+ return wireCodecFromContentType(contentType) === "msgpack" ? unpackWire(content) : JSON.parse(Buffer2.from(content).toString());
249
+ }
250
+ function wireBodyByteLength(value, codec) {
251
+ if (codec === "msgpack") {
252
+ return wireByteLength(value);
253
+ }
254
+ const json = JSON.stringify(value);
255
+ return json === undefined ? 0 : Buffer2.byteLength(json);
256
+ }
257
+
258
+ // src/createAmqpConnection.ts
259
+ import { connect } from "amqp-connection-manager";
260
+ import { z as z6 } from "zod/v4";
261
+
262
+ // ../files/src/errors.ts
263
+ class RequenceStreamTruncatedError extends Error {
264
+ constructor(message = "stream truncated") {
265
+ super(message);
266
+ this.name = "RequenceStreamTruncatedError";
267
+ }
268
+ }
269
+
270
+ // ../files/src/streamFraming.ts
271
+ var STREAM_PROTOCOL_HEADER = "x-requence-stream-protocol";
272
+ var STREAM_PROTOCOL_FRAMED = "framed";
273
+ var DATA = 0;
274
+ var END = 1;
275
+ var TRUNCATED = 2;
276
+ var HEADER_BYTES = 5;
277
+ var END_FRAME = new Uint8Array([END, 0, 0, 0, 0]);
278
+ function createFrameDecoder() {
279
+ let buffer = new Uint8Array(0);
280
+ let terminal = false;
281
+ return new TransformStream({
282
+ transform(chunk, controller) {
283
+ if (terminal) {
284
+ if (chunk.byteLength > 0) {
285
+ throw new Error("stream protocol error: bytes after terminal frame");
286
+ }
287
+ return;
288
+ }
289
+ if (buffer.byteLength === 0) {
290
+ buffer = chunk;
291
+ } else {
292
+ const merged = new Uint8Array(buffer.byteLength + chunk.byteLength);
293
+ merged.set(buffer, 0);
294
+ merged.set(chunk, buffer.byteLength);
295
+ buffer = merged;
296
+ }
297
+ while (buffer.byteLength >= HEADER_BYTES) {
298
+ const type = buffer[0];
299
+ const length = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength).getUint32(1, false);
300
+ if (buffer.byteLength < HEADER_BYTES + length) {
301
+ break;
302
+ }
303
+ const payload = buffer.slice(HEADER_BYTES, HEADER_BYTES + length);
304
+ buffer = buffer.subarray(HEADER_BYTES + length);
305
+ switch (type) {
306
+ case DATA: {
307
+ if (payload.byteLength > 0) {
308
+ controller.enqueue(payload);
309
+ }
310
+ break;
311
+ }
312
+ case END: {
313
+ terminal = true;
314
+ if (buffer.byteLength > 0) {
315
+ throw new Error("stream protocol error: bytes after terminal frame");
316
+ }
317
+ controller.terminate();
318
+ return;
319
+ }
320
+ case TRUNCATED: {
321
+ terminal = true;
322
+ controller.error(new RequenceStreamTruncatedError(new TextDecoder().decode(payload) || undefined));
323
+ return;
324
+ }
325
+ default: {
326
+ throw new Error(`stream protocol error: unknown frame type ${type}`);
327
+ }
328
+ }
329
+ }
330
+ },
331
+ flush(controller) {
332
+ if (!terminal) {
333
+ controller.error(new RequenceStreamTruncatedError("connection closed before terminal frame"));
334
+ }
335
+ }
336
+ });
337
+ }
338
+
339
+ // ../files/src/remoteBody.ts
340
+ function remoteBody(url, options = {}) {
341
+ const externalSignal = options.signal;
342
+ const timeoutMs = options.stallTimeoutMs && options.stallTimeoutMs > 0 ? options.stallTimeoutMs : 0;
343
+ const controller = new AbortController;
344
+ let reader = null;
345
+ let timer;
346
+ let onExternalAbort;
347
+ const clearTimer = () => {
348
+ if (timer !== undefined) {
349
+ clearTimeout(timer);
350
+ timer = undefined;
351
+ }
352
+ };
353
+ const cleanup = () => {
354
+ clearTimer();
355
+ if (externalSignal && onExternalAbort) {
356
+ externalSignal.removeEventListener("abort", onExternalAbort);
357
+ }
358
+ };
359
+ if (externalSignal) {
360
+ if (externalSignal.aborted) {
361
+ controller.abort(externalSignal.reason);
362
+ } else {
363
+ onExternalAbort = () => controller.abort(externalSignal.reason);
364
+ externalSignal.addEventListener("abort", onExternalAbort, {
365
+ once: true
366
+ });
367
+ }
368
+ }
369
+ const armTimer = () => {
370
+ if (timeoutMs <= 0) {
371
+ return;
372
+ }
373
+ clearTimer();
374
+ timer = setTimeout(() => {
375
+ controller.abort(new Error(`remote read stalled: no data for ${timeoutMs}ms`));
376
+ }, timeoutMs);
377
+ };
378
+ return new ReadableStream({
379
+ async start(streamController) {
380
+ let response;
381
+ try {
382
+ response = await fetch(url, {
383
+ signal: controller.signal,
384
+ headers: options.framed ? { [STREAM_PROTOCOL_HEADER]: STREAM_PROTOCOL_FRAMED } : undefined
385
+ });
386
+ } catch (error) {
387
+ cleanup();
388
+ streamController.error(error);
389
+ return;
390
+ }
391
+ if (!response.ok) {
392
+ await response.body?.cancel();
393
+ cleanup();
394
+ streamController.error(new Error(`remote read failed: ${response.status} ${response.statusText}`));
395
+ return;
396
+ }
397
+ if (!response.body) {
398
+ cleanup();
399
+ streamController.error(new Error("remote read response has no body"));
400
+ return;
401
+ }
402
+ const framed = options.framed && response.headers.get(STREAM_PROTOCOL_HEADER) === STREAM_PROTOCOL_FRAMED;
403
+ reader = framed ? response.body.pipeThrough(createFrameDecoder()).getReader() : response.body.getReader();
404
+ },
405
+ async pull(streamController) {
406
+ if (!reader) {
407
+ return;
408
+ }
409
+ armTimer();
410
+ try {
411
+ const { done, value } = await reader.read();
412
+ clearTimer();
413
+ if (done) {
414
+ cleanup();
415
+ streamController.close();
416
+ return;
417
+ }
418
+ streamController.enqueue(value);
419
+ } catch (error) {
420
+ clearTimer();
421
+ cleanup();
422
+ streamController.error(error);
423
+ }
424
+ },
425
+ async cancel(reason) {
426
+ cleanup();
427
+ controller.abort(reason);
428
+ await reader?.cancel(reason);
429
+ }
430
+ });
431
+ }
432
+
433
+ // ../files/src/RequenceFile.ts
434
+ function stallTimeoutMs() {
435
+ const raw = typeof process !== "undefined" ? Number(process.env?.REQUENCE_FILE_STALL_TIMEOUT_MS) : Number.NaN;
436
+ return Number.isFinite(raw) && raw > 0 ? raw : 0;
142
437
  }
143
438
 
144
- // ../helpers/src/files/RequenceFile.ts
145
439
  class RequenceFile {
146
440
  #data;
147
441
  #file = null;
442
+ #signal;
148
443
  constructor(blobParts, options) {
149
444
  this.#data = new Blob(blobParts, options);
150
445
  }
151
- static fromFileObject(file) {
446
+ static fromFileObject(file, signal) {
152
447
  const instance = new this([], { type: "x/x" });
153
448
  instance.#file = file;
449
+ instance.#signal = signal;
154
450
  return instance;
155
451
  }
452
+ static canHandle(value) {
453
+ return value instanceof RequenceFile || value instanceof Blob;
454
+ }
156
455
  get fileObject() {
157
456
  return this.#file;
158
457
  }
@@ -168,39 +467,74 @@ class RequenceFile {
168
467
  get subMimeType() {
169
468
  return this.mimeType.split("/")[1];
170
469
  }
470
+ stream() {
471
+ if (!this.#file) {
472
+ return this.#data.stream();
473
+ }
474
+ return remoteBody(this.#file.url, {
475
+ signal: this.#signal,
476
+ stallTimeoutMs: stallTimeoutMs()
477
+ });
478
+ }
479
+ async#bytes() {
480
+ const reader = this.stream().getReader();
481
+ const chunks = [];
482
+ let total = 0;
483
+ for (;; ) {
484
+ const { done, value } = await reader.read();
485
+ if (done) {
486
+ break;
487
+ }
488
+ chunks.push(value);
489
+ total += value.byteLength;
490
+ }
491
+ const out = new Uint8Array(total);
492
+ let offset = 0;
493
+ for (const chunk of chunks) {
494
+ out.set(chunk, offset);
495
+ offset += chunk.byteLength;
496
+ }
497
+ return out;
498
+ }
171
499
  async text() {
172
500
  if (this.#file) {
173
- return fetch(this.#file.url).then((response) => response.text());
501
+ return new TextDecoder().decode(await this.#bytes());
174
502
  }
175
503
  return this.#data.text();
176
504
  }
177
505
  async json() {
178
506
  if (this.#file) {
179
- return fetch(this.#file.url).then((response) => response.json());
507
+ const text = await this.text();
508
+ try {
509
+ return JSON.parse(text);
510
+ } catch (error) {
511
+ throw new Error(`RequenceFile JSON parse failed for ${this.#file.url}`, { cause: error });
512
+ }
180
513
  }
181
514
  return JSON.parse(await this.text());
182
515
  }
183
516
  async blob() {
184
517
  if (this.#file) {
185
- return fetch(this.#file.url).then((response) => response.blob());
518
+ return new Blob([await this.#bytes()], { type: this.#file.mime });
186
519
  }
187
520
  return this.#data;
188
521
  }
189
522
  async arrayBuffer() {
190
523
  if (this.#file) {
191
- return fetch(this.#file.url).then((response) => response.arrayBuffer());
524
+ return (await this.#bytes()).buffer;
192
525
  }
193
526
  return this.#data.arrayBuffer();
194
527
  }
195
528
  toString() {
196
529
  return `RequenceFile<${this.mimeType}>`;
197
530
  }
198
- toJSON() {
199
- return `RequenceFile<${this.mimeType}>`;
200
- }
531
+ }
532
+ // ../files/src/RequenceStream.ts
533
+ function stallTimeoutMs2() {
534
+ const raw = typeof process !== "undefined" ? Number(process.env?.REQUENCE_STREAM_STALL_TIMEOUT_MS) : Number.NaN;
535
+ return Number.isFinite(raw) && raw > 0 ? raw : 0;
201
536
  }
202
537
 
203
- // ../helpers/src/files/RequenceStream.ts
204
538
  class RequenceStream {
205
539
  #data;
206
540
  #stream = null;
@@ -209,13 +543,17 @@ class RequenceStream {
209
543
  this.#data = stream;
210
544
  this.#options = options;
211
545
  }
212
- static fromStreamObject(stream) {
546
+ static fromStreamObject(stream, signal) {
213
547
  const instance = new this(null, {
214
- type: "x/x"
548
+ type: "x/x",
549
+ signal
215
550
  });
216
551
  instance.#stream = stream;
217
552
  return instance;
218
553
  }
554
+ static canHandle(value) {
555
+ return value instanceof RequenceStream || value instanceof Response;
556
+ }
219
557
  get streamObject() {
220
558
  return this.#stream;
221
559
  }
@@ -229,12 +567,14 @@ class RequenceStream {
229
567
  return this.mimeType.split("/")[1];
230
568
  }
231
569
  stream() {
232
- if (this.#stream) {
233
- const { readable, writable } = new TransformStream;
234
- fetch(this.#stream.url).then((response) => response.body?.pipeTo(writable));
235
- return readable;
570
+ if (!this.#stream) {
571
+ return this.#data;
236
572
  }
237
- return this.#data;
573
+ return remoteBody(this.#stream.url, {
574
+ signal: this.#options.signal,
575
+ stallTimeoutMs: stallTimeoutMs2(),
576
+ framed: true
577
+ });
238
578
  }
239
579
  asyncIterable() {
240
580
  const reader = this.stream().getReader();
@@ -248,6 +588,11 @@ class RequenceStream {
248
588
  reader.cancel();
249
589
  reader.releaseLock();
250
590
  return { done: true, value: null };
591
+ },
592
+ async throw() {
593
+ reader.cancel();
594
+ reader.releaseLock();
595
+ return { done: true, value: null };
251
596
  }
252
597
  };
253
598
  }
@@ -256,163 +601,564 @@ class RequenceStream {
256
601
  toString() {
257
602
  return `RequenceStream<${this.mimeType}>`;
258
603
  }
259
- toJSON() {
260
- return `RequenceStream<${this.mimeType}>`;
261
- }
262
604
  }
263
-
264
- // ../helpers/src/files/streamObject.ts
265
- import { z as z4 } from "zod/v4";
266
- var streamObjectSchema = z4.object({
267
- mime: z4.string(),
268
- url: z4.string().url(),
269
- __REQUENCE_type: z4.literal("RequenceStream")
270
- });
271
- function isStreamObject(data) {
272
- return streamObjectSchema.safeParse(data).success;
273
- }
274
- function toStreamObject(streamInfo) {
275
- return {
276
- ...streamInfo,
277
- __REQUENCE_type: "RequenceStream"
278
- };
605
+ // ../files/src/handlers/transport.ts
606
+ async function assertOk(res, url, phase) {
607
+ if (res.ok) {
608
+ return;
609
+ }
610
+ const detail = await res.text().catch(() => "");
611
+ throw new Error(`${phase} failed: ${res.status} ${res.statusText} (${url})${detail ? ` — ${detail}` : ""}`);
279
612
  }
280
613
 
281
- // ../helpers/src/files/mapOutput.ts
282
- async function upload(uploadUrl, body, signal, contentType) {
283
- const uploadResponse = await fetch(uploadUrl, {
614
+ // ../files/src/handlers/fileHandler.ts
615
+ async function upload(ctx, uploadUrl, body, contentType, maxFileSize) {
616
+ const uploadResponse = await ctx.fetch(uploadUrl, {
284
617
  method: "POST",
285
- signal,
286
- headers: contentType ? {
287
- "Content-Type": contentType
288
- } : {},
618
+ signal: ctx.signal,
619
+ headers: {
620
+ ...contentType ? { "Content-Type": contentType } : {},
621
+ ...maxFileSize !== undefined ? { "file-size": String(maxFileSize) } : {}
622
+ },
289
623
  body
290
624
  });
625
+ await assertOk(uploadResponse, uploadUrl, "upload");
291
626
  const data = await uploadResponse.json();
292
- if (!data || typeof data !== "object") {
293
- throw new Error("invalid upload response");
627
+ if (!data || typeof data !== "object" || typeof data.url !== "string" || !data.url || typeof data.mime !== "string" || typeof data.size !== "number") {
628
+ throw new Error(`malformed upload response (${uploadUrl})`);
294
629
  }
295
630
  return toFileObject(data);
296
631
  }
297
- async function stream(streamUrl, stream2, signal, contentType) {
298
- const [testStream, dataStream] = stream2.tee();
299
- const reader = testStream.getReader();
300
- const dataPromise = reader.read().then(({ done: done2 }) => {
301
- if (done2) {
302
- throw new Error("No streaming date received");
632
+ function createRequenceFileHandler() {
633
+ return {
634
+ tag: "RequenceFile",
635
+ canHandle: (value) => RequenceFile.canHandle(value),
636
+ async serialize(value, ctx) {
637
+ if (value instanceof RequenceFile && value.fileObject) {
638
+ return value.fileObject;
639
+ }
640
+ if (!ctx.uploadUrl) {
641
+ ctx.onOffloadSkip?.();
642
+ return null;
643
+ }
644
+ try {
645
+ if (value instanceof RequenceFile) {
646
+ return await upload(ctx, ctx.uploadUrl, await value.blob(), value.mimeType, ctx.maxFileSize);
647
+ }
648
+ return await upload(ctx, ctx.uploadUrl, value, value.type, ctx.maxFileSize);
649
+ } catch (error) {
650
+ if (!(error instanceof Error)) {
651
+ throw error;
652
+ }
653
+ if (ctx.onOffloadFail) {
654
+ ctx.onOffloadFail(error);
655
+ return null;
656
+ }
657
+ throw error;
658
+ }
659
+ },
660
+ isReference: (value) => isFileObject(value),
661
+ deserialize(ref, ctx) {
662
+ return RequenceFile.fromFileObject(ref, ctx.signal);
303
663
  }
304
- reader.cancel();
305
- });
306
- const streamResponse = await fetch(streamUrl, {
664
+ };
665
+ }
666
+ // ../files/src/withRequenceStreams.ts
667
+ import { AsyncLocalStorage } from "node:async_hooks";
668
+ var pendingUploads = new AsyncLocalStorage;
669
+ async function withRequenceStreams(fn) {
670
+ const uploads = [];
671
+ const value = await pendingUploads.run(uploads, fn);
672
+ return { value, done: Promise.all(uploads).then(() => {
673
+ return;
674
+ }) };
675
+ }
676
+ function registerPendingUpload(work) {
677
+ const store = pendingUploads.getStore();
678
+ if (!store) {
679
+ return false;
680
+ }
681
+ store.push(work);
682
+ return true;
683
+ }
684
+
685
+ // ../files/src/handlers/streamHandler.ts
686
+ async function registerAndUpload(ctx, streamUrl, stream, contentType, maxFileSize) {
687
+ const [testStream, dataStream] = stream.tee();
688
+ const reader = testStream.getReader();
689
+ const { done: isEmpty } = await reader.read();
690
+ reader.cancel();
691
+ const streamResponse = await ctx.fetch(streamUrl, {
307
692
  method: "POST",
308
- signal,
309
- headers: contentType ? { "Content-Type": contentType } : {}
693
+ signal: ctx.signal,
694
+ headers: {
695
+ ...contentType ? { "Content-Type": contentType } : {},
696
+ ...maxFileSize !== undefined ? { "file-size": String(maxFileSize) } : {}
697
+ }
310
698
  });
699
+ await assertOk(streamResponse, streamUrl, "stream registration");
311
700
  const data = await streamResponse.json();
312
- if (!data || typeof data !== "object") {
313
- throw new Error("invalid stream response");
701
+ if (!isStreamObject(toStreamObject(data))) {
702
+ throw new Error(`malformed stream registration response (${streamUrl})`);
314
703
  }
315
704
  const { mime, url } = data;
316
- await dataPromise;
317
- const done = fetch(url, {
318
- method: "POST",
319
- signal,
320
- duplex: "half",
321
- body: dataStream
322
- });
323
- return [toStreamObject({ mime, url }), done];
324
- }
325
- async function mapOutput(params) {
326
- const streamPromises = [];
327
- const mapped = await mapData(params.value, {
328
- async Object(obj) {
329
- if (obj instanceof Blob || obj instanceof RequenceFile) {
330
- if (obj instanceof RequenceFile && obj.fileObject) {
331
- return obj.fileObject;
705
+ if (isEmpty) {
706
+ const emptyResponse = await ctx.fetch(url, {
707
+ method: "POST",
708
+ signal: ctx.signal,
709
+ headers: contentType ? { "Content-Type": contentType } : {},
710
+ body: new Uint8Array(0)
711
+ });
712
+ await assertOk(emptyResponse, url, "stream body upload");
713
+ await emptyResponse.body?.cancel();
714
+ return { ref: toStreamObject({ mime, url }) };
715
+ }
716
+ const bodyUpload = (async () => {
717
+ const bodyResponse = await ctx.fetch(url, {
718
+ method: "POST",
719
+ signal: ctx.signal,
720
+ duplex: "half",
721
+ body: dataStream
722
+ });
723
+ await assertOk(bodyResponse, url, "stream body upload");
724
+ await bodyResponse.body?.cancel();
725
+ })();
726
+ return { ref: toStreamObject({ mime, url }), bodyUpload };
727
+ }
728
+ function createRequenceStreamHandler() {
729
+ return {
730
+ tag: "RequenceStream",
731
+ canHandle: (value) => RequenceStream.canHandle(value),
732
+ async serialize(value, ctx) {
733
+ if (value instanceof RequenceStream && value.streamObject) {
734
+ return value.streamObject;
735
+ }
736
+ if (!ctx.streamUrl) {
737
+ ctx.onOffloadSkip?.();
738
+ return null;
739
+ }
740
+ const body = value instanceof Response ? value.body ?? new ReadableStream({
741
+ start(controller) {
742
+ controller.close();
332
743
  }
333
- if (params.options.uploadUrl) {
334
- try {
335
- if (obj instanceof Blob) {
336
- return await upload(params.options.uploadUrl, obj, params.signal, obj.type);
337
- }
338
- if (obj instanceof RequenceFile) {
339
- return await upload(params.options.uploadUrl, await obj.blob(), params.signal, obj.mimeType);
340
- }
341
- } catch (error) {
342
- if (!(error instanceof Error)) {
343
- throw error;
344
- }
345
- params.onFail?.(error);
346
- return null;
347
- }
348
- } else {
349
- params.onSkip?.();
350
- return null;
744
+ }) : value.stream();
745
+ const contentType = value instanceof Response ? value.headers.get("Content-Type") : value.mimeType;
746
+ try {
747
+ const { ref, bodyUpload } = await registerAndUpload(ctx, ctx.streamUrl, body, contentType, ctx.maxFileSize);
748
+ if (bodyUpload && !registerPendingUpload(bodyUpload)) {
749
+ await bodyUpload;
351
750
  }
352
- }
353
- if (obj instanceof Response || obj instanceof RequenceStream) {
354
- if (obj instanceof RequenceStream && obj.streamObject) {
355
- return obj.streamObject;
751
+ return ref;
752
+ } catch (error) {
753
+ if (!(error instanceof Error)) {
754
+ throw error;
356
755
  }
357
- if (params.options.streamUrl) {
358
- try {
359
- if (obj instanceof Response && obj.body) {
360
- const [streamObject, streamPromise] = await stream(params.options.streamUrl, obj.body, params.signal, obj.headers.get("Content-Type"));
361
- streamPromises.push(streamPromise);
362
- return streamObject;
363
- }
364
- if (obj instanceof RequenceStream) {
365
- const [streamObject, streamPromise] = await stream(params.options.streamUrl, obj.stream(), params.signal, obj.mimeType);
366
- streamPromises.push(streamPromise);
367
- return streamObject;
368
- }
369
- } catch (error) {
370
- if (!(error instanceof Error)) {
371
- throw error;
372
- }
373
- params.onFail?.(error);
374
- return null;
375
- }
376
- } else {
377
- params.onSkip?.();
756
+ if (ctx.onOffloadFail) {
757
+ ctx.onOffloadFail(error);
378
758
  return null;
379
759
  }
760
+ throw error;
380
761
  }
762
+ },
763
+ isReference: (value) => isStreamObject(value),
764
+ deserialize(ref, ctx) {
765
+ return RequenceStream.fromStreamObject(ref, ctx.signal);
381
766
  }
767
+ };
768
+ }
769
+ // ../files/src/handlers/claimCheckHandler.ts
770
+ import { Buffer as Buffer3 } from "node:buffer";
771
+ var DEFAULT_MAX_PAYLOAD_SIZE = 4 * 1024 * 1024;
772
+ function isRecord2(value) {
773
+ return typeof value === "object" && value !== null && !Array.isArray(value);
774
+ }
775
+ async function offload(ctx, uploadUrl, json) {
776
+ const response = await ctx.fetch(uploadUrl, {
777
+ method: "POST",
778
+ signal: ctx.signal,
779
+ headers: { "Content-Type": "application/json" },
780
+ body: json
382
781
  });
383
- Promise.allSettled(streamPromises).then(() => params.onDone?.());
384
- return mapped;
782
+ await assertOk(response, uploadUrl, "claim-check offload");
783
+ const data = await response.json();
784
+ if (!data || typeof data !== "object" || typeof data.url !== "string" || !data.url || typeof data.size !== "number") {
785
+ throw new Error(`malformed claim-check offload response (${uploadUrl})`);
786
+ }
787
+ return toClaimCheckObject({ url: data.url, size: data.size });
385
788
  }
386
-
387
- // ../helpers/src/utils/resolveRequenceTypes.ts
388
- function resolveRequenceTypes(data, onCallback) {
789
+ function jsonByteLength(value) {
790
+ const json = JSON.stringify(value);
791
+ return json === undefined ? 0 : Buffer3.byteLength(json);
792
+ }
793
+ function createMessageHandler() {
794
+ return {
795
+ async wrapOutbound(body, ctx) {
796
+ const maxBytes = ctx.maxPayloadSize ?? DEFAULT_MAX_PAYLOAD_SIZE;
797
+ if (maxBytes <= 0 || body === undefined) {
798
+ return body;
799
+ }
800
+ const measure = ctx.measure ?? jsonByteLength;
801
+ if (measure(body) <= maxBytes) {
802
+ return body;
803
+ }
804
+ const { uploadUrl } = ctx;
805
+ if (!uploadUrl) {
806
+ ctx.onOffloadSkip?.();
807
+ return body;
808
+ }
809
+ if (!isRecord2(body)) {
810
+ const json = JSON.stringify(body);
811
+ if (json === undefined) {
812
+ return body;
813
+ }
814
+ return offload(ctx, uploadUrl, json);
815
+ }
816
+ const entries = Object.entries(body).map(([key, value]) => ({
817
+ key,
818
+ valueJson: JSON.stringify(value),
819
+ size: measure(value)
820
+ })).sort((a, b) => b.size - a.size);
821
+ const wrapped = { ...body };
822
+ let total = measure(body);
823
+ for (const entry of entries) {
824
+ if (total <= maxBytes || entry.valueJson === undefined || entry.size <= 256) {
825
+ break;
826
+ }
827
+ const ref = await offload(ctx, uploadUrl, entry.valueJson);
828
+ wrapped[entry.key] = ref;
829
+ total += measure(ref) - entry.size;
830
+ }
831
+ return wrapped;
832
+ }
833
+ };
834
+ }
835
+ function createValueHandler() {
836
+ return {
837
+ tag: "ClaimCheck",
838
+ canHandle: () => false,
839
+ serialize() {
840
+ throw new Error("ClaimCheck egress is the bundled MessageHandler (wrapOutbound); it never reaches the value walk");
841
+ },
842
+ isReference: (value) => isClaimCheckObject(value),
843
+ async deserialize(ref, ctx) {
844
+ const response = await ctx.fetch(ref.url, { signal: ctx.signal });
845
+ await assertOk(response, ref.url, "claim-check fetch");
846
+ const text = await response.text();
847
+ try {
848
+ return JSON.parse(text);
849
+ } catch {
850
+ throw new Error(`malformed claim-check payload (${ref.url})`);
851
+ }
852
+ }
853
+ };
854
+ }
855
+ function createClaimCheckHandler() {
856
+ return {
857
+ valueHandler: createValueHandler(),
858
+ messageHandler: createMessageHandler()
859
+ };
860
+ }
861
+ // ../files/src/sanitizeLogData.ts
862
+ function sanitizeLogData(data) {
389
863
  return mapData(data, {
864
+ Function: () => "[Function]",
865
+ Symbol: (sym) => String(sym),
390
866
  Object(obj) {
391
- if (isFileObject(obj)) {
392
- return RequenceFile.fromFileObject(obj);
867
+ if (RequenceFile.canHandle(obj) || RequenceStream.canHandle(obj)) {
868
+ return;
393
869
  }
394
- if (isStreamObject(obj)) {
395
- return RequenceStream.fromStreamObject(obj);
870
+ const proto = Object.getPrototypeOf(obj);
871
+ if (proto === null || proto === Object.prototype) {
872
+ return;
396
873
  }
397
- if (isCallbackObject(obj)) {
398
- return (arg) => {
399
- onCallback?.({ ...obj, arg });
400
- };
874
+ if (typeof obj.toJSON === "function") {
875
+ return;
401
876
  }
877
+ return String(obj);
402
878
  }
403
879
  });
404
880
  }
881
+ // ../callbacks/src/handler.ts
882
+ function createRequenceCallbackHandler() {
883
+ return {
884
+ tag: "RequenceCallback",
885
+ canHandle: (value) => typeof value === "function",
886
+ serialize(callback, ctx, path) {
887
+ if (!ctx.onCallback) {
888
+ throw new Error(`functions are not serializable on this boundary (no ctx.onCallback) at path "${path.join(".")}"`);
889
+ }
890
+ return {
891
+ ...ctx.onCallback(callback),
892
+ outputName: ctx.outputName ?? null,
893
+ propertyPath: [...path],
894
+ __REQUENCE_type: "RequenceCallback"
895
+ };
896
+ },
897
+ isReference: (value) => isCallbackObject(value),
898
+ deserialize(ref, ctx) {
899
+ return (arg) => {
900
+ ctx.onCallbackInvoke?.({ ...ref, arg });
901
+ };
902
+ }
903
+ };
904
+ }
905
+ // ../transformer/src/errors.ts
906
+ function formatPath(path) {
907
+ if (path.length === 0) {
908
+ return "<root>";
909
+ }
910
+ let out = "";
911
+ for (const segment of path) {
912
+ out += typeof segment === "number" ? `[${segment}]` : out ? `.${segment}` : segment;
913
+ }
914
+ return out;
915
+ }
405
916
 
406
- // src/createAmqpConnection.ts
407
- import { connect } from "amqp-connection-manager";
408
- import { z as z5 } from "zod/v4";
917
+ class TransformError extends Error {
918
+ path;
919
+ detail;
920
+ constructor(detail, path) {
921
+ super(`${detail} at ${formatPath(path)}`);
922
+ this.name = "TransformError";
923
+ this.path = path;
924
+ this.detail = detail;
925
+ }
926
+ }
927
+
928
+ // ../transformer/src/guards.ts
929
+ var REFERENCE_TAG_KEY = "__REQUENCE_type";
930
+ function isPlainObject(value) {
931
+ if (value === null || typeof value !== "object") {
932
+ return false;
933
+ }
934
+ const proto = Object.getPrototypeOf(value);
935
+ return proto === null || proto === Object.prototype;
936
+ }
937
+ function isComplexValue(value) {
938
+ if (value === null) {
939
+ return false;
940
+ }
941
+ const type = typeof value;
942
+ if (type === "object") {
943
+ return !Array.isArray(value) && !isPlainObject(value);
944
+ }
945
+ return type === "function" || type === "symbol" || type === "bigint";
946
+ }
947
+ function hasReferenceTag(value) {
948
+ return isPlainObject(value) && REFERENCE_TAG_KEY in value;
949
+ }
950
+
951
+ // ../transformer/src/walk.ts
952
+ var recurse = { kind: "recurse" };
953
+ var replaceWith = (value) => ({
954
+ kind: "replace",
955
+ value
956
+ });
957
+ var MAX_REPLACE_DEPTH = 100;
958
+ async function walk(root, visit) {
959
+ const go = async (value, path, replaceDepth) => {
960
+ let node = value;
961
+ if (Array.isArray(node)) {
962
+ node = await Promise.all(node.map((item, index) => go(item, [...path, index], 0)));
963
+ } else if (isPlainObject(node)) {
964
+ const entries = await Promise.all(Object.entries(node).map(async ([key, item]) => [key, await go(item, [...path, key], 0)]));
965
+ node = Object.fromEntries(entries);
966
+ }
967
+ const verdict = await visit(node, path);
968
+ if (verdict.kind === "replace") {
969
+ if (replaceDepth >= MAX_REPLACE_DEPTH) {
970
+ throw new TransformError("transform did not reach a fixpoint (a handler keeps producing handleable output)", path);
971
+ }
972
+ return go(verdict.value, path, replaceDepth + 1);
973
+ }
974
+ return node;
975
+ };
976
+ return go(root, [], 0);
977
+ }
978
+
979
+ // ../transformer/src/transform.ts
980
+ function createTransformer() {
981
+ return build([], []);
982
+ }
983
+ function build(valueHandlers, messageHandlers) {
984
+ const transformer = {
985
+ withHandler(handler) {
986
+ const bundle = "tag" in handler ? { valueHandler: handler } : handler;
987
+ if (!bundle.valueHandler && !bundle.messageHandler) {
988
+ throw new Error("withHandler: bundle provides neither a valueHandler nor a messageHandler");
989
+ }
990
+ if (bundle.valueHandler) {
991
+ const { tag } = bundle.valueHandler;
992
+ if (valueHandlers.some((existing) => existing.tag === tag)) {
993
+ throw new Error(`withHandler: a ValueHandler with tag "${tag}" is already composed`);
994
+ }
995
+ }
996
+ return build(bundle.valueHandler ? [...valueHandlers, bundle.valueHandler] : valueHandlers, bundle.messageHandler ? [...messageHandlers, bundle.messageHandler] : messageHandlers);
997
+ },
998
+ async outbound(value, ctx) {
999
+ const seen = new Map;
1000
+ const visit = (node, path) => {
1001
+ if (!isComplexValue(node)) {
1002
+ return recurse;
1003
+ }
1004
+ const handler = valueHandlers.find((candidate) => candidate.canHandle(node));
1005
+ if (!handler) {
1006
+ const withToJSON = node;
1007
+ if (typeof node === "object" && typeof withToJSON.toJSON === "function") {
1008
+ return replaceWith(withToJSON.toJSON());
1009
+ }
1010
+ const label = node?.constructor?.name ?? (typeof node === "function" ? "function" : typeof node);
1011
+ throw new TransformError(`no composed ValueHandler for complex value of type ${label}`, path);
1012
+ }
1013
+ if (typeof node === "object" && node !== null) {
1014
+ const cached = seen.get(node);
1015
+ if (cached) {
1016
+ return cached.then(replaceWith);
1017
+ }
1018
+ const pending = Promise.resolve(handler.serialize(node, ctx, path));
1019
+ seen.set(node, pending);
1020
+ return pending.then(replaceWith);
1021
+ }
1022
+ return Promise.resolve(handler.serialize(node, ctx, path)).then(replaceWith);
1023
+ };
1024
+ const valueTransformed = await walk(value, visit);
1025
+ let body = valueTransformed;
1026
+ for (const [index, handler] of messageHandlers.entries()) {
1027
+ const wrapped = await handler.wrapOutbound(body, ctx);
1028
+ assertTopLevelKeysPreserved(body, wrapped, index);
1029
+ body = wrapped;
1030
+ }
1031
+ return body;
1032
+ },
1033
+ async inbound(value, ctx) {
1034
+ const visit = (node, path) => {
1035
+ if (!isPlainObject(node)) {
1036
+ return recurse;
1037
+ }
1038
+ const handler = valueHandlers.find((candidate) => candidate.isReference(node));
1039
+ if (handler) {
1040
+ if (handler.passthrough) {
1041
+ return recurse;
1042
+ }
1043
+ return Promise.resolve(handler.deserialize(node, ctx, path)).then(replaceWith);
1044
+ }
1045
+ if (hasReferenceTag(node)) {
1046
+ const tag = node.__REQUENCE_type;
1047
+ throw new TransformError(`no composed ValueHandler owns reference tag ${JSON.stringify(tag)}`, path);
1048
+ }
1049
+ return recurse;
1050
+ };
1051
+ return walk(value, visit);
1052
+ }
1053
+ };
1054
+ return transformer;
1055
+ }
1056
+ function assertTopLevelKeysPreserved(body, wrapped, handlerIndex) {
1057
+ if (!isPlainObject(body)) {
1058
+ return;
1059
+ }
1060
+ const label = `MessageHandler #${handlerIndex}`;
1061
+ if (!isPlainObject(wrapped)) {
1062
+ throw new TransformError(`${label} replaced a record body wholesale — wrapOutbound must preserve a record's top-level keys`, []);
1063
+ }
1064
+ const before = Object.keys(body);
1065
+ const after = new Set(Object.keys(wrapped));
1066
+ const removed = before.filter((key) => !after.has(key));
1067
+ const added = [...after].filter((key) => !before.includes(key));
1068
+ if (removed.length > 0 || added.length > 0) {
1069
+ throw new TransformError(`${label} changed a record body's top-level keys (removed: [${removed.join(", ")}], added: [${added.join(", ")}]) — wrapOutbound must preserve them`, []);
1070
+ }
1071
+ }
1072
+ // src/transformer.ts
1073
+ var transformer = createTransformer().withHandler(createRequenceFileHandler()).withHandler(createRequenceStreamHandler()).withHandler(createRequenceCallbackHandler()).withHandler(createClaimCheckHandler());
1074
+ var passthroughHandler = (handler) => ({
1075
+ tag: handler.tag,
1076
+ passthrough: true,
1077
+ canHandle: () => false,
1078
+ serialize() {
1079
+ throw new Error(`passthrough handler "${handler.tag}" is inbound-only`);
1080
+ },
1081
+ isReference: (value) => handler.isReference(value),
1082
+ deserialize(ref) {
1083
+ return ref;
1084
+ }
1085
+ });
1086
+ var passthroughInboundTransformer = createTransformer().withHandler(passthroughHandler(createRequenceFileHandler())).withHandler(passthroughHandler(createRequenceStreamHandler())).withHandler(passthroughHandler(createRequenceCallbackHandler())).withHandler(createClaimCheckHandler());
409
1087
 
410
- // src/errors.ts
411
- class RequenceConnectionError extends Error {
1088
+ // src/boundary.ts
1089
+ function createOutboundBoundary(base) {
1090
+ const warn = base.warn ?? ((message, error) => error === undefined ? console.warn(message) : console.warn(message, error));
1091
+ const ledger = [];
1092
+ const errors = [];
1093
+ const codec = base.wireCodec ?? "json";
1094
+ const measure = (value) => wireBodyByteLength(value, codec);
1095
+ const track = (promise) => {
1096
+ ledger.push(promise.then(() => {}, (error) => {
1097
+ errors.push(error instanceof Error ? error : new Error(String(error)));
1098
+ }));
1099
+ };
1100
+ return {
1101
+ track,
1102
+ async send(data, opts = {}) {
1103
+ const ctx = {
1104
+ fetch: base.fetch ?? globalThis.fetch,
1105
+ signal: base.signal,
1106
+ uploadUrl: base.uploadUrl,
1107
+ streamUrl: base.streamUrl,
1108
+ maxPayloadSize: base.maxPayloadSize,
1109
+ maxFileSize: base.maxFileSize,
1110
+ measure,
1111
+ outputName: opts.outputName ?? null,
1112
+ onCallback: opts.onCallback,
1113
+ ...opts.bestEffort ? {
1114
+ onOffloadFail: (error) => warn("offload failed (best-effort log path):", error),
1115
+ onOffloadSkip: () => warn("offload skipped: no upload transport configured")
1116
+ } : {}
1117
+ };
1118
+ if (opts.bestEffort) {
1119
+ try {
1120
+ const { value: value2, done: done2 } = await withRequenceStreams(() => transformer.outbound(sanitizeLogData(data), ctx));
1121
+ ledger.push(done2.then(() => {}, (error) => warn("log stream upload failed:", error)));
1122
+ return value2;
1123
+ } catch (error) {
1124
+ warn("log offload errored:", error);
1125
+ return;
1126
+ }
1127
+ }
1128
+ const { value, done } = await withRequenceStreams(() => transformer.outbound(data, ctx));
1129
+ track(done);
1130
+ return value;
1131
+ },
1132
+ async settle() {
1133
+ for (;; ) {
1134
+ const count = ledger.length;
1135
+ await Promise.all(ledger);
1136
+ if (count === ledger.length) {
1137
+ break;
1138
+ }
1139
+ }
1140
+ if (errors.length > 0) {
1141
+ const failed = errors.splice(0);
1142
+ throw new AggregateError(failed, failed[0].message);
1143
+ }
1144
+ }
1145
+ };
1146
+ }
1147
+ function createInboundBoundary(base = {}) {
1148
+ return (data, opts = {}) => {
1149
+ const timeout = base.timeoutMs && base.timeoutMs > 0 ? AbortSignal.timeout(base.timeoutMs) : undefined;
1150
+ const signal = base.signal && timeout ? AbortSignal.any([base.signal, timeout]) : timeout ?? base.signal;
1151
+ const ctx = {
1152
+ fetch: base.fetch ?? globalThis.fetch,
1153
+ signal,
1154
+ onCallbackInvoke: opts.onCallbackInvoke ?? base.onCallbackInvoke
1155
+ };
1156
+ return (base.transformer ?? transformer).inbound(data, ctx);
1157
+ };
412
1158
  }
413
1159
 
414
1160
  // src/helpers.ts
415
- import { AsyncLocalStorage } from "node:async_hooks";
1161
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
416
1162
  class RetryError extends Error {
417
1163
  delay;
418
1164
  constructor(delay) {
@@ -430,124 +1176,87 @@ var OUTPUT_VALUE = Symbol("output_value");
430
1176
  function isOutputValue(value) {
431
1177
  return value !== null && typeof value === "object" && OUTPUT_VALUE in value;
432
1178
  }
433
- function processData(params) {
434
- return mapOutput({
435
- value: mapData(params.data, {
436
- Function(data, path) {
437
- return {
438
- ...params.onCallback(data),
439
- outputName: params.outputName,
440
- propertyPath: path,
441
- __REQUENCE_type: "RequenceCallback"
442
- };
443
- }
444
- }),
445
- options: params.options,
446
- onDone: params.onDone
447
- });
448
- }
449
- async function unwrapResult(params) {
450
- if (isOutputValue(params.result)) {
451
- return {
452
- value: await processData({
453
- outputName: params.result[OUTPUT_VALUE],
454
- data: params.result.value,
455
- options: params.options,
456
- onDone: params.onDone,
457
- onCallback: params.onCallback
458
- }),
459
- outputName: params.result[OUTPUT_VALUE]
460
- };
1179
+ function unwrapOutputValue(result) {
1180
+ if (isOutputValue(result)) {
1181
+ return { value: result.value, outputName: result[OUTPUT_VALUE] };
461
1182
  }
462
- return {
463
- value: await processData({
464
- outputName: null,
465
- data: params.result,
466
- options: params.options,
467
- onDone: params.onDone,
468
- onCallback: params.onCallback
469
- }),
470
- outputName: null
471
- };
1183
+ return { value: result, outputName: null };
472
1184
  }
473
- function createContextHelper(options) {
1185
+ async function createContextHelper(options) {
474
1186
  const terminatePromise = Promise.withResolvers();
475
- const abortController = new AbortController;
1187
+ const abortController = options.abortController ?? new AbortController;
476
1188
  terminatePromise.promise.then(() => abortController.abort());
477
1189
  const terminated = Object.assign(terminatePromise.promise, {
478
1190
  signal: abortController.signal
479
1191
  });
480
- return [
481
- {
482
- taskId: options.taskId,
483
- input: resolveRequenceTypes(options.input, options.onCallback),
484
- configuration: resolveRequenceTypes(options.configuration, () => {
1192
+ const inbound = createInboundBoundary({
1193
+ signal: abortController.signal,
1194
+ ...options.passthroughByteReferences ? { transformer: passthroughInboundTransformer } : {}
1195
+ });
1196
+ const [input, configuration] = await Promise.all([
1197
+ inbound(options.input, { onCallbackInvoke: options.onCallback }),
1198
+ inbound(options.configuration, {
1199
+ onCallbackInvoke: () => {
485
1200
  throw new Error("configuration may not have callbacks");
486
- }),
487
- toOutput(name, value) {
488
- return {
489
- [OUTPUT_VALUE]: name,
490
- value
491
- };
492
- },
493
- defer: options.onDefer,
494
- debug: {
495
- log(...data) {
496
- options.onLog("log", data);
497
- },
498
- info(...data) {
499
- options.onLog("info", data);
500
- },
501
- warn(...data) {
502
- options.onLog("warn", data);
503
- },
504
- error(...data) {
505
- options.onLog("error", data);
506
- }
507
- },
508
- retry(delay) {
509
- throw new RetryError(delay);
1201
+ }
1202
+ })
1203
+ ]);
1204
+ const context = {
1205
+ taskId: options.taskId,
1206
+ input,
1207
+ configuration,
1208
+ toOutput(name, value) {
1209
+ return {
1210
+ [OUTPUT_VALUE]: name,
1211
+ value
1212
+ };
1213
+ },
1214
+ defer: options.onDefer,
1215
+ debug: {
1216
+ log(...data) {
1217
+ options.onLog("log", data);
510
1218
  },
511
- abort(reason) {
512
- throw new AbortError(reason);
1219
+ info(...data) {
1220
+ options.onLog("info", data);
513
1221
  },
514
- skip() {
515
- throw new SkipError;
1222
+ warn(...data) {
1223
+ options.onLog("warn", data);
516
1224
  },
517
- terminated
518
- },
519
- terminatePromise
520
- ];
521
- }
522
- var handlerStorage = new AsyncLocalStorage;
523
-
524
- // src/mapInput.ts
525
- function mapInput(data) {
526
- return mapData(data, {
527
- Object(obj) {
528
- if (isFileObject(obj)) {
529
- return RequenceFile.fromFileObject(obj);
1225
+ error(...data) {
1226
+ options.onLog("error", data);
530
1227
  }
531
- if (isStreamObject(obj)) {
532
- return RequenceStream.fromStreamObject(obj);
533
- }
534
- }
535
- });
1228
+ },
1229
+ retry(delay) {
1230
+ throw new RetryError(delay);
1231
+ },
1232
+ abort(reason) {
1233
+ throw new AbortError(reason);
1234
+ },
1235
+ skip() {
1236
+ throw new SkipError;
1237
+ },
1238
+ terminated
1239
+ };
1240
+ Object.assign(context, options.sends);
1241
+ return [context, terminatePromise];
536
1242
  }
1243
+ var handlerStorage = new AsyncLocalStorage2;
537
1244
 
538
1245
  // src/createAmqpConnection.ts
539
- var messageKeySchema = z5.string().transform((str) => deobfuscate(str)).pipe(z5.tuple([z5.uuid(), z5.uuid()]).rest(z5.string())).transform((arr) => ({
1246
+ var messageKeySchema = z6.string().transform((str) => deobfuscate(str)).pipe(z6.tuple([z6.uuid(), z6.uuid()]).rest(z6.string())).transform((arr) => ({
540
1247
  taskId: arr[0],
541
1248
  messageId: arr[1],
542
1249
  uploadUrl: arr[2] || undefined,
543
- streamUrl: arr[3] || undefined
1250
+ streamUrl: arr[3] || undefined,
1251
+ maxPayloadSize: arr[4] && Number.isFinite(Number(arr[4])) ? Number(arr[4]) : undefined,
1252
+ maxFileSize: arr[5] && Number.isFinite(Number(arr[5])) ? Number(arr[5]) : undefined
544
1253
  }));
545
- var headerSchema = z5.object({
546
- properties: z5.object({
547
- correlationId: z5.uuid(),
548
- headers: z5.object({
549
- taskId: z5.uuid(),
550
- mode: z5.enum(["LINEAR", "CONTINUOUS"]).default("LINEAR")
1254
+ var headerSchema = z6.object({
1255
+ properties: z6.object({
1256
+ correlationId: z6.uuid(),
1257
+ headers: z6.object({
1258
+ taskId: z6.uuid(),
1259
+ mode: z6.enum(["LINEAR", "CONTINUOUS"]).default("LINEAR")
551
1260
  })
552
1261
  })
553
1262
  }).transform((msg) => ({
@@ -555,62 +1264,136 @@ var headerSchema = z5.object({
555
1264
  taskId: msg.properties.headers.taskId,
556
1265
  mode: msg.properties.headers.mode
557
1266
  }));
558
- var payloadSchema = z5.object({ content: z5.instanceof(Buffer) }).transform((msg) => JSON.parse(msg.content.toString())).pipe(z5.object({
559
- input: z5.unknown(),
560
- configuration: z5.unknown(),
561
- options: z5.object({
562
- uploadUrl: z5.url().optional(),
563
- streamUrl: z5.url().optional()
1267
+ var payloadSchema = z6.object({
1268
+ content: z6.instanceof(Buffer),
1269
+ properties: z6.object({ contentType: z6.string().optional() })
1270
+ }).transform((msg) => decodeWireBody(msg.content, msg.properties.contentType)).pipe(z6.object({
1271
+ input: z6.unknown(),
1272
+ configuration: z6.unknown(),
1273
+ options: z6.object({
1274
+ uploadUrl: z6.url().optional(),
1275
+ streamUrl: z6.url().optional(),
1276
+ maxPayloadSize: z6.number().optional(),
1277
+ maxFileSize: z6.number().optional()
564
1278
  })
565
1279
  }));
566
- var backchannelMessageSchema = z5.object({
567
- content: z5.instanceof(Buffer).transform((content) => JSON.parse(content.toString())).pipe(z5.discriminatedUnion("type", [
568
- z5.object({
569
- type: z5.literal("stop")
1280
+ var backchannelMessageSchema = z6.object({
1281
+ content: z6.instanceof(Buffer),
1282
+ properties: z6.object({
1283
+ correlationId: z6.string(),
1284
+ contentType: z6.string().optional()
1285
+ })
1286
+ }).transform((message) => ({
1287
+ ...message,
1288
+ content: decodeWireBody(message.content, message.properties.contentType)
1289
+ })).pipe(z6.object({
1290
+ content: z6.discriminatedUnion("type", [
1291
+ z6.object({
1292
+ type: z6.literal("stop")
570
1293
  }),
571
- z5.object({
572
- type: z5.literal("callback"),
573
- callbackId: z5.uuid(),
574
- arg: z5.any()
1294
+ z6.object({
1295
+ type: z6.literal("callback"),
1296
+ callbackId: z6.uuid(),
1297
+ arg: z6.any()
575
1298
  })
576
- ])),
577
- properties: z5.object({
578
- correlationId: z5.string()
1299
+ ]),
1300
+ properties: z6.object({
1301
+ correlationId: z6.string()
579
1302
  })
580
- }).transform((message) => ({
1303
+ })).transform((message) => ({
581
1304
  payload: message.content,
582
1305
  messageId: message.properties.correlationId
583
1306
  }));
584
1307
  var abortSymbol = Symbol();
585
- var connectionOptionsSchema = z5.object({
586
- url: z5.union([
587
- z5.string().regex(/^amqps?:\/\/(.+):(.+)@(.+)$/).transform((str) => new URL(str)),
588
- z5.instanceof(URL).refine((url) => url.protocol.match(/^amqps?:/), "Wrong protocol")
1308
+ var connectionOptionsSchema = z6.object({
1309
+ url: z6.union([
1310
+ z6.string().regex(/^amqps?:\/\/(.+):(.+)@(.+)$/).transform((str) => new URL(str)),
1311
+ z6.instanceof(URL).refine((url) => url.protocol.match(/^amqps?:/), "Wrong protocol")
589
1312
  ]),
590
- version: z5.string(),
591
- devOverlay: z5.string().optional(),
592
- silent: z5.boolean().optional(),
593
- prefetch: z5.number().int().optional(),
594
- connectionTimeout: z5.number().positive().default(3000),
595
- connectionOptions: z5.any().optional()
1313
+ version: z6.string(),
1314
+ name: z6.string().optional(),
1315
+ devOverlay: z6.string().optional(),
1316
+ silent: z6.boolean().optional(),
1317
+ prefetch: z6.number().int().optional(),
1318
+ connectionTimeout: z6.number().positive().default(3000),
1319
+ heartbeatInterval: z6.number().int().positive().optional(),
1320
+ connectionOptions: z6.any().optional(),
1321
+ maxMessageSize: z6.number().int().positive().default(128 * 1024 * 1024),
1322
+ passthroughByteReferences: z6.boolean().optional()
596
1323
  });
597
1324
  function isMessageHandlerGenerator(handler) {
598
1325
  return handler.constructor.name === "GeneratorFunction" || handler.constructor.name === "AsyncGeneratorFunction";
599
1326
  }
600
1327
  var activeMessages = new Map;
1328
+ var messageCodecs = new Map;
1329
+ function isChannelClosedError(error) {
1330
+ return error instanceof Error && error.name === "IllegalOperationError";
1331
+ }
1332
+ function safeAck(channel, message) {
1333
+ try {
1334
+ channel.ack(message);
1335
+ } catch (error) {
1336
+ if (!isChannelClosedError(error)) {
1337
+ throw error;
1338
+ }
1339
+ }
1340
+ }
1341
+ function safeNack(channel, message) {
1342
+ try {
1343
+ channel.nack(message);
1344
+ } catch (error) {
1345
+ if (!isChannelClosedError(error)) {
1346
+ throw error;
1347
+ }
1348
+ }
1349
+ }
601
1350
  function createConnection({
602
1351
  url,
603
1352
  version,
604
1353
  prefetch = 1,
605
1354
  silent = false,
606
1355
  connectionTimeout,
1356
+ heartbeatInterval = DEFAULT_AMQP_HEARTBEAT_SECONDS,
607
1357
  connectionOptions,
608
- devOverlay = ""
1358
+ name,
1359
+ devOverlay = "",
1360
+ maxMessageSize,
1361
+ onConnectionStateChange,
1362
+ ...rest
609
1363
  }, messageHandler) {
1364
+ const passthroughByteReferences = rest.passthroughByteReferences ?? false;
610
1365
  const baseQueue = `${url.username}@${version}`;
611
1366
  const queue = devOverlay ? `${baseQueue}-dev-overlay-${devOverlay}` : baseQueue;
612
1367
  const exchange = url.username;
613
- const connection = connect(url.toString(), { connectionOptions });
1368
+ const connection = connect(url.toString(), {
1369
+ connectionOptions: {
1370
+ ...connectionOptions,
1371
+ clientProperties: {
1372
+ ...connectionOptions?.clientProperties,
1373
+ ...buildServiceClientProperties({
1374
+ libVersion: "javascript@0.8.2-edge.1149",
1375
+ serviceVersion: version,
1376
+ name,
1377
+ devOverlay: Boolean(devOverlay)
1378
+ })
1379
+ }
1380
+ },
1381
+ heartbeatIntervalInSeconds: heartbeatInterval
1382
+ });
1383
+ connection.on("disconnect", ({ err }) => {
1384
+ if (!silent && err) {
1385
+ console.error("Requence AMQP connection lost:", err.message);
1386
+ }
1387
+ onConnectionStateChange?.({ connected: false, err });
1388
+ });
1389
+ let hasConnected = false;
1390
+ connection.on("connect", () => {
1391
+ if (hasConnected && !silent) {
1392
+ console.info("Requence AMQP reconnected");
1393
+ }
1394
+ hasConnected = true;
1395
+ onConnectionStateChange?.({ connected: true });
1396
+ });
614
1397
  const connectedPromise = new Promise((resolve2, reject) => {
615
1398
  const unsubscribe = () => {
616
1399
  clearTimeout(timeout);
@@ -641,6 +1424,7 @@ function createConnection({
641
1424
  const backchannelQueue = `${baseQueue}-backchannel-${connectionId}`;
642
1425
  const generatorTerminators = new Map;
643
1426
  const callbacks = new Map;
1427
+ const backchannelInbound = createInboundBoundary(passthroughByteReferences ? { transformer: passthroughInboundTransformer } : {});
644
1428
  const channelWrapper = connection.createChannel({
645
1429
  async setup(channel) {
646
1430
  if (devOverlay) {
@@ -667,7 +1451,20 @@ function createConnection({
667
1451
  break;
668
1452
  }
669
1453
  case "callback": {
670
- callbacks.get(backchannelMessage.payload.callbackId)?.(backchannelMessage.payload.arg);
1454
+ const entry = callbacks.get(backchannelMessage.payload.callbackId);
1455
+ if (!entry) {
1456
+ break;
1457
+ }
1458
+ let arg;
1459
+ try {
1460
+ arg = await backchannelInbound(backchannelMessage.payload.arg, {
1461
+ onCallbackInvoke: entry.onCallbackInvoke
1462
+ });
1463
+ } catch (error) {
1464
+ console.warn(`dropped callback invocation |${backchannelMessage.payload.callbackId}|: argument rehydration failed`, error instanceof Error ? error.message : error);
1465
+ break;
1466
+ }
1467
+ entry.callback(arg);
671
1468
  break;
672
1469
  }
673
1470
  }
@@ -676,24 +1473,85 @@ function createConnection({
676
1473
  });
677
1474
  }
678
1475
  });
1476
+ channelWrapper.on("error", (err) => {
1477
+ if (!silent) {
1478
+ console.error("Requence AMQP channel error:", err.message);
1479
+ }
1480
+ });
679
1481
  const publish = ({
680
1482
  data,
681
1483
  outputName,
682
1484
  messageId,
683
1485
  priority,
684
1486
  ...headers
685
- }) => channelWrapper.publish(exchange, "", Buffer.from(JSON.stringify(data ?? null)), {
686
- correlationId: messageId,
687
- contentType: "application/json",
688
- persistent: true,
689
- priority,
690
- headers: {
691
- outputName: outputName ?? null,
692
- connectionId,
693
- libVersion: "javascript@0.7.1",
694
- ...headers
1487
+ }) => {
1488
+ const { body, contentType } = encodeWireBody(data ?? null, messageCodecs.get(messageId) ?? "json");
1489
+ if (body.byteLength > maxMessageSize) {
1490
+ return Promise.reject(new PayloadTooLargeError(body.byteLength, maxMessageSize));
695
1491
  }
696
- });
1492
+ return channelWrapper.publish(exchange, "", body, {
1493
+ correlationId: messageId,
1494
+ contentType,
1495
+ persistent: true,
1496
+ priority,
1497
+ headers: {
1498
+ outputName: outputName ?? null,
1499
+ connectionId,
1500
+ ...headers
1501
+ }
1502
+ });
1503
+ };
1504
+ const buildSendApi = (deps) => {
1505
+ const base = {
1506
+ ...deps.epoch === undefined ? {} : { epoch: deps.epoch },
1507
+ ...deps.priority === undefined ? {} : { priority: deps.priority }
1508
+ };
1509
+ return {
1510
+ async sendToOutput(outputName, data, options) {
1511
+ await deps.gate?.();
1512
+ deps.outbound.track(publish({
1513
+ index: deps.nextIndex(),
1514
+ version,
1515
+ messageId: deps.messageId,
1516
+ taskId: deps.taskId,
1517
+ data: await deps.outbound.send(data, {
1518
+ outputName,
1519
+ onCallback: deps.registerCallback
1520
+ }),
1521
+ outputName,
1522
+ ...options?.overwrite ? { overwrite: true } : {},
1523
+ ...base
1524
+ }));
1525
+ },
1526
+ async send(data, options) {
1527
+ await deps.gate?.();
1528
+ deps.outbound.track(publish({
1529
+ index: deps.nextIndex(),
1530
+ version,
1531
+ messageId: deps.messageId,
1532
+ taskId: deps.taskId,
1533
+ data: await deps.outbound.send(data, {
1534
+ outputName: null,
1535
+ onCallback: deps.registerCallback
1536
+ }),
1537
+ ...options?.overwrite ? { overwrite: true } : {},
1538
+ ...base
1539
+ }));
1540
+ },
1541
+ async sendState(state) {
1542
+ await deps.gate?.();
1543
+ deps.outbound.track(publish({
1544
+ index: 0,
1545
+ version,
1546
+ messageId: deps.messageId,
1547
+ taskId: deps.taskId,
1548
+ data: await deps.outbound.send(state, { outputName: null }),
1549
+ state: true,
1550
+ ...base
1551
+ }));
1552
+ }
1553
+ };
1554
+ };
697
1555
  channelWrapper.addSetup(async (channel) => {
698
1556
  channel.consume(queue, async (message) => {
699
1557
  if (!message) {
@@ -702,11 +1560,19 @@ function createConnection({
702
1560
  let publishIndex = 0;
703
1561
  let acked = false;
704
1562
  let terminated = false;
705
- const donePromises = [];
706
1563
  const registeredCallbackIds = new Set;
707
1564
  let resolveActiveMessage = () => {};
708
- const { messageId, taskId, mode } = headerSchema.parse(message);
1565
+ let messageIdForCleanup;
1566
+ const epoch = crypto.randomUUID();
709
1567
  try {
1568
+ const { messageId, taskId, mode } = headerSchema.parse(message);
1569
+ messageIdForCleanup = messageId;
1570
+ const unsupported = unsupportedCapabilities(readRequiredCapabilities(message.properties.headers));
1571
+ if (unsupported.length > 0) {
1572
+ throw new UnsupportedCapabilityError(unsupported);
1573
+ }
1574
+ const dispatchCodec = wireCodecFromContentType(message.properties.contentType);
1575
+ messageCodecs.set(messageId, dispatchCodec);
710
1576
  let deferred = false;
711
1577
  let deferredReason = null;
712
1578
  const messageExecution = Promise.withResolvers();
@@ -718,40 +1584,91 @@ function createConnection({
718
1584
  messageExecution.resolve();
719
1585
  };
720
1586
  const payload = payloadSchema.parse(message);
721
- const [extendedContext, terminatePromise] = createContextHelper({
1587
+ const abortController = new AbortController;
1588
+ const registerCallback = (callback) => {
1589
+ const callbackId = crypto.randomUUID();
1590
+ registeredCallbackIds.add(callbackId);
1591
+ callbacks.set(callbackId, {
1592
+ callback,
1593
+ onCallbackInvoke: dispatchInvocation
1594
+ });
1595
+ return { sourceId: connectionId, callbackId };
1596
+ };
1597
+ const outbound = createOutboundBoundary({
1598
+ uploadUrl: payload.options.uploadUrl,
1599
+ streamUrl: payload.options.streamUrl,
1600
+ maxPayloadSize: payload.options.maxPayloadSize,
1601
+ maxFileSize: payload.options.maxFileSize,
1602
+ wireCodec: dispatchCodec,
1603
+ signal: abortController.signal,
1604
+ warn: (msg, error) => console.warn(`${msg} (task ${taskId})`, error instanceof Error ? error.message : error ?? "")
1605
+ });
1606
+ const dispatchInvocation = (params) => {
1607
+ outbound.track(outbound.send(params.arg, {
1608
+ outputName: params.outputName,
1609
+ onCallback: registerCallback
1610
+ }).then((data) => publish({
1611
+ index: 0,
1612
+ version,
1613
+ taskId,
1614
+ messageId,
1615
+ data,
1616
+ outputName: params.outputName,
1617
+ connectionId: params.sourceId,
1618
+ callbackId: params.callbackId,
1619
+ propertyPath: params.propertyPath,
1620
+ epoch
1621
+ })));
1622
+ };
1623
+ const [extendedContext, terminatePromise] = await createContextHelper({
722
1624
  taskId,
723
- input: mapInput(payload.input),
724
- configuration: mapInput(payload.configuration),
725
- onLog(debugMethod, data) {
726
- publish({
727
- index: publishIndex++,
728
- version,
729
- messageId,
1625
+ input: payload.input,
1626
+ configuration: payload.configuration,
1627
+ abortController,
1628
+ passthroughByteReferences,
1629
+ sends: {
1630
+ ...buildSendApi({
1631
+ outbound,
1632
+ registerCallback,
730
1633
  taskId,
731
- data,
732
- debugMethod,
733
- priority: message.properties.priority,
734
- debug: true
1634
+ messageId,
1635
+ nextIndex: () => publishIndex++,
1636
+ epoch,
1637
+ priority: message.properties.priority
1638
+ }),
1639
+ invokeCallback: (ref, arg) => dispatchInvocation({
1640
+ sourceId: ref.sourceId,
1641
+ callbackId: ref.callbackId,
1642
+ outputName: ref.outputName,
1643
+ propertyPath: ref.propertyPath,
1644
+ arg
1645
+ }),
1646
+ options: payload.options
1647
+ },
1648
+ onLog(debugMethod, data) {
1649
+ outbound.send(data, { bestEffort: true }).then((mapped) => {
1650
+ if (mapped === undefined) {
1651
+ return;
1652
+ }
1653
+ publish({
1654
+ index: publishIndex++,
1655
+ version,
1656
+ messageId,
1657
+ taskId,
1658
+ data: mapped,
1659
+ debugMethod,
1660
+ priority: message.properties.priority,
1661
+ debug: true,
1662
+ epoch
1663
+ });
735
1664
  });
736
1665
  },
737
1666
  onDefer(reason) {
738
1667
  deferred = true;
739
1668
  deferredReason = reason || null;
740
- return obfuscate(taskId, messageId, payload.options.uploadUrl ?? "", payload.options.streamUrl ?? "");
1669
+ return obfuscate(taskId, messageId, payload.options.uploadUrl ?? "", payload.options.streamUrl ?? "", payload.options.maxPayloadSize?.toString() ?? "", payload.options.maxFileSize?.toString() ?? "");
741
1670
  },
742
- onCallback(params) {
743
- publish({
744
- index: 0,
745
- version,
746
- taskId,
747
- messageId,
748
- data: params.arg,
749
- outputName: params.outputName,
750
- connectionId: params.sourceId,
751
- callbackId: params.callbackId,
752
- propertyPath: params.propertyPath
753
- });
754
- }
1671
+ onCallback: dispatchInvocation
755
1672
  });
756
1673
  await publish({
757
1674
  index: publishIndex++,
@@ -759,11 +1676,18 @@ function createConnection({
759
1676
  messageId,
760
1677
  taskId,
761
1678
  priority: message.properties.priority,
762
- begin: true
1679
+ begin: true,
1680
+ epoch,
1681
+ ...buildServiceIdentityHeaders({
1682
+ libVersion: "javascript@0.8.2-edge.1149",
1683
+ name
1684
+ })
763
1685
  });
764
- if (isMessageHandlerGenerator(messageHandler) && mode === "CONTINUOUS") {
765
- channel.ack(message);
766
- acked = true;
1686
+ if (isMessageHandlerGenerator(messageHandler)) {
1687
+ if (mode === "CONTINUOUS") {
1688
+ safeAck(channel, message);
1689
+ acked = true;
1690
+ }
767
1691
  const generator = messageHandler(extendedContext);
768
1692
  const terminationPromise = Promise.withResolvers();
769
1693
  generatorTerminators.set(messageId, (reason) => {
@@ -797,31 +1721,21 @@ function createConnection({
797
1721
  deferred = false;
798
1722
  console.warn("returning a value in a deferred message resets the deferred status");
799
1723
  }
800
- const donePromise = Promise.withResolvers();
801
- donePromises.push(donePromise.promise);
802
- const { value, outputName } = await unwrapResult({
803
- result,
804
- options: payload.options,
805
- onDone: donePromise.resolve,
806
- onCallback: (callback) => {
807
- const callbackId = crypto.randomUUID();
808
- registeredCallbackIds.add(callbackId);
809
- callbacks.set(callbackId, callback);
810
- return {
811
- sourceId: connectionId,
812
- callbackId
813
- };
814
- }
1724
+ const { value: rawValue, outputName } = unwrapOutputValue(result);
1725
+ const value = await outbound.send(rawValue, {
1726
+ outputName,
1727
+ onCallback: registerCallback
815
1728
  });
816
1729
  if (!done || typeof value !== "undefined") {
817
- publish({
1730
+ await publish({
818
1731
  index: publishIndex++,
819
1732
  version,
820
1733
  messageId,
821
1734
  taskId,
822
1735
  data: value,
823
1736
  priority: message.properties.priority,
824
- outputName
1737
+ outputName,
1738
+ epoch
825
1739
  });
826
1740
  }
827
1741
  if (done) {
@@ -831,12 +1745,9 @@ function createConnection({
831
1745
  });
832
1746
  } else {
833
1747
  const result = await handlerStorage.run(extendedContext, () => messageHandler(extendedContext));
834
- const donePromise = Promise.withResolvers();
835
- donePromises.push(donePromise.promise);
836
- const { value, outputName } = await unwrapResult({
837
- result,
838
- options: payload.options,
839
- onDone: donePromise.resolve,
1748
+ const { value: rawValue, outputName } = unwrapOutputValue(result);
1749
+ const value = await outbound.send(rawValue, {
1750
+ outputName,
840
1751
  onCallback: () => {
841
1752
  throw new Error("callbacks can only be used in generator functions");
842
1753
  }
@@ -846,59 +1757,92 @@ function createConnection({
846
1757
  deferred = false;
847
1758
  }
848
1759
  if (!deferred || value) {
849
- publish({
1760
+ await publish({
850
1761
  index: publishIndex++,
851
1762
  version,
852
1763
  messageId,
853
1764
  taskId,
854
1765
  data: value,
855
1766
  priority: message.properties.priority,
856
- outputName
1767
+ outputName,
1768
+ epoch
857
1769
  });
858
1770
  }
859
1771
  }
860
- await new Promise((resolve2) => {
1772
+ await new Promise((resolve2, reject) => {
861
1773
  setImmediate(async () => {
862
- if (!deferred) {
863
- await Promise.allSettled(donePromises);
864
- }
865
- await publish({
866
- index: publishIndex++,
867
- version,
868
- messageId,
869
- taskId,
870
- data: deferredReason,
871
- priority: message.properties.priority,
872
- deferred,
873
- done: !deferred
874
- });
875
- if (!acked) {
876
- channel.ack(message);
1774
+ try {
1775
+ if (!deferred) {
1776
+ await outbound.settle();
1777
+ }
1778
+ await publish({
1779
+ index: publishIndex++,
1780
+ version,
1781
+ messageId,
1782
+ taskId,
1783
+ data: deferredReason,
1784
+ priority: message.properties.priority,
1785
+ deferred,
1786
+ done: !deferred,
1787
+ epoch
1788
+ });
1789
+ if (!acked) {
1790
+ safeAck(channel, message);
1791
+ }
1792
+ resolve2();
1793
+ } catch (error) {
1794
+ reject(error);
877
1795
  }
878
- resolve2();
879
1796
  });
880
1797
  });
881
1798
  } catch (error) {
882
1799
  if (error instanceof SkipError) {
883
1800
  if (!acked) {
884
- channel.nack(message);
1801
+ safeNack(channel, message);
885
1802
  }
886
1803
  return;
887
1804
  }
888
1805
  if (error instanceof RetryError) {
889
1806
  if (!acked) {
890
- channel.ack(message);
1807
+ safeAck(channel, message);
891
1808
  }
892
1809
  const properties = {
893
1810
  ...message.properties,
894
1811
  expiration: error.delay || 1000
895
1812
  };
896
- channel.publish(`${exchange}-retry`, version, message.content, properties);
1813
+ channelWrapper.publish(`${exchange}-retry`, version, message.content, properties).catch((publishError) => {
1814
+ if (!silent) {
1815
+ console.error("Failed to republish message for retry:", publishError);
1816
+ }
1817
+ });
1818
+ return;
1819
+ }
1820
+ if (error instanceof UnsupportedCapabilityError) {
1821
+ if (!silent) {
1822
+ console.error(error.message);
1823
+ }
1824
+ if (!acked) {
1825
+ safeAck(channel, message);
1826
+ }
1827
+ channelWrapper.publish(`${exchange}-retry`, "operator", message.content, {
1828
+ ...message.properties,
1829
+ headers: {
1830
+ ...message.properties.headers,
1831
+ version,
1832
+ [CAPABILITY_HEADER_KEYS.mismatch]: true,
1833
+ index: publishIndex++,
1834
+ "error-message": error.message
1835
+ }
1836
+ }).catch((publishError) => {
1837
+ if (!silent) {
1838
+ console.error("Failed to publish capability mismatch message:", publishError);
1839
+ }
1840
+ });
897
1841
  return;
898
1842
  }
899
1843
  if (error instanceof AbortError && error.message.length > 0) {
900
1844
  if (!acked) {
901
- channelWrapper.ack(message);
1845
+ safeAck(channel, message);
902
1846
  }
903
1847
  channelWrapper.publish(`${exchange}-retry`, "operator", error.message, {
904
1848
  ...message.properties,
@@ -906,15 +1850,18 @@ function createConnection({
906
1850
  headers: {
907
1851
  ...message.properties.headers,
908
1852
  index: publishIndex++,
909
- libVersion: "javascript@0.7.1",
910
1853
  abort: true
911
1854
  }
1855
+ }).catch((publishError) => {
1856
+ if (!silent) {
1857
+ console.error("Failed to publish abort message:", publishError);
1858
+ }
912
1859
  });
913
1860
  return;
914
1861
  }
915
1862
  if (terminated && error instanceof Error && error.name === "AbortError" && !(error instanceof AbortError)) {
916
1863
  if (!acked) {
917
- channel.ack(message);
1864
+ safeAck(channel, message);
918
1865
  }
919
1866
  return;
920
1867
  }
@@ -924,23 +1871,29 @@ function createConnection({
924
1871
  console.error(error);
925
1872
  }
926
1873
  if (!acked) {
927
- channel.ack(message);
1874
+ safeAck(channel, message);
928
1875
  }
929
- channel.publish(`${exchange}-retry`, "operator", message.content, {
1876
+ channelWrapper.publish(`${exchange}-retry`, "operator", message.content, {
930
1877
  ...message.properties,
931
1878
  headers: {
932
1879
  ...message.properties.headers,
933
1880
  version,
934
1881
  exception: true,
935
1882
  index: publishIndex++,
936
- libVersion: "javascript@0.7.1",
937
1883
  "error-message": error.message || "error in service handler"
938
1884
  }
1885
+ }).catch((publishError) => {
1886
+ if (!silent) {
1887
+ console.error("Failed to publish exception message:", publishError);
1888
+ }
939
1889
  });
940
1890
  return;
941
1891
  }
942
1892
  } finally {
943
- generatorTerminators.delete(messageId);
1893
+ if (messageIdForCleanup) {
1894
+ generatorTerminators.delete(messageIdForCleanup);
1895
+ messageCodecs.delete(messageIdForCleanup);
1896
+ }
944
1897
  registeredCallbackIds.forEach((id) => callbacks.delete(id));
945
1898
  resolveActiveMessage();
946
1899
  }
@@ -966,61 +1919,41 @@ function createConnection({
966
1919
  }
967
1920
  };
968
1921
  const registeredCallbackIds = new Set;
969
- const donePromises = [];
1922
+ const outbound = createOutboundBoundary(options);
1923
+ const registerCallback = (callback) => {
1924
+ const callbackId = crypto.randomUUID();
1925
+ registeredCallbackIds.add(callbackId);
1926
+ callbacks.set(callbackId, {
1927
+ callback,
1928
+ onCallbackInvoke: dispatchInvocation
1929
+ });
1930
+ return { sourceId: connectionId, callbackId };
1931
+ };
1932
+ const dispatchInvocation = (params) => {
1933
+ outbound.track(outbound.send(params.arg, {
1934
+ outputName: params.outputName,
1935
+ onCallback: registerCallback
1936
+ }).then((data) => publish({
1937
+ index: 0,
1938
+ version,
1939
+ taskId,
1940
+ messageId,
1941
+ data,
1942
+ outputName: params.outputName,
1943
+ connectionId: params.sourceId,
1944
+ callbackId: params.callbackId,
1945
+ propertyPath: params.propertyPath
1946
+ })));
1947
+ };
970
1948
  const sendApi = {
971
- async sendToOutput(outputName, data) {
972
- await activeMessage();
973
- const donePromise = Promise.withResolvers();
974
- donePromises.push(donePromise.promise);
975
- donePromises.push(publish({
976
- index: publishIndex++,
977
- version,
978
- messageId,
979
- taskId,
980
- data: await processData({
981
- outputName,
982
- data,
983
- options,
984
- onDone: donePromise.resolve,
985
- onCallback: (callback) => {
986
- const callbackId = crypto.randomUUID();
987
- registeredCallbackIds.add(callbackId);
988
- callbacks.set(callbackId, callback);
989
- return {
990
- sourceId: connectionId,
991
- callbackId
992
- };
993
- }
994
- }),
995
- outputName
996
- }));
997
- },
998
- async send(data) {
999
- await activeMessage();
1000
- const donePromise = Promise.withResolvers();
1001
- donePromises.push(donePromise.promise);
1002
- donePromises.push(publish({
1003
- index: publishIndex++,
1004
- version,
1005
- messageId,
1006
- taskId,
1007
- data: await processData({
1008
- outputName: null,
1009
- data,
1010
- options,
1011
- onDone: donePromise.resolve,
1012
- onCallback: (callback) => {
1013
- const callbackId = crypto.randomUUID();
1014
- registeredCallbackIds.add(callbackId);
1015
- callbacks.set(callbackId, callback);
1016
- return {
1017
- sourceId: connectionId,
1018
- callbackId
1019
- };
1020
- }
1021
- })
1022
- }));
1023
- },
1949
+ ...buildSendApi({
1950
+ outbound,
1951
+ registerCallback,
1952
+ taskId,
1953
+ messageId,
1954
+ nextIndex: () => publishIndex++,
1955
+ gate: activeMessage
1956
+ }),
1024
1957
  async abort(error) {
1025
1958
  await activeMessage();
1026
1959
  channelWrapper.publish(`${exchange}-retry`, "operator", error instanceof Error ? error.message : error, {
@@ -1031,7 +1964,6 @@ function createConnection({
1031
1964
  contentType: "text/plain",
1032
1965
  headers: {
1033
1966
  taskId,
1034
- libVersion: "javascript@0.7.1",
1035
1967
  index: publishIndex++,
1036
1968
  abort: true
1037
1969
  }
@@ -1051,12 +1983,14 @@ function createConnection({
1051
1983
  }
1052
1984
  await new Promise((resolve2) => setImmediate(resolve2));
1053
1985
  await activeMessage();
1054
- while (true) {
1055
- const promiseCount = donePromises.length;
1056
- await Promise.allSettled(donePromises);
1057
- if (promiseCount === donePromises.length) {
1058
- break;
1059
- }
1986
+ try {
1987
+ await outbound.settle();
1988
+ } catch (error) {
1989
+ registeredCallbackIds.forEach((id) => callbacks.delete(id));
1990
+ const first = error instanceof AggregateError && error.errors[0] instanceof Error ? error.errors[0] : error instanceof Error ? error : new Error(String(error));
1991
+ await sendApi.abort(first);
1992
+ activeMessageKeys.delete(messageKey);
1993
+ throw error;
1060
1994
  }
1061
1995
  registeredCallbackIds.forEach((id) => callbacks.delete(id));
1062
1996
  await publish({
@@ -1157,6 +2091,24 @@ function asyncEventEmitter(initial = []) {
1157
2091
  }
1158
2092
 
1159
2093
  // src/index.ts
2094
+ function resolveConnectionOptions(connectionOptions) {
2095
+ const rejectEnv = process.env.REJECT_UNAUTHORIZED;
2096
+ const caEnv = process.env.CA;
2097
+ const caFileEnv = process.env.CA_FILE;
2098
+ const tlsDefaults = {};
2099
+ if (rejectEnv !== undefined) {
2100
+ tlsDefaults.rejectUnauthorized = !/^(false|0|no)$/i.test(rejectEnv.trim());
2101
+ }
2102
+ if (caEnv) {
2103
+ tlsDefaults.ca = caEnv;
2104
+ } else if (caFileEnv) {
2105
+ tlsDefaults.ca = fs.readFileSync(caFileEnv);
2106
+ }
2107
+ if (Object.keys(tlsDefaults).length === 0) {
2108
+ return connectionOptions;
2109
+ }
2110
+ return { ...tlsDefaults, ...connectionOptions };
2111
+ }
1160
2112
  var pkgJson;
1161
2113
  function loadPkgJson() {
1162
2114
  if (!pkgJson) {
@@ -1209,21 +2161,33 @@ function createService(optionsOrVersion, optionalMessageHandler) {
1209
2161
  }
1210
2162
  devOverlay = devParts[1];
1211
2163
  }
1212
- return createConnection(connectionOptionsSchema.parse({
1213
- ...options,
1214
- url,
1215
- devOverlay
1216
- }), messageHandler);
2164
+ const envMaxMessageSize = process.env.REQUENCE_MAX_MESSAGE_SIZE ? Number(process.env.REQUENCE_MAX_MESSAGE_SIZE) : undefined;
2165
+ return createConnection({
2166
+ ...connectionOptionsSchema.parse({
2167
+ ...options,
2168
+ connectionOptions: resolveConnectionOptions(options.connectionOptions),
2169
+ maxMessageSize: options.maxMessageSize ?? envMaxMessageSize,
2170
+ url,
2171
+ devOverlay
2172
+ }),
2173
+ onConnectionStateChange: options.onConnectionStateChange
2174
+ }, messageHandler);
1217
2175
  }
1218
2176
  export {
1219
2177
  wrapIterable,
2178
+ reachableFetch,
2179
+ isUnreachableStatus,
1220
2180
  createService,
1221
2181
  createCallback,
1222
2182
  asyncEventEmitter,
2183
+ assertReachable,
2184
+ UnsupportedCapabilityError,
2185
+ RequenceUnreachableError,
1223
2186
  RequenceStream,
1224
2187
  RequenceFile,
1225
- RequenceConnectionError
2188
+ RequenceConnectionError,
2189
+ PayloadTooLargeError
1226
2190
  };
1227
2191
 
1228
- //# debugId=DF5C6A6E1370BBD564756E2164756E21
2192
+ //# debugId=339E2FADB6C273CF64756E2164756E21
1229
2193
  //# sourceMappingURL=index.js.map