@replit/river 0.23.15 → 0.200.0-rc.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 (72) hide show
  1. package/dist/{chunk-5HK7ZQYH.js → chunk-3FALN7ZG.js} +14 -2
  2. package/dist/{chunk-5HK7ZQYH.js.map → chunk-3FALN7ZG.js.map} +1 -1
  3. package/dist/{chunk-RQQZUQGE.js → chunk-6GK2IIDP.js} +2 -2
  4. package/dist/{chunk-JMVKSGND.js → chunk-6RKO3DDG.js} +4 -4
  5. package/dist/chunk-E2ZXI663.js +1995 -0
  6. package/dist/chunk-E2ZXI663.js.map +1 -0
  7. package/dist/{chunk-OXVWMLID.js → chunk-LK74ZG7M.js} +25 -10
  8. package/dist/chunk-LK74ZG7M.js.map +1 -0
  9. package/dist/{chunk-XYEOXPZQ.js → chunk-NDLWNT7B.js} +2 -2
  10. package/dist/{chunk-6LCL2ZZF.js → chunk-QMM35C3H.js} +1 -1
  11. package/dist/chunk-QMM35C3H.js.map +1 -0
  12. package/dist/{chunk-IJTGEBLG.js → chunk-TK7QHUFP.js} +4 -4
  13. package/dist/{chunk-MD4S7GO2.js → chunk-YUY37VAK.js} +23 -7
  14. package/dist/chunk-YUY37VAK.js.map +1 -0
  15. package/dist/{connection-5d0978ce.d.ts → connection-0638316b.d.ts} +1 -1
  16. package/dist/{connection-e57e98ea.d.ts → connection-c6521735.d.ts} +1 -1
  17. package/dist/{index-ea74cdbb.d.ts → index-10ebd26a.d.ts} +33 -33
  18. package/dist/logging/index.cjs.map +1 -1
  19. package/dist/logging/index.d.cts +1 -1
  20. package/dist/logging/index.d.ts +1 -1
  21. package/dist/logging/index.js +1 -1
  22. package/dist/router/index.cjs +1053 -912
  23. package/dist/router/index.cjs.map +1 -1
  24. package/dist/router/index.d.cts +19 -23
  25. package/dist/router/index.d.ts +19 -23
  26. package/dist/router/index.js +12 -6
  27. package/dist/services-34d97070.d.ts +1366 -0
  28. package/dist/transport/impls/uds/client.cjs +33 -5
  29. package/dist/transport/impls/uds/client.cjs.map +1 -1
  30. package/dist/transport/impls/uds/client.d.cts +3 -4
  31. package/dist/transport/impls/uds/client.d.ts +3 -4
  32. package/dist/transport/impls/uds/client.js +6 -6
  33. package/dist/transport/impls/uds/server.cjs +33 -5
  34. package/dist/transport/impls/uds/server.cjs.map +1 -1
  35. package/dist/transport/impls/uds/server.d.cts +4 -4
  36. package/dist/transport/impls/uds/server.d.ts +4 -4
  37. package/dist/transport/impls/uds/server.js +6 -6
  38. package/dist/transport/impls/ws/client.cjs +33 -5
  39. package/dist/transport/impls/ws/client.cjs.map +1 -1
  40. package/dist/transport/impls/ws/client.d.cts +5 -6
  41. package/dist/transport/impls/ws/client.d.ts +5 -6
  42. package/dist/transport/impls/ws/client.js +6 -6
  43. package/dist/transport/impls/ws/server.cjs +33 -5
  44. package/dist/transport/impls/ws/server.cjs.map +1 -1
  45. package/dist/transport/impls/ws/server.d.cts +4 -4
  46. package/dist/transport/impls/ws/server.d.ts +4 -4
  47. package/dist/transport/impls/ws/server.js +6 -6
  48. package/dist/transport/index.cjs +33 -5
  49. package/dist/transport/index.cjs.map +1 -1
  50. package/dist/transport/index.d.cts +27 -5
  51. package/dist/transport/index.d.ts +27 -5
  52. package/dist/transport/index.js +6 -6
  53. package/dist/util/testHelpers.cjs +382 -326
  54. package/dist/util/testHelpers.cjs.map +1 -1
  55. package/dist/util/testHelpers.d.cts +32 -21
  56. package/dist/util/testHelpers.d.ts +32 -21
  57. package/dist/util/testHelpers.js +76 -42
  58. package/dist/util/testHelpers.js.map +1 -1
  59. package/package.json +15 -15
  60. package/dist/chunk-6LCL2ZZF.js.map +0 -1
  61. package/dist/chunk-AEY7BBOZ.js +0 -1865
  62. package/dist/chunk-AEY7BBOZ.js.map +0 -1
  63. package/dist/chunk-MD4S7GO2.js.map +0 -1
  64. package/dist/chunk-OXVWMLID.js.map +0 -1
  65. package/dist/client-e13979ac.d.ts +0 -52
  66. package/dist/handshake-5665ffd3.d.ts +0 -511
  67. package/dist/server-1cfc88d1.d.ts +0 -24
  68. package/dist/services-86c4d10d.d.ts +0 -709
  69. /package/dist/{chunk-RQQZUQGE.js.map → chunk-6GK2IIDP.js.map} +0 -0
  70. /package/dist/{chunk-JMVKSGND.js.map → chunk-6RKO3DDG.js.map} +0 -0
  71. /package/dist/{chunk-XYEOXPZQ.js.map → chunk-NDLWNT7B.js.map} +0 -0
  72. /package/dist/{chunk-IJTGEBLG.js.map → chunk-TK7QHUFP.js.map} +0 -0
