@zlink-systems/stream-connector 0.17.0 → 0.18.1

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.
@@ -659,6 +659,53 @@ function utf8Decode2(value) {
659
659
  return new TextDecoder().decode(value);
660
660
  }
661
661
 
662
+ // packages/stream-connector/src/Runtime/ZlinkStreamAssertions.ts
663
+ var zlinkStreamAssert = {
664
+ ensure(condition, message) {
665
+ if (typeof message !== "string" || message.trim().length === 0) {
666
+ throw connectorError("validationFailed" /* ValidationFailed */, "zlinkStreamAssert.ensure requires a non-empty diagnostic message.");
667
+ }
668
+ if (!condition) {
669
+ throw connectorError("validationFailed" /* ValidationFailed */, message);
670
+ }
671
+ },
672
+ async expectFailure(action, errorKind) {
673
+ let failure;
674
+ try {
675
+ await action();
676
+ } catch (error) {
677
+ failure = error;
678
+ }
679
+ if (failure === void 0) {
680
+ throw connectorError("validationFailed" /* ValidationFailed */, "Expected action to fail.");
681
+ }
682
+ const streamError = unwrapStreamError(failure);
683
+ if (errorKind !== void 0 && streamError.code !== errorKind) {
684
+ throw connectorError(
685
+ "validationFailed" /* ValidationFailed */,
686
+ `Expected failure kind '${errorKind}', got '${streamError.code}'.`,
687
+ failure
688
+ );
689
+ }
690
+ return streamError;
691
+ },
692
+ async expectTimeout(action) {
693
+ let failure;
694
+ try {
695
+ await action();
696
+ } catch (error) {
697
+ failure = error;
698
+ }
699
+ if (failure === void 0) {
700
+ throw connectorError("validationFailed" /* ValidationFailed */, "Expected action to time out.");
701
+ }
702
+ const code = unwrapStreamError(failure).code;
703
+ if (code !== "requestTimeout" /* RequestTimeout */ && code !== "connectTimeout" /* ConnectTimeout */) {
704
+ throw failure;
705
+ }
706
+ }
707
+ };
708
+
662
709
  // packages/stream-connector/src/Runtime/Protocol/ZlinkStreamPacketNameValidator.ts
