@replit/river 0.20.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +3 -9
  2. package/dist/{chunk-ZIWOHAQM.js → chunk-2ERP6FUE.js} +5 -4
  3. package/dist/chunk-2ERP6FUE.js.map +1 -0
  4. package/dist/{chunk-XAG3SC7R.js → chunk-3AW3IXVD.js} +4 -2
  5. package/dist/chunk-3AW3IXVD.js.map +1 -0
  6. package/dist/{chunk-HGBAUTIW.js → chunk-MJR36SUY.js} +8 -3
  7. package/dist/{chunk-HGBAUTIW.js.map → chunk-MJR36SUY.js.map} +1 -1
  8. package/dist/{chunk-YB5LRYL6.js → chunk-NFV77C2M.js} +2 -2
  9. package/dist/{chunk-YB5LRYL6.js.map → chunk-NFV77C2M.js.map} +1 -1
  10. package/dist/{chunk-NYOK5VKK.js → chunk-QU2EE6YU.js} +2 -2
  11. package/dist/codec/index.cjs +3 -1
  12. package/dist/codec/index.cjs.map +1 -1
  13. package/dist/codec/index.js +1 -1
  14. package/dist/{connection-dba95bc8.d.ts → connection-8a71dbe2.d.ts} +1 -1
  15. package/dist/router/index.cjs +1 -1
  16. package/dist/router/index.cjs.map +1 -1
  17. package/dist/router/index.d.cts +1 -1
  18. package/dist/router/index.d.ts +1 -1
  19. package/dist/router/index.js +1 -1
  20. package/dist/transport/impls/uds/client.cjs +6 -1
  21. package/dist/transport/impls/uds/client.cjs.map +1 -1
  22. package/dist/transport/impls/uds/client.js +3 -3
  23. package/dist/transport/impls/uds/server.cjs +6 -1
  24. package/dist/transport/impls/uds/server.cjs.map +1 -1
  25. package/dist/transport/impls/uds/server.js +3 -3
  26. package/dist/transport/impls/ws/client.cjs +22 -10
  27. package/dist/transport/impls/ws/client.cjs.map +1 -1
  28. package/dist/transport/impls/ws/client.d.cts +6 -5
  29. package/dist/transport/impls/ws/client.d.ts +6 -5
  30. package/dist/transport/impls/ws/client.js +12 -11
  31. package/dist/transport/impls/ws/client.js.map +1 -1
  32. package/dist/transport/impls/ws/server.cjs +13 -2
  33. package/dist/transport/impls/ws/server.cjs.map +1 -1
  34. package/dist/transport/impls/ws/server.d.cts +2 -2
  35. package/dist/transport/impls/ws/server.d.ts +2 -2
  36. package/dist/transport/impls/ws/server.js +3 -3
  37. package/dist/transport/impls/ws/server.js.map +1 -1
  38. package/dist/transport/index.js +2 -2
  39. package/dist/util/testHelpers.cjs +0 -18
  40. package/dist/util/testHelpers.cjs.map +1 -1
  41. package/dist/util/testHelpers.d.cts +3 -10
  42. package/dist/util/testHelpers.d.ts +3 -10
  43. package/dist/util/testHelpers.js +3 -10
  44. package/dist/util/testHelpers.js.map +1 -1
  45. package/package.json +2 -2
  46. package/dist/chunk-XAG3SC7R.js.map +0 -1
  47. package/dist/chunk-ZIWOHAQM.js.map +0 -1
  48. /package/dist/{chunk-NYOK5VKK.js.map → chunk-QU2EE6YU.js.map} +0 -0
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # River
2
2
 
3
+ ⚠️ Not production ready, while Replit is using parts of river in production, we are still going through rapid breaking changes. First production ready version will be 1.x.x ⚠️
4
+
3
5
  River allows multiple clients to connect to and make remote procedure calls to a remote server as if they were local procedures.
4
6
 
5
7
  ## Long-lived streaming remote procedure calls
@@ -57,12 +59,6 @@ Before proceeding, ensure you have TypeScript 5 installed and configured appropr
57
59
  npm i @replit/river @sinclair/typebox
