@zlink-systems/stream-connector 0.26.0 → 0.27.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.
@@ -43,6 +43,10 @@ var ZlinkStreamConnectorBundle = (() => {
43
43
  });
44
44
 
45
45
  // packages/stream-wire/src/lz4-pickle.ts
46
+ var LZ4_MIN_MATCH_LENGTH = 4;
47
+ var LZ4_MATCH_OFFSET_BYTES = 2;
48
+ var LZ4_EXTENDED_LENGTH_NIBBLE = 15;
49
+ var LZ4_EXTENDED_LENGTH_BYTE = 255;
46
50
  var defaultMaxDecompressedPayloadSize = 64 * 1024;
47
51
  function lz4PickleUncompressed(payload) {
48
52
  if (payload.length === 0) {
@@ -118,15 +122,15 @@ var ZlinkStreamConnectorBundle = (() => {
118
122
  if (sourceOffset >= source.length) {
119
123
  break;
120
124
  }
121
- if (source.length - sourceOffset < 2) {
125
+ if (source.length - sourceOffset < LZ4_MATCH_OFFSET_BYTES) {
122
126
  throw new Error("LZ4 match offset is incomplete.");
123
127
  }
124
128
  const matchOffset = source[sourceOffset] | source[sourceOffset + 1] << 8;
125
- sourceOffset += 2;
129
+ sourceOffset += LZ4_MATCH_OFFSET_BYTES;
126
130
  if (matchOffset === 0 || matchOffset > targetOffset) {
127
131
  throw new Error("LZ4 match offset is invalid.");
128
132
  }
129
- const matchLength = readLz4Length(source, token & 15, () => sourceOffset++) + 4;
133
+ const matchLength = readLz4Length(source, token & 15, () => sourceOffset++) + LZ4_MIN_MATCH_LENGTH;
130
134
  if (target.length - targetOffset < matchLength) {
131
135
  throw new Error("LZ4 match run exceeds output size.");
132
136
  }
@@ -142,7 +146,7 @@ var ZlinkStreamConnectorBundle = (() => {
142
146
  }
143
147
  function readLz4Length(source, nibble, nextOffset) {
144
148
  let length = nibble;
145
- if (length !== 15) {
149
+ if (length !== LZ4_EXTENDED_LENGTH_NIBBLE) {
146
150
  return length;
147
151
  }
148
152
  for (; ; ) {
@@ -152,7 +156,7 @@ var ZlinkStreamConnectorBundle = (() => {
152
156
  }
153
157
  const value = source[offset];
154
158
  length += value;
155
- if (value !== 255) {
159
+ if (value !== LZ4_EXTENDED_LENGTH_BYTE) {
156
160
  return length;
157
161
  }
158
162
  }
@@ -166,54 +170,200 @@ var ZlinkStreamConnectorBundle = (() => {
166
170
  ZlinkStreamCodec2[ZlinkStreamCodec2["Protobuf"] = 3] = "Protobuf";
167
171
  return ZlinkStreamCodec2;
168
172
  })(ZlinkStreamCodec || {});
173
+ var ZlinkStreamMessageKind = /* @__PURE__ */ ((ZlinkStreamMessageKind2) => {
174
+ ZlinkStreamMessageKind2[ZlinkStreamMessageKind2["Send"] = 1] = "Send";
175
+ ZlinkStreamMessageKind2[ZlinkStreamMessageKind2["Request"] = 2] = "Request";
176
+ ZlinkStreamMessageKind2[ZlinkStreamMessageKind2["Response"] = 3] = "Response";
177
+ ZlinkStreamMessageKind2[ZlinkStreamMessageKind2["Error"] = 4] = "Error";
178
+ ZlinkStreamMessageKind2[ZlinkStreamMessageKind2["Control"] = 5] = "Control";
179
+ return ZlinkStreamMessageKind2;
180
+ })(ZlinkStreamMessageKind || {});
181
+ var ZlinkStreamHeaderFlags = /* @__PURE__ */ ((ZlinkStreamHeaderFlags2) => {
182
+ ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["None"] = 0] = "None";
183
+ ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["HasRequestSeq"] = 1] = "HasRequestSeq";
184
+ ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["HasMetadata"] = 2] = "HasMetadata";
185
+ ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["PayloadCompressed"] = 4] = "PayloadCompressed";
186
+ ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["HasCorrelationId"] = 8] = "HasCorrelationId";
187
+ ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["HasFlowId"] = 16] = "HasFlowId";
188
+ ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["HasActorSlot"] = 32] = "HasActorSlot";
189
+ return ZlinkStreamHeaderFlags2;
190
+ })(ZlinkStreamHeaderFlags || {});
191
+ var ZlinkStreamCloseReasonCode = /* @__PURE__ */ ((ZlinkStreamCloseReasonCode2) => {
192
+ ZlinkStreamCloseReasonCode2[ZlinkStreamCloseReasonCode2["ClientClose"] = 1] = "ClientClose";
193
+ ZlinkStreamCloseReasonCode2[ZlinkStreamCloseReasonCode2["IdleTimeout"] = 2] = "IdleTimeout";
194
+ ZlinkStreamCloseReasonCode2[ZlinkStreamCloseReasonCode2["HeartbeatTimeout"] = 3] = "HeartbeatTimeout";
195
+ ZlinkStreamCloseReasonCode2[ZlinkStreamCloseReasonCode2["ServerDrain"] = 4] = "ServerDrain";
196
+ ZlinkStreamCloseReasonCode2[ZlinkStreamCloseReasonCode2["ProtocolError"] = 5] = "ProtocolError";
197
+ ZlinkStreamCloseReasonCode2[ZlinkStreamCloseReasonCode2["TransportError"] = 6] = "TransportError";
198
+ return ZlinkStreamCloseReasonCode2;
199
+ })(ZlinkStreamCloseReasonCode || {});
200
+ var unicodeWhiteSpaceOnly = /^\p{White_Space}*$/u;
201
+ var validMessageKinds = new Set(
202
+ Object.values(ZlinkStreamMessageKind).filter((value) => typeof value === "number")
203
+ );
204
+ var validCodecs = new Set(
205
+ Object.values(ZlinkStreamCodec).filter((value) => typeof value === "number")
206
+ );
207
+ function isStreamWireMessageKind(value) {
208
+ return validMessageKinds.has(value);
209
+ }
210
+ function isStreamWireCodec(value) {
211
+ return validCodecs.has(value);
212
+ }
213
+ var UTF8_TWO_BYTE_MIN = 128;
214
+ var UTF8_THREE_BYTE_MIN = 2048;
215
+ var UTF16_HIGH_SURROGATE_MIN = 55296;
216
+ var UTF16_HIGH_SURROGATE_MAX = 56319;
217
+ var UTF16_LOW_SURROGATE_MIN = 56320;
218
+ var UTF16_LOW_SURROGATE_MAX = 57343;
219
+ var UINT8_MAX = 255;
220
+ var UINT16_MAX = 65535;
221
+ var UINT16_BYTES = 2;
222
+ var UINT32_BYTES = 4;
223
+ var UINT64_BYTES = 8;
224
+ var UINT64_MAX = 0xffffffffffffffffn;
225
+ var UINT32_MAX = 4294967295;
226
+ var ZLINK_STREAM_FRAME_PREFIX_BYTES = UINT16_BYTES + UINT32_BYTES;
227
+ var ZLINK_STREAM_MAX_PACKET_NAME_BYTES = UINT8_MAX;
228
+ var ZLINK_STREAM_MAX_METADATA_BYTES = 1024;
229
+ var FLOW_ID_BYTES = 36;
230
+ var FLOW_FIELDS_BYTES = FLOW_ID_BYTES + 1;
231
+ var HEADER_MIN_BYTES = 5;
232
+ var HEADER_FLAG_MASK = 1 /* HasRequestSeq */ | 2 /* HasMetadata */ | 4 /* PayloadCompressed */ | 8 /* HasCorrelationId */ | 16 /* HasFlowId */ | 32 /* HasActorSlot */;
233
+ var CONTROL_PAYLOAD_VERSION = 1;
234
+ var ACTOR_SLOT_OFFSET = 1;
235
+ var ACTOR_ID_LENGTH_OFFSET = ACTOR_SLOT_OFFSET + UINT16_BYTES;
236
+ var ACTOR_BOUND_PREFIX_BYTES = ACTOR_ID_LENGTH_OFFSET + 1;
237
+ var ACTOR_UNBOUND_BYTES = ACTOR_SLOT_OFFSET + UINT16_BYTES;
238
+ var CLOSING_DIAGNOSTIC_LENGTH_OFFSET = 2;
239
+ var CLOSING_PREFIX_BYTES = CLOSING_DIAGNOSTIC_LENGTH_OFFSET + UINT16_BYTES;
240
+ var MAX_CLOSING_DIAGNOSTIC_BYTES = 512;
241
+ function decodeStreamWireActorBoundPayload(payload) {
242
+ if (payload.length < ACTOR_BOUND_PREFIX_BYTES + 1 || payload[0] !== CONTROL_PAYLOAD_VERSION) {
243
+ throw new Error("Actor bound payload is invalid.");
244
+ }
245
+ const slot = readUInt16BE(payload, ACTOR_SLOT_OFFSET);
246
+ const idLength = payload[ACTOR_ID_LENGTH_OFFSET];
247
+ if (slot === 0 || idLength === 0 || payload.length !== ACTOR_BOUND_PREFIX_BYTES + idLength) {
248
+ throw new Error("Actor bound payload is invalid.");
249
+ }
250
+ try {
251
+ return { slot, actorId: decodeControlText(payload.subarray(ACTOR_BOUND_PREFIX_BYTES)) };
252
+ } catch (cause) {
253
+ throw new Error("Actor id is not valid UTF-8.", { cause });
254
+ }
255
+ }
256
+ function decodeStreamWireActorUnboundPayload(payload) {
257
+ if (payload.length !== ACTOR_UNBOUND_BYTES || payload[0] !== CONTROL_PAYLOAD_VERSION) {
258
+ throw new Error("Actor unbound payload is invalid.");
259
+ }
260
+ return readUInt16BE(payload, ACTOR_SLOT_OFFSET);
261
+ }
262
+ function decodeStreamWireSessionClosing(payload) {
263
+ if (payload.length < CLOSING_PREFIX_BYTES || payload[0] !== CONTROL_PAYLOAD_VERSION) {
264
+ throw new Error("Unsupported session-closing version.");
265
+ }
266
+ const closeReason = ZlinkStreamCloseReasonCode[payload[1]];
267
+ if (closeReason === void 0) throw new Error("Unknown session-closing reason.");
268
+ const length = readUInt16BE(payload, CLOSING_DIAGNOSTIC_LENGTH_OFFSET);
269
+ if (length > MAX_CLOSING_DIAGNOSTIC_BYTES || payload.length !== CLOSING_PREFIX_BYTES + length) {
270
+ throw new Error("Invalid session-closing diagnostic length.");
271
+ }
272
+ const diagnostic = length === 0 ? void 0 : decodeControlText(payload.subarray(CLOSING_PREFIX_BYTES));
273
+ return { closeReason, diagnostic };
274
+ }
275
+ function decodeControlText(value) {
276
+ return new TextDecoder("utf-8", { fatal: true }).decode(value);
277
+ }
278
+ function splitStreamWireFrames(chunk) {
279
+ if (chunk.length === 0) throw new Error("Stream frame prefix is incomplete.");
280
+ const frames = [];
281
+ let offset = 0;
282
+ while (offset < chunk.length) {
283
+ const remaining = chunk.length - offset;
284
+ if (remaining < ZLINK_STREAM_FRAME_PREFIX_BYTES) {
285
+ throw new Error("Stream frame prefix is incomplete.");
286
+ }
287
+ const headerLength = readUInt16BE(chunk, offset);
288
+ const payloadLength = readUInt32BE(chunk, offset + UINT16_BYTES);
289
+ const frameLength = ZLINK_STREAM_FRAME_PREFIX_BYTES + headerLength + payloadLength;
290
+ if (frameLength > remaining) throw new Error("Frame length does not match prefix.");
291
+ frames.push(chunk.subarray(offset, offset + frameLength));
292
+ offset += frameLength;
293
+ }
294
+ return frames;
295
+ }
296
+ var ZLINK_STREAM_RESERVED_PACKET_NAME_PREFIX = "$zlink.";
297
+ var ZlinkStreamControlPacket = Object.freeze({
298
+ HeartbeatPing: `${ZLINK_STREAM_RESERVED_PACKET_NAME_PREFIX}heartbeat.ping`,
299
+ HeartbeatPong: `${ZLINK_STREAM_RESERVED_PACKET_NAME_PREFIX}heartbeat.pong`,
300
+ ActorBound: `${ZLINK_STREAM_RESERVED_PACKET_NAME_PREFIX}actor.bound`,
301
+ ActorUnbound: `${ZLINK_STREAM_RESERVED_PACKET_NAME_PREFIX}actor.unbound`,
302
+ SessionClosing: "session-closing"
303
+ });
304
+ var ZlinkStreamContentType = Object.freeze({
305
+ Raw: "application/octet-stream",
306
+ Json: "application/json",
307
+ MessagePack: "application/x-msgpack",
308
+ Protobuf: "application/x-protobuf"
309
+ });
310
+ var contentTypesByCodec = /* @__PURE__ */ new Map([
311
+ [0 /* Raw */, ZlinkStreamContentType.Raw],
312
+ [1 /* Json */, ZlinkStreamContentType.Json],
313
+ [2 /* MessagePack */, ZlinkStreamContentType.MessagePack],
314
+ [3 /* Protobuf */, ZlinkStreamContentType.Protobuf]
315
+ ]);
316
+ var codecsByContentType = new Map(
317
+ Array.from(contentTypesByCodec, ([codec, contentType]) => [contentType, codec])
318
+ );
169
319
  var defaultHeaderFlags = {
170
- hasRequestSeq: 1,
171
- hasMetadata: 2,
172
- hasCorrelationId: 8,
173
- hasFlowId: 16,
174
- hasActorSlot: 32
320
+ hasRequestSeq: 1 /* HasRequestSeq */,
321
+ hasMetadata: 2 /* HasMetadata */,
322
+ hasCorrelationId: 8 /* HasCorrelationId */,
323
+ hasFlowId: 16 /* HasFlowId */,
324
+ hasActorSlot: 32 /* HasActorSlot */
175
325
  };
176
326
  var ZLINK_STREAM_FORMAT_MARKER = 242;
177
- var ZLINK_STREAM_RESPONSE_KIND = 3;
178
- var ZLINK_STREAM_ERROR_KIND = 4;
179
327
  function encodeStreamWireFrame(header, payload) {
180
- if (header.length > 65535) {
328
+ if (header.length > UINT16_MAX) {
181
329
  throw new Error("Stream header is too large.");
182
330
  }
183
- if (payload.length > 4294967295) {
331
+ if (payload.length > UINT32_MAX) {
184
332
  throw new Error("Stream payload is too large.");
185
333
  }
186
- const frame = new Uint8Array(6 + header.length + payload.length);
334
+ const frame = new Uint8Array(ZLINK_STREAM_FRAME_PREFIX_BYTES + header.length + payload.length);
187
335
  writeUInt16BE(frame, 0, header.length);
188
- writeUInt32BE(frame, 2, payload.length);
189
- frame.set(header, 6);
190
- frame.set(payload, 6 + header.length);
336
+ writeUInt32BE(frame, UINT16_BYTES, payload.length);
337
+ frame.set(header, ZLINK_STREAM_FRAME_PREFIX_BYTES);
338
+ frame.set(payload, ZLINK_STREAM_FRAME_PREFIX_BYTES + header.length);
191
339
  return frame;
192
340
  }
193
341
  function decodeStreamWireFrame(frame) {
194
- if (frame.length < 6) {
342
+ if (frame.length < ZLINK_STREAM_FRAME_PREFIX_BYTES) {
195
343
  throw new Error("Stream frame prefix is incomplete.");
196
344
  }
197
345
  const headerLength = readUInt16BE(frame, 0);
198
- const payloadLength = readUInt32BE(frame, 2);
199
- if (frame.length !== 6 + headerLength + payloadLength) {
346
+ const payloadLength = readUInt32BE(frame, UINT16_BYTES);
347
+ if (frame.length !== ZLINK_STREAM_FRAME_PREFIX_BYTES + headerLength + payloadLength) {
200
348
  throw new Error("Stream frame length does not match prefix.");
201
349
  }
202
350
  return {
203
- header: frame.slice(6, 6 + headerLength),
204
- payload: frame.slice(6 + headerLength)
351
+ header: frame.slice(
352
+ ZLINK_STREAM_FRAME_PREFIX_BYTES,
353
+ ZLINK_STREAM_FRAME_PREFIX_BYTES + headerLength
354
+ ),
355
+ payload: frame.slice(ZLINK_STREAM_FRAME_PREFIX_BYTES + headerLength)
205
356
  };
206
357
  }
207
358
  function encodeStreamWireHeader(header, flagOverrides) {
208
359
  const flags = flagOverrides != null ? flagOverrides : defaultHeaderFlags;
209
360
  const reply = isReplyKind(header.kind);
210
361
  const packetName = reply ? "" : header.name;
211
- if (!reply) validateStreamWirePacketName(packetName);
212
- const nameBytes = utf8Encode(packetName);
362
+ const nameBytes = reply ? new Uint8Array() : validateStreamWirePacketName(packetName);
213
363
  const hasRequestSeq = header.requestSeq !== void 0;
214
364
  const hasMetadata = header.metadata.size > 0;
215
365
  const correlationBytes = header.correlationId !== void 0 && header.correlationId.length > 0 ? utf8Encode(header.correlationId) : void 0;
216
- if (correlationBytes !== void 0 && correlationBytes.length > 255) {
366
+ if (correlationBytes !== void 0 && correlationBytes.length > UINT8_MAX) {
217
367
  throw new Error("Stream correlation id is too large.");
218
368
  }
219
369
  const hasCorrelation = correlationBytes !== void 0;
@@ -226,7 +376,7 @@ var ZlinkStreamConnectorBundle = (() => {
226
376
  if (header.flowOrigin !== void 0 && ![1, 2, 3, 4].includes(header.flowOrigin)) {
227
377
  throw new Error("Stream flow origin is invalid.");
228
378
  }
229
- if (header.actorSlot !== void 0 && (!Number.isInteger(header.actorSlot) || header.actorSlot < 1 || header.actorSlot > 65535)) {
379
+ if (header.actorSlot !== void 0 && (!Number.isInteger(header.actorSlot) || header.actorSlot < 1 || header.actorSlot > UINT16_MAX)) {
230
380
  throw new Error("Stream actor slot is invalid.");
231
381
  }
232
382
  let headerFlags = header.flags;
@@ -236,7 +386,7 @@ var ZlinkStreamConnectorBundle = (() => {
236
386
  headerFlags = hasFlow ? headerFlags | flags.hasFlowId : headerFlags & ~flags.hasFlowId;
237
387
  headerFlags = hasActorSlot ? headerFlags | flags.hasActorSlot : headerFlags & ~flags.hasActorSlot;
238
388
  const metadataBytes = hasMetadata ? encodeStreamWireMetadata(header.metadata) : new Uint8Array();
239
- const size = 4 + (hasRequestSeq ? 8 : 0) + 1 + nameBytes.length + (hasMetadata ? 2 + metadataBytes.length : 0) + (hasCorrelation ? 1 + correlationBytes.length : 0) + (hasFlow ? 37 : 0) + (hasActorSlot ? 2 : 0);
389
+ const size = 4 + (hasRequestSeq ? UINT64_BYTES : 0) + 1 + nameBytes.length + (hasMetadata ? UINT16_BYTES + metadataBytes.length : 0) + (hasCorrelation ? 1 + correlationBytes.length : 0) + (hasFlow ? FLOW_FIELDS_BYTES : 0) + (hasActorSlot ? UINT16_BYTES : 0);
240
390
  const buffer = new Uint8Array(size);
241
391
  let offset = 0;
242
392
  buffer[offset++] = ZLINK_STREAM_FORMAT_MARKER;
@@ -248,14 +398,14 @@ var ZlinkStreamConnectorBundle = (() => {
248
398
  throw new Error("Request sequence must not be zero.");
249
399
  }
250
400
  writeBigUInt64BE(buffer, offset, header.requestSeq);
251
- offset += 8;
401
+ offset += UINT64_BYTES;
252
402
  }
253
403
  buffer[offset++] = nameBytes.length;
254
404
  buffer.set(nameBytes, offset);
255
405
  offset += nameBytes.length;
256
406
  if (hasMetadata) {
257
407
  writeUInt16BE(buffer, offset, metadataBytes.length);
258
- offset += 2;
408
+ offset += UINT16_BYTES;
259
409
  buffer.set(metadataBytes, offset);
260
410
  offset += metadataBytes.length;
261
411
  }
@@ -266,7 +416,7 @@ var ZlinkStreamConnectorBundle = (() => {
266
416
  }
267
417
  if (hasFlow) {
268
418
  buffer.set(asciiEncode(header.flowId), offset);
269
- offset += 36;
419
+ offset += FLOW_ID_BYTES;
270
420
  buffer[offset++] = header.flowOrigin;
271
421
  }
272
422
  if (hasActorSlot) {
@@ -277,7 +427,7 @@ var ZlinkStreamConnectorBundle = (() => {
277
427
  function decodeStreamWireHeader(header, flagOverrides, includeFlow = true) {
278
428
  const flags = flagOverrides != null ? flagOverrides : defaultHeaderFlags;
279
429
  let offset = 0;
280
- if (header.length < 5) {
430
+ if (header.length < HEADER_MIN_BYTES) {
281
431
  throw new Error("Stream header is incomplete.");
282
432
  }
283
433
  if (header[offset++] !== ZLINK_STREAM_FORMAT_MARKER) {
@@ -291,29 +441,28 @@ var ZlinkStreamConnectorBundle = (() => {
291
441
  const hasCorrelation = (headerFlags & flags.hasCorrelationId) !== 0;
292
442
  const hasFlow = (headerFlags & flags.hasFlowId) !== 0;
293
443
  const hasActorSlot = (headerFlags & flags.hasActorSlot) !== 0;
294
- if ((headerFlags & ~63) !== 0) {
444
+ if ((headerFlags & ~HEADER_FLAG_MASK) !== 0) {
295
445
  throw new Error("Unknown mandatory stream header flag.");
296
446
  }
297
447
  let requestSeq;
298
448
  if (hasRequestSeq) {
299
- if (header.length - offset < 8) {
449
+ if (header.length - offset < UINT64_BYTES) {
300
450
  throw new Error("Stream request sequence is incomplete.");
301
451
  }
302
452
  requestSeq = readBigUInt64BE(header, offset);
303
453
  if (requestSeq === 0n) {
304
454
  throw new Error("Request sequence must not be zero.");
305
455
  }
306
- offset += 8;
456
+ offset += UINT64_BYTES;
307
457
  }
308
458
  if (header.length - offset < 1) {
309
459
  throw new Error("Stream packet name length is missing.");
310
460
  }
311
461
  const nameLength = header[offset++];
312
- if (!isReplyKind(kind) && nameLength === 0 || header.length - offset < nameLength) {
462
+ if ((isReplyKind(kind) ? nameLength !== 0 : nameLength === 0) || header.length - offset < nameLength) {
313
463
  throw new Error("Stream packet name is invalid.");
314
464
  }
315
- const decodedName = utf8Decode(header.subarray(offset, offset + nameLength));
316
- const name = isReplyKind(kind) ? "" : decodedName;
465
+ const name = utf8Decode(header.subarray(offset, offset + nameLength));
317
466
  offset += nameLength;
318
467
  const decodedMetadata = hasMetadata ? decodeStreamWireHeaderMetadata(header, offset) : { metadata: /* @__PURE__ */ new Map(), offset };
319
468
  offset = decodedMetadata.offset;
@@ -332,14 +481,14 @@ var ZlinkStreamConnectorBundle = (() => {
332
481
  let flowId;
333
482
  let flowOrigin;
334
483
  if (hasFlow) {
335
- if (header.length - offset < 37) {
484
+ if (header.length - offset < FLOW_FIELDS_BYTES) {
336
485
  throw new Error("Stream flow fields are incomplete.");
337
486
  }
338
487
  if (includeFlow) {
339
- flowId = asciiDecode(header.subarray(offset, offset + 36));
488
+ flowId = asciiDecode(header.subarray(offset, offset + FLOW_ID_BYTES));
340
489
  validateFlowId(flowId);
341
490
  }
342
- offset += 36;
491
+ offset += FLOW_ID_BYTES;
343
492
  const decodedFlowOrigin = header[offset++];
344
493
  if (includeFlow && ![1, 2, 3, 4].includes(decodedFlowOrigin)) {
345
494
  throw new Error("Stream flow origin is invalid.");
@@ -348,14 +497,14 @@ var ZlinkStreamConnectorBundle = (() => {
348
497
  }
349
498
  let actorSlot;
350
499
  if (hasActorSlot) {
351
- if (header.length - offset < 2) {
500
+ if (header.length - offset < UINT16_BYTES) {
352
501
  throw new Error("Stream actor slot is incomplete.");
353
502
  }
354
503
  actorSlot = readUInt16BE(header, offset);
355
504
  if (actorSlot === 0) {
356
505
  throw new Error("Stream actor slot must not be zero.");
357
506
  }
358
- offset += 2;
507
+ offset += UINT16_BYTES;
359
508
  }
360
509
  if (offset !== header.length) {
361
510
  throw new Error("Stream header has trailing bytes.");
@@ -385,44 +534,41 @@ var ZlinkStreamConnectorBundle = (() => {
385
534
  if (value.some((byte) => byte > 127)) throw new Error("Stream flow id must be ASCII.");
386
535
  return String.fromCharCode(...value);
387
536
  }
388
- function encodeStreamWireMetadata(metadata) {
389
- if (metadata.size > 255) {
537
+ function streamWireMetadataSize(metadata) {
538
+ if (metadata.size > UINT8_MAX) {
390
539
  throw new Error("Metadata entry count must not exceed 255.");
391
540
  }
392
541
  let size = 1;
393
- const encoded = [...metadata].map(([key, value]) => {
394
- const keyBytes = utf8Encode(key);
395
- const valueBytes = utf8Encode(value);
396
- if (keyBytes.length === 0 || keyBytes.length > 255) {
542
+ for (const [key, value] of metadata) {
543
+ const keySize = utf8Size(key);
544
+ const valueSize = utf8Size(value);
545
+ if (keySize === 0 || keySize > UINT8_MAX) {
397
546
  throw new Error("Metadata key length is invalid.");
398
547
  }
399
- if (valueBytes.length > 65535) {
548
+ if (valueSize > UINT16_MAX) {
400
549
  throw new Error("Metadata value is too large.");
401
550
  }
402
- size += 1 + keyBytes.length + 2 + valueBytes.length;
403
- return { keyBytes, valueBytes };
404
- });
405
- const buffer = new Uint8Array(size);
551
+ size += 1 + keySize + UINT16_BYTES + valueSize;
552
+ }
553
+ return size;
554
+ }
555
+ function encodeStreamWireMetadata(metadata) {
556
+ const buffer = new Uint8Array(streamWireMetadataSize(metadata));
406
557
  let offset = 0;
407
558
  buffer[offset++] = metadata.size;
408
- for (const { keyBytes, valueBytes } of encoded) {
559
+ for (const [key, value] of metadata) {
560
+ const keyBytes = utf8Encode(key);
561
+ const valueBytes = utf8Encode(value);
409
562
  buffer[offset++] = keyBytes.length;
410
563
  buffer.set(keyBytes, offset);
411
564
  offset += keyBytes.length;
412
565
  writeUInt16BE(buffer, offset, valueBytes.length);
413
- offset += 2;
566
+ offset += UINT16_BYTES;
414
567
  buffer.set(valueBytes, offset);
415
568
  offset += valueBytes.length;
416
569
  }
417
570
  return buffer;
418
571
  }
419
- function decodeStreamWireMetadata(metadata) {
420
- const decoded = decodeStreamWireMetadataAt(metadata, 0, metadata.length);
421
- if (decoded.offset !== metadata.length) {
422
- throw new Error("Stream metadata payload has trailing bytes.");
423
- }
424
- return decoded.metadata;
425
- }
426
572
  function lz4PickleUncompressed2(payload) {
427
573
  return lz4PickleUncompressed(payload);
428
574
  }
@@ -439,11 +585,11 @@ var ZlinkStreamConnectorBundle = (() => {
439
585
  return new TextDecoder().decode(value);
440
586
  }
441
587
  function decodeStreamWireHeaderMetadata(header, offset) {
442
- if (header.length - offset < 2) {
588
+ if (header.length - offset < UINT16_BYTES) {
443
589
  throw new Error("Stream metadata section is incomplete.");
444
590
  }
445
591
  const metadataLength = readUInt16BE(header, offset);
446
- offset += 2;
592
+ offset += UINT16_BYTES;
447
593
  if (header.length - offset < metadataLength) {
448
594
  throw new Error("Stream metadata payload is incomplete.");
449
595
  }
@@ -469,7 +615,7 @@ var ZlinkStreamConnectorBundle = (() => {
469
615
  throw new Error("Stream metadata value length is missing.");
470
616
  }
471
617
  const valueLength = readUInt16BE(source, offset);
472
- offset += 2;
618
+ offset += UINT16_BYTES;
473
619
  if (end - offset < valueLength) {
474
620
  throw new Error("Stream metadata value is incomplete.");
475
621
  }
@@ -486,16 +632,17 @@ var ZlinkStreamConnectorBundle = (() => {
486
632
  }
487
633
  function validateStreamWirePacketName(name) {
488
634
  const nameBytes = utf8Encode(name);
489
- if (name.trim().length === 0 || nameBytes.length > 255) {
635
+ if (unicodeWhiteSpaceOnly.test(name) || nameBytes.length > ZLINK_STREAM_MAX_PACKET_NAME_BYTES) {
490
636
  throw new Error("Stream packet name is invalid.");
491
637
  }
638
+ return nameBytes;
492
639
  }
493
640
  function isReplyKind(kind) {
494
- return kind === ZLINK_STREAM_RESPONSE_KIND || kind === ZLINK_STREAM_ERROR_KIND;
641
+ return kind === 3 /* Response */ || kind === 4 /* Error */;
495
642
  }
496
643
  function writeUInt16BE(buffer, offset, value) {
497
- buffer[offset] = value >>> 8 & 255;
498
- buffer[offset + 1] = value & 255;
644
+ buffer[offset] = value >>> 8 & UINT8_MAX;
645
+ buffer[offset + 1] = value & UINT8_MAX;
499
646
  }
500
647
  function readUInt16BE(buffer, offset) {
501
648
  return buffer[offset] << 8 | buffer[offset + 1];
@@ -504,10 +651,10 @@ var ZlinkStreamConnectorBundle = (() => {
504
651
  return buffer[offset] * 16777216 + (buffer[offset + 1] << 16 | buffer[offset + 2] << 8 | buffer[offset + 3]);
505
652
  }
506
653
  function writeUInt32BE(buffer, offset, value) {
507
- buffer[offset] = value >>> 24 & 255;
508
- buffer[offset + 1] = value >>> 16 & 255;
509
- buffer[offset + 2] = value >>> 8 & 255;
510
- buffer[offset + 3] = value & 255;
654
+ buffer[offset] = value >>> 24 & UINT8_MAX;
655
+ buffer[offset + 1] = value >>> 16 & UINT8_MAX;
656
+ buffer[offset + 2] = value >>> 8 & UINT8_MAX;
657
+ buffer[offset + 3] = value & UINT8_MAX;
511
658
  }
512
659
  function writeBigUInt64BE(buffer, offset, value) {
513
660
  for (let index = 7; index >= 0; index -= 1) {
@@ -522,6 +669,19 @@ var ZlinkStreamConnectorBundle = (() => {
522
669
  }
523
670
  return value;
524
671
  }
672
+ function utf8Size(value) {
673
+ let size = 0;
674
+ for (let index = 0; index < value.length; index += 1) {
675
+ const code = value.charCodeAt(index);
676
+ if (code < UTF8_TWO_BYTE_MIN) size += 1;
677
+ else if (code < UTF8_THREE_BYTE_MIN) size += 2;
678
+ else if (code >= UTF16_HIGH_SURROGATE_MIN && code <= UTF16_HIGH_SURROGATE_MAX && index + 1 < value.length && value.charCodeAt(index + 1) >= UTF16_LOW_SURROGATE_MIN && value.charCodeAt(index + 1) <= UTF16_LOW_SURROGATE_MAX) {
679
+ size += 4;
680
+ index += 1;
681
+ } else size += 3;
682
+ }
683
+ return size;
684
+ }
525
685
 
526
686
  // packages/stream-connector/src/Contracts/ZlinkStreamEnums.ts
527
687
  var ZlinkStreamTransport = /* @__PURE__ */ ((ZlinkStreamTransport2) => {
@@ -539,24 +699,6 @@ var ZlinkStreamConnectorBundle = (() => {
539
699
  ZlinkStreamDispatchMode2["Immediate"] = "immediate";
540
700
  return ZlinkStreamDispatchMode2;
541
701
  })(ZlinkStreamDispatchMode || {});
542
- var ZlinkStreamMessageKind = /* @__PURE__ */ ((ZlinkStreamMessageKind2) => {
543
- ZlinkStreamMessageKind2[ZlinkStreamMessageKind2["Send"] = 1] = "Send";
544
- ZlinkStreamMessageKind2[ZlinkStreamMessageKind2["Request"] = 2] = "Request";
545
- ZlinkStreamMessageKind2[ZlinkStreamMessageKind2["Response"] = 3] = "Response";
546
- ZlinkStreamMessageKind2[ZlinkStreamMessageKind2["Error"] = 4] = "Error";
547
- ZlinkStreamMessageKind2[ZlinkStreamMessageKind2["Control"] = 5] = "Control";
548
- return ZlinkStreamMessageKind2;
549
- })(ZlinkStreamMessageKind || {});
550
- var ZlinkStreamHeaderFlags = /* @__PURE__ */ ((ZlinkStreamHeaderFlags2) => {
551
- ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["None"] = 0] = "None";
552
- ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["HasRequestSeq"] = 1] = "HasRequestSeq";
553
- ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["HasMetadata"] = 2] = "HasMetadata";
554
- ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["PayloadCompressed"] = 4] = "PayloadCompressed";
555
- ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["HasCorrelationId"] = 8] = "HasCorrelationId";
556
- ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["HasFlowId"] = 16] = "HasFlowId";
557
- ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["HasActorSlot"] = 32] = "HasActorSlot";
558
- return ZlinkStreamHeaderFlags2;
559
- })(ZlinkStreamHeaderFlags || {});
560
702
  var ZlinkStreamErrorCode = /* @__PURE__ */ ((ZlinkStreamErrorCode2) => {
561
703
  ZlinkStreamErrorCode2["Disconnected"] = "disconnected";
562
704
  ZlinkStreamErrorCode2["ConfigurationError"] = "configurationError";
@@ -568,6 +710,7 @@ var ZlinkStreamConnectorBundle = (() => {
568
710
  ZlinkStreamErrorCode2["SendFailed"] = "sendFailed";
569
711
  ZlinkStreamErrorCode2["CompressionFailed"] = "compressionFailed";
570
712
  ZlinkStreamErrorCode2["DecompressionFailed"] = "decompressionFailed";
713
+ ZlinkStreamErrorCode2["TlsValidationFailed"] = "tlsValidationFailed";
571
714
  ZlinkStreamErrorCode2["UserCallbackFailed"] = "userCallbackFailed";
572
715
  ZlinkStreamErrorCode2["RemoteError"] = "remoteError";
573
716
  return ZlinkStreamErrorCode2;
@@ -582,6 +725,15 @@ var ZlinkStreamConnectorBundle = (() => {
582
725
  return ZlinkStreamConnectionState3;
583
726
  })(ZlinkStreamConnectionState || {});
584
727
 
728
+ // packages/stream-connector/src/Contracts/ZlinkStreamModels.ts
729
+ var ZlinkStreamException = class extends Error {
730
+ constructor(error) {
731
+ super(error.message);
732
+ this.error = error;
733
+ this.name = "ZlinkStreamException";
734
+ }
735
+ };
736
+
585
737
  // packages/stream-connector/src/Contracts/ZlinkStreamMetadata.ts
586
738
  var _ZlinkStreamMetadataMap = class _ZlinkStreamMetadataMap {
587
739
  constructor(values) {
@@ -615,25 +767,13 @@ var ZlinkStreamConnectorBundle = (() => {
615
767
  var ZlinkStreamMetadataMap = _ZlinkStreamMetadataMap;
616
768
  function validateMetadataKey(key) {
617
769
  if (key.length === 0) {
618
- throw new Error("Metadata key must not be empty.");
619
- }
620
- for (let index = 0; index < key.length; index++) {
621
- const code = key.charCodeAt(index);
622
- if (code < 32 || code > 126 || key[index] === "=") {
623
- throw new Error('Metadata key must contain printable ASCII characters except "=".');
624
- }
770
+ throw new ZlinkStreamException({
771
+ code: "validationFailed" /* ValidationFailed */,
772
+ message: "Metadata key must not be empty."
773
+ });
625
774
  }
626
775
  }
627
776
 
628
- // packages/stream-connector/src/Contracts/ZlinkStreamModels.ts
629
- var ZlinkStreamException = class extends Error {
630
- constructor(error) {
631
- super(error.message);
632
- this.error = error;
633
- this.name = "ZlinkStreamException";
634
- }
635
- };
636
-
637
777
  // packages/stream-connector/src/Contracts/ZlinkStreamJsonCodec.ts
638
778
  var zlinkStreamJsonCodecName = "json";
639
779
  var codecOptions = {};
@@ -686,6 +826,10 @@ var ZlinkStreamConnectorBundle = (() => {
686
826
  }
687
827
 
688
828
  // packages/stream-connector/src/Runtime/ZlinkStreamSupport.ts
829
+ var BACKING_ARRAY_COMPACTION_MIN_HEAD = 1024;
830
+ function shouldCompactBackingArray(head, length) {
831
+ return head >= BACKING_ARRAY_COMPACTION_MIN_HEAD && head * 2 >= length;
832
+ }
689
833
  function connectorError(code, message, cause) {
690
834
  return new ZlinkStreamException({ code, message, cause });
691
835
  }
@@ -699,15 +843,21 @@ var ZlinkStreamConnectorBundle = (() => {
699
843
  if (error instanceof ZlinkStreamException) {
700
844
  return error.error;
701
845
  }
702
- return {
703
- code: "remoteError" /* RemoteError */,
704
- message: error instanceof Error ? error.message : String(error),
705
- cause: error
706
- };
846
+ throw error;
707
847
  }
708
848
  function subscription(dispose) {
709
849
  return { dispose };
710
850
  }
851
+ function* currentRegistrations(registrations, snapshot = Array.from(registrations)) {
852
+ for (const registration of snapshot) {
853
+ if (registrations.has(registration)) yield registration;
854
+ }
855
+ }
856
+ function registerHandler(handlers, handler) {
857
+ const registration = { handler };
858
+ handlers.add(registration);
859
+ return subscription(() => handlers.delete(registration));
860
+ }
711
861
  function throwIfAborted(signal) {
712
862
  if ((signal == null ? void 0 : signal.aborted) === true) {
713
863
  throw connectorError("disconnected" /* Disconnected */, "Operation canceled.");
@@ -727,9 +877,6 @@ var ZlinkStreamConnectorBundle = (() => {
727
877
  signal == null ? void 0 : signal.addEventListener("abort", onAbort, { once: true });
728
878
  });
729
879
  }
730
- function utf8Encode2(value) {
731
- return new TextEncoder().encode(value);
732
- }
733
880
  function utf8Decode2(value) {
734
881
  return new TextDecoder().decode(value);
735
882
  }
@@ -748,59 +895,48 @@ var ZlinkStreamConnectorBundle = (() => {
748
895
  }
749
896
  },
750
897
  async expectFailure(action, errorKind) {
751
- let failure;
752
898
  try {
753
899
  await action();
754
- } catch (error) {
755
- failure = error;
756
- }
757
- if (failure === void 0) {
758
- throw connectorError("validationFailed" /* ValidationFailed */, "Expected action to fail.");
759
- }
760
- const streamError = unwrapStreamError(failure);
761
- if (errorKind !== void 0 && streamError.code !== errorKind) {
762
- throw connectorError(
763
- "validationFailed" /* ValidationFailed */,
764
- `Expected failure kind '${errorKind}', got '${streamError.code}'.`,
765
- failure
766
- );
900
+ } catch (failure) {
901
+ if (!(failure instanceof ZlinkStreamException)) throw failure;
902
+ const streamError = failure.error;
903
+ if (errorKind !== void 0 && streamError.code !== errorKind) {
904
+ throw connectorError(
905
+ "validationFailed" /* ValidationFailed */,
906
+ `Expected failure kind '${errorKind}', got '${streamError.code}'.`,
907
+ failure
908
+ );
909
+ }
910
+ return streamError;
767
911
  }
768
- return streamError;
912
+ throw connectorError("validationFailed" /* ValidationFailed */, "Expected action to fail.");
769
913
  },
770
914
  async expectTimeout(action) {
771
- let failure;
772
915
  try {
773
916
  await action();
774
- } catch (error) {
775
- failure = error;
776
- }
777
- if (failure === void 0) {
778
- throw connectorError("validationFailed" /* ValidationFailed */, "Expected action to time out.");
779
- }
780
- const code = unwrapStreamError(failure).code;
781
- if (code !== "requestTimeout" /* RequestTimeout */ && code !== "connectTimeout" /* ConnectTimeout */) {
782
- throw failure;
917
+ } catch (failure) {
918
+ if (!(failure instanceof ZlinkStreamException) || failure.error.code !== "requestTimeout" /* RequestTimeout */ && failure.error.code !== "connectTimeout" /* ConnectTimeout */) {
919
+ throw failure;
920
+ }
921
+ return;
783
922
  }
923
+ throw connectorError("validationFailed" /* ValidationFailed */, "Expected action to time out.");
784
924
  }
785
925
  };
786
926
 
787
927
  // packages/stream-connector/src/Runtime/Protocol/ZlinkStreamPacketNameValidator.ts
788
928
  function validateName(name, allowReserved = false) {
789
- if (name.length === 0) {
790
- throw connectorError("validationFailed" /* ValidationFailed */, "Message name must not be empty.");
929
+ try {
930
+ validateStreamWirePacketName(name);
931
+ } catch (cause) {
932
+ throw connectorError("validationFailed" /* ValidationFailed */, "Message name is invalid.", cause);
791
933
  }
792
- if (!allowReserved && name.startsWith("$zlink.")) {
934
+ if (!allowReserved && name.startsWith(ZLINK_STREAM_RESERVED_PACKET_NAME_PREFIX)) {
793
935
  throw connectorError(
794
936
  "validationFailed" /* ValidationFailed */,
795
937
  "Message name uses a reserved zlink prefix."
796
938
  );
797
939
  }
798
- if (utf8Encode2(name).length > 255) {
799
- throw connectorError(
800
- "validationFailed" /* ValidationFailed */,
801
- "Message name must not exceed 255 UTF-8 bytes."
802
- );
803
- }
804
940
  }
805
941
 
806
942
  // packages/stream-connector/src/Runtime/Calls/ZlinkStreamCallBuilders.ts
@@ -1181,9 +1317,165 @@ var ZlinkStreamConnectorBundle = (() => {
1181
1317
  return compressionCodec != null ? compressionCodec : zlinkStreamLz4CompressionCodec;
1182
1318
  }
1183
1319
 
1320
+ // packages/stream-connector/src/Contracts/ZlinkStreamConnectorOptions.ts
1321
+ var ZLINK_STREAM_DEFAULT_PAYLOAD_BYTES = 64 * 1024;
1322
+
1323
+ // packages/stream-connector/src/Runtime/Transport/ZlinkStreamEndpoint.ts
1324
+ function inferTransport(endpoint) {
1325
+ const url = parseEndpoint(endpoint);
1326
+ switch (url.protocol) {
1327
+ case "ws:":
1328
+ return "webSocket" /* WebSocket */;
1329
+ case "wss:":
1330
+ return "webSocketSecure" /* WebSocketSecure */;
1331
+ default:
1332
+ throw connectorError(
1333
+ "configurationError" /* ConfigurationError */,
1334
+ "The TypeScript Stream Connector supports only ws:// and wss:// endpoints."
1335
+ );
1336
+ }
1337
+ }
1338
+ function parseEndpoint(endpoint) {
1339
+ try {
1340
+ return new URL(endpoint);
1341
+ } catch (cause) {
1342
+ throw connectorError("configurationError" /* ConfigurationError */, "Endpoint is invalid.", cause);
1343
+ }
1344
+ }
1345
+
1346
+ // packages/stream-connector/src/Runtime/ZlinkStreamConnectorOptions.ts
1347
+ function normalizeOptions(options, defaultTransportFactory) {
1348
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
1349
+ const endpoint = options.endpoint;
1350
+ if (endpoint.trim().length === 0) {
1351
+ throw connectorError("configurationError" /* ConfigurationError */, "Endpoint must not be empty.");
1352
+ }
1353
+ const inferredTransport = inferTransport(endpoint);
1354
+ if (options.transport !== void 0 && options.transport !== inferredTransport) {
1355
+ throw connectorError(
1356
+ "configurationError" /* ConfigurationError */,
1357
+ "Configured transport conflicts with endpoint scheme."
1358
+ );
1359
+ }
1360
+ const normalized = {
1361
+ endpoint,
1362
+ transport: inferredTransport,
1363
+ connectTimeoutMs: (_a = options.connectTimeoutMs) != null ? _a : 5e3,
1364
+ requestTimeoutMs: (_b = options.requestTimeoutMs) != null ? _b : 3e4,
1365
+ waitTimeoutMs: (_c = options.waitTimeoutMs) != null ? _c : 5e3,
1366
+ heartbeat: {
1367
+ enabled: (_e = (_d = options.heartbeat) == null ? void 0 : _d.enabled) != null ? _e : true,
1368
+ intervalMs: (_g = (_f = options.heartbeat) == null ? void 0 : _f.intervalMs) != null ? _g : 1e3,
1369
+ timeoutMs: (_i = (_h = options.heartbeat) == null ? void 0 : _h.timeoutMs) != null ? _i : 5e3
1370
+ },
1371
+ reconnect: {
1372
+ enabled: (_k = (_j = options.reconnect) == null ? void 0 : _j.enabled) != null ? _k : true,
1373
+ initialDelayMs: (_m = (_l = options.reconnect) == null ? void 0 : _l.initialDelayMs) != null ? _m : 250,
1374
+ maxDelayMs: (_o = (_n = options.reconnect) == null ? void 0 : _n.maxDelayMs) != null ? _o : 5e3,
1375
+ backoffFactor: (_q = (_p = options.reconnect) == null ? void 0 : _p.backoffFactor) != null ? _q : 2,
1376
+ maxAttempts: ((_r = options.reconnect) == null ? void 0 : _r.maxAttempts) === void 0 ? 3 : options.reconnect.maxAttempts
1377
+ },
1378
+ maxSendPayloadSize: (_s = options.maxSendPayloadSize) != null ? _s : ZLINK_STREAM_DEFAULT_PAYLOAD_BYTES,
1379
+ maxReceivePayloadSize: (_t = options.maxReceivePayloadSize) != null ? _t : ZLINK_STREAM_DEFAULT_PAYLOAD_BYTES,
1380
+ dispatchMode: (_u = options.dispatchMode) != null ? _u : "manual" /* Manual */,
1381
+ compression: (_v = options.compression) != null ? _v : "lz4" /* Lz4 */,
1382
+ compressionCodec: options.compressionCodec,
1383
+ nameResolver: (_w = options.nameResolver) != null ? _w : defaultPacketNameResolver,
1384
+ transportFactory: (_x = options.transportFactory) != null ? _x : defaultTransportFactory,
1385
+ codec: options.codec
1386
+ };
1387
+ validatePositive(normalized.connectTimeoutMs, "ConnectTimeout");
1388
+ validatePositive(normalized.requestTimeoutMs, "RequestTimeout");
1389
+ validatePositive(normalized.waitTimeoutMs, "WaitTimeout");
1390
+ validatePositive(normalized.maxSendPayloadSize, "MaxSendPayloadSize");
1391
+ validatePositive(normalized.maxReceivePayloadSize, "MaxReceivePayloadSize");
1392
+ validateHeartbeat(normalized.heartbeat);
1393
+ validateReconnect(normalized.reconnect);
1394
+ if (((_y = options.heartbeat) == null ? void 0 : _y.enabled) !== void 0 && typeof options.heartbeat.enabled !== "boolean") {
1395
+ throw connectorError(
1396
+ "validationFailed" /* ValidationFailed */,
1397
+ "Heartbeat enabled must be boolean."
1398
+ );
1399
+ }
1400
+ if (((_z = options.reconnect) == null ? void 0 : _z.enabled) !== void 0 && typeof options.reconnect.enabled !== "boolean") {
1401
+ throw connectorError(
1402
+ "validationFailed" /* ValidationFailed */,
1403
+ "Reconnect enabled must be boolean."
1404
+ );
1405
+ }
1406
+ if (options.compressionCodec !== void 0 && !hasMethods(options.compressionCodec, "compress", "decompress")) {
1407
+ throw connectorError("validationFailed" /* ValidationFailed */, "Compression codec is invalid.");
1408
+ }
1409
+ if (options.codec !== void 0 && !hasMethods(options.codec, "encode", "decode")) {
1410
+ throw connectorError("validationFailed" /* ValidationFailed */, "Payload codec is invalid.");
1411
+ }
1412
+ if (options.nameResolver !== void 0 && !hasMethods(options.nameResolver, "resolve")) {
1413
+ throw connectorError("validationFailed" /* ValidationFailed */, "Packet name resolver is invalid.");
1414
+ }
1415
+ if (options.transportFactory !== void 0 && !hasMethods(options.transportFactory, "connect")) {
1416
+ throw connectorError("validationFailed" /* ValidationFailed */, "Transport factory is invalid.");
1417
+ }
1418
+ if (!Object.values(ZlinkStreamDispatchMode).includes(normalized.dispatchMode)) {
1419
+ throw connectorError("validationFailed" /* ValidationFailed */, "DispatchMode is invalid.");
1420
+ }
1421
+ if (!Object.values(ZlinkStreamCompression).includes(normalized.compression)) {
1422
+ throw connectorError("validationFailed" /* ValidationFailed */, "Compression is invalid.");
1423
+ }
1424
+ validateCompressionCodec(normalized);
1425
+ return normalized;
1426
+ }
1427
+ var defaultPacketNameResolver = {
1428
+ resolve(payloadType) {
1429
+ const declared = payloadType.packetName;
1430
+ if (typeof declared === "string" && declared.length > 0) {
1431
+ return declared;
1432
+ }
1433
+ return payloadType.name;
1434
+ }
1435
+ };
1436
+ function validateCompressionCodec(options) {
1437
+ const compression = options.compression;
1438
+ if (compression === "none" /* None */) {
1439
+ if (options.compressionCodec !== void 0) {
1440
+ throw connectorError(
1441
+ "configurationError" /* ConfigurationError */,
1442
+ "compressionCodec cannot be set when compression is none."
1443
+ );
1444
+ }
1445
+ }
1446
+ }
1447
+ function validatePositive(value, name) {
1448
+ if (!Number.isFinite(value) || value <= 0) {
1449
+ throw connectorError("validationFailed" /* ValidationFailed */, `${name} must be positive.`);
1450
+ }
1451
+ }
1452
+ function hasMethods(value, ...names) {
1453
+ if (value === null || typeof value !== "object") return false;
1454
+ const candidate = value;
1455
+ return names.every((name) => typeof candidate[name] === "function");
1456
+ }
1457
+ function validateHeartbeat(options) {
1458
+ const intervalMs = options.intervalMs;
1459
+ const timeoutMs = options.timeoutMs;
1460
+ validatePositive(intervalMs, "Heartbeat interval");
1461
+ validatePositive(timeoutMs, "Heartbeat timeout");
1462
+ }
1463
+ function validateReconnect(options) {
1464
+ validatePositive(options.initialDelayMs, "Reconnect InitialDelay");
1465
+ validatePositive(options.maxDelayMs, "Reconnect MaxDelay");
1466
+ validatePositive(options.backoffFactor, "Reconnect BackoffFactor");
1467
+ const maxAttempts = options.maxAttempts;
1468
+ if (maxAttempts !== null && !(Number.isFinite(maxAttempts) && maxAttempts > 0)) {
1469
+ throw connectorError(
1470
+ "validationFailed" /* ValidationFailed */,
1471
+ "Reconnect MaxAttempts must be null or positive."
1472
+ );
1473
+ }
1474
+ }
1475
+
1184
1476
  // packages/stream-connector/src/Runtime/Protocol/ZlinkStreamFrameCodec.ts
1185
1477
  var ZlinkStreamFrameCodec = class {
1186
- static encode(header, payload, maxPayloadSize = 64 * 1024) {
1478
+ static encode(header, payload, maxPayloadSize = ZLINK_STREAM_DEFAULT_PAYLOAD_BYTES) {
1187
1479
  validatePayload(payload.length, maxPayloadSize);
1188
1480
  try {
1189
1481
  return encodeStreamWireFrame(header, payload);
@@ -1204,35 +1496,14 @@ var ZlinkStreamConnectorBundle = (() => {
1204
1496
  }
1205
1497
  };
1206
1498
  function splitZlinkStreamFrames(chunk) {
1207
- if (chunk.length === 0) {
1499
+ try {
1500
+ return splitStreamWireFrames(chunk);
1501
+ } catch (cause) {
1208
1502
  throw connectorError(
1209
1503
  "frameDecodeFailed" /* FrameDecodeFailed */,
1210
- "Stream frame prefix is incomplete."
1504
+ cause instanceof Error ? cause.message : "Frame length does not match prefix."
1211
1505
  );
1212
1506
  }
1213
- const frames = [];
1214
- let offset = 0;
1215
- while (offset < chunk.length) {
1216
- const remaining = chunk.length - offset;
1217
- if (remaining < 6) {
1218
- throw connectorError(
1219
- "frameDecodeFailed" /* FrameDecodeFailed */,
1220
- "Stream frame prefix is incomplete."
1221
- );
1222
- }
1223
- const headerLength = chunk[offset] << 8 | chunk[offset + 1];
1224
- const payloadLength = chunk[offset + 2] * 16777216 + (chunk[offset + 3] << 16) + (chunk[offset + 4] << 8) + chunk[offset + 5];
1225
- const frameLength = 6 + headerLength + payloadLength;
1226
- if (frameLength > remaining) {
1227
- throw connectorError(
1228
- "frameDecodeFailed" /* FrameDecodeFailed */,
1229
- "Frame length does not match prefix."
1230
- );
1231
- }
1232
- frames.push(chunk.subarray(offset, offset + frameLength));
1233
- offset += frameLength;
1234
- }
1235
- return frames;
1236
1507
  }
1237
1508
  function validatePayload(payloadLength, maxPayloadSize) {
1238
1509
  if (payloadLength > maxPayloadSize) {
@@ -1244,59 +1515,34 @@ var ZlinkStreamConnectorBundle = (() => {
1244
1515
  }
1245
1516
 
1246
1517
  // packages/stream-connector/src/Runtime/Protocol/ZlinkStreamMetadataCodec.ts
1247
- var ZLINK_STREAM_MAX_METADATA_BYTES = 1024;
1248
1518
  var ZlinkStreamMetadataCodec = class {
1249
1519
  static size(metadata) {
1520
+ let size;
1250
1521
  try {
1251
- const size = metadata.count === 0 ? 0 : encodeStreamWireMetadata(metadata.values).length;
1252
- if (size > ZLINK_STREAM_MAX_METADATA_BYTES) {
1253
- throw connectorError(
1254
- "validationFailed" /* ValidationFailed */,
1255
- `Metadata must not exceed ${ZLINK_STREAM_MAX_METADATA_BYTES} bytes.`
1256
- );
1257
- }
1258
- return size;
1522
+ size = metadata.count === 0 ? 0 : streamWireMetadataSize(metadata.values);
1259
1523
  } catch (cause) {
1260
1524
  throw connectorError(
1261
1525
  "validationFailed" /* ValidationFailed */,
1262
- streamWireErrorMessage(cause),
1526
+ cause instanceof Error ? cause.message : "Metadata is invalid.",
1263
1527
  cause
1264
1528
  );
1265
1529
  }
1266
- }
1267
- static write(metadata, destination) {
1268
- try {
1269
- destination.set(encodeStreamWireMetadata(metadata.values));
1270
- } catch (cause) {
1530
+ if (size > ZLINK_STREAM_MAX_METADATA_BYTES) {
1271
1531
  throw connectorError(
1272
1532
  "validationFailed" /* ValidationFailed */,
1273
- streamWireErrorMessage(cause),
1274
- cause
1275
- );
1276
- }
1277
- }
1278
- static decode(metadata) {
1279
- try {
1280
- const values = decodeStreamWireMetadata(metadata);
1281
- return values.size === 0 ? ZlinkStreamMetadataMap.empty : ZlinkStreamMetadataMap.from(values);
1282
- } catch (cause) {
1283
- throw connectorError(
1284
- "frameDecodeFailed" /* FrameDecodeFailed */,
1285
- streamWireErrorMessage(cause),
1286
- cause
1533
+ `Metadata must not exceed ${ZLINK_STREAM_MAX_METADATA_BYTES} bytes.`
1287
1534
  );
1288
1535
  }
1536
+ return size;
1289
1537
  }
1290
1538
  };
1291
- function streamWireErrorMessage(cause) {
1292
- return cause instanceof Error ? cause.message : "Metadata is invalid.";
1293
- }
1294
1539
 
1295
1540
  // packages/stream-connector/src/Runtime/Protocol/ZlinkStreamHeaderCodec.ts
1296
1541
  var ZlinkStreamHeaderCodec = class {
1297
1542
  static encode(header) {
1298
1543
  const reply = isReplyKind2(header.kind);
1299
1544
  if (!reply) validateName(header.name, header.kind === 5 /* Control */);
1545
+ validateEncodeFlags(header.flags);
1300
1546
  validateHeaderSemantics(header);
1301
1547
  ZlinkStreamMetadataCodec.size(header.metadata);
1302
1548
  try {
@@ -1313,7 +1559,7 @@ var ZlinkStreamConnectorBundle = (() => {
1313
1559
  } catch (cause) {
1314
1560
  throw connectorError(
1315
1561
  "validationFailed" /* ValidationFailed */,
1316
- streamWireErrorMessage2(cause),
1562
+ streamWireErrorMessage(cause),
1317
1563
  cause
1318
1564
  );
1319
1565
  }
@@ -1333,25 +1579,24 @@ var ZlinkStreamConnectorBundle = (() => {
1333
1579
  correlationId: wire.correlationId,
1334
1580
  actorSlot: wire.actorSlot
1335
1581
  };
1582
+ if (!isReplyKind2(decoded.kind)) {
1583
+ validateName(decoded.name, decoded.kind === 5 /* Control */);
1584
+ }
1585
+ validateHeaderSemantics(decoded);
1336
1586
  } catch (cause) {
1337
1587
  throw connectorError(
1338
1588
  "frameDecodeFailed" /* FrameDecodeFailed */,
1339
- streamWireErrorMessage2(cause),
1589
+ streamWireErrorMessage(cause),
1340
1590
  cause
1341
1591
  );
1342
1592
  }
1343
- validateEnum(decoded.kind, decoded.codec, decoded.flags);
1344
- if (!isReplyKind2(decoded.kind)) {
1345
- validateName(decoded.name, decoded.kind === 5 /* Control */);
1346
- }
1347
- validateHeaderSemantics(decoded);
1348
1593
  return decoded;
1349
1594
  }
1350
1595
  };
1351
1596
  function isReplyKind2(kind) {
1352
1597
  return kind === 3 /* Response */ || kind === 4 /* Error */;
1353
1598
  }
1354
- function streamWireErrorMessage2(cause) {
1599
+ function streamWireErrorMessage(cause) {
1355
1600
  return cause instanceof Error ? cause.message : "Stream header is invalid.";
1356
1601
  }
1357
1602
  function buildHeader(kind, name, codec, metadata, compress, requestSeq, correlationId, actorSlot) {
@@ -1381,7 +1626,7 @@ var ZlinkStreamConnectorBundle = (() => {
1381
1626
  };
1382
1627
  }
1383
1628
  function validateHeaderSemantics(header) {
1384
- validateEnum(header.kind, header.codec, header.flags);
1629
+ validateEnum(header.kind, header.codec);
1385
1630
  const hasRequestSeq = header.requestSeq !== void 0 || (header.flags & 1 /* HasRequestSeq */) !== 0;
1386
1631
  const hasMetadata = header.metadata.count > 0 || (header.flags & 2 /* HasMetadata */) !== 0;
1387
1632
  if (header.kind === 1 /* Send */ && hasRequestSeq) {
@@ -1414,13 +1659,15 @@ var ZlinkStreamConnectorBundle = (() => {
1414
1659
  }
1415
1660
  }
1416
1661
  }
1417
- function validateEnum(kind, codec, flags) {
1418
- if (![1, 2, 3, 4, 5].includes(kind)) {
1662
+ function validateEnum(kind, codec) {
1663
+ if (!isStreamWireMessageKind(kind)) {
1419
1664
  throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Unknown stream message kind.");
1420
1665
  }
1421
- if (![0, 1, 2, 3].includes(codec)) {
1666
+ if (!isStreamWireCodec(codec)) {
1422
1667
  throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Unknown stream codec.");
1423
1668
  }
1669
+ }
1670
+ function validateEncodeFlags(flags) {
1424
1671
  const known = 1 /* HasRequestSeq */ | 2 /* HasMetadata */ | 4 /* PayloadCompressed */ | 8 /* HasCorrelationId */ | 16 /* HasFlowId */ | 32 /* HasActorSlot */;
1425
1672
  if ((flags & ~known) !== 0) {
1426
1673
  throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Unknown stream header flag.");
@@ -1428,8 +1675,8 @@ var ZlinkStreamConnectorBundle = (() => {
1428
1675
  }
1429
1676
 
1430
1677
  // packages/stream-connector/src/Runtime/Protocol/ZlinkStreamFrameProtocol.ts
1431
- var ZLINK_STREAM_HEARTBEAT_PING = "$zlink.heartbeat.ping";
1432
- var ZLINK_STREAM_HEARTBEAT_PONG = "$zlink.heartbeat.pong";
1678
+ var ZLINK_STREAM_HEARTBEAT_PING = ZlinkStreamControlPacket.HeartbeatPing;
1679
+ var ZLINK_STREAM_HEARTBEAT_PONG = ZlinkStreamControlPacket.HeartbeatPong;
1433
1680
  var ZlinkStreamFrameProtocol = class {
1434
1681
  constructor(options) {
1435
1682
  this.options = options;
@@ -1497,166 +1744,6 @@ var ZlinkStreamConnectorBundle = (() => {
1497
1744
  }
1498
1745
  };
1499
1746
 
1500
- // packages/stream-connector/src/Runtime/Transport/ZlinkStreamEndpoint.ts
1501
- function inferTransport(endpoint) {
1502
- const url = parseEndpoint(endpoint);
1503
- switch (url.protocol) {
1504
- case "ws:":
1505
- return "webSocket" /* WebSocket */;
1506
- case "wss:":
1507
- return "webSocketSecure" /* WebSocketSecure */;
1508
- default:
1509
- throw connectorError(
1510
- "configurationError" /* ConfigurationError */,
1511
- "The TypeScript Stream Connector supports only ws:// and wss:// endpoints."
1512
- );
1513
- }
1514
- }
1515
- function parseEndpoint(endpoint) {
1516
- try {
1517
- return new URL(endpoint);
1518
- } catch (cause) {
1519
- throw connectorError("configurationError" /* ConfigurationError */, "Endpoint is invalid.", cause);
1520
- }
1521
- }
1522
-
1523
- // packages/stream-connector/src/Runtime/ZlinkStreamConnectorOptions.ts
1524
- function normalizeOptions(options, defaultTransportFactory) {
1525
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G;
1526
- const endpoint = options.endpoint;
1527
- if (endpoint.trim().length === 0) {
1528
- throw connectorError("configurationError" /* ConfigurationError */, "Endpoint must not be empty.");
1529
- }
1530
- const inferredTransport = inferTransport(endpoint);
1531
- if (options.transport !== void 0 && options.transport !== inferredTransport) {
1532
- throw connectorError(
1533
- "configurationError" /* ConfigurationError */,
1534
- "Configured transport conflicts with endpoint scheme."
1535
- );
1536
- }
1537
- validatePositive((_a = options.connectTimeoutMs) != null ? _a : 5e3, "ConnectTimeout");
1538
- validatePositive((_b = options.requestTimeoutMs) != null ? _b : 3e4, "RequestTimeout");
1539
- validatePositive((_c = options.waitTimeoutMs) != null ? _c : 5e3, "WaitTimeout");
1540
- validatePositive((_d = options.maxSendPayloadSize) != null ? _d : 64 * 1024, "MaxSendPayloadSize");
1541
- validatePositive((_e = options.maxReceivePayloadSize) != null ? _e : 64 * 1024, "MaxReceivePayloadSize");
1542
- validateHeartbeat(options.heartbeat);
1543
- validateReconnect(options.reconnect);
1544
- if (((_f = options.heartbeat) == null ? void 0 : _f.enabled) !== void 0 && typeof options.heartbeat.enabled !== "boolean") {
1545
- throw connectorError(
1546
- "validationFailed" /* ValidationFailed */,
1547
- "Heartbeat enabled must be boolean."
1548
- );
1549
- }
1550
- if (((_g = options.reconnect) == null ? void 0 : _g.enabled) !== void 0 && typeof options.reconnect.enabled !== "boolean") {
1551
- throw connectorError(
1552
- "validationFailed" /* ValidationFailed */,
1553
- "Reconnect enabled must be boolean."
1554
- );
1555
- }
1556
- if (options.compressionCodec !== void 0 && !hasMethods(options.compressionCodec, "compress", "decompress")) {
1557
- throw connectorError("validationFailed" /* ValidationFailed */, "Compression codec is invalid.");
1558
- }
1559
- if (options.codec !== void 0 && !hasMethods(options.codec, "encode", "decode")) {
1560
- throw connectorError("validationFailed" /* ValidationFailed */, "Payload codec is invalid.");
1561
- }
1562
- if (options.nameResolver !== void 0 && !hasMethods(options.nameResolver, "resolve")) {
1563
- throw connectorError("validationFailed" /* ValidationFailed */, "Packet name resolver is invalid.");
1564
- }
1565
- if (options.transportFactory !== void 0 && !hasMethods(options.transportFactory, "connect")) {
1566
- throw connectorError("validationFailed" /* ValidationFailed */, "Transport factory is invalid.");
1567
- }
1568
- if (!Object.values(ZlinkStreamDispatchMode).includes(
1569
- (_h = options.dispatchMode) != null ? _h : "manual" /* Manual */
1570
- )) {
1571
- throw connectorError("validationFailed" /* ValidationFailed */, "DispatchMode is invalid.");
1572
- }
1573
- if (!Object.values(ZlinkStreamCompression).includes(
1574
- (_i = options.compression) != null ? _i : "lz4" /* Lz4 */
1575
- )) {
1576
- throw connectorError("validationFailed" /* ValidationFailed */, "Compression is invalid.");
1577
- }
1578
- return {
1579
- endpoint,
1580
- transport: inferredTransport,
1581
- connectTimeoutMs: (_j = options.connectTimeoutMs) != null ? _j : 5e3,
1582
- requestTimeoutMs: (_k = options.requestTimeoutMs) != null ? _k : 3e4,
1583
- waitTimeoutMs: (_l = options.waitTimeoutMs) != null ? _l : 5e3,
1584
- heartbeat: {
1585
- enabled: (_n = (_m = options.heartbeat) == null ? void 0 : _m.enabled) != null ? _n : true,
1586
- intervalMs: (_p = (_o = options.heartbeat) == null ? void 0 : _o.intervalMs) != null ? _p : 1e3,
1587
- timeoutMs: (_r = (_q = options.heartbeat) == null ? void 0 : _q.timeoutMs) != null ? _r : 5e3
1588
- },
1589
- reconnect: {
1590
- enabled: (_t = (_s = options.reconnect) == null ? void 0 : _s.enabled) != null ? _t : true,
1591
- initialDelayMs: (_v = (_u = options.reconnect) == null ? void 0 : _u.initialDelayMs) != null ? _v : 250,
1592
- maxDelayMs: (_x = (_w = options.reconnect) == null ? void 0 : _w.maxDelayMs) != null ? _x : 5e3,
1593
- backoffFactor: (_z = (_y = options.reconnect) == null ? void 0 : _y.backoffFactor) != null ? _z : 2,
1594
- maxAttempts: ((_A = options.reconnect) == null ? void 0 : _A.maxAttempts) === void 0 ? 3 : options.reconnect.maxAttempts
1595
- },
1596
- maxSendPayloadSize: (_B = options.maxSendPayloadSize) != null ? _B : 64 * 1024,
1597
- maxReceivePayloadSize: (_C = options.maxReceivePayloadSize) != null ? _C : 64 * 1024,
1598
- dispatchMode: (_D = options.dispatchMode) != null ? _D : "manual" /* Manual */,
1599
- compression: (_E = options.compression) != null ? _E : "lz4" /* Lz4 */,
1600
- compressionCodec: resolveCompressionCodec2(options),
1601
- nameResolver: (_F = options.nameResolver) != null ? _F : defaultPacketNameResolver,
1602
- transportFactory: (_G = options.transportFactory) != null ? _G : defaultTransportFactory,
1603
- codec: options.codec
1604
- };
1605
- }
1606
- var defaultPacketNameResolver = {
1607
- resolve(payloadType) {
1608
- const declared = payloadType.packetName;
1609
- if (typeof declared === "string" && declared.length > 0) {
1610
- return declared;
1611
- }
1612
- return payloadType.name;
1613
- }
1614
- };
1615
- function resolveCompressionCodec2(options) {
1616
- var _a;
1617
- const compression = (_a = options.compression) != null ? _a : "lz4" /* Lz4 */;
1618
- if (compression === "none" /* None */) {
1619
- if (options.compressionCodec !== void 0) {
1620
- throw connectorError(
1621
- "configurationError" /* ConfigurationError */,
1622
- "compressionCodec cannot be set when compression is none."
1623
- );
1624
- }
1625
- return void 0;
1626
- }
1627
- return options.compressionCodec;
1628
- }
1629
- function validatePositive(value, name) {
1630
- if (!Number.isFinite(value) || value <= 0) {
1631
- throw connectorError("validationFailed" /* ValidationFailed */, `${name} must be positive.`);
1632
- }
1633
- }
1634
- function hasMethods(value, ...names) {
1635
- if (value === null || typeof value !== "object") return false;
1636
- const candidate = value;
1637
- return names.every((name) => typeof candidate[name] === "function");
1638
- }
1639
- function validateHeartbeat(options) {
1640
- var _a, _b;
1641
- const intervalMs = (_a = options == null ? void 0 : options.intervalMs) != null ? _a : 1e3;
1642
- const timeoutMs = (_b = options == null ? void 0 : options.timeoutMs) != null ? _b : 5e3;
1643
- validatePositive(intervalMs, "Heartbeat interval");
1644
- validatePositive(timeoutMs, "Heartbeat timeout");
1645
- }
1646
- function validateReconnect(options) {
1647
- var _a, _b, _c;
1648
- validatePositive((_a = options == null ? void 0 : options.initialDelayMs) != null ? _a : 250, "Reconnect InitialDelay");
1649
- validatePositive((_b = options == null ? void 0 : options.maxDelayMs) != null ? _b : 5e3, "Reconnect MaxDelay");
1650
- validatePositive((_c = options == null ? void 0 : options.backoffFactor) != null ? _c : 2, "Reconnect BackoffFactor");
1651
- const maxAttempts = (options == null ? void 0 : options.maxAttempts) === void 0 ? 3 : options.maxAttempts;
1652
- if (maxAttempts !== null && !(Number.isFinite(maxAttempts) && maxAttempts > 0)) {
1653
- throw connectorError(
1654
- "validationFailed" /* ValidationFailed */,
1655
- "Reconnect MaxAttempts must be null or positive."
1656
- );
1657
- }
1658
- }
1659
-
1660
1747
  // packages/stream-connector/src/Runtime/ZlinkStreamPendingRequests.ts
1661
1748
  var ZlinkStreamPendingRequests = class {
1662
1749
  constructor() {
@@ -1664,7 +1751,7 @@ var ZlinkStreamConnectorBundle = (() => {
1664
1751
  __publicField(this, "active", /* @__PURE__ */ new Map());
1665
1752
  }
1666
1753
  create(packetName, timeoutMs) {
1667
- if (this.nextRequestSeq > 0xffffffffffffffffn) {
1754
+ if (this.nextRequestSeq > UINT64_MAX) {
1668
1755
  throw connectorError("sendFailed" /* SendFailed */, "Request sequence is exhausted.");
1669
1756
  }
1670
1757
  const requestSeq = this.nextRequestSeq++;
@@ -1748,8 +1835,8 @@ var ZlinkStreamConnectorBundle = (() => {
1748
1835
  };
1749
1836
 
1750
1837
  // packages/stream-connector/src/Runtime/ZlinkStreamActors.ts
1751
- var ACTOR_BOUND = "$zlink.actor.bound";
1752
- var ACTOR_UNBOUND = "$zlink.actor.unbound";
1838
+ var ACTOR_BOUND = ZlinkStreamControlPacket.ActorBound;
1839
+ var ACTOR_UNBOUND = ZlinkStreamControlPacket.ActorUnbound;
1753
1840
  var zlinkStreamActorBinding = Symbol("zlink.stream.actorBinding");
1754
1841
  var DefaultZlinkStreamActor = class {
1755
1842
  constructor(connector, actorId, slot) {
@@ -1791,7 +1878,6 @@ var ZlinkStreamConnectorBundle = (() => {
1791
1878
  this.events = events;
1792
1879
  __publicField(this, "bySlot", /* @__PURE__ */ new Map());
1793
1880
  __publicField(this, "byId", /* @__PURE__ */ new Map());
1794
- __publicField(this, "issued", []);
1795
1881
  __publicField(this, "boundHandlers", /* @__PURE__ */ new Set());
1796
1882
  __publicField(this, "unboundHandlers", /* @__PURE__ */ new Set());
1797
1883
  }
@@ -1802,12 +1888,10 @@ var ZlinkStreamConnectorBundle = (() => {
1802
1888
  return this.byId.get(actorId);
1803
1889
  }
1804
1890
  onBound(handler) {
1805
- this.boundHandlers.add(handler);
1806
- return subscription(() => this.boundHandlers.delete(handler));
1891
+ return registerHandler(this.boundHandlers, handler);
1807
1892
  }
1808
1893
  onUnbound(handler) {
1809
- this.unboundHandlers.add(handler);
1810
- return subscription(() => this.unboundHandlers.delete(handler));
1894
+ return registerHandler(this.unboundHandlers, handler);
1811
1895
  }
1812
1896
  processControl(name, payload, signal) {
1813
1897
  if (name === ACTOR_BOUND) {
@@ -1831,48 +1915,43 @@ var ZlinkStreamConnectorBundle = (() => {
1831
1915
  return actor;
1832
1916
  }
1833
1917
  closeAll(signal) {
1834
- for (const actor of this.issued) {
1835
- if (!actor.isBound) continue;
1918
+ for (const actor of this.bySlot.values()) {
1836
1919
  this.bySlot.delete(actor.slot);
1837
1920
  this.byId.delete(actor.actorId);
1838
1921
  actor.close();
1839
1922
  this.queue(this.unboundHandlers, actor, signal);
1840
1923
  }
1841
- this.issued.length = 0;
1842
1924
  }
1843
1925
  bind(payload, signal) {
1844
- if (payload.length < 5 || payload[0] !== 1) {
1845
- throw invalidControl("Actor bound payload is invalid.");
1846
- }
1847
- const slot = payload[1] << 8 | payload[2];
1848
- const idLength = payload[3];
1849
- if (slot === 0 || idLength === 0 || payload.length !== 4 + idLength) {
1850
- throw invalidControl("Actor bound payload is invalid.");
1851
- }
1852
- let actorId;
1926
+ let binding;
1853
1927
  try {
1854
- actorId = new TextDecoder("utf-8", { fatal: true }).decode(payload.subarray(4));
1928
+ binding = decodeStreamWireActorBoundPayload(payload);
1855
1929
  } catch (cause) {
1856
1930
  throw connectorError(
1857
1931
  "frameDecodeFailed" /* FrameDecodeFailed */,
1858
- "Actor id is not valid UTF-8.",
1859
- cause
1932
+ cause instanceof Error ? cause.message : "Actor bound payload is invalid.",
1933
+ cause instanceof Error ? cause.cause : void 0
1860
1934
  );
1861
1935
  }
1936
+ const { slot, actorId } = binding;
1862
1937
  if (actorId.length === 0 || this.bySlot.has(slot) || this.byId.has(actorId)) {
1863
1938
  throw invalidControl("Actor bound identity is already in use.");
1864
1939
  }
1865
1940
  const actor = new DefaultZlinkStreamActor(this.connector, actorId, slot);
1866
1941
  this.bySlot.set(slot, actor);
1867
1942
  this.byId.set(actorId, actor);
1868
- this.issued.push(actor);
1869
1943
  this.queue(this.boundHandlers, actor, signal);
1870
1944
  }
1871
1945
  unbind(payload, signal) {
1872
- if (payload.length !== 3 || payload[0] !== 1) {
1873
- throw invalidControl("Actor unbound payload is invalid.");
1946
+ let slot;
1947
+ try {
1948
+ slot = decodeStreamWireActorUnboundPayload(payload);
1949
+ } catch (cause) {
1950
+ throw connectorError(
1951
+ "frameDecodeFailed" /* FrameDecodeFailed */,
1952
+ cause instanceof Error ? cause.message : "Actor unbound payload is invalid."
1953
+ );
1874
1954
  }
1875
- const slot = payload[1] << 8 | payload[2];
1876
1955
  const actor = this.bySlot.get(slot);
1877
1956
  if (slot === 0 || actor === void 0) {
1878
1957
  throw invalidControl(`Actor slot '${slot}' is not bound.`);
@@ -1885,7 +1964,7 @@ var ZlinkStreamConnectorBundle = (() => {
1885
1964
  queue(handlers, actor, signal) {
1886
1965
  this.receivedMessages.enqueueCallback(
1887
1966
  () => {
1888
- for (const handler of Array.from(handlers)) {
1967
+ for (const { handler } of currentRegistrations(handlers)) {
1889
1968
  this.events.runUserCallback(
1890
1969
  () => handler(actor, signal),
1891
1970
  "Actor lifecycle handler failed.",
@@ -1903,7 +1982,7 @@ var ZlinkStreamConnectorBundle = (() => {
1903
1982
 
1904
1983
  // packages/stream-connector/src/Runtime/ZlinkStreamReceivedMessages.ts
1905
1984
  function receives(registration, message) {
1906
- return registration.actor === void 0 || registration.actor === message[zlinkStreamActorBinding];
1985
+ return registration.actor === void 0 || registration.actor.isBound && registration.actor === message[zlinkStreamActorBinding];
1907
1986
  }
1908
1987
  var ZlinkStreamReceivedMessages = class {
1909
1988
  /**
@@ -2112,7 +2191,8 @@ var ZlinkStreamConnectorBundle = (() => {
2112
2191
  }
2113
2192
  const { message, signal } = queued;
2114
2193
  const handlers = this.receiversOf(message);
2115
- for (const handler of handlers) {
2194
+ for (const handler of currentRegistrations(this.handlers.get(message.name), handlers)) {
2195
+ if (!receives(handler, message)) continue;
2116
2196
  this.events.runUserCallback(
2117
2197
  () => handler.handle(message, signal),
2118
2198
  "Typed message handler failed.",
@@ -2227,8 +2307,14 @@ var ZlinkStreamConnectorBundle = (() => {
2227
2307
  this.deliverable.length = 0;
2228
2308
  return;
2229
2309
  }
2230
- if (this.queueHead >= 1024 && this.queueHead * 2 >= this.queue.length) {
2231
- this.queue.splice(0, this.queueHead);
2310
+ const removed = this.queue.length - this.queuedCount;
2311
+ if (shouldCompactBackingArray(removed, this.queue.length)) {
2312
+ let destination = 0;
2313
+ for (let source = this.queueHead; source < this.queue.length; source += 1) {
2314
+ const queued = this.queue[source];
2315
+ if (queued !== void 0) this.queue[destination++] = queued;
2316
+ }
2317
+ this.queue.length = destination;
2232
2318
  this.queueHead = 0;
2233
2319
  this.deliverable.length = 0;
2234
2320
  for (let index = 0; index < this.queue.length; index += 1) {
@@ -2259,7 +2345,7 @@ var ZlinkStreamConnectorBundle = (() => {
2259
2345
  this.advance();
2260
2346
  }
2261
2347
  cancel(operation, error) {
2262
- if (this.queue.has(operation) || this.active === operation) operation.fail(error);
2348
+ if (this.queue.delete(operation) || this.active === operation) operation.fail(error);
2263
2349
  }
2264
2350
  /**
2265
2351
  * Spec stream-connector 32 §7: when the connection ends, frames that have not
@@ -2267,7 +2353,8 @@ var ZlinkStreamConnectorBundle = (() => {
2267
2353
  * waited for. The operations of both fail with `error`.
2268
2354
  */
2269
2355
  failAll(error) {
2270
- const operations = this.active === void 0 ? [...this.queue] : [this.active, ...this.queue];
2356
+ const operations = Array.from(this.queue);
2357
+ if (this.active !== void 0) operations.unshift(this.active);
2271
2358
  this.queue.clear();
2272
2359
  this.active = void 0;
2273
2360
  for (const operation of operations) operation.fail(error);
@@ -2406,26 +2493,7 @@ var ZlinkStreamConnectorBundle = (() => {
2406
2493
  };
2407
2494
 
2408
2495
  // packages/stream-connector/src/Runtime/Protocol/ZlinkSessionClosing.ts
2409
- var ZLINK_SESSION_CLOSING = "session-closing";
2410
- var reasons = {
2411
- 1: "ClientClose",
2412
- 2: "IdleTimeout",
2413
- 3: "HeartbeatTimeout",
2414
- 4: "ServerDrain",
2415
- 5: "ProtocolError",
2416
- 6: "TransportError"
2417
- };
2418
- function decodeSessionClosing(payload) {
2419
- if (payload.length < 4 || payload[0] !== 1)
2420
- throw new Error("Unsupported session-closing version.");
2421
- const closeReason = reasons[payload[1]];
2422
- if (closeReason === void 0) throw new Error("Unknown session-closing reason.");
2423
- const length = payload[2] << 8 | payload[3];
2424
- if (length > 512 || payload.length !== 4 + length)
2425
- throw new Error("Invalid session-closing diagnostic length.");
2426
- const diagnostic = length === 0 ? void 0 : new TextDecoder("utf-8", { fatal: true }).decode(payload.subarray(4));
2427
- return { closeReason, diagnostic };
2428
- }
2496
+ var ZLINK_SESSION_CLOSING = ZlinkStreamControlPacket.SessionClosing;
2429
2497
 
2430
2498
  // packages/stream-connector/src/Runtime/ZlinkStreamReceiveDispatcher.ts
2431
2499
  function closeReasonFor(error) {
@@ -2551,27 +2619,21 @@ var ZlinkStreamConnectorBundle = (() => {
2551
2619
  }
2552
2620
  return;
2553
2621
  }
2554
- if (header.kind === 4 /* Error */ && header.requestSeq !== void 0) {
2622
+ if (header.kind === 4 /* Error */) {
2623
+ let error;
2555
2624
  try {
2556
- const remoteError = decodeRemoteError(this.decodePayload(header, payload));
2557
- if (!this.pendingRequests.reject(header.requestSeq, remoteError)) {
2558
- this.events.publishError(remoteError, signal);
2559
- }
2625
+ error = decodeRemoteError(this.decodePayload(header, payload));
2560
2626
  } catch (cause) {
2561
2627
  if (cause instanceof ZlinkStreamConnectionEnd) throw cause;
2562
- const decodeError = toStreamError(
2628
+ error = toStreamError(
2563
2629
  cause,
2564
2630
  "frameDecodeFailed" /* FrameDecodeFailed */,
2565
2631
  "Remote error payload is invalid."
2566
2632
  );
2567
- if (!this.pendingRequests.reject(header.requestSeq, decodeError)) {
2568
- this.events.publishError(decodeError, signal);
2569
- }
2570
2633
  }
2571
- return;
2572
- }
2573
- if (header.kind === 4 /* Error */) {
2574
- this.events.publishError(decodeRemoteError(this.decodePayload(header, payload)), signal);
2634
+ if (header.requestSeq === void 0 || !this.pendingRequests.reject(header.requestSeq, error)) {
2635
+ this.events.publishError(error, signal);
2636
+ }
2575
2637
  return;
2576
2638
  }
2577
2639
  if (header.kind === 5 /* Control */) {
@@ -2597,7 +2659,7 @@ var ZlinkStreamConnectorBundle = (() => {
2597
2659
  return;
2598
2660
  }
2599
2661
  if (header.name === ZLINK_SESSION_CLOSING) {
2600
- const closing = decodeSessionClosing(payload);
2662
+ const closing = decodeStreamWireSessionClosing(payload);
2601
2663
  await ((_a = this.serverClosing) == null ? void 0 : _a.call(this, closing.closeReason));
2602
2664
  return;
2603
2665
  }
@@ -2638,8 +2700,11 @@ var ZlinkStreamConnectorBundle = (() => {
2638
2700
  }
2639
2701
 
2640
2702
  // packages/stream-connector/src/Runtime/ZlinkStreamConnectorLifecycle.ts
2703
+ var RECONNECT_JITTER_FLOOR = 0.5;
2641
2704
  function randomizedDelay(baseDelayMs) {
2642
- return Math.round(baseDelayMs * (0.5 + Math.random() * 0.5));
2705
+ return Math.round(
2706
+ baseDelayMs * (RECONNECT_JITTER_FLOOR + Math.random() * (1 - RECONNECT_JITTER_FLOOR))
2707
+ );
2643
2708
  }
2644
2709
  var ZlinkStreamConnectorLifecycle = class {
2645
2710
  constructor(options, pendingRequests, frameSender, receiveDispatcher, receivedMessages, actors, events) {
@@ -2667,7 +2732,6 @@ var ZlinkStreamConnectorBundle = (() => {
2667
2732
  __publicField(this, "closeRequested", false);
2668
2733
  __publicField(this, "disconnectedPublished", false);
2669
2734
  __publicField(this, "closeReasonValue");
2670
- __publicField(this, "lateConnectCleanupError");
2671
2735
  }
2672
2736
  get isConnected() {
2673
2737
  return this.currentState === "connected" /* Connected */;
@@ -2711,12 +2775,7 @@ var ZlinkStreamConnectorBundle = (() => {
2711
2775
  try {
2712
2776
  const connection = await this.connectWithReconnect(attempts.signal);
2713
2777
  if (this.closeRequested) {
2714
- try {
2715
- await connection.close(signal);
2716
- } catch (error) {
2717
- this.lateConnectCleanupError = error;
2718
- throw error;
2719
- }
2778
+ await this.closeTransport(connection, void 0, signal);
2720
2779
  throw connectorError(
2721
2780
  "disconnected" /* Disconnected */,
2722
2781
  "Connector closed while connecting."
@@ -2796,23 +2855,10 @@ var ZlinkStreamConnectorBundle = (() => {
2796
2855
  (_a = this.connectAbort) == null ? void 0 : _a.abort();
2797
2856
  await ((_b = this.connectTask) == null ? void 0 : _b.catch(() => void 0));
2798
2857
  await ((_c = this.disconnectTask) == null ? void 0 : _c.catch(() => void 0));
2799
- const errors = [];
2800
- if (this.lateConnectCleanupError !== void 0) {
2801
- errors.push(this.lateConnectCleanupError);
2802
- this.lateConnectCleanupError = void 0;
2803
- }
2804
- try {
2805
- await this.tearDownConnection(
2806
- { code: "disconnected" /* Disconnected */, message: "Connector closed." },
2807
- signal
2808
- );
2809
- } catch (error) {
2810
- errors.push(error);
2811
- }
2812
- this.setState("closed" /* Closed */, void 0, signal);
2813
- this.publishDisconnected(signal);
2814
- if (errors.length === 1) throw errors[0];
2815
- if (errors.length > 1) throw new AggregateError(errors, "Stream connector close failed.");
2858
+ await this.tearDownConnection(
2859
+ { code: "disconnected" /* Disconnected */, message: "Connector closed." },
2860
+ signal
2861
+ );
2816
2862
  }
2817
2863
  /**
2818
2864
  * Spec stream-connector 32 §7: `dispatch` runs the callbacks the receive loop
@@ -3021,19 +3067,26 @@ var ZlinkStreamConnectorBundle = (() => {
3021
3067
  if (this.disconnectTask !== void 0) {
3022
3068
  return await this.disconnectTask;
3023
3069
  }
3024
- this.disconnectTask = this.tearDownConnection(error).catch(() => {
3025
- }).finally(() => {
3026
- this.disconnectTask = void 0;
3070
+ let resolve;
3071
+ let reject;
3072
+ const pending = new Promise((complete, fail) => {
3073
+ resolve = complete;
3074
+ reject = fail;
3027
3075
  });
3028
- await this.disconnectTask;
3029
- await this.announceDisconnect(error);
3076
+ const task = pending.finally(() => {
3077
+ if (this.disconnectTask === task) this.disconnectTask = void 0;
3078
+ });
3079
+ this.disconnectTask = task;
3080
+ void this.tearDownConnection(error).then(resolve, reject);
3081
+ await task;
3082
+ this.announceDisconnect();
3030
3083
  }
3031
3084
  isCurrentConnection(connection, generation) {
3032
3085
  return !this.closeRequested && this.currentConnection === connection && this.connectionGeneration === generation;
3033
3086
  }
3034
3087
  /**
3035
3088
  * Ends the current connection, for close and for transport loss alike. No
3036
- * application callback runs from here. Spec stream-connector 32 §7 and §9:
3089
+ * application callback runs before terminal operations settle. Spec stream-connector 32 §7 and §9:
3037
3090
  * every operation the ending connection fails (the frames it has not
3038
3091
  * written, the one it is writing and the pending requests) fails with
3039
3092
  * `Disconnected`, whatever ended it; the cause stays in the close reason.
@@ -3054,7 +3107,31 @@ var ZlinkStreamConnectorBundle = (() => {
3054
3107
  this.pendingRequests.failAll(disconnected);
3055
3108
  this.receivedMessages.connectionEnded();
3056
3109
  this.actors.closeAll(signal);
3057
- await (connection == null ? void 0 : connection.close(signal));
3110
+ await this.closeTransport(connection, error, signal);
3111
+ }
3112
+ async closeTransport(connection, error, signal) {
3113
+ try {
3114
+ try {
3115
+ await (connection == null ? void 0 : connection.close(signal));
3116
+ } finally {
3117
+ this.setState(
3118
+ this.closeRequested ? "closed" /* Closed */ : "disconnected" /* Disconnected */,
3119
+ this.closeRequested ? void 0 : error,
3120
+ signal
3121
+ );
3122
+ }
3123
+ } catch (cause) {
3124
+ this.events.publishError(
3125
+ {
3126
+ code: "disconnected" /* Disconnected */,
3127
+ message: `Transport close failed: ${cause instanceof Error ? cause.message : String(cause)}`,
3128
+ cause
3129
+ },
3130
+ signal
3131
+ );
3132
+ } finally {
3133
+ this.publishDisconnected(signal);
3134
+ }
3058
3135
  }
3059
3136
  /**
3060
3137
  * Runs once the teardown promise has settled, so a handler reached from here
@@ -3064,10 +3141,7 @@ var ZlinkStreamConnectorBundle = (() => {
3064
3141
  * handler that is slow — or whose promise never settles at all — must not
3065
3142
  * cost the connector the attempt.
3066
3143
  */
3067
- async announceDisconnect(error) {
3068
- if (this.closeRequested) return;
3069
- this.setState("disconnected" /* Disconnected */, error);
3070
- this.publishDisconnected();
3144
+ announceDisconnect() {
3071
3145
  if (this.shouldReconnect()) {
3072
3146
  queueMicrotask(() => {
3073
3147
  void this.connect().catch(() => void 0);
@@ -3111,16 +3185,13 @@ var ZlinkStreamConnectorBundle = (() => {
3111
3185
  __publicField(this, "stateHandlers", /* @__PURE__ */ new Set());
3112
3186
  }
3113
3187
  onError(handler) {
3114
- this.errorHandlers.add(handler);
3115
- return subscription(() => this.errorHandlers.delete(handler));
3188
+ return registerHandler(this.errorHandlers, handler);
3116
3189
  }
3117
3190
  onDisconnected(handler) {
3118
- this.disconnectedHandlers.add(handler);
3119
- return subscription(() => this.disconnectedHandlers.delete(handler));
3191
+ return registerHandler(this.disconnectedHandlers, handler);
3120
3192
  }
3121
3193
  onStateChanged(handler) {
3122
- this.stateHandlers.add(handler);
3123
- return subscription(() => this.stateHandlers.delete(handler));
3194
+ return registerHandler(this.stateHandlers, handler);
3124
3195
  }
3125
3196
  publishError(error, signal) {
3126
3197
  this.publish(this.errorHandlers, (handler) => handler(error, signal), signal);
@@ -3148,13 +3219,13 @@ var ZlinkStreamConnectorBundle = (() => {
3148
3219
  publish(handlers, invoke, signal) {
3149
3220
  this.enqueueCallback(
3150
3221
  () => {
3151
- for (const handler of Array.from(handlers)) {
3222
+ for (const handler of currentRegistrations(handlers)) {
3152
3223
  const report = (cause) => this.reportFailure(
3153
3224
  cause,
3154
3225
  signal,
3155
3226
  handlers === this.errorHandlers ? handler : void 0
3156
3227
  );
3157
- this.invoke(() => invoke(handler), report);
3228
+ this.invoke(() => invoke(handler.handler), report);
3158
3229
  }
3159
3230
  },
3160
3231
  () => handlers.size
@@ -3177,15 +3248,22 @@ var ZlinkStreamConnectorBundle = (() => {
3177
3248
  (candidate) => !attempted.has(candidate)
3178
3249
  );
3179
3250
  if (remaining.length === 0) return;
3180
- const nextAttempted = /* @__PURE__ */ new Set([...attempted, ...remaining]);
3251
+ const nextAttempted = new Set(attempted);
3252
+ for (const handler of remaining) nextAttempted.add(handler);
3181
3253
  this.enqueueCallback(
3182
3254
  () => {
3183
- for (const handler of remaining) {
3255
+ for (const handler of currentRegistrations(this.errorHandlers, remaining)) {
3184
3256
  const report = (cause) => this.reportToRemaining({ ...error, cause }, signal, nextAttempted);
3185
- this.invoke(() => handler(error, signal), report);
3257
+ const callback = handler.handler;
3258
+ this.invoke(() => callback(error, signal), report);
3186
3259
  }
3187
3260
  },
3188
- () => remaining.length
3261
+ () => {
3262
+ let count = 0;
3263
+ const registrations = currentRegistrations(this.errorHandlers, remaining);
3264
+ while (registrations.next().done !== true) count += 1;
3265
+ return count;
3266
+ }
3189
3267
  );
3190
3268
  }
3191
3269
  invoke(run, report) {
@@ -3333,7 +3411,7 @@ var ZlinkStreamConnectorBundle = (() => {
3333
3411
  const message = this.messages[this.messageHead];
3334
3412
  this.messages[this.messageHead] = void 0;
3335
3413
  this.messageHead += 1;
3336
- if (this.messageHead >= 1024 && this.messageHead * 2 >= this.messages.length) {
3414
+ if (shouldCompactBackingArray(this.messageHead, this.messages.length)) {
3337
3415
  this.messages.splice(0, this.messageHead);
3338
3416
  this.messageHead = 0;
3339
3417
  }
@@ -3348,8 +3426,8 @@ var ZlinkStreamConnectorBundle = (() => {
3348
3426
  connectTimeoutMs
3349
3427
  );
3350
3428
  const onOpen = () => finish();
3351
- const onClose = () => finish(connectorError("connectTimeout" /* ConnectTimeout */, "Connect closed before opening."));
3352
- const onError = () => finish(connectorError("connectTimeout" /* ConnectTimeout */, "Connect failed."));
3429
+ const onClose = () => finish(connectorError("disconnected" /* Disconnected */, "Connect closed before opening."));
3430
+ const onError = () => finish(connectorError("disconnected" /* Disconnected */, "Connect failed."));
3353
3431
  const onAbort = () => finish(connectorError("disconnected" /* Disconnected */, "Connect canceled."));
3354
3432
  const finish = (error) => {
3355
3433
  clearTimeout(timeout);
@@ -3471,12 +3549,10 @@ var ZlinkStreamConnectorBundle = (() => {
3471
3549
  return this.events.onStateChanged(handler);
3472
3550
  }
3473
3551
  onRequestSending(handler) {
3474
- this.requestSendingHandlers.add(handler);
3475
- return subscription(() => this.requestSendingHandlers.delete(handler));
3552
+ return registerHandler(this.requestSendingHandlers, handler);
3476
3553
  }
3477
3554
  onReplyReceived(handler) {
3478
- this.replyReceivedHandlers.add(handler);
3479
- return subscription(() => this.replyReceivedHandlers.delete(handler));
3555
+ return registerHandler(this.replyReceivedHandlers, handler);
3480
3556
  }
3481
3557
  async connect(signal) {
3482
3558
  await this.lifecycle.connect(signal);
@@ -3713,7 +3789,7 @@ var ZlinkStreamConnectorBundle = (() => {
3713
3789
  let stopCancellation;
3714
3790
  try {
3715
3791
  throwIfAborted(signal);
3716
- for (const handler of Array.from(this.requestSendingHandlers)) {
3792
+ for (const { handler } of currentRegistrations(this.requestSendingHandlers)) {
3717
3793
  try {
3718
3794
  handler(sendingContext);
3719
3795
  } catch (cause) {
@@ -3785,7 +3861,7 @@ var ZlinkStreamConnectorBundle = (() => {
3785
3861
  if (this.replyReceivedHandlers.size === 0) return;
3786
3862
  this.receivedMessages.enqueueCallback(
3787
3863
  () => {
3788
- for (const handler of Array.from(this.replyReceivedHandlers)) {
3864
+ for (const { handler } of currentRegistrations(this.replyReceivedHandlers)) {
3789
3865
  this.events.runUserCallback(
3790
3866
  () => handler(context, signal),
3791
3867
  "Reply received hook failed.",