@naeemo/capnp 0.4.0 → 0.5.2

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.
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
- import { a as QueuedCallManager, c as AnswerTable, d as QuestionTable, i as PipelineResolutionTracker, l as ExportTable, n as PIPELINE_CLIENT_SYMBOL, o as createPipelineClient, r as PipelineOpTracker, s as isPipelineClient, t as RpcConnection, u as ImportTable } from "./rpc-connection-Dz3rYT1P.js";
1
+ import { C as QuestionTable, S as ImportTable, _ as QueuedCallManager, a as serializeGetSchemaParams, b as AnswerTable, c as serializeSchemaRequest, d as parseSchemaNodes, f as SchemaFormat, g as PipelineResolutionTracker, h as PipelineOpTracker, i as deserializeSchemaResponse, l as serializeSchemaResponse, m as PIPELINE_CLIENT_SYMBOL, n as SCHEMA_MESSAGE_TYPES, o as serializeGetSchemaResults, p as SchemaNodeType, r as deserializeSchemaRequest, s as serializeListSchemasResults, t as RpcConnection, u as createSchemaRegistry, v as createPipelineClient, x as ExportTable, y as isPipelineClient } from "./rpc-connection-C3-uEtpd.js";
2
2
  import { createRequire } from "node:module";
3
+ import * as net from "node:net";
3
4
 
4
5
  //#region \0rolldown/runtime.js