58
60
  ```
59
61
 
60
- 3. If you plan on using WebSocket for the underlying transport, also install
61
-
62
- ```bash
63
- npm i ws isomorphic-ws
64
- ```
65
-
66
62
  ## Writing services
67
63
 
68
64
  ### Concepts
@@ -136,14 +132,12 @@ httpServer.listen(port);
136
132
  In another file for the client (to create a separate entrypoint),
137
133
 
138
134
  ```ts
139
- import WebSocket from 'isomorphic-ws';
140
135
  import { WebSocketClientTransport } from '@replit/river/transport/ws/client';
141
136
  import { createClient } from '@replit/river';
142
137
  import type ServiceSurface from './server';
143
138
 
144
- const websocketUrl = `ws://localhost:3000`;
145
139
  const transport = new WebSocketClientTransport(
146
- async () => new WebSocket(websocketUrl),
140
+ async () => `ws://localhost:3000`,
147
141
  'my-client-id',
148
142
  );
149
143
 
@@ -1,8 +1,9 @@
1
1
  import {
2
2
  Connection
3
- } from "./chunk-NYOK5VKK.js";
3
+ } from "./chunk-QU2EE6YU.js";
4
4
 
5
5
  // transport/impls/ws/connection.ts
6
+ import WebSocket from "agnostic-ws";
6
7
  var WebSocketConnection = class extends Connection {
7
8
  ws;
8
9
  constructor(ws) {
@@ -20,10 +21,10 @@ var WebSocketConnection = class extends Connection {
20
21
  this.ws.onclose = cb;
21
22
  }
22
23
  addErrorListener(cb) {
23
- this.ws.onerror = (err) => cb(new Error(err.message));
24
+ this.ws.onerror = (err) => cb(err.error);
24
25
  }
25
26
  send(payload) {
26
- if (this.ws.readyState === this.ws.OPEN) {
27
+ if (this.ws.readyState === WebSocket.OPEN) {
27
28
  this.ws.send(payload);
28
29
  return true;
29
30
  } else {
@@ -38,4 +39,4 @@ var WebSocketConnection = class extends Connection {
38
39
  export {
39
40
  WebSocketConnection
40
41
  };
41
- //# sourceMappingURL=chunk-ZIWOHAQM.js.map
42
+ //# sourceMappingURL=chunk-2ERP6FUE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../transport/impls/ws/connection.ts"],"sourcesContent":["import WebSocket from 'agnostic-ws';\nimport { Connection } from '../../session';\n\nexport class WebSocketConnection extends Connection {\n ws: WebSocket;\n\n constructor(ws: WebSocket) {\n super();\n this.ws = ws;\n this.ws.binaryType = 'arraybuffer';\n }\n\n addDataListener(cb: (msg: Uint8Array) => void) {\n this.ws.onmessage = (msg) => cb(msg.data as Uint8Array);\n }\n\n removeDataListener(): void {\n this.ws.onmessage = null;\n }\n\n addCloseListener(cb: () => void): void {\n this.ws.onclose = cb;\n }\n\n addErrorListener(cb: (err: Error) => void): void {\n this.ws.onerror = (err) => cb(err.error);\n }\n\n send(payload: Uint8Array) {\n if (this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(payload);\n return true;\n } else {\n return false;\n }\n }\n\n close() {\n this.ws.close();\n }\n}\n"],"mappings":";;;;;AAAA,OAAO,eAAe;AAGf,IAAM,sBAAN,cAAkC,WAAW;AAAA,EAClD;AAAA,EAEA,YAAY,IAAe;AACzB,UAAM;AACN,SAAK,KAAK;AACV,SAAK,GAAG,aAAa;AAAA,EACvB;AAAA,EAEA,gBAAgB,IAA+B;AAC7C,SAAK,GAAG,YAAY,CAAC,QAAQ,GAAG,IAAI,IAAkB;AAAA,EACxD;AAAA,EAEA,qBAA2B;AACzB,SAAK,GAAG,YAAY;AAAA,EACtB;AAAA,EAEA,iBAAiB,IAAsB;AACrC,SAAK,GAAG,UAAU;AAAA,EACpB;AAAA,EAEA,iBAAiB,IAAgC;AAC/C,SAAK,GAAG,UAAU,CAAC,QAAQ,GAAG,IAAI,KAAK;AAAA,EACzC;AAAA,EAEA,KAAK,SAAqB;AACxB,QAAI,KAAK,GAAG,eAAe,UAAU,MAAM;AACzC,WAAK,GAAG,KAAK,OAAO;AACpB,aAAO;AAAA,IACT,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,QAAQ;AACN,SAAK,GAAG,MAAM;AAAA,EAChB;AACF;","names":[]}
@@ -1,7 +1,9 @@
1
1
  // codec/binary.ts
2
2
  import { decode, encode } from "@msgpack/msgpack";
3
3
  var BinaryCodec = {
4
- toBuffer: encode,
4
+ toBuffer(obj) {
5
+ return encode(obj, { ignoreUndefined: true });
6
+ },
5
7
  fromBuffer: (buff) => {
6
8
  try {
7
9
  const res = decode(buff);
@@ -71,4 +73,4 @@ export {
71
73
  BinaryCodec,
72
74
  NaiveJsonCodec
73
75
  };
74
- //# sourceMappingURL=chunk-XAG3SC7R.js.map
76
+ //# sourceMappingURL=chunk-3AW3IXVD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../codec/binary.ts","../codec/json.ts"],"sourcesContent":["import { decode, encode } from '@msgpack/msgpack';\nimport { Codec } from './types';\n\n/**\n * Binary codec, uses [msgpack](https://www.npmjs.com/package/@msgpack/msgpack) under the hood\n * @type {Codec}\n */\nexport const BinaryCodec: Codec = {\n toBuffer(obj) {\n return encode(obj, { ignoreUndefined: true });\n },\n fromBuffer: (buff: Uint8Array) => {\n try {\n const res = decode(buff);\n if (typeof res !== 'object') {\n return null;\n }\n\n return res;\n } catch {\n return null;\n }\n },\n};\n","import { Codec } from './types';\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\n\n// Convert Uint8Array to base64\nfunction uint8ArrayToBase64(uint8Array: Uint8Array) {\n let binary = '';\n uint8Array.forEach((byte) => {\n binary += String.fromCharCode(byte);\n });\n return btoa(binary);\n}\n\n// Convert base64 to Uint8Array\nfunction base64ToUint8Array(base64: string) {\n const binaryString = atob(base64);\n const uint8Array = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n uint8Array[i] = binaryString.charCodeAt(i);\n }\n return uint8Array;\n}\n\ninterface Base64EncodedValue {\n $t: string;\n}\n\n/**\n * Naive JSON codec implementation using JSON.stringify and JSON.parse.\n * @type {Codec}\n */\nexport const NaiveJsonCodec: Codec = {\n toBuffer: (obj: object) => {\n return encoder.encode(\n JSON.stringify(obj, function replacer<\n T extends object,\n >(this: T, key: keyof T) {\n const val = this[key];\n if (val instanceof Uint8Array) {\n return { $t: uint8ArrayToBase64(val) } satisfies Base64EncodedValue;\n } else {\n return val;\n }\n }),\n );\n },\n fromBuffer: (buff: Uint8Array) => {\n try {\n const parsed = JSON.parse(\n decoder.decode(buff),\n function reviver(_key, val: unknown) {\n if ((val as Base64EncodedValue | undefined)?.$t) {\n return base64ToUint8Array((val as Base64EncodedValue).$t);\n } else {\n return val;\n }\n },\n ) as unknown;\n\n if (typeof parsed === 'object') return parsed;\n return null;\n } catch {\n return null;\n }\n },\n};\n"],"mappings":";AAAA,SAAS,QAAQ,cAAc;AAOxB,IAAM,cAAqB;AAAA,EAChC,SAAS,KAAK;AACZ,WAAO,OAAO,KAAK,EAAE,iBAAiB,KAAK,CAAC;AAAA,EAC9C;AAAA,EACA,YAAY,CAAC,SAAqB;AAChC,QAAI;AACF,YAAM,MAAM,OAAO,IAAI;AACvB,UAAI,OAAO,QAAQ,UAAU;AAC3B,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;ACrBA,IAAM,UAAU,IAAI,YAAY;AAChC,IAAM,UAAU,IAAI,YAAY;AAGhC,SAAS,mBAAmB,YAAwB;AAClD,MAAI,SAAS;AACb,aAAW,QAAQ,CAAC,SAAS;AAC3B,cAAU,OAAO,aAAa,IAAI;AAAA,EACpC,CAAC;AACD,SAAO,KAAK,MAAM;AACpB;AAGA,SAAS,mBAAmB,QAAgB;AAC1C,QAAM,eAAe,KAAK,MAAM;AAChC,QAAM,aAAa,IAAI,WAAW,aAAa,MAAM;AACrD,WAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC5C,eAAW,CAAC,IAAI,aAAa,WAAW,CAAC;AAAA,EAC3C;AACA,SAAO;AACT;AAUO,IAAM,iBAAwB;AAAA,EACnC,UAAU,CAAC,QAAgB;AACzB,WAAO,QAAQ;AAAA,MACb,KAAK,UAAU,KAAK,SAAS,SAElB,KAAc;AACvB,cAAM,MAAM,KAAK,GAAG;AACpB,YAAI,eAAe,YAAY;AAC7B,iBAAO,EAAE,IAAI,mBAAmB,GAAG,EAAE;AAAA,QACvC,OAAO;AACL,iBAAO;AAAA,QACT;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EACA,YAAY,CAAC,SAAqB;AAChC,QAAI;AACF,YAAM,SAAS,KAAK;AAAA,QAClB,QAAQ,OAAO,IAAI;AAAA,QACnB,SAAS,QAAQ,MAAM,KAAc;AACnC,cAAK,KAAwC,IAAI;AAC/C,mBAAO,mBAAoB,IAA2B,EAAE;AAAA,UAC1D,OAAO;AACL,mBAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAEA,UAAI,OAAO,WAAW;AAAU,eAAO;AACvC,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Connection
3
- } from "./chunk-NYOK5VKK.js";
3
+ } from "./chunk-QU2EE6YU.js";
4
4
 
5
5
  // transport/transforms/messageFraming.ts
6
6
  import { Transform } from "node:stream";
@@ -82,7 +82,12 @@ var UdsConnection = class extends Connection {
82
82
  this.sock.on("close", cb);
83
83
  }
84
84
  addErrorListener(cb) {
85
- this.sock.on("error", cb);
85
+ this.sock.on("error", (err) => {
86
+ if (err instanceof Error && "code" in err && err.code === "EPIPE") {
87
+ return;
88
+ }
89
+ cb(err);
90
+ });
86
91
  }
87
92
  send(payload) {
88
93
  if (this.framer.destroyed || !this.sock.writable)
@@ -98,4 +103,4 @@ var UdsConnection = class extends Connection {
98
103
  export {
99
104
  UdsConnection
100
105
  };
101
- //# sourceMappingURL=chunk-HGBAUTIW.js.map
106
+ //# sourceMappingURL=chunk-MJR36SUY.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../transport/transforms/messageFraming.ts","../transport/impls/uds/connection.ts"],"sourcesContent":["import { Transform, TransformCallback, TransformOptions } from 'node:stream';\n\nexport interface LengthEncodedOptions extends TransformOptions {\n /** Maximum in-memory buffer size before we throw */\n maxBufferSizeBytes: number;\n}\n\n/**\n * A transform stream that emits data each time a message with a network/BigEndian uint32 length prefix is received.\n * @extends Transform\n */\nexport class Uint32LengthPrefixFraming extends Transform {\n receivedBuffer: Buffer;\n maxBufferSizeBytes: number;\n\n constructor({ maxBufferSizeBytes, ...options }: LengthEncodedOptions) {\n super(options);\n this.maxBufferSizeBytes = maxBufferSizeBytes;\n this.receivedBuffer = Buffer.alloc(0);\n }\n\n _transform(chunk: Buffer, _encoding: BufferEncoding, cb: TransformCallback) {\n if (\n this.receivedBuffer.byteLength + chunk.byteLength >\n this.maxBufferSizeBytes\n ) {\n const err = new Error(\n `buffer overflow: ${this.receivedBuffer.byteLength}B > ${this.maxBufferSizeBytes}B`,\n );\n\n this.emit('error', err);\n cb(err);\n return;\n }\n\n this.receivedBuffer = Buffer.concat([this.receivedBuffer, chunk]);\n\n // ensure there's enough for a length prefix\n while (this.receivedBuffer.length > 4) {\n // read length from buffer (accounting for uint32 prefix)\n const claimedMessageLength = this.receivedBuffer.readUInt32BE(0) + 4;\n if (this.receivedBuffer.length >= claimedMessageLength) {\n // slice the buffer to extract the message\n const message = this.receivedBuffer.subarray(4, claimedMessageLength);\n this.push(message);\n this.receivedBuffer =\n this.receivedBuffer.subarray(claimedMessageLength);\n } else {\n // not enough data for a complete message, wait for more data\n break;\n }\n }\n\n cb();\n }\n\n _flush(cb: TransformCallback) {\n // if there's any leftover data that doesn't form a complete message\n if (this.receivedBuffer.length) {\n this.emit('error', new Error('got incomplete message while flushing'));\n }\n\n this.receivedBuffer = Buffer.alloc(0);\n cb();\n }\n\n _destroy(error: Error | null, callback: (error: Error | null) => void): void {\n this.receivedBuffer = Buffer.alloc(0);\n super._destroy(error, callback);\n }\n}\n\nfunction createLengthEncodedStream(options?: Partial<LengthEncodedOptions>) {\n return new Uint32LengthPrefixFraming({\n maxBufferSizeBytes: options?.maxBufferSizeBytes ?? 16 * 1024 * 1024, // 16MB\n });\n}\n\nexport const MessageFramer = {\n createFramedStream: createLengthEncodedStream,\n write: (buf: Uint8Array) => {\n const lengthPrefix = Buffer.alloc(4);\n lengthPrefix.writeUInt32BE(buf.length, 0);\n return Buffer.concat([lengthPrefix, buf]);\n },\n};\n","import { Connection } from '../../session';\nimport { type Socket } from 'node:net';\nimport stream from 'node:stream';\nimport {\n MessageFramer,\n Uint32LengthPrefixFraming,\n} from '../../transforms/messageFraming';\n\nexport class UdsConnection extends Connection {\n sock: Socket;\n input: stream.Readable;\n framer: Uint32LengthPrefixFraming;\n\n constructor(sock: Socket) {\n super();\n this.framer = MessageFramer.createFramedStream();\n this.sock = sock;\n this.input = sock.pipe(this.framer);\n }\n\n addDataListener(cb: (msg: Uint8Array) => void) {\n this.input.on('data', cb);\n }\n\n removeDataListener(cb: (msg: Uint8Array) => void): void {\n this.input.off('data', cb);\n }\n\n addCloseListener(cb: () => void): void {\n this.sock.on('close', cb);\n }\n\n addErrorListener(cb: (err: Error) => void): void {\n this.sock.on('error', cb);\n }\n\n send(payload: Uint8Array) {\n if (this.framer.destroyed || !this.sock.writable) return false;\n return this.sock.write(MessageFramer.write(payload));\n }\n\n close() {\n this.sock.destroy();\n this.framer.destroy();\n }\n}\n"],"mappings":";;;;;AAAA,SAAS,iBAAsD;AAWxD,IAAM,4BAAN,cAAwC,UAAU;AAAA,EACvD;AAAA,EACA;AAAA,EAEA,YAAY,EAAE,oBAAoB,GAAG,QAAQ,GAAyB;AACpE,UAAM,OAAO;AACb,SAAK,qBAAqB;AAC1B,SAAK,iBAAiB,OAAO,MAAM,CAAC;AAAA,EACtC;AAAA,EAEA,WAAW,OAAe,WAA2B,IAAuB;AAC1E,QACE,KAAK,eAAe,aAAa,MAAM,aACvC,KAAK,oBACL;AACA,YAAM,MAAM,IAAI;AAAA,QACd,oBAAoB,KAAK,eAAe,UAAU,OAAO,KAAK,kBAAkB;AAAA,MAClF;AAEA,WAAK,KAAK,SAAS,GAAG;AACtB,SAAG,GAAG;AACN;AAAA,IACF;AAEA,SAAK,iBAAiB,OAAO,OAAO,CAAC,KAAK,gBAAgB,KAAK,CAAC;AAGhE,WAAO,KAAK,eAAe,SAAS,GAAG;AAErC,YAAM,uBAAuB,KAAK,eAAe,aAAa,CAAC,IAAI;AACnE,UAAI,KAAK,eAAe,UAAU,sBAAsB;AAEtD,cAAM,UAAU,KAAK,eAAe,SAAS,GAAG,oBAAoB;AACpE,aAAK,KAAK,OAAO;AACjB,aAAK,iBACH,KAAK,eAAe,SAAS,oBAAoB;AAAA,MACrD,OAAO;AAEL;AAAA,MACF;AAAA,IACF;AAEA,OAAG;AAAA,EACL;AAAA,EAEA,OAAO,IAAuB;AAE5B,QAAI,KAAK,eAAe,QAAQ;AAC9B,WAAK,KAAK,SAAS,IAAI,MAAM,uCAAuC,CAAC;AAAA,IACvE;AAEA,SAAK,iBAAiB,OAAO,MAAM,CAAC;AACpC,OAAG;AAAA,EACL;AAAA,EAEA,SAAS,OAAqB,UAA+C;AAC3E,SAAK,iBAAiB,OAAO,MAAM,CAAC;AACpC,UAAM,SAAS,OAAO,QAAQ;AAAA,EAChC;AACF;AAEA,SAAS,0BAA0B,SAAyC;AAC1E,SAAO,IAAI,0BAA0B;AAAA,IACnC,oBAAoB,SAAS,sBAAsB,KAAK,OAAO;AAAA;AAAA,EACjE,CAAC;AACH;AAEO,IAAM,gBAAgB;AAAA,EAC3B,oBAAoB;AAAA,EACpB,OAAO,CAAC,QAAoB;AAC1B,UAAM,eAAe,OAAO,MAAM,CAAC;AACnC,iBAAa,cAAc,IAAI,QAAQ,CAAC;AACxC,WAAO,OAAO,OAAO,CAAC,cAAc,GAAG,CAAC;AAAA,EAC1C;AACF;;;AC7EO,IAAM,gBAAN,cAA4B,WAAW;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YAAY,MAAc;AACxB,UAAM;AACN,SAAK,SAAS,cAAc,mBAAmB;AAC/C,SAAK,OAAO;AACZ,SAAK,QAAQ,KAAK,KAAK,KAAK,MAAM;AAAA,EACpC;AAAA,EAEA,gBAAgB,IAA+B;AAC7C,SAAK,MAAM,GAAG,QAAQ,EAAE;AAAA,EAC1B;AAAA,EAEA,mBAAmB,IAAqC;AACtD,SAAK,MAAM,IAAI,QAAQ,EAAE;AAAA,EAC3B;AAAA,EAEA,iBAAiB,IAAsB;AACrC,SAAK,KAAK,GAAG,SAAS,EAAE;AAAA,EAC1B;AAAA,EAEA,iBAAiB,IAAgC;AAC/C,SAAK,KAAK,GAAG,SAAS,EAAE;AAAA,EAC1B;AAAA,EAEA,KAAK,SAAqB;AACxB,QAAI,KAAK,OAAO,aAAa,CAAC,KAAK,KAAK;AAAU,aAAO;AACzD,WAAO,KAAK,KAAK,MAAM,cAAc,MAAM,OAAO,CAAC;AAAA,EACrD;AAAA,EAEA,QAAQ;AACN,SAAK,KAAK,QAAQ;AAClB,SAAK,OAAO,QAAQ;AAAA,EACtB;AACF;","names":[]}
1
+ {"version":3,"sources":["../transport/transforms/messageFraming.ts","../transport/impls/uds/connection.ts"],"sourcesContent":["import { Transform, TransformCallback, TransformOptions } from 'node:stream';\n\nexport interface LengthEncodedOptions extends TransformOptions {\n /** Maximum in-memory buffer size before we throw */\n maxBufferSizeBytes: number;\n}\n\n/**\n * A transform stream that emits data each time a message with a network/BigEndian uint32 length prefix is received.\n * @extends Transform\n */\nexport class Uint32LengthPrefixFraming extends Transform {\n receivedBuffer: Buffer;\n maxBufferSizeBytes: number;\n\n constructor({ maxBufferSizeBytes, ...options }: LengthEncodedOptions) {\n super(options);\n this.maxBufferSizeBytes = maxBufferSizeBytes;\n this.receivedBuffer = Buffer.alloc(0);\n }\n\n _transform(chunk: Buffer, _encoding: BufferEncoding, cb: TransformCallback) {\n if (\n this.receivedBuffer.byteLength + chunk.byteLength >\n this.maxBufferSizeBytes\n ) {\n const err = new Error(\n `buffer overflow: ${this.receivedBuffer.byteLength}B > ${this.maxBufferSizeBytes}B`,\n );\n\n this.emit('error', err);\n cb(err);\n return;\n }\n\n this.receivedBuffer = Buffer.concat([this.receivedBuffer, chunk]);\n\n // ensure there's enough for a length prefix\n while (this.receivedBuffer.length > 4) {\n // read length from buffer (accounting for uint32 prefix)\n const claimedMessageLength = this.receivedBuffer.readUInt32BE(0) + 4;\n if (this.receivedBuffer.length >= claimedMessageLength) {\n // slice the buffer to extract the message\n const message = this.receivedBuffer.subarray(4, claimedMessageLength);\n this.push(message);\n this.receivedBuffer =\n this.receivedBuffer.subarray(claimedMessageLength);\n } else {\n // not enough data for a complete message, wait for more data\n break;\n }\n }\n\n cb();\n }\n\n _flush(cb: TransformCallback) {\n // if there's any leftover data that doesn't form a complete message\n if (this.receivedBuffer.length) {\n this.emit('error', new Error('got incomplete message while flushing'));\n }\n\n this.receivedBuffer = Buffer.alloc(0);\n cb();\n }\n\n _destroy(error: Error | null, callback: (error: Error | null) => void): void {\n this.receivedBuffer = Buffer.alloc(0);\n super._destroy(error, callback);\n }\n}\n\nfunction createLengthEncodedStream(options?: Partial<LengthEncodedOptions>) {\n return new Uint32LengthPrefixFraming({\n maxBufferSizeBytes: options?.maxBufferSizeBytes ?? 16 * 1024 * 1024, // 16MB\n });\n}\n\nexport const MessageFramer = {\n createFramedStream: createLengthEncodedStream,\n write: (buf: Uint8Array) => {\n const lengthPrefix = Buffer.alloc(4);\n lengthPrefix.writeUInt32BE(buf.length, 0);\n return Buffer.concat([lengthPrefix, buf]);\n },\n};\n","import { Connection } from '../../session';\nimport { type Socket } from 'node:net';\nimport stream from 'node:stream';\nimport {\n MessageFramer,\n Uint32LengthPrefixFraming,\n} from '../../transforms/messageFraming';\n\nexport class UdsConnection extends Connection {\n sock: Socket;\n input: stream.Readable;\n framer: Uint32LengthPrefixFraming;\n\n constructor(sock: Socket) {\n super();\n this.framer = MessageFramer.createFramedStream();\n this.sock = sock;\n this.input = sock.pipe(this.framer);\n }\n\n addDataListener(cb: (msg: Uint8Array) => void) {\n this.input.on('data', cb);\n }\n\n removeDataListener(cb: (msg: Uint8Array) => void): void {\n this.input.off('data', cb);\n }\n\n addCloseListener(cb: () => void): void {\n this.sock.on('close', cb);\n }\n\n addErrorListener(cb: (err: Error) => void): void {\n this.sock.on('error', (err) => {\n if (err instanceof Error && 'code' in err && err.code === 'EPIPE') {\n // Ignore EPIPE errors\n return;\n }\n\n cb(err);\n });\n }\n\n send(payload: Uint8Array) {\n if (this.framer.destroyed || !this.sock.writable) return false;\n return this.sock.write(MessageFramer.write(payload));\n }\n\n close() {\n this.sock.destroy();\n this.framer.destroy();\n }\n}\n"],"mappings":"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","names":[]}
@@ -1512,7 +1512,7 @@ function createServer(transport, services, extendedContext) {
1512
1512
  }
1513
1513
 
1514
1514
  // package.json
1515
- var version = "0.20.0";
1515
+ var version = "0.21.0";
1516
1516
 
1517
1517
  export {
1518
1518
  serializeSchema,
@@ -1527,4 +1527,4 @@ export {
1527
1527
  createServer,
1528
1528
  version
1529
1529
  };
1530
- //# sourceMappingURL=chunk-YB5LRYL6.js.map
1530
+ //# sourceMappingURL=chunk-NFV77C2M.js.map