663
710
  function validateName(name, allowReserved = false) {
664
711
  if (name.length === 0) {
@@ -814,14 +861,17 @@ var ZlinkStreamWaitBuilder = class {
814
861
  this.timeoutMs = timeoutMs;
815
862
  return this;
816
863
  }
817
- submit(signal) {
864
+ async submit(signal) {
818
865
  this.markExecuted();
819
- return this.connector.waitForMessage(
820
- this.name,
821
- this.timeoutMs ?? this.connector.options.waitTimeoutMs,
822
- this.predicate,
823
- signal
824
- );
866
+ const timeoutMs = this.timeoutMs ?? this.connector.options.waitTimeoutMs;
867
+ const message = await this.connector.waitForMessage(this.name, timeoutMs, this.predicate, signal);
868
+ if (message === void 0) {
869
+ throw connectorError(
870
+ "validationFailed" /* ValidationFailed */,
871
+ `No '${this.name}' message arrived within ${timeoutMs}ms.`
872
+ );
873
+ }
874
+ return message;
825
875
  }
826
876
  ensureConfigurable() {
827
877
  if (this.executed) {
@@ -853,13 +903,9 @@ var ZlinkStreamExpectNoneBuilder = class {
853
903
  if (this.windowMs === void 0) {
854
904
  throw connectorError("validationFailed" /* ValidationFailed */, "expectNone requires within(windowMs).");
855
905
  }
856
- try {
857
- await this.connector.waitForMessage(this.name, this.windowMs, () => true, signal);
858
- } catch (error) {
859
- if (unwrapStreamError(error).code === "requestTimeout" /* RequestTimeout */) {
860
- return;
861
- }
862
- throw error;
906
+ const message = await this.connector.waitForMessage(this.name, this.windowMs, () => true, signal);
907
+ if (message === void 0) {
908
+ return;
863
909
  }
864
910
  throw connectorError(
865
911
  "validationFailed" /* ValidationFailed */,
@@ -895,6 +941,9 @@ var ZlinkStreamSequenceBuilder = class {
895
941
  this.timeoutMs = timeoutMs;
896
942
  return this;
897
943
  }
944
+ // Spec stream-connector 32 §10.1: the predicate reads the whole message, and
945
+ // the call answers with the messages themselves, so a caller can assert on the
946
+ // packet name and the metadata and not only on the payload.
898
947
  async run(signal) {
899
948
  this.markExecuted();
900
949
  if (this.predicates.length === 0) {
@@ -902,13 +951,13 @@ var ZlinkStreamSequenceBuilder = class {
902
951
  }
903
952
  const timeoutMs = this.timeoutMs ?? this.connector.options.waitTimeoutMs;
904
953
  const deadline = Date.now() + timeoutMs;
905
- const payloads = [];
954
+ const messages = [];
906
955
  for (const predicate of this.predicates) {
907
956
  const message = await this.connector.waitForMessage(
908
957
  this.name,
909
958
  Math.max(0, deadline - Date.now()),
910
959
  (candidate) => {
911
- if (!predicate(candidate.payload)) {
960
+ if (!predicate(candidate)) {
912
961
  throw connectorError(
913
962
  "validationFailed" /* ValidationFailed */,
914
963
  `Message '${this.name}' arrived out of the expected sequence.`
@@ -918,9 +967,15 @@ var ZlinkStreamSequenceBuilder = class {
918
967
  },
919
968
  signal
920
969
  );
921
- payloads.push(message.payload);
970
+ if (message === void 0) {
971
+ throw connectorError(
972
+ "validationFailed" /* ValidationFailed */,
973
+ `The '${this.name}' sequence did not complete within ${timeoutMs}ms.`
974
+ );
975
+ }
976
+ messages.push(message);
922
977
  }
923
- return payloads;
978
+ return messages;
924
979
  }
925
980
  ensureConfigurable() {
926
981
  if (this.executed) {
@@ -1021,7 +1076,7 @@ function splitZlinkStreamFrames(chunk) {
1021
1076
  }
1022
1077
  function validatePayload(payloadLength, maxPayloadSize) {
1023
1078
  if (payloadLength > maxPayloadSize) {
1024
- throw connectorError("frameTooLarge" /* FrameTooLarge */, "Payload exceeds MaxSendPayloadSize.");
1079
+ throw connectorError("validationFailed" /* ValidationFailed */, "Payload exceeds MaxSendPayloadSize.");
1025
1080
  }
1026
1081
  }
1027
1082
 
@@ -1303,22 +1358,30 @@ function normalizeOptions(options, defaultTransportFactory) {
1303
1358
  initialDelayMs: options.reconnect?.initialDelayMs ?? 250,
1304
1359
  maxDelayMs: options.reconnect?.maxDelayMs ?? 5e3,
1305
1360
  backoffFactor: options.reconnect?.backoffFactor ?? 2,
1306
- maxAttempts: options.reconnect?.maxAttempts ?? 3
1361
+ maxAttempts: options.reconnect?.maxAttempts === void 0 ? 3 : options.reconnect.maxAttempts
1307
1362
  },
1308
1363
  maxSendPayloadSize: options.maxSendPayloadSize ?? 64 * 1024,
1309
1364
  maxReceivePayloadSize: options.maxReceivePayloadSize ?? 64 * 1024,
1310
1365
  dispatchMode: options.dispatchMode ?? "manual" /* Manual */,
1311
1366
  compression: options.compression ?? "lz4" /* Lz4 */,
1312
1367
  compressionCodec: resolveCompressionCodec2(options),
1313
- nameResolver: options.nameResolver ?? { resolve: (type) => type.name },
1368
+ nameResolver: options.nameResolver ?? defaultPacketNameResolver,
1314
1369
  transportFactory: options.transportFactory ?? defaultTransportFactory,
1315
1370
  codec: options.codec,
1316
- meterProvider: options.meterProvider,
1317
1371
  // Spec 26 §4: the default diagnostics level is Errors, which preserves
1318
1372
  // the connector's established wire behavior.
1319
1373
  diagnosticsLevel: options.diagnosticsLevel ?? "errors" /* Errors */
1320
1374
  };
1321
1375
  }
1376
+ var defaultPacketNameResolver = {
1377
+ resolve(payloadType) {
1378
+ const declared = payloadType.packetName;
1379
+ if (typeof declared === "string" && declared.length > 0) {
1380
+ return declared;
1381
+ }
1382
+ return payloadType.name;
1383
+ }
1384
+ };
1322
1385
  function resolveCompressionCodec2(options) {
1323
1386
  const compression = options.compression ?? "lz4" /* Lz4 */;
1324
1387
  if (compression === "none" /* None */) {
@@ -1362,7 +1425,8 @@ function validateReconnect(options) {
1362
1425
  if ((options?.backoffFactor ?? 2) < 1) {
1363
1426
  throw connectorError("validationFailed" /* ValidationFailed */, "Reconnect BackoffFactor must be at least 1.0.");
1364
1427
  }
1365
- if ((options?.maxAttempts ?? 3) <= 0) {
1428
+ const maxAttempts = options?.maxAttempts === void 0 ? 3 : options.maxAttempts;
1429
+ if (maxAttempts !== null && !(Number.isFinite(maxAttempts) && maxAttempts > 0)) {
1366
1430
  throw connectorError("validationFailed" /* ValidationFailed */, "Reconnect MaxAttempts must be null or positive.");
1367
1431
  }
1368
1432
  }
@@ -1486,6 +1550,16 @@ var ZlinkStreamReceivedMessages = class {
1486
1550
  queueHead = 0;
1487
1551
  queuedCount = 0;
1488
1552
  drainTask;
1553
+ // True for as long as `drain` is on the stack, handler awaits included. It
1554
+ // marks the execution context a registered handler runs in, so a `dispatch`
1555
+ // made from inside a handler is recognised as re-entry rather than a fresh
1556
+ // pump. It is not a lock: a single event loop admits no second thread, and
1557
+ // nothing ever waits for this flag to fall.
1558
+ draining = false;
1559
+ // Spec stream-connector 32 §10: arrivals per packet name on the current
1560
+ // connection. It is raised where a packet arrives, never where one is taken,
1561
+ // so consuming does not lower it and the dispatch mode does not change it.
1562
+ receivedCounts = /* @__PURE__ */ new Map();
1489
1563
  on(name, handler) {
1490
1564
  validateName(name);
1491
1565
  let set = this.handlers.get(name);
@@ -1511,30 +1585,86 @@ var ZlinkStreamReceivedMessages = class {
1511
1585
  * `Manual` needs no dispatch pump to complete a wait. The queue is scanned in
1512
1586
  * a microtask so a message that arrived before the wait started is still
1513
1587
  * observed, and so the caller has its subscription in hand by then.
1588
+ *
1589
+ * @param onConnectionEnded Called, instead of {@link observer}, when
1590
+ * {@link connectionEnded} abandons this registration because the
1591
+ * connection it was watching ended before a message matched (spec
1592
+ * stream-connector 32 §10.1.1: "연결이 끝나 대기를 이어갈 수 없으면
1593
+ * `Disconnected`다", released when that connection ends).
1514
1594
  */
1515
- observe(name, observer) {
1595
+ observe(name, observer, onConnectionEnded) {
1516
1596
  validateName(name);
1517
1597
  let set = this.observers.get(name);
1518
1598
  if (set === void 0) {
1519
1599
  set = /* @__PURE__ */ new Set();
1520
1600
  this.observers.set(name, set);
1521
1601
  }
1522
- set.add(observer);
1602
+ const registration = { consume: observer, onConnectionEnded };
1603
+ set.add(registration);
1523
1604
  queueMicrotask(() => {
1524
- if (this.observers.get(name)?.has(observer) === true) {
1525
- this.offerQueued(name, observer);
1605
+ if (this.observers.get(name)?.has(registration) === true) {
1606
+ this.offerQueued(name, registration);
1526
1607
  }
1527
1608
  });
1528
1609
  return subscription(() => {
1529
- set.delete(observer);
1610
+ set.delete(registration);
1530
1611
  if (set.size === 0 && this.observers.get(name) === set) {
1531
1612
  this.observers.delete(name);
1532
1613
  }
1533
1614
  });
1534
1615
  }
1616
+ /** Spec stream-connector 32 §10: arrivals under `name` on this connection. */
1617
+ receivedCount(name) {
1618
+ return this.receivedCounts.get(name) ?? 0;
1619
+ }
1620
+ /**
1621
+ * Rebaselines the queue for a connection that was just established. Spec
1622
+ * stream-connector 32 §10 (line ~649): the reference point is the moment a
1623
+ * connection is established, so counts restart at 0 and whatever the
1624
+ * previous connection left unconsumed goes with it — keeping the queue
1625
+ * while only the counts reset would let counts and queue describe two
1626
+ * different connections, and let `waitFor` hand back a packet from before
1627
+ * the drop as if the new connection had delivered it.
1628
+ *
1629
+ * `ZlinkStreamMessage`/`ZlinkStreamEncodedPayload` are plain data (name,
1630
+ * metadata, a `Uint8Array` payload) with no dispose/close of their own —
1631
+ * unlike Java's queued frames, which `closeMessage` releases — so dropping
1632
+ * the queue's references is the whole of the release here.
1633
+ *
1634
+ * Wait surfaces are not touched here. The ones of the previous connection
1635
+ * were released by {@link connectionEnded} when that connection ended, and
1636
+ * one registered since then is waiting for this connection.
1637
+ */
1638
+ resetForNewConnection() {
1639
+ this.receivedCounts.clear();
1640
+ this.queue.length = 0;
1641
+ this.queueHead = 0;
1642
+ this.queuedCount = 0;
1643
+ }
1644
+ /**
1645
+ * Releases every registered wait surface because the connection it was
1646
+ * watching has ended — a transport loss, a server close, or `close()`.
1647
+ * Spec stream-connector 32 §10.1.1: "푸는 시점은 연결이 끝난 때이지 다음
1648
+ * 연결이 성립한 때가 아니다". The release belongs to the ending, so a wait
1649
+ * does not hang until its own timeout when no next connection comes
1650
+ * (reconnect off, attempts spent) and does not silently rebind to the next
1651
+ * one when it does. The queue and the counts stay: they are rebaselined by
1652
+ * the next {@link resetForNewConnection}, not by the ending (§10).
1653
+ */
1654
+ connectionEnded() {
1655
+ if (this.observers.size === 0) {
1656
+ return;
1657
+ }
1658
+ const abandoned = [...this.observers.values()].flatMap((set) => [...set]);
1659
+ this.observers.clear();
1660
+ for (const registration of abandoned) {
1661
+ registration.onConnectionEnded();
1662
+ }
1663
+ }
1535
1664
  enqueue(message, signal) {
1536
- for (const observer of [...this.observers.get(message.name) ?? []]) {
1537
- if (observer(message)) {
1665
+ this.receivedCounts.set(message.name, (this.receivedCounts.get(message.name) ?? 0) + 1);
1666
+ for (const registration of [...this.observers.get(message.name) ?? []]) {
1667
+ if (registration.consume(message)) {
1538
1668
  return;
1539
1669
  }
1540
1670
  }
@@ -1547,18 +1677,28 @@ var ZlinkStreamReceivedMessages = class {
1547
1677
  /**
1548
1678
  * Runs the registered handlers the receive path left queued. `Manual` calls
1549
1679
  * this from `dispatch`; `Immediate` has already drained on arrival.
1680
+ *
1681
+ * A handler that calls `dispatch` arrives back here from inside the drain it
1682
+ * was started by. `scheduleDrain` would find `drainTask` already set and
1683
+ * return, and the await below would then be the drain waiting on itself —
1684
+ * a deadlock with neither timeout nor error. The drain loop already takes
1685
+ * every message a handler exists for, so there is nothing a second drain
1686
+ * would deliver and returning is the whole of the correct behaviour.
1550
1687
  */
1551
1688
  async pump() {
1689
+ if (this.draining) {
1690
+ return;
1691
+ }
1552
1692
  this.scheduleDrain();
1553
1693
  await this.drainTask;
1554
1694
  }
1555
- offerQueued(name, observer) {
1695
+ offerQueued(name, registration) {
1556
1696
  for (let index = this.queueHead; index < this.queue.length; index += 1) {
1557
1697
  const queued = this.queue[index];
1558
1698
  if (queued === void 0 || queued.message.name !== name) {
1559
1699
  continue;
1560
1700
  }
1561
- if (!observer(queued.message)) {
1701
+ if (!registration.consume(queued.message)) {
1562
1702
  continue;
1563
1703
  }
1564
1704
  this.removeAt(index);
@@ -1577,23 +1717,28 @@ var ZlinkStreamReceivedMessages = class {
1577
1717
  });
1578
1718
  }
1579
1719
  async drain() {
1580
- for (let index = this.findDeliverableIndex(); index >= 0; index = this.findDeliverableIndex()) {
1581
- const queued = this.queue[index];
1582
- if (queued === void 0) continue;
1583
- this.removeAt(index);
1584
- const { message, signal } = queued;
1585
- const handlers = [...this.handlers.get(message.name)];
1586
- for (const handler of handlers) {
1587
- try {
1588
- await handler(message, signal);
1589
- } catch (cause) {
1590
- await this.events.publishError({
1591
- code: "userCallbackFailed" /* UserCallbackFailed */,
1592
- message: "Typed message handler failed.",
1593
- cause
1594
- }, signal);
1720
+ this.draining = true;
1721
+ try {
1722
+ for (let index = this.findDeliverableIndex(); index >= 0; index = this.findDeliverableIndex()) {
1723
+ const queued = this.queue[index];
1724
+ if (queued === void 0) continue;
1725
+ this.removeAt(index);
1726
+ const { message, signal } = queued;
1727
+ const handlers = [...this.handlers.get(message.name)];
1728
+ for (const handler of handlers) {
1729
+ try {
1730
+ await handler(message, signal);
1731
+ } catch (cause) {
1732
+ await this.events.publishError({
1733
+ code: "userCallbackFailed" /* UserCallbackFailed */,
1734
+ message: "Typed message handler failed.",
1735
+ cause
1736
+ }, signal);
1737
+ }
1595
1738
  }
1596
1739
  }
1740
+ } finally {
1741
+ this.draining = false;
1597
1742
  }
1598
1743
  }
1599
1744
  removeAt(index) {
@@ -1637,10 +1782,9 @@ var ZlinkStreamReceivedMessages = class {
1637
1782
 
1638
1783
  // packages/stream-connector/src/Runtime/ZlinkStreamFrameSender.ts
1639
1784
  var ZlinkStreamFrameSender = class {
1640
- constructor(protocol, flowContext, metrics) {
1785
+ constructor(protocol, flowContext) {
1641
1786
  this.protocol = protocol;
1642
1787
  this.flowContext = flowContext;
1643
- this.metrics = metrics;
1644
1788
  }
1645
1789
  pendingWrites = /* @__PURE__ */ new Set();
1646
1790
  async send(connection, kind, name, payload, metadata, compress, requestSeq, signal, correlationId, explicitFlow) {
@@ -1666,7 +1810,6 @@ var ZlinkStreamFrameSender = class {
1666
1810
  this.pendingWrites.add(write);
1667
1811
  try {
1668
1812
  await write;
1669
- this.metrics.outbound(frame.byteLength);
1670
1813
  } finally {
1671
1814
  this.pendingWrites.delete(write);
1672
1815
  }
@@ -1695,17 +1838,29 @@ function decodeSessionClosing(payload) {
1695
1838
 
1696
1839
  // packages/stream-connector/src/Runtime/ZlinkStreamReceiveDispatcher.ts
1697
1840
  var ZlinkStreamReceiveDispatcher = class {
1698
- constructor(protocol, pendingRequests, receivedMessages, frameSender, events, flowContext, metrics, serverClosing) {
1841
+ constructor(protocol, pendingRequests, receivedMessages, frameSender, events, flowContext, serverClosing) {
1699
1842
  this.protocol = protocol;
1700
1843
  this.pendingRequests = pendingRequests;
1701
1844
  this.receivedMessages = receivedMessages;
1702
1845
  this.frameSender = frameSender;
1703
1846
  this.events = events;
1704
1847
  this.flowContext = flowContext;
1705
- this.metrics = metrics;
1706
1848
  this.serverClosing = serverClosing;
1707
1849
  }
1708
- async readAndDispatch(connection, signal, isCurrent) {
1850
+ /**
1851
+ * @param isCurrent Tells whether the connection this batch was read from is
1852
+ * still the connector's connection. It is asked again at the head of every
1853
+ * frame, not only after the read: `dispatch` awaits application code —
1854
+ * registered handlers in `Immediate`, the error handler on a failed frame —
1855
+ * and a disconnect and reconnect can complete inside that await. Without
1856
+ * the recheck the rest of a dead connection's batch lands on the new
1857
+ * connection's state, and the §10 arrival counts, which start at 0 when a
1858
+ * connection is established, take the stale frames on top.
1859
+ * @param connectionForSend Resolves the connection a reply belongs on at the
1860
+ * moment it is written. The captured `connection` is the one the batch was
1861
+ * read from, which a reconnect may already have replaced.
1862
+ */
1863
+ async readAndDispatch(connection, signal, isCurrent, connectionForSend) {
1709
1864
  if (connection?.read === void 0) {
1710
1865
  return { available: false, inbound: false };
1711
1866
  }
@@ -1716,7 +1871,6 @@ var ZlinkStreamReceiveDispatcher = class {
1716
1871
  if (frameBytes === void 0) {
1717
1872
  return { available: false, inbound: false };
1718
1873
  }
1719
- this.metrics.inbound(frameBytes.byteLength);
1720
1874
  const flowEnabled = this.protocol.flowEnabled();
1721
1875
  let frames;
1722
1876
  try {
@@ -1729,8 +1883,11 @@ var ZlinkStreamReceiveDispatcher = class {
1729
1883
  return { available: true, inbound: false };
1730
1884
  }
1731
1885
  for (const frame of frames) {
1886
+ if (isCurrent !== void 0 && !isCurrent()) {
1887
+ break;
1888
+ }
1732
1889
  try {
1733
- await this.dispatch(connection, frame.header, frame.payload, signal, flowEnabled);
1890
+ await this.dispatch(connection, frame.header, frame.payload, signal, flowEnabled, connectionForSend);
1734
1891
  } catch (cause) {
1735
1892
  if (frame.header.kind === 5 /* Control */ && frame.header.name === ZLINK_STREAM_HEARTBEAT_PING) {
1736
1893
  throw cause;
@@ -1743,7 +1900,7 @@ var ZlinkStreamReceiveDispatcher = class {
1743
1900
  }
1744
1901
  return { available: true, inbound: true };
1745
1902
  }
1746
- async dispatch(connection, header, payload, signal, flowEnabled) {
1903
+ async dispatch(connection, header, payload, signal, flowEnabled, connectionForSend) {
1747
1904
  if (header.kind === 3 /* Response */ && header.requestSeq !== void 0) {
1748
1905
  try {
1749
1906
  if (!this.pendingRequests.resolve(header.requestSeq, {
@@ -1796,7 +1953,7 @@ var ZlinkStreamReceiveDispatcher = class {
1796
1953
  return;
1797
1954
  }
1798
1955
  if (header.kind === 5 /* Control */) {
1799
- await this.dispatchControl(connection, header, payload, signal);
1956
+ await this.dispatchControl(connection, header, payload, signal, connectionForSend);
1800
1957
  return;
1801
1958
  }
1802
1959
  if (header.kind === 1 /* Send */) {
@@ -1810,7 +1967,7 @@ var ZlinkStreamReceiveDispatcher = class {
1810
1967
  }, signal);
1811
1968
  }
1812
1969
  }
1813
- async dispatchControl(connection, header, payload, signal) {
1970
+ async dispatchControl(connection, header, payload, signal, connectionForSend) {
1814
1971
  if (header.name === ZLINK_SESSION_CLOSING) {
1815
1972
  const closing = decodeSessionClosing(payload);
1816
1973
  await this.serverClosing?.(closing.closeReason);
@@ -1821,7 +1978,11 @@ var ZlinkStreamReceiveDispatcher = class {
1821
1978
  }
1822
1979
  if (header.name === ZLINK_STREAM_HEARTBEAT_PING) {
1823
1980
  try {
1824
- await this.frameSender.sendControl(connection, ZLINK_STREAM_HEARTBEAT_PONG, signal);
1981
+ await this.frameSender.sendControl(
1982
+ connectionForSend?.() ?? connection,
1983
+ ZLINK_STREAM_HEARTBEAT_PONG,
1984
+ signal
1985
+ );
1825
1986
  } catch (cause) {
1826
1987
  throw connectorError(
1827
1988
  "sendFailed" /* SendFailed */,
@@ -1854,15 +2015,17 @@ function decodeRemoteError(protocol, header, payload) {
1854
2015
  }
1855
2016
 
1856
2017
  // packages/stream-connector/src/Runtime/ZlinkStreamConnectorLifecycle.ts
2018
+ function randomizedDelay(baseDelayMs) {
2019
+ return Math.round(baseDelayMs * (0.5 + Math.random() * 0.5));
2020
+ }
1857
2021
  var ZlinkStreamConnectorLifecycle = class {
1858
- constructor(options, pendingRequests, frameSender, receiveDispatcher, receivedMessages, events, metrics) {
2022
+ constructor(options, pendingRequests, frameSender, receiveDispatcher, receivedMessages, events) {
1859
2023
  this.options = options;
1860
2024
  this.pendingRequests = pendingRequests;
1861
2025
  this.frameSender = frameSender;
1862
2026
  this.receiveDispatcher = receiveDispatcher;
1863
2027
  this.receivedMessages = receivedMessages;
1864
2028
  this.events = events;
1865
- this.metrics = metrics;
1866
2029
  }
1867
2030
  receiveLoopAbort;
1868
2031
  receiveLoopSleeping = false;
@@ -1872,6 +2035,7 @@ var ZlinkStreamConnectorLifecycle = class {
1872
2035
  connectionGeneration = 0;
1873
2036
  currentState = "created" /* Created */;
1874
2037
  heartbeatTimer;
2038
+ heartbeatTickRunning = false;
1875
2039
  lastInboundAt = 0;
1876
2040
  closeTask;
1877
2041
  connectTask;
@@ -1922,6 +2086,7 @@ var ZlinkStreamConnectorLifecycle = class {
1922
2086
  this.currentConnection = connection;
1923
2087
  this.connectionGeneration += 1;
1924
2088
  this.disconnectedPublished = false;
2089
+ this.receivedMessages.resetForNewConnection();
1925
2090
  this.lastInboundAt = Date.now();
1926
2091
  await this.setState("connected" /* Connected */, void 0, signal);
1927
2092
  this.startHeartbeat();
@@ -1933,7 +2098,9 @@ var ZlinkStreamConnectorLifecycle = class {
1933
2098
  throw new ZlinkStreamException(error2);
1934
2099
  }
1935
2100
  const error = toStreamError(cause, "connectTimeout" /* ConnectTimeout */, "Connect failed.");
2101
+ this.closeReasonValue ??= "TransportError";
1936
2102
  await this.setState("disconnected" /* Disconnected */, error, signal);
2103
+ await this.publishDisconnectedOnce(signal);
1937
2104
  throw new ZlinkStreamException(error);
1938
2105
  }
1939
2106
  }
@@ -1979,8 +2146,9 @@ var ZlinkStreamConnectorLifecycle = class {
1979
2146
  errors.push(error);
1980
2147
  }
1981
2148
  this.pendingRequests.failAll({ code: "disconnected" /* Disconnected */, message: "Connector closed." });
2149
+ this.receivedMessages.connectionEnded();
1982
2150
  await this.setState("closed" /* Closed */, void 0, signal);
1983
- await this.publishDisconnectedOnce(signal);
2151
+ this.publishDisconnectedWithoutWaiting(signal);
1984
2152
  if (errors.length === 1) throw errors[0];
1985
2153
  if (errors.length > 1) throw new AggregateError(errors, "Stream connector close failed.");
1986
2154
  }
@@ -2011,7 +2179,8 @@ var ZlinkStreamConnectorLifecycle = class {
2011
2179
  const result = await this.receiveDispatcher.readAndDispatch(
2012
2180
  connection,
2013
2181
  signal,
2014
- () => this.isCurrentConnection(connection, generation)
2182
+ () => this.isCurrentConnection(connection, generation),
2183
+ () => this.connectionForSend()
2015
2184
  );
2016
2185
  if (result.inbound && this.isCurrentConnection(connection, generation)) {
2017
2186
  this.lastInboundAt = Date.now();
@@ -2023,25 +2192,18 @@ var ZlinkStreamConnectorLifecycle = class {
2023
2192
  let delayMs = this.options.reconnect.initialDelayMs;
2024
2193
  let lastError;
2025
2194
  const maxAttempts = this.options.reconnect.enabled ? this.options.reconnect.maxAttempts : 1;
2026
- while (attempt < maxAttempts) {
2195
+ const unlimited = maxAttempts === null;
2196
+ while (unlimited || attempt < maxAttempts) {
2027
2197
  attempt += 1;
2028
- if (attempt > 1) {
2029
- this.metrics.reconnect();
2030
- }
2031
- const handshakeStartedAt = performance.now();
2032
2198
  try {
2033
- const connection = await this.options.transportFactory.connect(this.options, signal);
2034
- this.metrics.handshakeCompleted(handshakeStartedAt);
2035
- return connection;
2199
+ return await this.options.transportFactory.connect(this.options, signal);
2036
2200
  } catch (cause) {
2037
- this.metrics.handshakeCompleted(handshakeStartedAt);
2038
- this.metrics.handshakeFailed(cause);
2039
2201
  lastError = toStreamError(cause, "connectTimeout" /* ConnectTimeout */, "Connect failed.");
2040
- if (!this.options.reconnect.enabled || attempt >= maxAttempts) {
2202
+ if (!this.options.reconnect.enabled || !unlimited && attempt >= maxAttempts) {
2041
2203
  break;
2042
2204
  }
2043
2205
  await this.setState("reconnecting" /* Reconnecting */, lastError, signal);
2044
- await delay(delayMs, signal);
2206
+ await delay(randomizedDelay(delayMs), signal);
2045
2207
  delayMs = Math.min(
2046
2208
  this.options.reconnect.maxDelayMs,
2047
2209
  Math.ceil(delayMs * this.options.reconnect.backoffFactor)
@@ -2057,15 +2219,25 @@ var ZlinkStreamConnectorLifecycle = class {
2057
2219
  if (!this.options.heartbeat.enabled) {
2058
2220
  return;
2059
2221
  }
2060
- this.heartbeatTimer = setInterval(() => {
2061
- void this.runHeartbeatTick();
2222
+ const timer = setInterval(() => {
2223
+ if (this.heartbeatTickRunning) {
2224
+ return;
2225
+ }
2226
+ this.heartbeatTickRunning = true;
2227
+ void this.runHeartbeatTick().finally(() => {
2228
+ if (this.heartbeatTimer === timer) {
2229
+ this.heartbeatTickRunning = false;
2230
+ }
2231
+ });
2062
2232
  }, this.options.heartbeat.intervalMs);
2233
+ this.heartbeatTimer = timer;
2063
2234
  }
2064
2235
  stopHeartbeat() {
2065
2236
  if (this.heartbeatTimer !== void 0) {
2066
2237
  clearInterval(this.heartbeatTimer);
2067
2238
  this.heartbeatTimer = void 0;
2068
2239
  }
2240
+ this.heartbeatTickRunning = false;
2069
2241
  }
2070
2242
  // Spec stream-connector 32 §7: the receive loop runs in both dispatch modes.
2071
2243
  // `Manual` only changes what the loop does with a frame — it queues the
@@ -2180,41 +2352,96 @@ var ZlinkStreamConnectorLifecycle = class {
2180
2352
  if (this.disconnectTask !== void 0) {
2181
2353
  return await this.disconnectTask;
2182
2354
  }
2183
- this.disconnectTask = this.disconnectOnce(error).finally(() => {
2355
+ this.disconnectTask = this.tearDownConnection(error).finally(() => {
2184
2356
  this.disconnectTask = void 0;
2185
2357
  });
2186
- return await this.disconnectTask;
2358
+ await this.disconnectTask;
2359
+ await this.announceDisconnect(error);
2187
2360
  }
2188
2361
  isCurrentConnection(connection, generation) {
2189
2362
  return !this.closeRequested && this.currentConnection === connection && this.connectionGeneration === generation;
2190
2363
  }
2191
- async disconnectOnce(error) {
2364
+ /** Transport teardown only — no application callback runs from here. */
2365
+ async tearDownConnection(error) {
2192
2366
  this.stopHeartbeat();
2193
2367
  this.stopReceiveLoop();
2194
2368
  const connection = this.currentConnection;
2195
2369
  this.currentConnection = void 0;
2196
2370
  this.pendingRequests.failAll(error);
2371
+ this.receivedMessages.connectionEnded();
2197
2372
  try {
2198
2373
  await connection?.close();
2199
2374
  } catch {
2200
2375
  }
2376
+ }
2377
+ /**
2378
+ * Runs once the teardown promise has settled, so a handler reached from here
2379
+ * may call `connect` without waiting for a task its own caller still holds.
2380
+ * The reconnect is queued before the notification is awaited for the same
2381
+ * reason: spec stream-connector 32 §6 has reconnect on by default, and a
2382
+ * handler that is slow — or whose promise never settles at all — must not
2383
+ * cost the connector the attempt. The state is already `Disconnected` and the
2384
+ * state handlers are already invoked by the time the queued microtask runs,
2385
+ * because `setState` records the state and hands the change to the handlers
2386
+ * before it awaits any of them.
2387
+ */
2388
+ async announceDisconnect(error) {
2201
2389
  if (this.closeRequested) return;
2202
- await this.setState("disconnected" /* Disconnected */, error);
2203
- await this.publishDisconnectedOnce();
2390
+ const announce = this.claimDisconnectedPublish();
2391
+ const notified = (async () => {
2392
+ await this.setState("disconnected" /* Disconnected */, error);
2393
+ if (announce) {
2394
+ await this.events.publishDisconnected();
2395
+ }
2396
+ })();
2204
2397
  if (this.shouldReconnect()) {
2205
2398
  queueMicrotask(() => {
2206
2399
  void this.connect().catch(() => void 0);
2207
2400
  });
2208
2401
  }
2402
+ await notified;
2209
2403
  }
2210
2404
  shouldReconnect() {
2211
2405
  return this.options.reconnect.enabled && !this.closeRequested;
2212
2406
  }
2213
- async publishDisconnectedOnce(signal) {
2214
- if (this.disconnectedPublished) return;
2407
+ // Synchronous test-and-set, taken before any await, so the single disconnect
2408
+ // notification the spec promises is claimed by exactly one caller even when
2409
+ // the publishing itself is deferred.
2410
+ claimDisconnectedPublish() {
2411
+ if (this.disconnectedPublished) return false;
2215
2412
  this.disconnectedPublished = true;
2413
+ return true;
2414
+ }
2415
+ async publishDisconnectedOnce(signal) {
2416
+ if (!this.claimDisconnectedPublish()) return;
2216
2417
  await this.events.publishDisconnected(signal);
2217
2418
  }
2419
+ /**
2420
+ * Spec stream-connector 32 §7: the connector runs the registered handler, it
2421
+ * does not wait for it to finish. `close` returns once its own work is done —
2422
+ * the drain, the transport close, the pending requests — having run the
2423
+ * disconnect handler but without looking at whether that handler has ended.
2424
+ *
2425
+ * Starting the publish without awaiting it still runs every handler right
2426
+ * here: an `async` function body runs synchronously up to its first `await`,
2427
+ * and `publishDisconnected` reaches each handler before that point. So the
2428
+ * handler has run by the time `close` returns, which is what the spec asks
2429
+ * for, while a handler that calls `close` no longer waits for the very
2430
+ * `closeTask` it is running inside. Java and C++ hand the handler to a queue
2431
+ * and return the same way.
2432
+ *
2433
+ * `claimDisconnectedPublish` is taken by the same call and before any await,
2434
+ * so deferring the completion never turns the one notification into two.
2435
+ *
2436
+ * Nothing awaits the promise, so a rejection would reach the process as an
2437
+ * unhandled rejection and kill it. Handler failures are already contained
2438
+ * where they were before this call stopped waiting — the `Promise.allSettled`
2439
+ * in `publishDisconnected` — and this `catch` covers what is left rather than
2440
+ * reporting the same failure a second time on the error surface.
2441
+ */
2442
+ publishDisconnectedWithoutWaiting(signal) {
2443
+ void this.publishDisconnectedOnce(signal).catch(() => void 0);
2444
+ }
2218
2445
  async setState(current, error, signal) {
2219
2446
  const previous = this.currentState;
2220
2447
  this.currentState = current;
@@ -2396,9 +2623,6 @@ var BrowserWebSocketConnection = class {
2396
2623
  this.readWaiter = void 0;
2397
2624
  resolve();
2398
2625
  };
2399
- if (this.hasQueuedMessage() || this.closed) {
2400
- this.wakeReader();
2401
- }
2402
2626
  });
2403
2627
  }
2404
2628
  wakeReader() {
@@ -2478,50 +2702,6 @@ function toUint8Array(data) {
2478
2702
  throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "WebSocket text messages are not supported.");
2479
2703
  }
2480
2704
 
2481
- // packages/stream-connector/src/Runtime/ZlinkStreamRuntimeMetrics.ts
2482
- var ZlinkStreamRuntimeMetrics = class {
2483
- constructor(options) {
2484
- this.options = options;
2485
- const meter = options.meterProvider?.getMeter("zlink.framework");
2486
- this.reconnects = meter?.createCounter("zlink.stream.reconnects", { unit: "{event}" });
2487
- this.handshakeDuration = meter?.createHistogram("zlink.stream.handshake.duration", { unit: "s" });
2488
- this.handshakeFailures = meter?.createCounter("zlink.stream.handshake.failures", { unit: "{failure}" });
2489
- this.inboundBytes = meter?.createCounter("zlink.stream.inbound.bytes", { unit: "By" });
2490
- this.outboundBytes = meter?.createCounter("zlink.stream.outbound.bytes", { unit: "By" });
2491
- }
2492
- reconnects;
2493
- handshakeDuration;
2494
- handshakeFailures;
2495
- inboundBytes;
2496
- outboundBytes;
2497
- reconnect() {
2498
- this.safe(() => this.reconnects?.add(1, { transport: this.transportLabel() }));
2499
- }
2500
- handshakeCompleted(startedAt) {
2501
- const seconds = (performance.now() - startedAt) / 1e3;
2502
- this.safe(() => this.handshakeDuration?.record(seconds, { transport: this.transportLabel() }));
2503
- }
2504
- handshakeFailed(error) {
2505
- const reason = error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError") ? "canceled" : "transport_error";
2506
- this.safe(() => this.handshakeFailures?.add(1, { transport: this.transportLabel(), reason }));
2507
- }
2508
- inbound(byteCount) {
2509
- this.safe(() => this.inboundBytes?.add(byteCount, { transport: this.transportLabel() }));
2510
- }
2511
- outbound(byteCount) {
2512
- this.safe(() => this.outboundBytes?.add(byteCount, { transport: this.transportLabel() }));
2513
- }
2514
- transportLabel() {
2515
- return this.options.endpoint.startsWith("wss:") ? "wss" : "ws";
2516
- }
2517
- safe(record) {
2518
- try {
2519
- record();
2520
- } catch {
2521
- }
2522
- }
2523
- };
2524
-
2525
2705
  // packages/stream-connector/src/Runtime/ZlinkStreamConnector.ts
2526
2706
  var DefaultZlinkStreamConnector = class {
2527
2707
  static heartbeatPingName = ZLINK_STREAM_HEARTBEAT_PING;
@@ -2544,9 +2724,8 @@ var DefaultZlinkStreamConnector = class {
2544
2724
  configurable: true,
2545
2725
  get: () => this.diagnosticsLevelCell.level
2546
2726
  });
2547
- const metrics = new ZlinkStreamRuntimeMetrics(this.options);
2548
2727
  const protocol = new ZlinkStreamFrameProtocol(this.options);
2549
- this.frameSender = new ZlinkStreamFrameSender(protocol, flowContext, metrics);
2728
+ this.frameSender = new ZlinkStreamFrameSender(protocol, flowContext);
2550
2729
  this.receivedMessages = new ZlinkStreamReceivedMessages(
2551
2730
  this.events,
2552
2731
  this.options.dispatchMode === "immediate" /* Immediate */
@@ -2558,7 +2737,6 @@ var DefaultZlinkStreamConnector = class {
2558
2737
  this.frameSender,
2559
2738
  this.events,
2560
2739
  flowContext,
2561
- metrics,
2562
2740
  (reason) => this.lifecycle.serverClosing(reason)
2563
2741
  );
2564
2742
  this.lifecycle = new ZlinkStreamConnectorLifecycle(
@@ -2567,8 +2745,7 @@ var DefaultZlinkStreamConnector = class {
2567
2745
  this.frameSender,
2568
2746
  this.receiveDispatcher,
2569
2747
  this.receivedMessages,
2570
- this.events,
2571
- metrics
2748
+ this.events
2572
2749
  );
2573
2750
  }
2574
2751
  get isConnected() {
@@ -2583,6 +2760,17 @@ var DefaultZlinkStreamConnector = class {
2583
2760
  get pendingDispatchCount() {
2584
2761
  return this.pendingRequests.count;
2585
2762
  }
2763
+ /**
2764
+ * Spec stream-connector 32 §10: how many packets carrying `name` arrived on
2765
+ * the current connection. Arrivals are what is counted, so a message a
2766
+ * handler dispatched or a wait surface consumed still counts, and `Manual`
2767
+ * and `Immediate` report the same number. Establishing a connection resets
2768
+ * the count to 0, a reconnect included.
2769
+ */
2770
+ receivedCount(name) {
2771
+ validateName(name);
2772
+ return this.receivedMessages.receivedCount(name);
2773
+ }
2586
2774
  /**
2587
2775
  * Current diagnostics level (spec 26 §4.1, spec stream-connector 32 §13).
2588
2776
  * Reflects the level set by the most recent {@link setDiagnosticsLevel}
@@ -2598,14 +2786,20 @@ var DefaultZlinkStreamConnector = class {
2598
2786
  * state update: it applies to processing points that read the level after
2599
2787
  * this call returns and is never applied retroactively to frames already
2600
2788
  * built. Rejects unknown values with {@link ZlinkStreamErrorCode.ConfigurationError}.
2601
- * Do not call this synchronous bridge from a framework execution context such
2602
- * as a handler or callback; use setDiagnosticsLevelAsync there.
2789
+ * Spec stream-connector 32 §13: this surface changes the value without
2790
+ * waiting for anything; it is not a blocking call over the asynchronous pair,
2791
+ * which a receive callback would otherwise make wait for its own completion.
2603
2792
  */
2604
2793
  setDiagnosticsLevel(level) {
2605
- void this.setDiagnosticsLevelAsync(level);
2794
+ this.diagnosticsLevelCell.set(level);
2606
2795
  }
2796
+ /**
2797
+ * Asynchronous counterpart of {@link setDiagnosticsLevel} (spec
2798
+ * stream-connector 32 §13). It changes the same value; awaiting it is how a
2799
+ * caller observes the change, and it never replaces the synchronous surface.
2800
+ */
2607
2801
  setDiagnosticsLevelAsync(level) {
2608
- this.diagnosticsLevelCell.set(level);
2802
+ this.setDiagnosticsLevel(level);
2609
2803
  return Promise.resolve();
2610
2804
  }
2611
2805
  onErrorReceived(handler) {
@@ -2644,18 +2838,41 @@ var DefaultZlinkStreamConnector = class {
2644
2838
  }, signal);
2645
2839
  return this.receivedMessages.on(name, encodedHandler);
2646
2840
  }
2647
- waitFor(name) {
2648
- validateName(name);
2649
- return new ZlinkStreamWaitBuilder(this, name);
2841
+ waitFor(nameOrType) {
2842
+ return new ZlinkStreamWaitBuilder(this, this.observedName(nameOrType));
2650
2843
  }
2651
- expectNone(name) {
2652
- validateName(name);
2653
- return new ZlinkStreamExpectNoneBuilder(this, name);
2844
+ expectNone(nameOrType) {
2845
+ return new ZlinkStreamExpectNoneBuilder(this, this.observedName(nameOrType));
2846
+ }
2847
+ waitForSequence(nameOrType) {
2848
+ return new ZlinkStreamSequenceBuilder(this, this.observedName(nameOrType));
2654
2849
  }
2655
- waitForSequence(name) {
2850
+ /**
2851
+ * Spec stream-connector 32 §10.1: each wait surface offers both ways of
2852
+ * naming a packet. A string is the name the caller states; a constructor
2853
+ * goes through the options' `nameResolver`, which is the same resolver
2854
+ * `send` and `request` use, so both paths land on one name for one type.
2855
+ */
2856
+ observedName(nameOrType) {
2857
+ const name = typeof nameOrType === "function" ? this.options.nameResolver.resolve(nameOrType) : nameOrType;
2858
+ if (typeof name !== "string") {
2859
+ throw connectorError("validationFailed" /* ValidationFailed */, "Packet name must be a string or a payload constructor.");
2860
+ }
2656
2861
  validateName(name);
2657
- return new ZlinkStreamSequenceBuilder(this, name);
2862
+ return name;
2658
2863
  }
2864
+ /**
2865
+ * Consumes the first message under `name` that `predicate` accepts, or
2866
+ * resolves `undefined` when `timeoutMs` elapses first.
2867
+ *
2868
+ * A timeout is not a failure here. Each wait surface decides what its own
2869
+ * timeout means — `waitFor` fails on it while `expectNone` succeeds — and
2870
+ * reports that decision as `ValidationFailed` (spec stream-connector 32
2871
+ * §10.1.1; .NET `ZlinkStreamReceivedMessages.WaitForAsync` parity). Losing
2872
+ * the connection the wait observes is the one ending decided here, because
2873
+ * the wait has no place left to observe: that is `Disconnected` for every
2874
+ * surface (§10.1.1).
2875
+ */
2659
2876
  waitForMessage(name, timeoutMs, predicate, signal) {
2660
2877
  validateName(name);
2661
2878
  if (!Number.isFinite(timeoutMs) || timeoutMs < 0) {
@@ -2683,9 +2900,7 @@ var DefaultZlinkStreamConnector = class {
2683
2900
  resolve(message);
2684
2901
  }
2685
2902
  };
2686
- timer = setTimeout(() => {
2687
- finish(connectorError("requestTimeout" /* RequestTimeout */, "Wait for stream message timed out."));
2688
- }, timeoutMs);
2903
+ timer = setTimeout(() => finish(), timeoutMs);
2689
2904
  signal?.addEventListener("abort", onAbort, { once: true });
2690
2905
  disposable = this.receivedMessages.observe(name, (message) => {
2691
2906
  if (done) {
@@ -2707,7 +2922,10 @@ var DefaultZlinkStreamConnector = class {
2707
2922
  finish(cause);
2708
2923
  }
2709
2924
  return true;
2710
- });
2925
+ }, () => finish(connectorError(
2926
+ "disconnected" /* Disconnected */,
2927
+ `The connection this wait for '${name}' observed has ended.`
2928
+ )));
2711
2929
  });
2712
2930
  }
2713
2931
  encodePayload(payload, messageType) {
@@ -2786,50 +3004,6 @@ function isEncodedPayload(value) {
2786
3004
  return typeof candidate.codec === "number" && candidate.payload instanceof Uint8Array;
2787
3005
  }
2788
3006
 
2789
- // packages/stream-connector/src/Runtime/ZlinkStreamAssertions.ts
2790
- var zlinkStreamAssert = {
2791
- ensure(condition, message) {
2792
- if (!condition) {
2793
- throw connectorError("validationFailed" /* ValidationFailed */, message);
2794
- }
2795
- },
2796
- async expectFailure(action, errorKind) {
2797
- let failure;
2798
- try {
2799
- await action();
2800
- } catch (error) {
2801
- failure = error;
2802
- }
2803
- if (failure === void 0) {
2804
- throw connectorError("validationFailed" /* ValidationFailed */, "Expected action to fail.");
2805
- }
2806
- const streamError = unwrapStreamError(failure);
2807
- if (errorKind !== void 0 && streamError.code !== errorKind) {
2808
- throw connectorError(
2809
- "validationFailed" /* ValidationFailed */,
2810
- `Expected failure kind '${errorKind}', got '${streamError.code}'.`,
2811
- failure
2812
- );
2813
- }
2814
- return streamError;
2815
- },
2816
- async expectTimeout(action) {
2817
- let failure;
2818
- try {
2819
- await action();
2820
- } catch (error) {
2821
- failure = error;
2822
- }
2823
- if (failure === void 0) {
2824
- throw connectorError("validationFailed" /* ValidationFailed */, "Expected action to time out.");
2825
- }
2826
- const code = unwrapStreamError(failure).code;
2827
- if (code !== "requestTimeout" /* RequestTimeout */ && code !== "connectTimeout" /* ConnectTimeout */) {
2828
- throw failure;
2829
- }
2830
- }
2831
- };
2832
-
2833
3007
  // packages/stream-connector/src/index.ts
2834
3008
  var zlinkStreamConnectorFactory = {
2835
3009
  create(options) {
@@ -2837,7 +3011,6 @@ var zlinkStreamConnectorFactory = {
2837
3011
  }
2838
3012
  };
2839
3013
  export {
2840
- DefaultZlinkStreamConnector,
2841
3014
  ZlinkStreamCodec,
2842
3015
  ZlinkStreamCompression,
2843
3016
  ZlinkStreamConnectionState,