@@ -38,6 +38,7 @@ __export(testHelpers_exports, {
38
38
  createLocalWebSocketClient: () => createLocalWebSocketClient,
39
39
  createWebSocketServer: () => createWebSocketServer,
40
40
  dummySession: () => dummySession,
41
+ getIteratorFromStream: () => getIteratorFromStream,
41
42
  getUnixSocketPath: () => getUnixSocketPath,
42
43
  iterNext: () => iterNext,
43
44
  onUdsServeReady: () => onUdsServeReady,
@@ -49,299 +50,55 @@ __export(testHelpers_exports, {
49
50
  module.exports = __toCommonJS(testHelpers_exports);
50
51
  var import_ws = __toESM(require("ws"), 1);
51
52
 
52
- // node_modules/p-defer/index.js
53
- function pDefer() {
54
- const deferred = {};
55
- deferred.promise = new Promise((resolve, reject) => {
56
- deferred.resolve = resolve;
57
- deferred.reject = reject;
58
- });
59
- return deferred;
60
- }
61
-
62
- // node_modules/it-pushable/dist/src/fifo.js
63
- var FixedFIFO = class {
64
- buffer;
65
- mask;
66
- top;
67
- btm;
68
- next;
69
- constructor(hwm) {
70
- if (!(hwm > 0) || (hwm - 1 & hwm) !== 0) {
71
- throw new Error("Max size for a FixedFIFO should be a power of two");
72
- }
73
- this.buffer = new Array(hwm);
74
- this.mask = hwm - 1;
75
- this.top = 0;
76
- this.btm = 0;
77
- this.next = null;
78
- }
79
- push(data) {
80
- if (this.buffer[this.top] !== void 0) {
81
- return false;
82
- }
83
- this.buffer[this.top] = data;
84
- this.top = this.top + 1 & this.mask;
85
- return true;
86
- }
87
- shift() {
88
- const last = this.buffer[this.btm];
89
- if (last === void 0) {
90
- return void 0;
91
- }
92
- this.buffer[this.btm] = void 0;
93
- this.btm = this.btm + 1 & this.mask;
94
- return last;
95
- }
96
- isEmpty() {
97
- return this.buffer[this.btm] === void 0;
98
- }
99
- };
100
- var FIFO = class {
101
- size;
102
- hwm;
103
- head;
104
- tail;
105
- constructor(options = {}) {
106
- this.hwm = options.splitLimit ?? 16;
107
- this.head = new FixedFIFO(this.hwm);
108
- this.tail = this.head;
109
- this.size = 0;
110
- }
111
- calculateSize(obj) {
112
- if (obj?.byteLength != null) {
113
- return obj.byteLength;
114
- }
115
- return 1;
116
- }
117
- push(val) {
118
- if (val?.value != null) {
119
- this.size += this.calculateSize(val.value);
120
- }
121
- if (!this.head.push(val)) {
122
- const prev = this.head;
123
- this.head = prev.next = new FixedFIFO(2 * this.head.buffer.length);
124
- this.head.push(val);
125
- }
126
- }
127
- shift() {
128
- let val = this.tail.shift();
129
- if (val === void 0 && this.tail.next != null) {
130
- const next = this.tail.next;
131
- this.tail.next = null;
132
- this.tail = next;
133
- val = this.tail.shift();
134
- }
135
- if (val?.value != null) {
136
- this.size -= this.calculateSize(val.value);
137
- }
138
- return val;
139
- }
140
- isEmpty() {
141
- return this.head.isEmpty();
142
- }
143
- };
144
-
145
- // node_modules/it-pushable/dist/src/index.js
146
- var AbortError = class extends Error {
147
- type;
148
- code;
149
- constructor(message, code) {
150
- super(message ?? "The operation was aborted");
151
- this.type = "aborted";
152
- this.code = code ?? "ABORT_ERR";
153
- }
154
- };
155
- function pushable(options = {}) {
156
- const getNext = (buffer) => {
157
- const next = buffer.shift();
158
- if (next == null) {
159
- return { done: true };
160
- }
161
- if (next.error != null) {
162
- throw next.error;
163
- }
164
- return {
165
- done: next.done === true,
166
- // @ts-expect-error if done is false, value will be present
167
- value: next.value
168
- };
169
- };
170
- return _pushable(getNext, options);
171
- }
172
- function _pushable(getNext, options) {
173
- options = options ?? {};
174
- let onEnd = options.onEnd;
175
- let buffer = new FIFO();
176
- let pushable2;
177
- let onNext;
178
- let ended;
179
- let drain = pDefer();
180
- const waitNext = async () => {
181
- try {
182
- if (!buffer.isEmpty()) {
183
- return getNext(buffer);
184
- }
185
- if (ended) {
186
- return { done: true };
187
- }
188
- return await new Promise((resolve, reject) => {
189
- onNext = (next) => {
190
- onNext = null;
191
- buffer.push(next);
192
- try {
193
- resolve(getNext(buffer));
194
- } catch (err) {
195
- reject(err);
196
- }
197
- return pushable2;
198
- };
199
- });
200
- } finally {
201
- if (buffer.isEmpty()) {
202
- queueMicrotask(() => {
203
- drain.resolve();
204
- drain = pDefer();
205
- });
206
- }
207
- }
208
- };
209
- const bufferNext = (next) => {
210
- if (onNext != null) {
211
- return onNext(next);
212
- }
213
- buffer.push(next);
214
- return pushable2;
215
- };
216
- const bufferError = (err) => {
217
- buffer = new FIFO();
218
- if (onNext != null) {
219
- return onNext({ error: err });
220
- }
221
- buffer.push({ error: err });
222
- return pushable2;
223
- };
224
- const push = (value) => {
225
- if (ended) {
226
- return pushable2;
227
- }
228
- if (options?.objectMode !== true && value?.byteLength == null) {
229
- throw new Error("objectMode was not true but tried to push non-Uint8Array value");
230
- }
231
- return bufferNext({ done: false, value });
232
- };
233
- const end = (err) => {
234
- if (ended)
235
- return pushable2;
236
- ended = true;
237
- return err != null ? bufferError(err) : bufferNext({ done: true });
238
- };
239
- const _return = () => {
240
- buffer = new FIFO();
241
- end();
242
- return { done: true };
243
- };
244
- const _throw = (err) => {
245
- end(err);
246
- return { done: true };
247
- };
248
- pushable2 = {
249
- [Symbol.asyncIterator]() {
250
- return this;
251
- },
252
- next: waitNext,
253
- return: _return,
254
- throw: _throw,
255
- push,
256
- end,
257
- get readableLength() {
258
- return buffer.size;
259
- },
260
- onEmpty: async (options2) => {
261
- const signal = options2?.signal;
262
- signal?.throwIfAborted();
263
- if (buffer.isEmpty()) {
264
- return;
265
- }
266
- let cancel;
267
- let listener;
268
- if (signal != null) {
269
- cancel = new Promise((resolve, reject) => {
270
- listener = () => {
271
- reject(new AbortError());
272
- };
273
- signal.addEventListener("abort", listener);
274
- });
275
- }
276
- try {
277
- await Promise.race([
278
- drain.promise,
279
- cancel
280
- ]);
281
- } finally {
282
- if (listener != null && signal != null) {
283
- signal?.removeEventListener("abort", listener);
284
- }
285
- }
286
- }
287
- };
288
- if (onEnd == null) {
289
- return pushable2;
290
- }
291
- const _pushable2 = pushable2;
292
- pushable2 = {
293
- [Symbol.asyncIterator]() {
294
- return this;
295
- },
296
- next() {
297
- return _pushable2.next();
298
- },
299
- throw(err) {
300
- _pushable2.throw(err);
301
- if (onEnd != null) {
302
- onEnd(err);
303
- onEnd = void 0;
304
- }
305
- return { done: true };
306
- },
307
- return() {
308
- _pushable2.return();
309
- if (onEnd != null) {
310
- onEnd();
311
- onEnd = void 0;
312
- }
313
- return { done: true };
314
- },
315
- push,
316
- end(err) {
317
- _pushable2.end(err);
318
- if (onEnd != null) {
319
- onEnd(err);
320
- onEnd = void 0;
321
- }
322
- return pushable2;
323
- },
324
- get readableLength() {
325
- return _pushable2.readableLength;
326
- },
327
- onEmpty: (opts) => {
328
- return _pushable2.onEmpty(opts);
329
- }
330
- };
331
- return pushable2;
332
- }
333
-
334
- // router/result.ts
53
+ // router/procedures.ts
335
54
  var import_typebox = require("@sinclair/typebox");
336
- var UNCAUGHT_ERROR = "UNCAUGHT_ERROR";
337
- var UNEXPECTED_DISCONNECT = "UNEXPECTED_DISCONNECT";
338
- var RiverUncaughtSchema = import_typebox.Type.Object({
55
+ var INTERNAL_RIVER_ERROR_CODE = "INTERNAL_RIVER_ERROR";
56
+ var UNCAUGHT_ERROR_CODE = "UNCAUGHT_ERROR";
57
+ var UNEXPECTED_DISCONNECT_CODE = "UNEXPECTED_DISCONNECT";
58
+ var INVALID_REQUEST_CODE = "INVALID_REQUEST";
59
+ var ABORT_CODE = "ABORT";
60
+ var OutputReaderErrorSchema = import_typebox.Type.Object({
61
+ code: import_typebox.Type.Union([
62
+ import_typebox.Type.Literal(INTERNAL_RIVER_ERROR_CODE),
63
+ import_typebox.Type.Literal(UNCAUGHT_ERROR_CODE),
64
+ import_typebox.Type.Literal(UNEXPECTED_DISCONNECT_CODE),
65
+ import_typebox.Type.Literal(INVALID_REQUEST_CODE),
66
+ import_typebox.Type.Literal(ABORT_CODE)
67
+ ]),
68
+ message: import_typebox.Type.String()
69
+ });
70
+ var InputReaderErrorSchema = import_typebox.Type.Object({
339
71
  code: import_typebox.Type.Union([
340
- import_typebox.Type.Literal(UNCAUGHT_ERROR),
341
- import_typebox.Type.Literal(UNEXPECTED_DISCONNECT)
72
+ import_typebox.Type.Literal(UNCAUGHT_ERROR_CODE),
73
+ import_typebox.Type.Literal(UNEXPECTED_DISCONNECT_CODE),
74
+ import_typebox.Type.Literal(INVALID_REQUEST_CODE),
75
+ import_typebox.Type.Literal(ABORT_CODE)
342
76
  ]),
343
77
  message: import_typebox.Type.String()
344
78
  });
79
+
80
+ // router/result.ts
81
+ var import_typebox2 = require("@sinclair/typebox");
82
+ var AnyResultSchema = import_typebox2.Type.Union([
83
+ import_typebox2.Type.Object({
84
+ ok: import_typebox2.Type.Literal(false),
85
+ payload: import_typebox2.Type.Object({
86
+ code: import_typebox2.Type.String(),
87
+ message: import_typebox2.Type.String(),
88
+ extras: import_typebox2.Type.Optional(import_typebox2.Type.Unknown())
89
+ })
90
+ }),
91
+ import_typebox2.Type.Object({
92
+ ok: import_typebox2.Type.Literal(true),
93
+ payload: import_typebox2.Type.Unknown()
94
+ })
95
+ ]);
96
+ function Ok(payload) {
97
+ return {
98
+ ok: true,
99
+ payload
100
+ };
101
+ }
345
102
  function Err(error) {
346
103
  return {
347
104
  ok: false,
@@ -353,7 +110,7 @@ function Err(error) {
353
110
  var import_api = require("@opentelemetry/api");
354
111
 
355
112
  // package.json
356
- var version = "0.23.15";
113
+ var version = "0.200.0-rc.0";
357
114
 
358
115
  // tracing/index.ts
359
116
  function createSessionTelemetryInfo(session, propagationCtx) {
@@ -375,6 +132,261 @@ function createSessionTelemetryInfo(session, propagationCtx) {
375
132
  }
376
133
  var tracer = import_api.trace.getTracer("river", version);
377
134
 
135
+ // router/streams.ts
136
+ var StreamDrainedError = {
137
+ code: "STREAM_DRAINED",
138
+ message: "Stream was drained"
139
+ };
140
+ var ReadStreamImpl = class {
141
+ /**
142
+ * Whether the stream is closed.
143
+ */
144
+ closed = false;
145
+ /**
146
+ * A list of listeners that will be called when the stream is closed.
147
+ */
148
+ onCloseListeners;
149
+ /**
150
+ * Whether the user has requested to close the stream.
151
+ */
152
+ closeRequested = false;
153
+ /**
154
+ * Used to signal to the outside world that the user has requested to close the stream.
155
+ */
156
+ closeRequestCallback;
157
+ /**
158
+ * Whether the stream is locked.
159
+ */
160
+ locked = false;
161
+ /**
162
+ * Whether drain was called.
163
+ */
164
+ drained = false;
165
+ /**
166
+ * This flag allows us to avoid cases where drain was called,
167
+ * but the stream is fully consumed and closed. We don't need
168
+ * to signal that drain was closed.
169
+ */
170
+ didDrainDisposeValues = false;
171
+ /**
172
+ * A list of values that have been pushed to the stream but not yet emitted to the user.
173
+ */
174
+ queue = [];
175
+ /**
176
+ * Used by methods in the class to signal to the iterator that it
177
+ * should check for the next value.
178
+ */
179
+ nextPromise = null;
180
+ /**
181
+ * Resolves nextPromise
182
+ */
183
+ resolveNextPromise = null;
184
+ constructor(closeRequestCallback) {
185
+ this.closeRequestCallback = closeRequestCallback;
186
+ this.onCloseListeners = /* @__PURE__ */ new Set();
187
+ }
188
+ [Symbol.asyncIterator]() {
189
+ if (this.isLocked()) {
190
+ throw new TypeError("ReadStream is already locked");
191
+ }
192
+ let didSignalDrain = false;
193
+ this.locked = true;
194
+ return {
195
+ next: async () => {
196
+ if (this.drained && didSignalDrain) {
197
+ return {
198
+ done: true,
199
+ value: void 0
200
+ };
201
+ }
202
+ while (this.queue.length === 0) {
203
+ if (this.isClosed() && !this.didDrainDisposeValues) {
204
+ return {
205
+ done: true,
206
+ value: void 0
207
+ };
208
+ }
209
+ if (this.drained) {
210
+ didSignalDrain = true;
211
+ return {
212
+ done: false,
213
+ value: Err(StreamDrainedError)
214
+ };
215
+ }
216
+ if (!this.nextPromise) {
217
+ this.nextPromise = new Promise((resolve) => {
218
+ this.resolveNextPromise = resolve;
219
+ });
220
+ }
221
+ await this.nextPromise;
222
+ this.nextPromise = null;
223
+ this.resolveNextPromise = null;
224
+ }
225
+ const value = this.queue.shift();
226
+ return { done: false, value };
227
+ },
228
+ return: async () => {
229
+ this.drain();
230
+ return { done: true, value: void 0 };
231
+ }
232
+ };
233
+ }
234
+ async asArray() {
235
+ const array = [];
236
+ for await (const value of this) {
237
+ array.push(value);
238
+ }
239
+ return array;
240
+ }
241
+ drain() {
242
+ if (this.drained) {
243
+ return;
244
+ }
245
+ this.locked = true;
246
+ this.drained = true;
247
+ this.didDrainDisposeValues = this.queue.length > 0;
248
+ this.queue.length = 0;
249
+ this.resolveNextPromise?.();
250
+ }
251
+ isClosed() {
252
+ return this.closed;
253
+ }
254
+ isLocked() {
255
+ return this.locked;
256
+ }
257
+ onClose(cb) {
258
+ if (this.isClosed()) {
259
+ throw new Error("Stream is already closed");
260
+ }
261
+ this.onCloseListeners.add(cb);
262
+ return () => {
263
+ this.onCloseListeners.delete(cb);
264
+ };
265
+ }
266
+ requestClose() {
267
+ if (this.isClosed()) {
268
+ throw new Error("Cannot request close after stream already closed");
269
+ }
270
+ if (!this.closeRequested) {
271
+ this.closeRequested = true;
272
+ this.closeRequestCallback();
273
+ }
274
+ return new Promise((resolve) => {
275
+ this.onClose(() => {
276
+ resolve(void 0);
277
+ });
278
+ });
279
+ }
280
+ isCloseRequested() {
281
+ return this.closeRequested;
282
+ }
283
+ /**
284
+ * @internal meant for use within river, not exposed as a public API
285
+ *
286
+ * Pushes a value to the stream.
287
+ */
288
+ pushValue(value) {
289
+ if (this.drained) {
290
+ return;
291
+ }
292
+ if (this.closed) {
293
+ throw new Error("Cannot push to closed stream");
294
+ }
295
+ this.queue.push(value);
296
+ this.resolveNextPromise?.();
297
+ }
298
+ /**
299
+ * @internal meant for use within river, not exposed as a public API
300
+ *
301
+ * Triggers the close of the stream. Make sure to push all remaining
302
+ * values before calling this method.
303
+ */
304
+ triggerClose() {
305
+ if (this.isClosed()) {
306
+ throw new Error("Unexpected closing multiple times");
307
+ }
308
+ this.closed = true;
309
+ this.resolveNextPromise?.();
310
+ this.onCloseListeners.forEach((cb) => cb());
311
+ this.onCloseListeners.clear();
312
+ }
313
+ /**
314
+ * @internal meant for use within river, not exposed as a public API
315
+ */
316
+ hasValuesInQueue() {
317
+ return this.queue.length > 0;
318
+ }
319
+ };
320
+ var WriteStreamImpl = class {
321
+ /**
322
+ * Passed via constructor to pass on write requests
323
+ */
324
+ writeCb;
325
+ /**
326
+ * Passed via constructor to pass on close requests
327
+ */
328
+ closeCb;
329
+ /**
330
+ * Whether the stream is closed.
331
+ */
332
+ closed = false;
333
+ /**
334
+ * Whether the reader has requested to close the stream.
335
+ */
336
+ closeRequested = false;
337
+ /**
338
+ * A list of listeners that will be called when the stream is closed.
339
+ */
340
+ onCloseListeners;
341
+ constructor(writeCb, closeCb) {
342
+ this.writeCb = writeCb;
343
+ this.closeCb = closeCb;
344
+ this.onCloseListeners = /* @__PURE__ */ new Set();
345
+ }
346
+ write(value) {
347
+ if (this.isClosed()) {
348
+ throw new Error("Cannot write to closed stream");
349
+ }
350
+ this.writeCb(value);
351
+ }
352
+ close() {
353
+ if (this.isClosed()) {
354
+ return;
355
+ }
356
+ this.closed = true;
357
+ this.closeCb();
358
+ }
359
+ isCloseRequested() {
360
+ return this.closeRequested;
361
+ }
362
+ onCloseRequest(cb) {
363
+ if (this.isClosed()) {
364
+ throw new Error("Stream is already closed");
365
+ }
366
+ this.onCloseListeners.add(cb);
367
+ return () => this.onCloseListeners.delete(cb);
368
+ }
369
+ isClosed() {
370
+ return this.closed;
371
+ }
372
+ /**
373
+ * @internal meant for use within river, not exposed as a public API
374
+ *
375
+ * Triggers a close request.
376
+ */
377
+ triggerCloseRequest() {
378
+ if (this.isCloseRequested()) {
379
+ throw new Error("Cannot trigger close request multiple times");
380
+ }
381
+ if (this.isClosed()) {
382
+ throw new Error("Cannot trigger close request on closed stream");
383
+ }
384
+ this.closeRequested = true;
385
+ this.onCloseListeners.forEach((cb) => cb());
386
+ this.onCloseListeners.clear();
387
+ }
388
+ };
389
+
378
390
  // util/stringify.ts
379
391
  function coerceErrorString(err) {
380
392
  if (err instanceof Error) {
@@ -643,6 +655,18 @@ var Session = class {
643
655
  get nextExpectedSeq() {
644
656
  return this.ack;
645
657
  }
658
+ /**
659
+ * Check that the peer's next expected seq number matches something that is in our send buffer
660
+ * _or_ matches our actual next seq.
661
+ */
662
+ nextExpectedSeqInRange(nextExpectedSeq) {
663
+ for (const msg of this.sendBuffer) {
664
+ if (nextExpectedSeq === msg.seq) {
665
+ return true;
666
+ }
667
+ }
668
+ return nextExpectedSeq === this.seq;
669
+ }
646
670
  // This is only used in tests to make the session misbehave.
647
671
  /* @internal */
648
672
  advanceAckForTesting(by) {
@@ -766,6 +790,9 @@ function onUdsServeReady(server, path) {
766
790
  server.listen(path, resolve);
767
791
  });
768
792
  }
793
+ function getIteratorFromStream(readStream) {
794
+ return readStream[Symbol.asyncIterator]();
795
+ }
769
796
  async function iterNext(iter) {
770
797
  return await iter.next().then((res) => res.value);
771
798
  }
@@ -801,7 +828,7 @@ async function waitForMessage(t, filter, rejectMismatch) {
801
828
  }
802
829
  function catchProcError(err) {
803
830
  const errorMsg = coerceErrorString(err);
804
- return Err({ code: UNCAUGHT_ERROR, message: errorMsg });
831
+ return Err({ code: UNCAUGHT_ERROR_CODE, message: errorMsg });
805
832
  }
806
833
  var testingSessionOptions = defaultTransportOptions;
807
834
  function dummySession() {
@@ -815,57 +842,85 @@ function dummySession() {
815
842
  function dummyCtx(state, session, extendedContext) {
816
843
  return {
817
844
  ...extendedContext,
818
- state,
819
- to: session.to,
820
845
  from: session.from,
821
- streamId: (0, import_nanoid2.nanoid)(),
822
- session,
823
- metadata: {}
846
+ state,
847
+ metadata: {},
848
+ abortController: new AbortController(),
849
+ clientAbortSignal: new AbortController().signal,
850
+ onRequestFinished: () => void 0
824
851
  };
825
852
  }
826
853
  function asClientRpc(state, proc, extendedContext, session = dummySession()) {
827
854
  return async (msg) => {
828
- return await proc.handler(dummyCtx(state, session, extendedContext), msg).catch(catchProcError);
855
+ return proc.handler(dummyCtx(state, session, extendedContext), msg).catch(catchProcError);
829
856
  };
830
857
  }
831
- function asClientStream(state, proc, init, extendedContext, session = dummySession()) {
832
- const input = pushable({ objectMode: true });
833
- const output = pushable({
834
- objectMode: true
858
+ function createOutputPipe() {
859
+ const reader = new ReadStreamImpl(() => {
860
+ void Promise.resolve().then(() => {
861
+ writer.triggerCloseRequest();
862
+ });
835
863
  });
836
- void (async () => {
837
- if (init) {
838
- const _proc = proc;
839
- await _proc.handler(dummyCtx(state, session, extendedContext), init, input, output).catch((err) => output.push(catchProcError(err)));
840
- } else {
841
- const _proc = proc;
842
- await _proc.handler(dummyCtx(state, session, extendedContext), input, output).catch((err) => output.push(catchProcError(err)));
864
+ const writer = new WriteStreamImpl(
865
+ (v) => {
866
+ reader.pushValue(v);
867
+ },
868
+ () => {
869
+ void Promise.resolve().then(() => {
870
+ reader.triggerClose();
871
+ });
843
872
  }
844
- })();
845
- return [input, output];
873
+ );
874
+ return { reader, writer };
846
875
  }
847
- function asClientSubscription(state, proc, extendedContext, session = dummySession()) {
848
- const output = pushable({
849
- objectMode: true
876
+ function createInputPipe() {
877
+ const reader = new ReadStreamImpl(() => {
878
+ void Promise.resolve().then(() => {
879
+ writer.triggerCloseRequest();
880
+ });
850
881
  });
882
+ const writer = new WriteStreamImpl(
883
+ (v) => {
884
+ reader.pushValue(Ok(v));
885
+ },
886
+ () => {
887
+ void Promise.resolve().then(() => {
888
+ reader.triggerClose();
889
+ });
890
+ }
891
+ );
892
+ return { reader, writer };
893
+ }
894
+ function asClientStream(state, proc, init, extendedContext, session = dummySession()) {
895
+ const inputPipe = createInputPipe();
896
+ const outputPipe = createOutputPipe();
897
+ void proc.handler(
898
+ dummyCtx(state, session, extendedContext),
899
+ init ?? {},
900
+ inputPipe.reader,
901
+ outputPipe.writer
902
+ ).catch((err) => outputPipe.writer.write(catchProcError(err)));
903
+ return [inputPipe.writer, outputPipe.reader];
904
+ }
905
+ function asClientSubscription(state, proc, extendedContext, session = dummySession()) {
906
+ const outputPipe = createOutputPipe();
851
907
  return (msg) => {
852
- void (async () => {
853
- return await proc.handler(dummyCtx(state, session, extendedContext), msg, output).catch((err) => output.push(catchProcError(err)));
854
- })();
855
- return output;
908
+ void proc.handler(
909
+ dummyCtx(state, session, extendedContext),
910
+ msg,
911
+ outputPipe.writer
912
+ ).catch((err) => outputPipe.writer.write(catchProcError(err)));
913
+ return outputPipe.reader;
856
914
  };
857
915
  }
858
916
  function asClientUpload(state, proc, init, extendedContext, session = dummySession()) {
859
- const input = pushable({ objectMode: true });
860
- if (init) {
861
- const _proc = proc;
862
- const result = _proc.handler(dummyCtx(state, session, extendedContext), init, input).catch(catchProcError);
863
- return [input, result];
864
- } else {
865
- const _proc = proc;
866
- const result = _proc.handler(dummyCtx(state, session, extendedContext), input).catch(catchProcError);
867
- return [input, result];
868
- }
917
+ const inputPipe = createInputPipe();
918
+ const result = proc.handler(
919
+ dummyCtx(state, session, extendedContext),
920
+ init ?? {},
921
+ inputPipe.reader
922
+ ).catch(catchProcError);
923
+ return [inputPipe.writer, () => result];
869
924
  }
870
925
  var getUnixSocketPath = () => {
871
926
  return process.platform === "win32" ? `\\\\?\\pipe\\${(0, import_nanoid2.nanoid)()}` : `/tmp/${(0, import_nanoid2.nanoid)()}.sock`;
@@ -880,6 +935,7 @@ var getUnixSocketPath = () => {
880
935
  createLocalWebSocketClient,
881
936
  createWebSocketServer,
882
937
  dummySession,
938
+ getIteratorFromStream,
883
939
  getUnixSocketPath,
884
940
  iterNext,
885
941
  onUdsServeReady,