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