5
6
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
@@ -132,6 +133,7 @@ var Segment = class Segment {
132
133
  */
133
134
  getWord(wordOffset) {
134
135
  const byteOffset = wordOffset * WORD_SIZE;
136
+ if (byteOffset + 8 > this._size) throw new Error(`Offset ${wordOffset} is outside the bounds of the segment (${this.wordCount} words)`);
135
137
  const low = BigInt(this.view.getUint32(byteOffset, true));
136
138
  return BigInt(this.view.getUint32(byteOffset + 4, true)) << BigInt(32) | low;
137
139
  }
@@ -140,6 +142,7 @@ var Segment = class Segment {
140
142
  */
141
143
  setWord(wordOffset, value) {
142
144
  const byteOffset = wordOffset * WORD_SIZE;
145
+ if (byteOffset + 8 > this.buffer.byteLength) throw new Error(`Offset ${wordOffset} is outside the bounds of the segment`);
143
146
  this.view.setUint32(byteOffset, Number(value & BigInt(4294967295)), true);
144
147
  this.view.setUint32(byteOffset + 4, Number(value >> BigInt(32)), true);
145
148
  }
@@ -641,73 +644,113 @@ var StructReader = class StructReader {
641
644
  getBool(bitOffset) {
642
645
  const byteOffset = Math.floor(bitOffset / 8);
643
646
  const bitInByte = bitOffset % 8;
644
- return (this.message.getSegment(this.segmentIndex).dataView.getUint8(this.wordOffset * WORD_SIZE + byteOffset) & 1 << bitInByte) !== 0;
647
+ const segment = this.message.getSegment(this.segmentIndex);
648
+ const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;
649
+ const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;
650
+ if (dataOffset < 0 || dataOffset >= dataSectionEnd) return false;
651
+ return (segment.dataView.getUint8(dataOffset) & 1 << bitInByte) !== 0;
645
652
  }
646
653
  /**
647
654
  * 获取 int8 字段
648
655
  */
649
656
  getInt8(byteOffset) {
650
- return this.message.getSegment(this.segmentIndex).dataView.getInt8(this.wordOffset * WORD_SIZE + byteOffset);
657
+ const segment = this.message.getSegment(this.segmentIndex);
658
+ const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;
659
+ const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;
660
+ if (dataOffset < 0 || dataOffset >= dataSectionEnd) return 0;
661
+ return segment.dataView.getInt8(dataOffset);
651
662
  }
652
663
  /**
653
664
  * 获取 int16 字段
654
665
  */
655
666
  getInt16(byteOffset) {
656
- return this.message.getSegment(this.segmentIndex).dataView.getInt16(this.wordOffset * WORD_SIZE + byteOffset, true);
667
+ const segment = this.message.getSegment(this.segmentIndex);
668
+ const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;
669
+ const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;
670
+ if (dataOffset < 0 || dataOffset + 2 > dataSectionEnd) return 0;
671
+ return segment.dataView.getInt16(dataOffset, true);
657
672
  }
658
673
  /**
659
674
  * 获取 int32 字段
660
675
  */
661
676
  getInt32(byteOffset) {
662
- return this.message.getSegment(this.segmentIndex).dataView.getInt32(this.wordOffset * WORD_SIZE + byteOffset, true);
677
+ const segment = this.message.getSegment(this.segmentIndex);
678
+ const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;
679
+ const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;
680
+ if (dataOffset < 0 || dataOffset + 4 > dataSectionEnd) return 0;
681
+ return segment.dataView.getInt32(dataOffset, true);
663
682
  }
664
683
  /**
665
684
  * 获取 int64 字段
666
685
  */
667
686
  getInt64(byteOffset) {
668
687
  const segment = this.message.getSegment(this.segmentIndex);
669
- const offset = this.wordOffset * WORD_SIZE + byteOffset;
670
- const low = BigInt(segment.dataView.getUint32(offset, true));
671
- return BigInt(segment.dataView.getInt32(offset + 4, true)) << BigInt(32) | low;
688
+ const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;
689
+ const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;
690
+ if (dataOffset < 0 || dataOffset + 8 > dataSectionEnd) return BigInt(0);
691
+ const low = BigInt(segment.dataView.getUint32(dataOffset, true));
692
+ return BigInt(segment.dataView.getInt32(dataOffset + 4, true)) << BigInt(32) | low;
672
693
  }
673
694
  /**
674
695
  * 获取 uint8 字段
675
696
  */
676
697
  getUint8(byteOffset) {
677
- return this.message.getSegment(this.segmentIndex).dataView.getUint8(this.wordOffset * WORD_SIZE + byteOffset);
698
+ const segment = this.message.getSegment(this.segmentIndex);
699
+ const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;
700
+ const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;
701
+ if (dataOffset < 0 || dataOffset >= dataSectionEnd) return 0;
702
+ return segment.dataView.getUint8(dataOffset);
678
703
  }
679
704
  /**
680
705
  * 获取 uint16 字段
681
706
  */
682
707
  getUint16(byteOffset) {
683
- return this.message.getSegment(this.segmentIndex).dataView.getUint16(this.wordOffset * WORD_SIZE + byteOffset, true);
708
+ const segment = this.message.getSegment(this.segmentIndex);
709
+ const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;
710
+ const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;
711
+ if (dataOffset < 0 || dataOffset + 2 > dataSectionEnd) return 0;
712
+ return segment.dataView.getUint16(dataOffset, true);
684
713
  }
685
714
  /**
686
715
  * 获取 uint32 字段
687
716
  */
688
717
  getUint32(byteOffset) {
689
- return this.message.getSegment(this.segmentIndex).dataView.getUint32(this.wordOffset * WORD_SIZE + byteOffset, true);
718
+ const segment = this.message.getSegment(this.segmentIndex);
719
+ const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;
720
+ const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;
721
+ if (dataOffset < 0 || dataOffset + 4 > dataSectionEnd) return 0;
722
+ return segment.dataView.getUint32(dataOffset, true);
690
723
  }
691
724
  /**
692
725
  * 获取 uint64 字段
693
726
  */
694
727
  getUint64(byteOffset) {
695
728
  const segment = this.message.getSegment(this.segmentIndex);
696
- const offset = this.wordOffset * WORD_SIZE + byteOffset;
697
- const low = BigInt(segment.dataView.getUint32(offset, true));
698
- return BigInt(segment.dataView.getUint32(offset + 4, true)) << BigInt(32) | low;
729
+ const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;
730
+ const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;
731
+ if (dataOffset < 0 || dataOffset + 8 > dataSectionEnd) return BigInt(0);
732
+ const low = BigInt(segment.dataView.getUint32(dataOffset, true));
733
+ return BigInt(segment.dataView.getUint32(dataOffset + 4, true)) << BigInt(32) | low;
699
734
  }
700
735
  /**
701
736
  * 获取 float32 字段
702
737
  */
703
738
  getFloat32(byteOffset) {
704
- return this.message.getSegment(this.segmentIndex).dataView.getFloat32(this.wordOffset * WORD_SIZE + byteOffset, true);
739
+ const segment = this.message.getSegment(this.segmentIndex);
740
+ const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;
741
+ const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;
742
+ if (dataOffset < 0 || dataOffset + 4 > dataSectionEnd) return 0;
743
+ return segment.dataView.getFloat32(dataOffset, true);
705
744
  }
706
745
  /**
707
746
  * 获取 float64 字段
708
747
  */
709
748
  getFloat64(byteOffset) {
710
- return this.message.getSegment(this.segmentIndex).dataView.getFloat64(this.wordOffset * WORD_SIZE + byteOffset, true);
749
+ const segment = this.message.getSegment(this.segmentIndex);
750
+ const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;
751
+ const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;
752
+ if (dataOffset < 0 || dataOffset + 8 > dataSectionEnd) return 0;
753
+ return segment.dataView.getFloat64(dataOffset, true);
711
754
  }
712
755
  /**
713
756
  * 获取文本字段
@@ -752,13 +795,18 @@ var StructReader = class StructReader {
752
795
  let actualStructSize = structSize;
753
796
  const segment = this.message.getSegment(segmentIndex);
754
797
  if (listPtr.elementSize === ElementSize.COMPOSITE) {
755
- const tagWord = segment.getWord(targetOffset);
756
- elementCount = Number(tagWord & BigInt(4294967295));
757
- actualStructSize = {
758
- dataWords: Number(tagWord >> BigInt(32) & BigInt(65535)),
759
- pointerCount: Number(tagWord >> BigInt(48) & BigInt(65535))
760
- };
761
- targetOffset += 1;
798
+ if (targetOffset < 0 || targetOffset >= segment.wordCount) return;
799
+ try {
800
+ const tagWord = segment.getWord(targetOffset);
801
+ elementCount = Number(tagWord & BigInt(4294967295));
802
+ actualStructSize = {
803
+ dataWords: Number(tagWord >> BigInt(32) & BigInt(65535)),
804
+ pointerCount: Number(tagWord >> BigInt(48) & BigInt(65535))
805
+ };
806
+ targetOffset += 1;
807
+ } catch {
808
+ return;
809
+ }
762
810
  }
763
811
  return new ListReader(this.message, segmentIndex, listPtr.elementSize, elementCount, actualStructSize, targetOffset);
764
812
  }
@@ -1698,6 +1746,316 @@ var WebSocketTransport = class WebSocketTransport {
1698
1746
  }
1699
1747
  };
1700
1748
 
1749
+ //#endregion
1750
+ //#region src/rpc/tcp-transport.ts
1751
+ /**
1752
+ * TCP Transport Implementation for Node.js
1753
+ *
1754
+ * Implements RpcTransport over raw TCP socket for C++ interop testing.
1755
+ * This allows direct communication with the official Cap'n Proto C++ implementation.
1756
+ */
1757
+ /**
1758
+ * TCP Transport for Cap'n Proto RPC
1759
+ *
1760
+ * Uses length-prefixed binary message framing compatible with Cap'n Proto C++ implementation.
1761
+ * Format: [4 bytes: message length (little-endian)] [N bytes: message data]
1762
+ */
1763
+ var TcpTransport = class TcpTransport {
1764
+ socket = null;
1765
+ messageQueue = [];
1766
+ receiveQueue = [];
1767
+ _connected = false;
1768
+ pendingBuffer = Buffer.alloc(0);
1769
+ pendingLength = 0;
1770
+ hasPendingLength = false;
1771
+ onClose;
1772
+ onError;
1773
+ constructor(host, port, options = {}) {
1774
+ this.host = host;
1775
+ this.port = port;
1776
+ this.options = options;
1777
+ }
1778
+ static async connect(host, port, options) {
1779
+ const transport = new TcpTransport(host, port, options);
1780
+ await transport.connect();
1781
+ return transport;
1782
+ }
1783
+ static fromSocket(socket, options) {
1784
+ const transport = new TcpTransport("", 0, options);
1785
+ transport.attachSocket(socket);
1786
+ return transport;
1787
+ }
1788
+ get connected() {
1789
+ return this._connected && this.socket?.readyState === "open";
1790
+ }
1791
+ connect() {
1792
+ return new Promise((resolve, reject) => {
1793
+ const timeout = setTimeout(() => {
1794
+ this.socket?.destroy();
1795
+ reject(/* @__PURE__ */ new Error("Connection timeout"));
1796
+ }, this.options.connectTimeoutMs ?? 1e4);
1797
+ this.socket = new net.Socket();
1798
+ this.socket.on("connect", () => {
1799
+ clearTimeout(timeout);
1800
+ this._connected = true;
1801
+ resolve();
1802
+ });
1803
+ this.socket.on("data", (data) => {
1804
+ this.handleData(data);
1805
+ });
1806
+ this.socket.on("close", (hadError) => {
1807
+ this._connected = false;
1808
+ this.flushReceiveQueue(null);
1809
+ if (hadError) this.onClose?.(/* @__PURE__ */ new Error("Connection closed with error"));
1810
+ else this.onClose?.();
1811
+ });
1812
+ this.socket.on("error", (err) => {
1813
+ clearTimeout(timeout);
1814
+ this._connected = false;
1815
+ this.onError?.(err);
1816
+ reject(err);
1817
+ });
1818
+ this.socket.on("end", () => {
1819
+ this._connected = false;
1820
+ });
1821
+ this.socket.connect(this.port, this.host);
1822
+ });
1823
+ }
1824
+ attachSocket(socket) {
1825
+ this.socket = socket;
1826
+ this._connected = socket.readyState === "open";
1827
+ socket.on("data", (data) => {
1828
+ this.handleData(data);
1829
+ });
1830
+ socket.on("close", (hadError) => {
1831
+ this._connected = false;
1832
+ this.flushReceiveQueue(null);
1833
+ if (hadError) this.onClose?.(/* @__PURE__ */ new Error("Connection closed with error"));
1834
+ else this.onClose?.();
1835
+ });
1836
+ socket.on("error", (err) => {
1837
+ this._connected = false;
1838
+ this.onError?.(err);
1839
+ });
1840
+ socket.on("end", () => {
1841
+ this._connected = false;
1842
+ });
1843
+ }
1844
+ handleData(data) {
1845
+ this.pendingBuffer = Buffer.concat([this.pendingBuffer, data]);
1846
+ while (this.pendingBuffer.length >= 4) {
1847
+ if (!this.hasPendingLength) {
1848
+ this.pendingLength = this.pendingBuffer.readUInt32LE(0);
1849
+ this.hasPendingLength = true;
1850
+ if (this.pendingLength > 64 * 1024 * 1024) {
1851
+ this.onError?.(/* @__PURE__ */ new Error(`Message too large: ${this.pendingLength} bytes`));
1852
+ this.close(/* @__PURE__ */ new Error("Message too large"));
1853
+ return;
1854
+ }
1855
+ }
1856
+ const totalLength = 4 + this.pendingLength;
1857
+ if (this.pendingBuffer.length < totalLength) break;
1858
+ const messageData = this.pendingBuffer.subarray(4, totalLength);
1859
+ this.pendingBuffer = this.pendingBuffer.subarray(totalLength);
1860
+ this.hasPendingLength = false;
1861
+ try {
1862
+ const message = deserializeRpcMessage(new Uint8Array(messageData));
1863
+ this.handleRpcMessage(message);
1864
+ } catch (err) {
1865
+ this.onError?.(err instanceof Error ? err : new Error(String(err)));
1866
+ }
1867
+ }
1868
+ }
1869
+ handleRpcMessage(message) {
1870
+ if (this.receiveQueue.length > 0) {
1871
+ const { resolve } = this.receiveQueue.shift();
1872
+ resolve(message);
1873
+ } else this.messageQueue.push(message);
1874
+ }
1875
+ async send(message) {
1876
+ if (!this.socket || this.socket.readyState !== "open") throw new Error("Socket not connected");
1877
+ const data = serializeRpcMessage(message);
1878
+ const frame = Buffer.allocUnsafe(4 + data.length);
1879
+ frame.writeUInt32LE(data.length, 0);
1880
+ frame.set(data, 4);
1881
+ return new Promise((resolve, reject) => {
1882
+ this.socket.write(frame, (err) => {
1883
+ if (err) reject(err);
1884
+ else resolve();
1885
+ });
1886
+ });
1887
+ }
1888
+ async receive() {
1889
+ if (this.messageQueue.length > 0) return this.messageQueue.shift();
1890
+ if (!this._connected) return null;
1891
+ return new Promise((resolve, reject) => {
1892
+ this.receiveQueue.push({
1893
+ resolve,
1894
+ reject
1895
+ });
1896
+ });
1897
+ }
1898
+ close(reason) {
1899
+ this._connected = false;
1900
+ this.socket?.end();
1901
+ this.socket?.destroy();
1902
+ this.flushReceiveQueue(null);
1903
+ this.onClose?.(reason);
1904
+ }
1905
+ flushReceiveQueue(value) {
1906
+ while (this.receiveQueue.length > 0) {
1907
+ const { resolve } = this.receiveQueue.shift();
1908
+ resolve(value);
1909
+ }
1910
+ }
1911
+ };
1912
+
1913
+ //#endregion
1914
+ //#region src/rpc/ezrpc-transport.ts
1915
+ /**
1916
+ * EzRpc TCP Transport
1917
+ *
1918
+ * Implements RpcTransport over raw TCP socket for C++ EzRpc compatibility.
1919
+ * Does NOT use length-prefixed framing - sends raw Cap'n Proto messages.
1920
+ */
1921
+ /**
1922
+ * EzRpc TCP Transport
1923
+ *
1924
+ * Compatible with Cap'n Proto C++ EzRpcServer/EzRpcClient.
1925
+ * Sends raw Cap'n Proto messages without length prefix.
1926
+ */
1927
+ var EzRpcTransport = class EzRpcTransport {
1928
+ socket = null;
1929
+ messageQueue = [];
1930
+ receiveQueue = [];
1931
+ _connected = false;
1932
+ pendingBuffer = Buffer.alloc(0);
1933
+ onClose;
1934
+ onError;
1935
+ constructor(host, port, options = {}) {
1936
+ this.host = host;
1937
+ this.port = port;
1938
+ this.options = options;
1939
+ }
1940
+ static async connect(host, port, options) {
1941
+ const transport = new EzRpcTransport(host, port, options);
1942
+ await transport.doConnect();
1943
+ return transport;
1944
+ }
1945
+ get connected() {
1946
+ return this._connected && this.socket !== null && !this.socket.destroyed;
1947
+ }
1948
+ doConnect() {
1949
+ return new Promise((resolve, reject) => {
1950
+ const timeout = setTimeout(() => {
1951
+ this.socket?.destroy();
1952
+ reject(/* @__PURE__ */ new Error(`Connection timeout: failed to connect to ${this.host}:${this.port}`));
1953
+ }, this.options.connectTimeoutMs ?? 1e4);
1954
+ this.socket = new net.Socket();
1955
+ this.socket.on("connect", () => {
1956
+ clearTimeout(timeout);
1957
+ this._connected = true;
1958
+ resolve();
1959
+ });
1960
+ this.socket.on("data", (data) => {
1961
+ try {
1962
+ this.handleData(data);
1963
+ } catch (err) {
1964
+ this.onError?.(err instanceof Error ? err : new Error(String(err)));
1965
+ }
1966
+ });
1967
+ this.socket.on("close", (hadError) => {
1968
+ const wasConnected = this._connected;
1969
+ this._connected = false;
1970
+ const error = hadError ? /* @__PURE__ */ new Error("Connection closed with error") : /* @__PURE__ */ new Error("Connection closed");
1971
+ this.flushReceiveQueueWithError(error);
1972
+ if (wasConnected) this.onClose?.(hadError ? error : void 0);
1973
+ });
1974
+ this.socket.on("error", (err) => {
1975
+ clearTimeout(timeout);
1976
+ this._connected = false;
1977
+ this.flushReceiveQueueWithError(err);
1978
+ this.onError?.(err);
1979
+ reject(err);
1980
+ });
1981
+ this.socket.connect(this.port, this.host);
1982
+ });
1983
+ }
1984
+ handleData(data) {
1985
+ if (this.pendingBuffer.length > 0) this.pendingBuffer = Buffer.concat([this.pendingBuffer, data]);
1986
+ else this.pendingBuffer = Buffer.from(data);
1987
+ while (this.pendingBuffer.length >= 8) {
1988
+ const segmentCount = this.pendingBuffer.readUInt32LE(0) + 1;
1989
+ const firstSegmentSize = this.pendingBuffer.readUInt32LE(4);
1990
+ let headerSize = 8;
1991
+ if (segmentCount > 1) headerSize += (segmentCount - 1) * 4;
1992
+ const messageSize = headerSize + firstSegmentSize * 8;
1993
+ if (this.pendingBuffer.length < messageSize) break;
1994
+ const messageData = this.pendingBuffer.subarray(0, messageSize);
1995
+ this.pendingBuffer = this.pendingBuffer.subarray(messageSize);
1996
+ try {
1997
+ const message = deserializeRpcMessage(new Uint8Array(messageData));
1998
+ if (this.receiveQueue.length > 0) {
1999
+ const { resolve } = this.receiveQueue.shift();
2000
+ resolve(message);
2001
+ } else this.messageQueue.push(message);
2002
+ } catch (err) {
2003
+ this.onError?.(err instanceof Error ? err : new Error(String(err)));
2004
+ }
2005
+ }
2006
+ }
2007
+ async send(message) {
2008
+ if (!this.connected) throw new Error(`Cannot send: socket not connected to ${this.host}:${this.port}`);
2009
+ const data = serializeRpcMessage(message);
2010
+ return new Promise((resolve, reject) => {
2011
+ this.socket.write(Buffer.from(data), (err) => {
2012
+ if (err) reject(/* @__PURE__ */ new Error(`Failed to send message: ${err.message}`));
2013
+ else resolve();
2014
+ });
2015
+ });
2016
+ }
2017
+ async receive() {
2018
+ if (this.messageQueue.length > 0) return this.messageQueue.shift();
2019
+ if (!this.connected) return null;
2020
+ return new Promise((resolve, reject) => {
2021
+ const timeoutId = setTimeout(() => {
2022
+ const index = this.receiveQueue.findIndex((item) => item.resolve === resolve);
2023
+ if (index !== -1) this.receiveQueue.splice(index, 1);
2024
+ reject(/* @__PURE__ */ new Error("Receive timeout"));
2025
+ }, 3e4);
2026
+ this.receiveQueue.push({
2027
+ resolve: (msg) => {
2028
+ clearTimeout(timeoutId);
2029
+ resolve(msg);
2030
+ },
2031
+ reject: (err) => {
2032
+ clearTimeout(timeoutId);
2033
+ reject(err);
2034
+ }
2035
+ });
2036
+ });
2037
+ }
2038
+ close(reason) {
2039
+ this._connected = false;
2040
+ this.socket?.end();
2041
+ this.socket?.destroy();
2042
+ this.flushReceiveQueue(null);
2043
+ this.onClose?.(reason);
2044
+ }
2045
+ flushReceiveQueueWithError(error) {
2046
+ while (this.receiveQueue.length > 0) {
2047
+ const { reject } = this.receiveQueue.shift();
2048
+ reject(error);
2049
+ }
2050
+ }
2051
+ flushReceiveQueue(value) {
2052
+ while (this.receiveQueue.length > 0) {
2053
+ const { resolve } = this.receiveQueue.shift();
2054
+ resolve(value);
2055
+ }
2056
+ }
2057
+ };
2058
+
1701
2059
  //#endregion
1702
2060
  //#region src/rpc/capability-client.ts
1703
2061
  /** Base class for capability client implementations */
@@ -2310,7 +2668,7 @@ var ConnectionManager = class {
2310
2668
  }
2311
2669
  }
2312
2670
  async doEstablishConnection(vatId, address) {
2313
- const { RpcConnection } = await import("./rpc-connection-C2C1wyga.js");
2671
+ const { RpcConnection } = await import("./rpc-connection-jIPnPyT6.js");
2314
2672
  const connection = new RpcConnection(await this.options.connectionFactory(vatId, address), this.options.connectionOptions);
2315
2673
  await connection.start();
2316
2674
  this.registerConnection(vatId, connection);
@@ -4906,5 +5264,933 @@ function supportsStreaming(connection) {
4906
5264
  }
4907
5265
 
4908
5266
  //#endregion
4909
- export { AnswerTable, BaseCapabilityClient, BulkTransfer, BulkTransferManager, ConnectionManager, DEFAULT_BULK_CONFIG, DEFAULT_ESCROW_CONFIG, DEFAULT_FLOW_CONTROL, DEFAULT_JOIN_OPTIONS, DEFAULT_JOIN_SECURITY_POLICY, DEFAULT_REALTIME_CONFIG, DEFAULT_STREAMING_CAPABILITIES, DropPolicy, ElementSize, ExportTable, ImportTable, Level3Handlers, Level4Handlers, ListBuilder, ListReader, MemoryPool, MessageBuilder, MessageReader, MultiSegmentMessageBuilder, OptimizedRpcMessageBuilder, PIPELINE_CLIENT_SYMBOL, PipelineOpTracker, PipelineResolutionTracker, PointerTag, QuestionTable, QueuedCallManager, RealtimeStream, RealtimeStreamManager, RestoreHandler, RpcConnection, Segment, Stream, StreamManager, StreamPriority, StreamType, StreamingRpcConnection, StructBuilder, StructReader, SturdyRefManager, UnionBuilder, UnionReader, WORD_SIZE, WebSocketTransport, configureGlobalMemoryPool, createBulkTransferManager, createPipelineClient, createProvisionId, createRealtimeStreamManager, createRecipientId, createStream, createStreamManager, createStreamingConnection, createSturdyRef, createThirdPartyCapId, createUnionBuilder, createUnionReader, createZeroCopyView, decodePointer, deserializeRpcMessage, deserializeSturdyRef, encodeListPointer, encodeStructPointer, fastCopy, generateProvisionId, generateVatId, getGlobalMemoryPool, isPipelineClient, isSameBuffer, isStream, isSturdyRefValid, serializeRpcMessage, serializeSturdyRef, supportsStreaming };
5267
+ //#region src/rpc/dynamic-reader.ts
5268
+ /**
5269
+ * Create a dynamic reader from schema and buffer
5270
+ *
5271
+ * @param schema - The schema node describing the struct type
5272
+ * @param buffer - The Cap'n Proto message buffer
5273
+ * @returns A DynamicReader for accessing the message fields
5274
+ */
5275
+ function createDynamicReader(schema, buffer) {
5276
+ const messageReader = new MessageReader(buffer);
5277
+ if (!schema.structInfo) throw new Error(`Schema node ${schema.displayName} is not a struct`);
5278
+ const { dataWordCount, pointerCount } = schema.structInfo;
5279
+ return new DynamicReaderImpl(schema, messageReader.getRoot(dataWordCount, pointerCount), messageReader);
5280
+ }
5281
+ /**
5282
+ * Create a dynamic reader from an existing StructReader
5283
+ *
5284
+ * @param schema - The schema node describing the struct type
5285
+ * @param structReader - The StructReader to wrap
5286
+ * @param messageReader - The underlying MessageReader
5287
+ * @returns A DynamicReader for accessing the message fields
5288
+ */
5289
+ function createDynamicReaderFromStruct(schema, structReader, messageReader) {
5290
+ return new DynamicReaderImpl(schema, structReader, messageReader);
5291
+ }
5292
+ /**
5293
+ * Implementation of DynamicReader
5294
+ */
5295
+ var DynamicReaderImpl = class {
5296
+ fieldCache;
5297
+ pointerOffset;
5298
+ constructor(schema, structReader, messageReader) {
5299
+ this.schema = schema;
5300
+ this.structReader = structReader;
5301
+ this.messageReader = messageReader;
5302
+ this.fieldCache = /* @__PURE__ */ new Map();
5303
+ this.pointerOffset = schema.structInfo?.dataWordCount ?? 0;
5304
+ if (schema.structInfo?.fields) for (const field of schema.structInfo.fields) this.fieldCache.set(field.name, field);
5305
+ }
5306
+ get(fieldName) {
5307
+ const field = this.fieldCache.get(fieldName);
5308
+ if (!field) throw new Error(`Field '${fieldName}' not found in schema ${this.schema.displayName}`);
5309
+ return this.readFieldValue(field);
5310
+ }
5311
+ has(fieldName) {
5312
+ return this.fieldCache.has(fieldName);
5313
+ }
5314
+ getFieldNames() {
5315
+ return Array.from(this.fieldCache.keys());
5316
+ }
5317
+ getSchema() {
5318
+ return this.schema;
5319
+ }
5320
+ getStruct(fieldName) {
5321
+ const field = this.fieldCache.get(fieldName);
5322
+ if (!field) return;
5323
+ if (field.type.kind.type !== "struct") return;
5324
+ const pointerIndex = this.getPointerIndex(field);
5325
+ const nestedStruct = this.structReader.getStruct(pointerIndex, 0, 0);
5326
+ if (!nestedStruct) return;
5327
+ return new DynamicStructReaderWithoutSchema(nestedStruct, this.messageReader);
5328
+ }
5329
+ getList(fieldName) {
5330
+ const field = this.fieldCache.get(fieldName);
5331
+ if (!field) return;
5332
+ if (field.type.kind.type !== "list") return;
5333
+ const pointerIndex = this.getPointerIndex(field);
5334
+ const elementType = field.type.kind.elementType;
5335
+ return this.readListField(pointerIndex, elementType);
5336
+ }
5337
+ getRawReader() {
5338
+ return this.structReader;
5339
+ }
5340
+ /**
5341
+ * Read a field value based on its type
5342
+ */
5343
+ readFieldValue(field) {
5344
+ const kind = field.type.kind;
5345
+ switch (kind.type) {
5346
+ case "void": return;
5347
+ case "bool": return this.structReader.getBool(field.offset);
5348
+ case "int8": return this.structReader.getInt8(field.offset);
5349
+ case "int16": return this.structReader.getInt16(field.offset);
5350
+ case "int32": return this.structReader.getInt32(field.offset);
5351
+ case "int64": return this.structReader.getInt64(field.offset);
5352
+ case "uint8": return this.structReader.getUint8(field.offset);
5353
+ case "uint16": return this.structReader.getUint16(field.offset);
5354
+ case "uint32": return this.structReader.getUint32(field.offset);
5355
+ case "uint64": return this.structReader.getUint64(field.offset);
5356
+ case "float32": return this.structReader.getFloat32(field.offset);
5357
+ case "float64": return this.structReader.getFloat64(field.offset);
5358
+ case "text": return this.readTextField(field);
5359
+ case "data": return this.readDataField(field);
5360
+ case "list": return this.readListFieldBySchema(field);
5361
+ case "enum": return this.readEnumField(field);
5362
+ case "struct": return this.readStructField(field);
5363
+ case "interface": return this.readInterfaceField(field);
5364
+ case "anyPointer": return this.readAnyPointerField(field);
5365
+ default: throw new Error(`Unsupported field type: ${kind.type}`);
5366
+ }
5367
+ }
5368
+ /**
5369
+ * Get the pointer index for a field
5370
+ * In Cap'n Proto, pointer fields have offsets that start from 0 for the first pointer
5371
+ * The offset is measured in bits from the start of the data section
5372
+ * For pointer fields, offset = dataWordCount * 64 + pointerIndex * 64
5373
+ * So pointerIndex = (offset - dataWordCount * 64) / 64
5374
+ */
5375
+ getPointerIndex(field) {
5376
+ const dataSectionBits = (this.schema.structInfo?.dataWordCount ?? 0) * 64;
5377
+ return (field.offset - dataSectionBits) / 64;
5378
+ }
5379
+ /**
5380
+ * Read a text field
5381
+ */
5382
+ readTextField(field) {
5383
+ const pointerIndex = this.getPointerIndex(field);
5384
+ return this.structReader.getText(pointerIndex);
5385
+ }
5386
+ /**
5387
+ * Read a data field
5388
+ */
5389
+ readDataField(field) {
5390
+ const pointerIndex = this.getPointerIndex(field);
5391
+ const text = this.structReader.getText(pointerIndex);
5392
+ return new TextEncoder().encode(text);
5393
+ }
5394
+ /**
5395
+ * Read a list field using schema information
5396
+ */
5397
+ readListFieldBySchema(field) {
5398
+ if (field.type.kind.type !== "list") throw new Error(`Field '${field.name}' is not a list type`);
5399
+ const pointerIndex = this.getPointerIndex(field);
5400
+ const elementType = field.type.kind.elementType;
5401
+ return this.readListField(pointerIndex, elementType);
5402
+ }
5403
+ /**
5404
+ * Read a list field
5405
+ */
5406
+ readListField(pointerIndex, elementType) {
5407
+ const elementSize = this.mapTypeToElementSize(elementType);
5408
+ const listReader = this.structReader.getList(pointerIndex, elementSize);
5409
+ if (!listReader) return [];
5410
+ const result = [];
5411
+ const length = listReader.length;
5412
+ for (let i = 0; i < length; i++) result.push(this.readListElement(listReader, i, elementType));
5413
+ return result;
5414
+ }
5415
+ /**
5416
+ * Map schema type to ElementSize
5417
+ */
5418
+ mapTypeToElementSize(type) {
5419
+ switch (type.kind.type) {
5420
+ case "void": return ElementSize.VOID;
5421
+ case "bool": return ElementSize.BIT;
5422
+ case "int8":
5423
+ case "uint8": return ElementSize.BYTE;
5424
+ case "int16":
5425
+ case "uint16": return ElementSize.TWO_BYTES;
5426
+ case "int32":
5427
+ case "uint32":
5428
+ case "float32": return ElementSize.FOUR_BYTES;
5429
+ case "int64":
5430
+ case "uint64":
5431
+ case "float64": return ElementSize.EIGHT_BYTES;
5432
+ case "struct": return ElementSize.COMPOSITE;
5433
+ default: return ElementSize.POINTER;
5434
+ }
5435
+ }
5436
+ /**
5437
+ * Read a single list element
5438
+ */
5439
+ readListElement(listReader, index, elementType) {
5440
+ switch (elementType.kind.type) {
5441
+ case "void": return;
5442
+ case "bool": return listReader.getPrimitive(index) !== 0;
5443
+ case "int8": return listReader.getPrimitive(index);
5444
+ case "int16": return listReader.getPrimitive(index);
5445
+ case "int32": return listReader.getPrimitive(index);
5446
+ case "int64": return listReader.getPrimitive(index);
5447
+ case "uint8": return listReader.getPrimitive(index);
5448
+ case "uint16": return listReader.getPrimitive(index);
5449
+ case "uint32": return listReader.getPrimitive(index);
5450
+ case "uint64": return listReader.getPrimitive(index);
5451
+ case "float32": return listReader.getPrimitive(index);
5452
+ case "float64": return listReader.getPrimitive(index);
5453
+ case "struct": {
5454
+ const structReader = listReader.getStruct(index);
5455
+ if (!structReader) return void 0;
5456
+ return new DynamicStructReaderWithoutSchema(structReader, this.messageReader);
5457
+ }
5458
+ default: return;
5459
+ }
5460
+ }
5461
+ /**
5462
+ * Read an enum field
5463
+ */
5464
+ readEnumField(field) {
5465
+ return this.structReader.getUint16(field.offset);
5466
+ }
5467
+ /**
5468
+ * Read a struct field
5469
+ */
5470
+ readStructField(field) {
5471
+ const pointerIndex = this.getPointerIndex(field);
5472
+ const nestedStruct = this.structReader.getStruct(pointerIndex, 0, 0);
5473
+ if (!nestedStruct) return;
5474
+ return new DynamicStructReaderWithoutSchema(nestedStruct, this.messageReader);
5475
+ }
5476
+ /**
5477
+ * Read an interface field (capability)
5478
+ */
5479
+ readInterfaceField(_field) {
5480
+ throw new Error("Interface fields not yet supported in dynamic reader");
5481
+ }
5482
+ /**
5483
+ * Read an anyPointer field
5484
+ */
5485
+ readAnyPointerField(_field) {
5486
+ throw new Error("anyPointer fields not yet supported in dynamic reader");
5487
+ }
5488
+ };
5489
+ /**
5490
+ * A limited dynamic reader for structs without schema information
5491
+ * Provides basic field access but no type information
5492
+ */
5493
+ var DynamicStructReaderWithoutSchema = class {
5494
+ constructor(structReader, messageReader) {
5495
+ this.structReader = structReader;
5496
+ this.messageReader = messageReader;
5497
+ }
5498
+ get(_fieldName) {
5499
+ throw new Error("Cannot access fields without schema information");
5500
+ }
5501
+ has(_fieldName) {
5502
+ return false;
5503
+ }
5504
+ getFieldNames() {
5505
+ return [];
5506
+ }
5507
+ getSchema() {
5508
+ throw new Error("No schema information available");
5509
+ }
5510
+ getStruct(_fieldName) {}
5511
+ getList(_fieldName) {}
5512
+ getRawReader() {
5513
+ return this.structReader;
5514
+ }
5515
+ };
5516
+ /**
5517
+ * Create a dynamic reader for a specific type ID
5518
+ * This looks up the schema in a registry and creates the appropriate reader
5519
+ *
5520
+ * @param typeId - The type ID of the struct
5521
+ * @param buffer - The Cap'n Proto message buffer
5522
+ * @param schemaRegistry - A map of type IDs to schema nodes
5523
+ * @returns A DynamicReader for the message
5524
+ */
5525
+ function createDynamicReaderByTypeId(typeId, buffer, schemaRegistry) {
5526
+ const schema = schemaRegistry.get(typeId);
5527
+ if (!schema) throw new Error(`Schema not found for type ID: ${typeId}`);
5528
+ if (schema.type !== SchemaNodeType.STRUCT) throw new Error(`Type ${typeId} is not a struct`);
5529
+ return createDynamicReader(schema, buffer);
5530
+ }
5531
+ /**
5532
+ * Utility function to dump all fields from a dynamic reader
5533
+ * Useful for debugging and exploration
5534
+ *
5535
+ * @param reader - The DynamicReader to dump
5536
+ * @returns An object with all field names and values
5537
+ */
5538
+ function dumpDynamicReader(reader) {
5539
+ const result = {};
5540
+ for (const fieldName of reader.getFieldNames()) try {
5541
+ result[fieldName] = reader.get(fieldName);
5542
+ } catch (error) {
5543
+ result[fieldName] = `<error: ${error}>`;
5544
+ }
5545
+ return result;
5546
+ }
5547
+
5548
+ //#endregion
5549
+ //#region src/rpc/dynamic-writer.ts
5550
+ /**
5551
+ * Create a dynamic writer from schema
5552
+ *
5553
+ * @param schema - The schema node describing the struct type
5554
+ * @returns A DynamicWriter for setting message fields
5555
+ */
5556
+ function createDynamicWriter(schema) {
5557
+ if (!schema.structInfo) throw new Error(`Schema node ${schema.displayName} is not a struct`);
5558
+ const { dataWordCount, pointerCount } = schema.structInfo;
5559
+ const messageBuilder = new MessageBuilder();
5560
+ return new DynamicWriterImpl(schema, messageBuilder.initRoot(dataWordCount, pointerCount), messageBuilder);
5561
+ }
5562
+ /**
5563
+ * Create a dynamic writer for a nested struct
5564
+ *
5565
+ * @param schema - The schema node describing the struct type
5566
+ * @param structBuilder - The StructBuilder to wrap
5567
+ * @param messageBuilder - The underlying MessageBuilder
5568
+ * @returns A DynamicWriter for setting message fields
5569
+ */
5570
+ function createNestedDynamicWriter(schema, structBuilder, messageBuilder) {
5571
+ return new DynamicWriterImpl(schema, structBuilder, messageBuilder);
5572
+ }
5573
+ /**
5574
+ * Implementation of DynamicWriter
5575
+ */
5576
+ var DynamicWriterImpl = class {
5577
+ fieldCache;
5578
+ pointerOffset;
5579
+ constructor(schema, structBuilder, messageBuilder) {
5580
+ this.schema = schema;
5581
+ this.structBuilder = structBuilder;
5582
+ this.messageBuilder = messageBuilder;
5583
+ this.fieldCache = /* @__PURE__ */ new Map();
5584
+ this.pointerOffset = schema.structInfo?.dataWordCount ?? 0;
5585
+ if (schema.structInfo?.fields) for (const field of schema.structInfo.fields) this.fieldCache.set(field.name, field);
5586
+ }
5587
+ set(fieldName, value) {
5588
+ const field = this.fieldCache.get(fieldName);
5589
+ if (!field) throw new Error(`Field '${fieldName}' not found in schema ${this.schema.displayName}`);
5590
+ this.writeFieldValue(field, value);
5591
+ }
5592
+ setFields(fields) {
5593
+ for (const [name, value] of Object.entries(fields)) this.set(name, value);
5594
+ }
5595
+ initStruct(fieldName) {
5596
+ const field = this.fieldCache.get(fieldName);
5597
+ if (!field) throw new Error(`Field '${fieldName}' not found in schema ${this.schema.displayName}`);
5598
+ if (field.type.kind.type !== "struct") throw new Error(`Field '${fieldName}' is not a struct type`);
5599
+ const pointerIndex = this.getPointerIndex(field);
5600
+ return new DynamicWriterWithoutSchema(this.structBuilder.initStruct(pointerIndex, 0, 0), this.messageBuilder);
5601
+ }
5602
+ initList(fieldName, size) {
5603
+ const field = this.fieldCache.get(fieldName);
5604
+ if (!field) throw new Error(`Field '${fieldName}' not found in schema ${this.schema.displayName}`);
5605
+ if (field.type.kind.type !== "list") throw new Error(`Field '${fieldName}' is not a list type`);
5606
+ const pointerIndex = this.getPointerIndex(field);
5607
+ const elementType = field.type.kind.elementType;
5608
+ return this.createListWriter(pointerIndex, size, elementType);
5609
+ }
5610
+ setText(fieldName, value) {
5611
+ const field = this.fieldCache.get(fieldName);
5612
+ if (!field) throw new Error(`Field '${fieldName}' not found in schema ${this.schema.displayName}`);
5613
+ if (field.type.kind.type !== "text") throw new Error(`Field '${fieldName}' is not a text type`);
5614
+ const pointerIndex = this.getPointerIndex(field);
5615
+ this.structBuilder.setText(pointerIndex, value);
5616
+ }
5617
+ setData(fieldName, value) {
5618
+ const field = this.fieldCache.get(fieldName);
5619
+ if (!field) throw new Error(`Field '${fieldName}' not found in schema ${this.schema.displayName}`);
5620
+ if (field.type.kind.type !== "data") throw new Error(`Field '${fieldName}' is not a data type`);
5621
+ const pointerIndex = this.getPointerIndex(field);
5622
+ const textValue = new TextDecoder().decode(value);
5623
+ this.structBuilder.setText(pointerIndex, `${textValue}\0`);
5624
+ }
5625
+ getSchema() {
5626
+ return this.schema;
5627
+ }
5628
+ getRawBuilder() {
5629
+ return this.structBuilder;
5630
+ }
5631
+ toBuffer() {
5632
+ return this.messageBuilder.toArrayBuffer();
5633
+ }
5634
+ /**
5635
+ * Write a field value based on its type
5636
+ */
5637
+ writeFieldValue(field, value) {
5638
+ const kind = field.type.kind;
5639
+ switch (kind.type) {
5640
+ case "void": break;
5641
+ case "bool":
5642
+ this.structBuilder.setBool(field.offset, Boolean(value));
5643
+ break;
5644
+ case "int8":
5645
+ this.structBuilder.setInt8(field.offset, Number(value));
5646
+ break;
5647
+ case "int16":
5648
+ this.structBuilder.setInt16(field.offset, Number(value));
5649
+ break;
5650
+ case "int32":
5651
+ this.structBuilder.setInt32(field.offset, Number(value));
5652
+ break;
5653
+ case "int64":
5654
+ this.structBuilder.setInt64(field.offset, BigInt(value));
5655
+ break;
5656
+ case "uint8":
5657
+ this.structBuilder.setUint8(field.offset, Number(value));
5658
+ break;
5659
+ case "uint16":
5660
+ this.structBuilder.setUint16(field.offset, Number(value));
5661
+ break;
5662
+ case "uint32":
5663
+ this.structBuilder.setUint32(field.offset, Number(value));
5664
+ break;
5665
+ case "uint64":
5666
+ this.structBuilder.setUint64(field.offset, BigInt(value));
5667
+ break;
5668
+ case "float32":
5669
+ this.structBuilder.setFloat32(field.offset, Number(value));
5670
+ break;
5671
+ case "float64":
5672
+ this.structBuilder.setFloat64(field.offset, Number(value));
5673
+ break;
5674
+ case "text":
5675
+ this.setText(field.name, String(value));
5676
+ break;
5677
+ case "data":
5678
+ if (value instanceof Uint8Array) this.setData(field.name, value);
5679
+ else throw new Error(`Field '${field.name}' expects Uint8Array`);
5680
+ break;
5681
+ case "list":
5682
+ if (Array.isArray(value)) this.initList(field.name, value.length).setAll(value);
5683
+ else throw new Error(`Field '${field.name}' expects an array`);
5684
+ break;
5685
+ case "enum":
5686
+ this.structBuilder.setUint16(field.offset, Number(value));
5687
+ break;
5688
+ case "struct":
5689
+ if (typeof value === "object" && value !== null) {
5690
+ const structWriter = this.initStruct(field.name);
5691
+ if (!(value instanceof Uint8Array) && !Array.isArray(value)) structWriter.setFields(value);
5692
+ } else throw new Error(`Field '${field.name}' expects an object`);
5693
+ break;
5694
+ case "interface": throw new Error("Interface fields not yet supported in dynamic writer");
5695
+ case "anyPointer": throw new Error("anyPointer fields not yet supported in dynamic writer");
5696
+ default: throw new Error(`Unsupported field type: ${kind.type}`);
5697
+ }
5698
+ }
5699
+ /**
5700
+ * Get the pointer index for a field
5701
+ * In Cap'n Proto, pointer fields have offsets that start from 0 for the first pointer
5702
+ * The offset is measured in bits from the start of the data section
5703
+ * For pointer fields, offset = dataWordCount * 64 + pointerIndex * 64
5704
+ * So pointerIndex = (offset - dataWordCount * 64) / 64
5705
+ */
5706
+ getPointerIndex(field) {
5707
+ const dataSectionBits = (this.schema.structInfo?.dataWordCount ?? 0) * 64;
5708
+ return (field.offset - dataSectionBits) / 64;
5709
+ }
5710
+ /**
5711
+ * Create a list writer for a field
5712
+ */
5713
+ createListWriter(pointerIndex, size, elementType) {
5714
+ const elementSize = this.mapTypeToElementSize(elementType);
5715
+ let structSize;
5716
+ if (elementSize === ElementSize.COMPOSITE) structSize = {
5717
+ dataWords: 0,
5718
+ pointerCount: 0
5719
+ };
5720
+ return new DynamicListWriterImpl(this.structBuilder.initList(pointerIndex, elementSize, size, structSize), elementType, this.messageBuilder);
5721
+ }
5722
+ /**
5723
+ * Map schema type to ElementSize
5724
+ */
5725
+ mapTypeToElementSize(type) {
5726
+ switch (type.kind.type) {
5727
+ case "void": return ElementSize.VOID;
5728
+ case "bool": return ElementSize.BIT;
5729
+ case "int8":
5730
+ case "uint8": return ElementSize.BYTE;
5731
+ case "int16":
5732
+ case "uint16": return ElementSize.TWO_BYTES;
5733
+ case "int32":
5734
+ case "uint32":
5735
+ case "float32": return ElementSize.FOUR_BYTES;
5736
+ case "int64":
5737
+ case "uint64":
5738
+ case "float64": return ElementSize.EIGHT_BYTES;
5739
+ case "struct": return ElementSize.COMPOSITE;
5740
+ default: return ElementSize.POINTER;
5741
+ }
5742
+ }
5743
+ };
5744
+ /**
5745
+ * Implementation of DynamicListWriter
5746
+ */
5747
+ var DynamicListWriterImpl = class {
5748
+ constructor(listBuilder, elementType, messageBuilder) {
5749
+ this.listBuilder = listBuilder;
5750
+ this.elementType = elementType;
5751
+ this.messageBuilder = messageBuilder;
5752
+ }
5753
+ set(index, value) {
5754
+ if (index < 0 || index >= this.listBuilder.length) throw new Error(`Index ${index} out of bounds`);
5755
+ const kind = this.elementType.kind;
5756
+ switch (kind.type) {
5757
+ case "void": break;
5758
+ case "bool":
5759
+ this.listBuilder.setPrimitive(index, value ? 1 : 0);
5760
+ break;
5761
+ case "int8":
5762
+ case "uint8":
5763
+ case "int16":
5764
+ case "uint16":
5765
+ case "int32":
5766
+ case "uint32":
5767
+ case "float32":
5768
+ this.listBuilder.setPrimitive(index, Number(value));
5769
+ break;
5770
+ case "int64":
5771
+ case "uint64":
5772
+ case "float64":
5773
+ this.listBuilder.setPrimitive(index, BigInt(value));
5774
+ break;
5775
+ case "struct":
5776
+ if (typeof value === "object" && value !== null && !(value instanceof Uint8Array)) this.initStruct(index).setFields(value);
5777
+ break;
5778
+ default: throw new Error(`Unsupported list element type: ${kind.type}`);
5779
+ }
5780
+ }
5781
+ getSize() {
5782
+ return this.listBuilder.length;
5783
+ }
5784
+ getLength() {
5785
+ return this.listBuilder.length;
5786
+ }
5787
+ initStruct(index) {
5788
+ return new DynamicWriterWithoutSchema(this.listBuilder.getStruct(index), this.messageBuilder);
5789
+ }
5790
+ setAll(values) {
5791
+ if (values.length > this.getSize()) throw new Error(`Cannot set ${values.length} values in list of size ${this.getSize()}`);
5792
+ for (let i = 0; i < values.length; i++) this.set(i, values[i]);
5793
+ }
5794
+ };
5795
+ /**
5796
+ * A limited dynamic writer for structs without full schema information
5797
+ * Provides basic field setting but no type validation
5798
+ */
5799
+ var DynamicWriterWithoutSchema = class {
5800
+ constructor(structBuilder, messageBuilder) {
5801
+ this.structBuilder = structBuilder;
5802
+ this.messageBuilder = messageBuilder;
5803
+ }
5804
+ set(fieldName, _value) {
5805
+ throw new Error(`Cannot set field '${fieldName}' without schema information`);
5806
+ }
5807
+ setFields(_fields) {
5808
+ throw new Error("Cannot set fields without schema information");
5809
+ }
5810
+ initStruct(_fieldName) {
5811
+ throw new Error("Cannot init struct without schema information");
5812
+ }
5813
+ initList(_fieldName, _size) {
5814
+ throw new Error("Cannot init list without schema information");
5815
+ }
5816
+ setText(_fieldName, _value) {
5817
+ throw new Error("Cannot set text without schema information");
5818
+ }
5819
+ setData(_fieldName, _value) {
5820
+ throw new Error("Cannot set data without schema information");
5821
+ }
5822
+ getSchema() {
5823
+ throw new Error("No schema information available");
5824
+ }
5825
+ getRawBuilder() {
5826
+ return this.structBuilder;
5827
+ }
5828
+ toBuffer() {
5829
+ return this.messageBuilder.toArrayBuffer();
5830
+ }
5831
+ };
5832
+ /**
5833
+ * Create a dynamic writer for a specific type ID
5834
+ * This looks up the schema in a registry and creates the appropriate writer
5835
+ *
5836
+ * @param typeId - The type ID of the struct
5837
+ * @param schemaRegistry - A map of type IDs to schema nodes
5838
+ * @returns A DynamicWriter for the message
5839
+ */
5840
+ function createDynamicWriterByTypeId(typeId, schemaRegistry) {
5841
+ const schema = schemaRegistry.get(typeId);
5842
+ if (!schema) throw new Error(`Schema not found for type ID: ${typeId}`);
5843
+ if (schema.type !== SchemaNodeType.STRUCT) throw new Error(`Type ${typeId} is not a struct`);
5844
+ return createDynamicWriter(schema);
5845
+ }
5846
+ /**
5847
+ * Utility function to create a message from a plain object
5848
+ * Uses schema information to properly serialize the data
5849
+ *
5850
+ * @param schema - The schema node describing the struct type
5851
+ * @param data - The data object to serialize
5852
+ * @returns The serialized message buffer
5853
+ */
5854
+ function serializeDynamic(schema, data) {
5855
+ const writer = createDynamicWriter(schema);
5856
+ writer.setFields(data);
5857
+ return writer.toBuffer();
5858
+ }
5859
+ /**
5860
+ * Utility function to create a message from a plain object using type ID
5861
+ *
5862
+ * @param typeId - The type ID of the struct
5863
+ * @param data - The data object to serialize
5864
+ * @param schemaRegistry - A map of type IDs to schema nodes
5865
+ * @returns The serialized message buffer
5866
+ */
5867
+ function serializeDynamicByTypeId(typeId, data, schemaRegistry) {
5868
+ const writer = createDynamicWriterByTypeId(typeId, schemaRegistry);
5869
+ writer.setFields(data);
5870
+ return writer.toBuffer();
5871
+ }
5872
+
5873
+ //#endregion
5874
+ //#region src/rpc/schema-capability.ts
5875
+ /**
5876
+ * Server-side implementation of the SchemaCapability interface.
5877
+ * Provides schema information to remote clients.
5878
+ */
5879
+ var SchemaCapabilityServer = class {
5880
+ registry;
5881
+ schemasByName;
5882
+ /**
5883
+ * Create a new SchemaCapabilityServer
5884
+ * @param initialSchemas - Optional map of schemas to register initially
5885
+ */
5886
+ constructor(initialSchemas) {
5887
+ this.registry = new Map(initialSchemas);
5888
+ this.schemasByName = /* @__PURE__ */ new Map();
5889
+ for (const schema of this.registry.values()) this.schemasByName.set(schema.displayName, schema);
5890
+ }
5891
+ /**
5892
+ * Register a schema node
5893
+ * @param node - The schema node to register
5894
+ */
5895
+ registerSchema(node) {
5896
+ this.registry.set(node.id, node);
5897
+ this.schemasByName.set(node.displayName, node);
5898
+ }
5899
+ /**
5900
+ * Unregister a schema by ID
5901
+ * @param typeId - The type ID to unregister
5902
+ */
5903
+ unregisterSchema(typeId) {
5904
+ const node = this.registry.get(typeId);
5905
+ if (node) {
5906
+ this.registry.delete(typeId);
5907
+ this.schemasByName.delete(node.displayName);
5908
+ }
5909
+ }
5910
+ /**
5911
+ * Get schema information based on target specification
5912
+ * @param params - GetSchemaParams containing target and format
5913
+ * @returns GetSchemaResults with the schema payload
5914
+ */
5915
+ async getSchema(params) {
5916
+ const { target, format = SchemaFormat.BINARY } = params;
5917
+ let schemaData;
5918
+ let dependencies = [];
5919
+ switch (target.type) {
5920
+ case "byTypeId": {
5921
+ const node = this.registry.get(target.typeId);
5922
+ if (!node) throw new Error(`Schema not found for type ID: ${target.typeId.toString(16)}`);
5923
+ schemaData = this.serializeSchemaNode(node, format);
5924
+ dependencies = this.collectDependencies(node);
5925
+ break;
5926
+ }
5927
+ case "byTypeName": {
5928
+ const node = this.schemasByName.get(target.typeName);
5929
+ if (!node) throw new Error(`Schema not found for type name: ${target.typeName}`);
5930
+ schemaData = this.serializeSchemaNode(node, format);
5931
+ dependencies = this.collectDependencies(node);
5932
+ break;
5933
+ }
5934
+ case "byFileId": {
5935
+ const nodes = this.getSchemasByFileId(target.fileId);
5936
+ schemaData = this.serializeSchemaNodes(nodes, format);
5937
+ break;
5938
+ }
5939
+ case "byFileName": {
5940
+ const nodes = this.getSchemasByFileName(target.fileName);
5941
+ schemaData = this.serializeSchemaNodes(nodes, format);
5942
+ break;
5943
+ }
5944
+ case "allSchemas": {
5945
+ const nodes = Array.from(this.registry.values());
5946
+ schemaData = this.serializeSchemaNodes(nodes, format);
5947
+ break;
5948
+ }
5949
+ case "bootstrapInterface": {
5950
+ const bootstrapSchema = this.findBootstrapSchema();
5951
+ if (!bootstrapSchema) throw new Error("Bootstrap interface schema not available");
5952
+ schemaData = this.serializeSchemaNode(bootstrapSchema, format);
5953
+ dependencies = this.collectDependencies(bootstrapSchema);
5954
+ break;
5955
+ }
5956
+ default: throw new Error(`Unsupported schema target type: ${target.type}`);
5957
+ }
5958
+ return { payload: {
5959
+ schemaData,
5960
+ format,
5961
+ dependencies
5962
+ } };
5963
+ }
5964
+ /**
5965
+ * List all available schemas
5966
+ * @returns ListSchemasResults with available schema information
5967
+ */
5968
+ async listAvailableSchemas() {
5969
+ const schemas = [];
5970
+ for (const node of this.registry.values()) schemas.push({
5971
+ typeId: node.id,
5972
+ displayName: node.displayName,
5973
+ fileId: node.scopeId,
5974
+ fileName: this.inferFileName(node),
5975
+ isInterface: node.type === SchemaNodeType.INTERFACE,
5976
+ isStruct: node.type === SchemaNodeType.STRUCT,
5977
+ isEnum: node.type === SchemaNodeType.ENUM
5978
+ });
5979
+ return { schemas };
5980
+ }
5981
+ /**
5982
+ * Handle a raw schema request (for RPC integration)
5983
+ * @param requestData - The serialized SchemaRequest
5984
+ * @returns The serialized SchemaResponse
5985
+ */
5986
+ handleRequest(requestData) {
5987
+ try {
5988
+ const request = deserializeSchemaRequest(requestData);
5989
+ this.getSchema({ target: request.targetSchema });
5990
+ throw new Error("Async handling not implemented in handleRequest");
5991
+ } catch (error) {
5992
+ return serializeSchemaResponse({
5993
+ answerId: 0,
5994
+ result: {
5995
+ type: "exception",
5996
+ exception: {
5997
+ reason: error instanceof Error ? error.message : "Unknown error",
5998
+ type: "failed",
5999
+ obsoleteIsCallersFault: false,
6000
+ obsoleteDurability: 0
6001
+ }
6002
+ }
6003
+ });
6004
+ }
6005
+ }
6006
+ /**
6007
+ * Get the number of registered schemas
6008
+ */
6009
+ getSchemaCount() {
6010
+ return this.registry.size;
6011
+ }
6012
+ /**
6013
+ * Check if a schema is registered
6014
+ */
6015
+ hasSchema(typeId) {
6016
+ return this.registry.has(typeId);
6017
+ }
6018
+ serializeSchemaNode(node, format) {
6019
+ switch (format) {
6020
+ case SchemaFormat.BINARY: return this.serializeToBinary([node]);
6021
+ case SchemaFormat.JSON: return this.serializeToJson([node]);
6022
+ case SchemaFormat.CAPNP: return this.serializeToCapnp([node]);
6023
+ default: throw new Error(`Unsupported schema format: ${format}`);
6024
+ }
6025
+ }
6026
+ serializeSchemaNodes(nodes, format) {
6027
+ switch (format) {
6028
+ case SchemaFormat.BINARY: return this.serializeToBinary(nodes);
6029
+ case SchemaFormat.JSON: return this.serializeToJson(nodes);
6030
+ case SchemaFormat.CAPNP: return this.serializeToCapnp(nodes);
6031
+ default: throw new Error(`Unsupported schema format: ${format}`);
6032
+ }
6033
+ }
6034
+ serializeToBinary(nodes) {
6035
+ const encoder = new TextEncoder();
6036
+ const json = JSON.stringify(nodes, (_key, value) => {
6037
+ if (typeof value === "bigint") return value.toString();
6038
+ return value;
6039
+ });
6040
+ return encoder.encode(json);
6041
+ }
6042
+ serializeToJson(nodes) {
6043
+ const encoder = new TextEncoder();
6044
+ const json = JSON.stringify({ nodes: nodes.map((node) => ({
6045
+ id: node.id.toString(),
6046
+ displayName: node.displayName,
6047
+ displayNamePrefixLength: node.displayNamePrefixLength,
6048
+ scopeId: node.scopeId.toString(),
6049
+ type: node.type,
6050
+ structInfo: node.structInfo,
6051
+ enumInfo: node.enumInfo,
6052
+ interfaceInfo: node.interfaceInfo
6053
+ })) });
6054
+ return encoder.encode(json);
6055
+ }
6056
+ serializeToCapnp(nodes) {
6057
+ const lines = [];
6058
+ for (const node of nodes) if (node.structInfo) {
6059
+ lines.push(`struct ${node.displayName} {`);
6060
+ for (const field of node.structInfo.fields) lines.push(` ${field.name} @${field.codeOrder} :${this.typeToCapnp(field.type)};`);
6061
+ lines.push("}");
6062
+ }
6063
+ return new TextEncoder().encode(lines.join("\n"));
6064
+ }
6065
+ typeToCapnp(type) {
6066
+ switch (type.kind.type) {
6067
+ case "void": return "Void";
6068
+ case "bool": return "Bool";
6069
+ case "int8": return "Int8";
6070
+ case "int16": return "Int16";
6071
+ case "int32": return "Int32";
6072
+ case "int64": return "Int64";
6073
+ case "uint8": return "UInt8";
6074
+ case "uint16": return "UInt16";
6075
+ case "uint32": return "UInt32";
6076
+ case "uint64": return "UInt64";
6077
+ case "float32": return "Float32";
6078
+ case "float64": return "Float64";
6079
+ case "text": return "Text";
6080
+ case "data": return "Data";
6081
+ case "list": return "List";
6082
+ case "enum": return "UInt16";
6083
+ case "struct": return "AnyPointer";
6084
+ case "interface": return "Capability";
6085
+ default: return "AnyPointer";
6086
+ }
6087
+ }
6088
+ collectDependencies(_node) {
6089
+ return [];
6090
+ }
6091
+ getSchemasByFileId(fileId) {
6092
+ return Array.from(this.registry.values()).filter((node) => node.scopeId === fileId);
6093
+ }
6094
+ getSchemasByFileName(fileName) {
6095
+ return Array.from(this.registry.values()).filter((node) => {
6096
+ return this.inferFileName(node) === fileName || node.displayName.startsWith(fileName);
6097
+ });
6098
+ }
6099
+ inferFileName(node) {
6100
+ const parts = node.displayName.split(".");
6101
+ if (parts.length > 1) return `${parts.slice(0, -1).join("/")}.capnp`;
6102
+ return "unknown.capnp";
6103
+ }
6104
+ findBootstrapSchema() {
6105
+ for (const node of this.registry.values()) if (node.type === SchemaNodeType.INTERFACE) return node;
6106
+ }
6107
+ };
6108
+ /**
6109
+ * Client-side implementation for accessing remote SchemaCapability
6110
+ */
6111
+ var SchemaCapabilityClient = class {
6112
+ connection;
6113
+ /**
6114
+ * Create a new SchemaCapabilityClient
6115
+ * @param connection - The RPC connection to use
6116
+ */
6117
+ constructor(connection) {
6118
+ this.connection = connection;
6119
+ }
6120
+ /**
6121
+ * Fetch schema information from the remote server
6122
+ * @param target - The schema target specification
6123
+ * @param format - The desired format (defaults to BINARY)
6124
+ * @returns The schema node
6125
+ */
6126
+ async getSchema(target, format = SchemaFormat.BINARY) {
6127
+ if (target.type === "byTypeId") return this.connection.getDynamicSchema(target.typeId);
6128
+ if (target.type === "byTypeName") return this.connection.getDynamicSchemaByName(target.typeName);
6129
+ throw new Error(`Schema target type not implemented: ${target.type}`);
6130
+ }
6131
+ /**
6132
+ * Fetch schema by type ID
6133
+ * @param typeId - The type ID
6134
+ * @returns The schema node
6135
+ */
6136
+ async getSchemaById(typeId) {
6137
+ return this.connection.getDynamicSchema(typeId);
6138
+ }
6139
+ /**
6140
+ * Fetch schema by type name
6141
+ * @param typeName - The fully qualified type name
6142
+ * @returns The schema node
6143
+ */
6144
+ async getSchemaByName(typeName) {
6145
+ return this.connection.getDynamicSchemaByName(typeName);
6146
+ }
6147
+ /**
6148
+ * List all available schemas from the remote server
6149
+ * @returns Array of available schema information
6150
+ */
6151
+ async listAvailableSchemas() {
6152
+ return (await this.connection.listAvailableSchemas()).map((s) => ({
6153
+ typeId: s.typeId,
6154
+ displayName: s.displayName,
6155
+ fileId: BigInt(0),
6156
+ fileName: "",
6157
+ isInterface: false,
6158
+ isStruct: true,
6159
+ isEnum: false
6160
+ }));
6161
+ }
6162
+ /**
6163
+ * Fetch multiple schemas at once
6164
+ * @param typeIds - Array of type IDs to fetch
6165
+ * @returns Map of type ID to schema node
6166
+ */
6167
+ async getSchemas(typeIds) {
6168
+ const results = /* @__PURE__ */ new Map();
6169
+ await Promise.all(typeIds.map(async (typeId) => {
6170
+ try {
6171
+ const schema = await this.getSchemaById(typeId);
6172
+ results.set(typeId, schema);
6173
+ } catch (error) {
6174
+ console.warn(`Failed to fetch schema ${typeId.toString(16)}:`, error);
6175
+ }
6176
+ }));
6177
+ return results;
6178
+ }
6179
+ /**
6180
+ * Check if a schema is available on the remote server
6181
+ * @param typeId - The type ID to check
6182
+ * @returns True if the schema is available
6183
+ */
6184
+ async hasSchema(typeId) {
6185
+ try {
6186
+ await this.getSchemaById(typeId);
6187
+ return true;
6188
+ } catch {
6189
+ return false;
6190
+ }
6191
+ }
6192
+ };
6193
+
6194
+ //#endregion
6195
+ export { AnswerTable, BaseCapabilityClient, BulkTransfer, BulkTransferManager, ConnectionManager, DEFAULT_BULK_CONFIG, DEFAULT_ESCROW_CONFIG, DEFAULT_FLOW_CONTROL, DEFAULT_JOIN_OPTIONS, DEFAULT_JOIN_SECURITY_POLICY, DEFAULT_REALTIME_CONFIG, DEFAULT_STREAMING_CAPABILITIES, DropPolicy, ElementSize, ExportTable, EzRpcTransport, ImportTable, Level3Handlers, Level4Handlers, ListBuilder, ListReader, MemoryPool, MessageBuilder, MessageReader, MultiSegmentMessageBuilder, OptimizedRpcMessageBuilder, PIPELINE_CLIENT_SYMBOL, PipelineOpTracker, PipelineResolutionTracker, PointerTag, QuestionTable, QueuedCallManager, RealtimeStream, RealtimeStreamManager, RestoreHandler, RpcConnection, SCHEMA_MESSAGE_TYPES, SchemaCapabilityClient, SchemaCapabilityServer, SchemaFormat, Segment, Stream, StreamManager, StreamPriority, StreamType, StreamingRpcConnection, StructBuilder, StructReader, SturdyRefManager, TcpTransport, UnionBuilder, UnionReader, WORD_SIZE, WebSocketTransport, configureGlobalMemoryPool, createBulkTransferManager, createDynamicReader, createDynamicReaderByTypeId, createDynamicReaderFromStruct, createDynamicWriter, createDynamicWriterByTypeId, createNestedDynamicWriter, createPipelineClient, createProvisionId, createRealtimeStreamManager, createRecipientId, createSchemaRegistry, createStream, createStreamManager, createStreamingConnection, createSturdyRef, createThirdPartyCapId, createUnionBuilder, createUnionReader, createZeroCopyView, decodePointer, deserializeRpcMessage, deserializeSchemaRequest, deserializeSchemaResponse, deserializeSturdyRef, dumpDynamicReader, encodeListPointer, encodeStructPointer, fastCopy, generateProvisionId, generateVatId, getGlobalMemoryPool, isPipelineClient, isSameBuffer, isStream, isSturdyRefValid, parseSchemaNodes, serializeDynamic, serializeDynamicByTypeId, serializeGetSchemaParams, serializeGetSchemaResults, serializeListSchemasResults, serializeRpcMessage, serializeSchemaRequest, serializeSchemaResponse, serializeSturdyRef, supportsStreaming };
4910
6196
  //# sourceMappingURL=index.js.map