@replit/river 0.10.0 → 0.10.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.
Files changed (135) hide show
  1. package/dist/{router/builder.d.ts → builder-3c4485f0.d.ts} +76 -21
  2. package/dist/chunk-AJQU4AZG.js +284 -0
  3. package/dist/chunk-IYRPZPSQ.js +964 -0
  4. package/dist/chunk-ORAG7IAU.js +0 -0
  5. package/dist/chunk-PC65ZFWJ.js +29 -0
  6. package/dist/chunk-R6H2BIMC.js +49 -0
  7. package/dist/chunk-RGMHF6PF.js +65 -0
  8. package/dist/chunk-SLUSVGQH.js +30 -0
  9. package/dist/chunk-UU2Z7LDR.js +113 -0
  10. package/dist/chunk-WVT5QXMZ.js +20 -0
  11. package/dist/chunk-ZE4MX7DF.js +75 -0
  12. package/dist/codec/index.cjs +94 -0
  13. package/dist/codec/index.d.cts +15 -0
  14. package/dist/codec/index.d.ts +15 -4
  15. package/dist/codec/index.js +10 -2
  16. package/dist/connection-8e19874c.d.ts +11 -0
  17. package/dist/connection-f7688cc1.d.ts +11 -0
  18. package/dist/logging/index.cjs +56 -0
  19. package/dist/logging/index.d.cts +28 -0
  20. package/dist/logging/index.d.ts +6 -6
  21. package/dist/logging/index.js +9 -40
  22. package/dist/router/index.cjs +1046 -0
  23. package/dist/router/index.d.cts +114 -0
  24. package/dist/router/index.d.ts +114 -12
  25. package/dist/router/index.js +24 -5
  26. package/dist/transport/impls/ws/client.cjs +505 -0
  27. package/dist/transport/impls/ws/client.d.cts +42 -0
  28. package/dist/transport/impls/ws/client.d.ts +8 -8
  29. package/dist/transport/impls/ws/client.js +10 -100
  30. package/dist/transport/impls/ws/server.cjs +457 -0
  31. package/dist/transport/impls/ws/server.d.cts +21 -0
  32. package/dist/transport/impls/ws/server.d.ts +11 -10
  33. package/dist/transport/impls/ws/server.js +11 -52
  34. package/dist/transport/index.cjs +362 -0
  35. package/dist/transport/{transport.d.ts → index.d.cts} +119 -7
  36. package/dist/transport/index.d.ts +273 -4
  37. package/dist/transport/index.js +20 -2
  38. package/dist/{codec/types.d.ts → types-3e5768ec.d.ts} +3 -2
  39. package/dist/util/testHelpers.cjs +1010 -0
  40. package/dist/util/testHelpers.d.cts +79 -0
  41. package/dist/util/testHelpers.d.ts +22 -19
  42. package/dist/util/testHelpers.js +135 -163
  43. package/package.json +42 -14
  44. package/dist/__tests__/bandwidth.bench.d.ts +0 -2
  45. package/dist/__tests__/bandwidth.bench.d.ts.map +0 -1
  46. package/dist/__tests__/bandwidth.bench.js +0 -90
  47. package/dist/__tests__/cleanup.test.d.ts +0 -2
  48. package/dist/__tests__/cleanup.test.d.ts.map +0 -1
  49. package/dist/__tests__/cleanup.test.js +0 -165
  50. package/dist/__tests__/disconnects.test.d.ts +0 -2
  51. package/dist/__tests__/disconnects.test.d.ts.map +0 -1
  52. package/dist/__tests__/disconnects.test.js +0 -163
  53. package/dist/__tests__/e2e.test.d.ts +0 -2
  54. package/dist/__tests__/e2e.test.d.ts.map +0 -1
  55. package/dist/__tests__/e2e.test.js +0 -317
  56. package/dist/__tests__/fixtures/cleanup.d.ts +0 -12
  57. package/dist/__tests__/fixtures/cleanup.d.ts.map +0 -1
  58. package/dist/__tests__/fixtures/cleanup.js +0 -36
  59. package/dist/__tests__/fixtures/largePayload.json +0 -33
  60. package/dist/__tests__/fixtures/observable.d.ts +0 -26
  61. package/dist/__tests__/fixtures/observable.d.ts.map +0 -1
  62. package/dist/__tests__/fixtures/observable.js +0 -38
  63. package/dist/__tests__/fixtures/observable.test.d.ts +0 -2
  64. package/dist/__tests__/fixtures/observable.test.d.ts.map +0 -1
  65. package/dist/__tests__/fixtures/observable.test.js +0 -39
  66. package/dist/__tests__/fixtures/services.d.ts +0 -288
  67. package/dist/__tests__/fixtures/services.d.ts.map +0 -1
  68. package/dist/__tests__/fixtures/services.js +0 -207
  69. package/dist/__tests__/handler.test.d.ts +0 -2
  70. package/dist/__tests__/handler.test.d.ts.map +0 -1
  71. package/dist/__tests__/handler.test.js +0 -120
  72. package/dist/__tests__/serialize.test.d.ts +0 -2
  73. package/dist/__tests__/serialize.test.d.ts.map +0 -1
  74. package/dist/__tests__/serialize.test.js +0 -208
  75. package/dist/__tests__/typescript-stress.test.d.ts +0 -1583
  76. package/dist/__tests__/typescript-stress.test.d.ts.map +0 -1
  77. package/dist/__tests__/typescript-stress.test.js +0 -123
  78. package/dist/codec/binary.d.ts +0 -7
  79. package/dist/codec/binary.d.ts.map +0 -1
  80. package/dist/codec/binary.js +0 -20
  81. package/dist/codec/codec.test.d.ts +0 -5
  82. package/dist/codec/codec.test.d.ts.map +0 -1
  83. package/dist/codec/codec.test.js +0 -41
  84. package/dist/codec/index.d.ts.map +0 -1
  85. package/dist/codec/json.d.ts +0 -7
  86. package/dist/codec/json.d.ts.map +0 -1
  87. package/dist/codec/json.js +0 -51
  88. package/dist/codec/types.d.ts.map +0 -1
  89. package/dist/codec/types.js +0 -1
  90. package/dist/logging/index.d.ts.map +0 -1
  91. package/dist/router/builder.d.ts.map +0 -1
  92. package/dist/router/builder.js +0 -91
  93. package/dist/router/client.d.ts +0 -72
  94. package/dist/router/client.d.ts.map +0 -1
  95. package/dist/router/client.js +0 -257
  96. package/dist/router/context.d.ts +0 -30
  97. package/dist/router/context.d.ts.map +0 -1
  98. package/dist/router/context.js +0 -1
  99. package/dist/router/defs.d.ts +0 -16
  100. package/dist/router/defs.d.ts.map +0 -1
  101. package/dist/router/defs.js +0 -11
  102. package/dist/router/index.d.ts.map +0 -1
  103. package/dist/router/result.d.ts +0 -26
  104. package/dist/router/result.d.ts.map +0 -1
  105. package/dist/router/result.js +0 -22
  106. package/dist/router/server.d.ts +0 -39
  107. package/dist/router/server.d.ts.map +0 -1
  108. package/dist/router/server.js +0 -260
  109. package/dist/transport/events.d.ts +0 -19
  110. package/dist/transport/events.d.ts.map +0 -1
  111. package/dist/transport/events.js +0 -26
  112. package/dist/transport/impls/stdio/stdio.d.ts +0 -33
  113. package/dist/transport/impls/stdio/stdio.d.ts.map +0 -1
  114. package/dist/transport/impls/stdio/stdio.js +0 -75
  115. package/dist/transport/impls/stdio/stdio.test.d.ts +0 -2
  116. package/dist/transport/impls/stdio/stdio.test.d.ts.map +0 -1
  117. package/dist/transport/impls/stdio/stdio.test.js +0 -24
  118. package/dist/transport/impls/ws/client.d.ts.map +0 -1
  119. package/dist/transport/impls/ws/connection.d.ts +0 -11
  120. package/dist/transport/impls/ws/connection.d.ts.map +0 -1
  121. package/dist/transport/impls/ws/connection.js +0 -23
  122. package/dist/transport/impls/ws/server.d.ts.map +0 -1
  123. package/dist/transport/impls/ws/ws.test.d.ts +0 -2
  124. package/dist/transport/impls/ws/ws.test.d.ts.map +0 -1
  125. package/dist/transport/impls/ws/ws.test.js +0 -185
  126. package/dist/transport/index.d.ts.map +0 -1
  127. package/dist/transport/message.d.ts +0 -142
  128. package/dist/transport/message.d.ts.map +0 -1
  129. package/dist/transport/message.js +0 -113
  130. package/dist/transport/message.test.d.ts +0 -2
  131. package/dist/transport/message.test.d.ts.map +0 -1
  132. package/dist/transport/message.test.js +0 -52
  133. package/dist/transport/transport.d.ts.map +0 -1
  134. package/dist/transport/transport.js +0 -281
  135. package/dist/util/testHelpers.d.ts.map +0 -1
@@ -0,0 +1,1046 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // router/index.ts
21
+ var router_exports = {};
22
+ __export(router_exports, {
23
+ Err: () => Err,
24
+ Ok: () => Ok,
25
+ RiverUncaughtSchema: () => RiverUncaughtSchema,
26
+ ServiceBuilder: () => ServiceBuilder,
27
+ UNCAUGHT_ERROR: () => UNCAUGHT_ERROR,
28
+ buildServiceDefs: () => buildServiceDefs,
29
+ createClient: () => createClient,
30
+ createServer: () => createServer,
31
+ serializeService: () => serializeService
32
+ });
33
+ module.exports = __toCommonJS(router_exports);
34
+
35
+ // router/builder.ts
36
+ var import_typebox = require("@sinclair/typebox");
37
+ function serializeService(s) {
38
+ return {
39
+ name: s.name,
40
+ state: s.state,
41
+ procedures: Object.fromEntries(
42
+ Object.entries(s.procedures).map(([procName, procDef]) => [
43
+ procName,
44
+ {
45
+ input: import_typebox.Type.Strict(procDef.input),
46
+ output: import_typebox.Type.Strict(procDef.output),
47
+ // Only add the `errors` field if it is non-never.
48
+ ..."errors" in procDef ? {
49
+ errors: import_typebox.Type.Strict(procDef.errors)
50
+ } : {},
51
+ type: procDef.type,
52
+ // Only add the `init` field if the type declares it.
53
+ ..."init" in procDef ? {
54
+ init: import_typebox.Type.Strict(procDef.init)
55
+ } : {}
56
+ }
57
+ ])
58
+ )
59
+ };
60
+ }
61
+ var ServiceBuilder = class _ServiceBuilder {
62
+ schema;
63
+ constructor(schema) {
64
+ this.schema = schema;
65
+ }
66
+ /**
67
+ * Finalizes the schema for the service.
68
+ * @returns {T} The finalized schema for the service.
69
+ */
70
+ finalize() {
71
+ return this.schema;
72
+ }
73
+ /**
74
+ * Sets the initial state for the service.
75
+ * @template InitState The type of the initial state.
76
+ * @param {InitState} state The initial state for the service.
77
+ * @returns {ServiceBuilder<{ name: T['name']; state: InitState; procedures: T['procedures']; }>} A new ServiceBuilder instance with the updated schema.
78
+ */
79
+ initialState(state) {
80
+ return new _ServiceBuilder({
81
+ ...this.schema,
82
+ state
83
+ });
84
+ }
85
+ /**
86
+ * Defines a new procedure for the service.
87
+ * @param {ProcName} procName The name of the procedure.
88
+ * @param {Procedure<T['state'], Ty, I, O, E, Init>} procDef The definition of the procedure.
89
+ * @returns {ServiceBuilder<{ name: T['name']; state: T['state']; procedures: T['procedures'] & { [k in ProcName]: Procedure<T['state'], Ty, I, O, E, Init>; }; }>} A new ServiceBuilder instance with the updated schema.
90
+ */
91
+ defineProcedure(procName, procDef) {
92
+ const newProcedure = { [procName]: procDef };
93
+ const procedures = {
94
+ ...this.schema.procedures,
95
+ ...newProcedure
96
+ };
97
+ return new _ServiceBuilder({
98
+ ...this.schema,
99
+ procedures
100
+ });
101
+ }
102
+ /**
103
+ * Creates a new instance of ServiceBuilder.
104
+ * @param {Name} name The name of the service.
105
+ * @returns {ServiceBuilder<{ name: Name; state: {}; procedures: {}; }>} A new instance of ServiceBuilder.
106
+ */
107
+ static create(name) {
108
+ return new _ServiceBuilder({
109
+ name,
110
+ state: {},
111
+ procedures: {}
112
+ });
113
+ }
114
+ };
115
+
116
+ // router/defs.ts
117
+ function buildServiceDefs(services) {
118
+ return services.reduce((acc, service) => {
119
+ acc[service.name] = service;
120
+ return acc;
121
+ }, {});
122
+ }
123
+
124
+ // node_modules/p-defer/index.js
125
+ function pDefer() {
126
+ const deferred = {};
127
+ deferred.promise = new Promise((resolve, reject) => {
128
+ deferred.resolve = resolve;
129
+ deferred.reject = reject;
130
+ });
131
+ return deferred;
132
+ }
133
+
134
+ // node_modules/it-pushable/dist/src/fifo.js
135
+ var FixedFIFO = class {
136
+ buffer;
137
+ mask;
138
+ top;
139
+ btm;
140
+ next;
141
+ constructor(hwm) {
142
+ if (!(hwm > 0) || (hwm - 1 & hwm) !== 0) {
143
+ throw new Error("Max size for a FixedFIFO should be a power of two");
144
+ }
145
+ this.buffer = new Array(hwm);
146
+ this.mask = hwm - 1;
147
+ this.top = 0;
148
+ this.btm = 0;
149
+ this.next = null;
150
+ }
151
+ push(data) {
152
+ if (this.buffer[this.top] !== void 0) {
153
+ return false;
154
+ }
155
+ this.buffer[this.top] = data;
156
+ this.top = this.top + 1 & this.mask;
157
+ return true;
158
+ }
159
+ shift() {
160
+ const last = this.buffer[this.btm];
161
+ if (last === void 0) {
162
+ return void 0;
163
+ }
164
+ this.buffer[this.btm] = void 0;
165
+ this.btm = this.btm + 1 & this.mask;
166
+ return last;
167
+ }
168
+ isEmpty() {
169
+ return this.buffer[this.btm] === void 0;
170
+ }
171
+ };
172
+ var FIFO = class {
173
+ size;
174
+ hwm;
175
+ head;
176
+ tail;
177
+ constructor(options = {}) {
178
+ this.hwm = options.splitLimit ?? 16;
179
+ this.head = new FixedFIFO(this.hwm);
180
+ this.tail = this.head;
181
+ this.size = 0;
182
+ }
183
+ calculateSize(obj) {
184
+ if (obj?.byteLength != null) {
185
+ return obj.byteLength;
186
+ }
187
+ return 1;
188
+ }
189
+ push(val) {
190
+ if (val?.value != null) {
191
+ this.size += this.calculateSize(val.value);
192
+ }
193
+ if (!this.head.push(val)) {
194
+ const prev = this.head;
195
+ this.head = prev.next = new FixedFIFO(2 * this.head.buffer.length);
196
+ this.head.push(val);
197
+ }
198
+ }
199
+ shift() {
200
+ let val = this.tail.shift();
201
+ if (val === void 0 && this.tail.next != null) {
202
+ const next = this.tail.next;
203
+ this.tail.next = null;
204
+ this.tail = next;
205
+ val = this.tail.shift();
206
+ }
207
+ if (val?.value != null) {
208
+ this.size -= this.calculateSize(val.value);
209
+ }
210
+ return val;
211
+ }
212
+ isEmpty() {
213
+ return this.head.isEmpty();
214
+ }
215
+ };
216
+
217
+ // node_modules/it-pushable/dist/src/index.js
218
+ var AbortError = class extends Error {
219
+ type;
220
+ code;
221
+ constructor(message, code) {
222
+ super(message ?? "The operation was aborted");
223
+ this.type = "aborted";
224
+ this.code = code ?? "ABORT_ERR";
225
+ }
226
+ };
227
+ function pushable(options = {}) {
228
+ const getNext = (buffer) => {
229
+ const next = buffer.shift();
230
+ if (next == null) {
231
+ return { done: true };
232
+ }
233
+ if (next.error != null) {
234
+ throw next.error;
235
+ }
236
+ return {
237
+ done: next.done === true,
238
+ // @ts-expect-error if done is false, value will be present
239
+ value: next.value
240
+ };
241
+ };
242
+ return _pushable(getNext, options);
243
+ }
244
+ function _pushable(getNext, options) {
245
+ options = options ?? {};
246
+ let onEnd = options.onEnd;
247
+ let buffer = new FIFO();
248
+ let pushable2;
249
+ let onNext;
250
+ let ended;
251
+ let drain = pDefer();
252
+ const waitNext = async () => {
253
+ try {
254
+ if (!buffer.isEmpty()) {
255
+ return getNext(buffer);
256
+ }
257
+ if (ended) {
258
+ return { done: true };
259
+ }
260
+ return await new Promise((resolve, reject) => {
261
+ onNext = (next) => {
262
+ onNext = null;
263
+ buffer.push(next);
264
+ try {
265
+ resolve(getNext(buffer));
266
+ } catch (err) {
267
+ reject(err);
268
+ }
269
+ return pushable2;
270
+ };
271
+ });
272
+ } finally {
273
+ if (buffer.isEmpty()) {
274
+ queueMicrotask(() => {
275
+ drain.resolve();
276
+ drain = pDefer();
277
+ });
278
+ }
279
+ }
280
+ };
281
+ const bufferNext = (next) => {
282
+ if (onNext != null) {
283
+ return onNext(next);
284
+ }
285
+ buffer.push(next);
286
+ return pushable2;
287
+ };
288
+ const bufferError = (err) => {
289
+ buffer = new FIFO();
290
+ if (onNext != null) {
291
+ return onNext({ error: err });
292
+ }
293
+ buffer.push({ error: err });
294
+ return pushable2;
295
+ };
296
+ const push = (value) => {
297
+ if (ended) {
298
+ return pushable2;
299
+ }
300
+ if (options?.objectMode !== true && value?.byteLength == null) {
301
+ throw new Error("objectMode was not true but tried to push non-Uint8Array value");
302
+ }
303
+ return bufferNext({ done: false, value });
304
+ };
305
+ const end = (err) => {
306
+ if (ended)
307
+ return pushable2;
308
+ ended = true;
309
+ return err != null ? bufferError(err) : bufferNext({ done: true });
310
+ };
311
+ const _return = () => {
312
+ buffer = new FIFO();
313
+ end();
314
+ return { done: true };
315
+ };
316
+ const _throw = (err) => {
317
+ end(err);
318
+ return { done: true };
319
+ };
320
+ pushable2 = {
321
+ [Symbol.asyncIterator]() {
322
+ return this;
323
+ },
324
+ next: waitNext,
325
+ return: _return,
326
+ throw: _throw,
327
+ push,
328
+ end,
329
+ get readableLength() {
330
+ return buffer.size;
331
+ },
332
+ onEmpty: async (options2) => {
333
+ const signal = options2?.signal;
334
+ signal?.throwIfAborted();
335
+ if (buffer.isEmpty()) {
336
+ return;
337
+ }
338
+ let cancel;
339
+ let listener;
340
+ if (signal != null) {
341
+ cancel = new Promise((resolve, reject) => {
342
+ listener = () => {
343
+ reject(new AbortError());
344
+ };
345
+ signal.addEventListener("abort", listener);
346
+ });
347
+ }
348
+ try {
349
+ await Promise.race([
350
+ drain.promise,
351
+ cancel
352
+ ]);
353
+ } finally {
354
+ if (listener != null && signal != null) {
355
+ signal?.removeEventListener("abort", listener);
356
+ }
357
+ }
358
+ }
359
+ };
360
+ if (onEnd == null) {
361
+ return pushable2;
362
+ }
363
+ const _pushable2 = pushable2;
364
+ pushable2 = {
365
+ [Symbol.asyncIterator]() {
366
+ return this;
367
+ },
368
+ next() {
369
+ return _pushable2.next();
370
+ },
371
+ throw(err) {
372
+ _pushable2.throw(err);
373
+ if (onEnd != null) {
374
+ onEnd(err);
375
+ onEnd = void 0;
376
+ }
377
+ return { done: true };
378
+ },
379
+ return() {
380
+ _pushable2.return();
381
+ if (onEnd != null) {
382
+ onEnd();
383
+ onEnd = void 0;
384
+ }
385
+ return { done: true };
386
+ },
387
+ push,
388
+ end(err) {
389
+ _pushable2.end(err);
390
+ if (onEnd != null) {
391
+ onEnd(err);
392
+ onEnd = void 0;
393
+ }
394
+ return pushable2;
395
+ },
396
+ get readableLength() {
397
+ return _pushable2.readableLength;
398
+ },
399
+ onEmpty: (opts) => {
400
+ return _pushable2.onEmpty(opts);
401
+ }
402
+ };
403
+ return pushable2;
404
+ }
405
+
406
+ // transport/message.ts
407
+ var import_typebox2 = require("@sinclair/typebox");
408
+ var import_nanoid = require("nanoid");
409
+ var TransportMessageSchema = (t) => import_typebox2.Type.Object({
410
+ id: import_typebox2.Type.String(),
411
+ from: import_typebox2.Type.String(),
412
+ to: import_typebox2.Type.String(),
413
+ serviceName: import_typebox2.Type.Optional(import_typebox2.Type.Union([import_typebox2.Type.String(), import_typebox2.Type.Null()])),
414
+ procedureName: import_typebox2.Type.Optional(import_typebox2.Type.Union([import_typebox2.Type.String(), import_typebox2.Type.Null()])),
415
+ streamId: import_typebox2.Type.String(),
416
+ controlFlags: import_typebox2.Type.Integer(),
417
+ payload: t
418
+ });
419
+ var TransportAckSchema = TransportMessageSchema(
420
+ import_typebox2.Type.Object({
421
+ ack: import_typebox2.Type.String()
422
+ })
423
+ );
424
+ var ControlMessagePayloadSchema = import_typebox2.Type.Object({
425
+ type: import_typebox2.Type.Literal("CLOSE")
426
+ });
427
+ var OpaqueTransportMessageSchema = TransportMessageSchema(
428
+ import_typebox2.Type.Unknown()
429
+ );
430
+ function msg(from, to, streamId, payload, serviceName, procedureName) {
431
+ return {
432
+ id: (0, import_nanoid.nanoid)(),
433
+ to,
434
+ from,
435
+ serviceName,
436
+ procedureName,
437
+ streamId,
438
+ controlFlags: 0,
439
+ payload
440
+ };
441
+ }
442
+ function reply(msg2, response) {
443
+ return {
444
+ id: (0, import_nanoid.nanoid)(),
445
+ streamId: msg2.streamId,
446
+ controlFlags: 0,
447
+ to: msg2.from,
448
+ from: msg2.to,
449
+ payload: response
450
+ };
451
+ }
452
+ function closeStream(from, to, stream) {
453
+ const closeMessage = msg(from, to, stream, {
454
+ type: "CLOSE"
455
+ });
456
+ closeMessage.controlFlags |= 4 /* StreamClosedBit */;
457
+ return closeMessage;
458
+ }
459
+ function isStreamOpen(controlFlag) {
460
+ return (controlFlag & 2 /* StreamOpenBit */) === 2 /* StreamOpenBit */;
461
+ }
462
+ function isStreamClose(controlFlag) {
463
+ return (controlFlag & 4 /* StreamClosedBit */) === 4 /* StreamClosedBit */;
464
+ }
465
+
466
+ // router/client.ts
467
+ var import_nanoid2 = require("nanoid");
468
+
469
+ // router/result.ts
470
+ var import_typebox3 = require("@sinclair/typebox");
471
+ var UNCAUGHT_ERROR = "UNCAUGHT_ERROR";
472
+ var UNEXPECTED_DISCONNECT = "UNEXPECTED_DISCONNECT";
473
+ var RiverUncaughtSchema = import_typebox3.Type.Object({
474
+ code: import_typebox3.Type.Union([
475
+ import_typebox3.Type.Literal(UNCAUGHT_ERROR),
476
+ import_typebox3.Type.Literal(UNEXPECTED_DISCONNECT)
477
+ ]),
478
+ message: import_typebox3.Type.String()
479
+ });
480
+ function Ok(payload) {
481
+ return {
482
+ ok: true,
483
+ payload
484
+ };
485
+ }
486
+ function Err(error) {
487
+ return {
488
+ ok: false,
489
+ payload: error
490
+ };
491
+ }
492
+
493
+ // router/client.ts
494
+ var noop = () => {
495
+ };
496
+ function _createRecursiveProxy(callback, path) {
497
+ const proxy = new Proxy(noop, {
498
+ // property access, recurse and add field to path
499
+ get(_obj, key) {
500
+ if (typeof key !== "string")
501
+ return void 0;
502
+ return _createRecursiveProxy(callback, [...path, key]);
503
+ },
504
+ // hit the end, let's invoke the handler
505
+ apply(_target, _this, args) {
506
+ return callback({
507
+ path,
508
+ args
509
+ });
510
+ }
511
+ });
512
+ return proxy;
513
+ }
514
+ var createClient = (transport, serverId = "SERVER") => _createRecursiveProxy(async (opts) => {
515
+ const [serviceName, procName, procType] = [...opts.path];
516
+ if (!(serviceName && procName && procType)) {
517
+ throw new Error(
518
+ "invalid river call, ensure the service and procedure you are calling exists"
519
+ );
520
+ }
521
+ const [input] = opts.args;
522
+ if (procType === "rpc") {
523
+ return handleRpc(
524
+ transport,
525
+ serverId,
526
+ input,
527
+ serviceName,
528
+ procName
529
+ );
530
+ } else if (procType === "stream") {
531
+ return handleStream(
532
+ transport,
533
+ serverId,
534
+ input,
535
+ serviceName,
536
+ procName
537
+ );
538
+ } else if (procType === "subscribe") {
539
+ return handleSubscribe(
540
+ transport,
541
+ serverId,
542
+ input,
543
+ serviceName,
544
+ procName
545
+ );
546
+ } else if (procType === "upload") {
547
+ return handleUpload(
548
+ transport,
549
+ serverId,
550
+ input,
551
+ serviceName,
552
+ procName
553
+ );
554
+ } else {
555
+ throw new Error(`invalid river call, unknown procedure type ${procType}`);
556
+ }
557
+ }, []);
558
+ var CONNECTION_GRACE_PERIOD_MS = 5e3;
559
+ function rejectAfterDisconnectGrace(from, cb) {
560
+ let timeout = void 0;
561
+ return (evt) => {
562
+ if (evt.status === "connect" && evt.conn.connectedTo === from) {
563
+ clearTimeout(timeout);
564
+ timeout = void 0;
565
+ }
566
+ if (evt.status === "disconnect" && evt.conn.connectedTo === from) {
567
+ timeout = setTimeout(cb, CONNECTION_GRACE_PERIOD_MS);
568
+ }
569
+ };
570
+ }
571
+ function handleRpc(transport, serverId, input, serviceName, procName) {
572
+ const streamId = (0, import_nanoid2.nanoid)();
573
+ const m = msg(
574
+ transport.clientId,
575
+ serverId,
576
+ streamId,
577
+ input,
578
+ serviceName,
579
+ procName
580
+ );
581
+ m.controlFlags |= 2 /* StreamOpenBit */ | 4 /* StreamClosedBit */;
582
+ transport.send(m);
583
+ const responsePromise = new Promise((resolve) => {
584
+ const onConnectionStatus = rejectAfterDisconnectGrace(serverId, () => {
585
+ cleanup();
586
+ resolve(
587
+ Err({
588
+ code: UNEXPECTED_DISCONNECT,
589
+ message: `${serverId} unexpectedly disconnected`
590
+ })
591
+ );
592
+ });
593
+ function cleanup() {
594
+ transport.removeEventListener("message", onMessage);
595
+ transport.removeEventListener("connectionStatus", onConnectionStatus);
596
+ }
597
+ function onMessage(msg2) {
598
+ if (msg2.streamId === streamId) {
599
+ cleanup();
600
+ resolve(msg2.payload);
601
+ }
602
+ }
603
+ transport.addEventListener("message", onMessage);
604
+ transport.addEventListener("connectionStatus", onConnectionStatus);
605
+ });
606
+ return responsePromise;
607
+ }
608
+ function handleStream(transport, serverId, init, serviceName, procName) {
609
+ const streamId = (0, import_nanoid2.nanoid)();
610
+ const inputStream = pushable({ objectMode: true });
611
+ const outputStream = pushable({ objectMode: true });
612
+ let firstMessage = true;
613
+ if (init) {
614
+ const m = msg(
615
+ transport.clientId,
616
+ serverId,
617
+ streamId,
618
+ init,
619
+ serviceName,
620
+ procName
621
+ );
622
+ m.controlFlags = 2 /* StreamOpenBit */;
623
+ transport.send(m);
624
+ firstMessage = false;
625
+ }
626
+ (async () => {
627
+ for await (const rawIn of inputStream) {
628
+ const m = msg(transport.clientId, serverId, streamId, rawIn);
629
+ if (firstMessage) {
630
+ m.serviceName = serviceName;
631
+ m.procedureName = procName;
632
+ m.controlFlags |= 2 /* StreamOpenBit */;
633
+ firstMessage = false;
634
+ }
635
+ transport.send(m);
636
+ }
637
+ transport.send(closeStream(transport.clientId, serverId, streamId));
638
+ })();
639
+ function onMessage(msg2) {
640
+ if (msg2.streamId !== streamId) {
641
+ return;
642
+ }
643
+ if (isStreamClose(msg2.controlFlags)) {
644
+ cleanup();
645
+ } else {
646
+ outputStream.push(msg2.payload);
647
+ }
648
+ }
649
+ function cleanup() {
650
+ inputStream.end();
651
+ outputStream.end();
652
+ transport.removeEventListener("message", onMessage);
653
+ transport.removeEventListener("connectionStatus", onConnectionStatus);
654
+ }
655
+ const closeHandler = () => {
656
+ cleanup();
657
+ transport.send(closeStream(transport.clientId, serverId, streamId));
658
+ };
659
+ const onConnectionStatus = rejectAfterDisconnectGrace(serverId, () => {
660
+ outputStream.push(
661
+ Err({
662
+ code: UNEXPECTED_DISCONNECT,
663
+ message: `${serverId} unexpectedly disconnected`
664
+ })
665
+ );
666
+ cleanup();
667
+ });
668
+ transport.addEventListener("message", onMessage);
669
+ transport.addEventListener("connectionStatus", onConnectionStatus);
670
+ return [inputStream, outputStream, closeHandler];
671
+ }
672
+ function handleSubscribe(transport, serverId, input, serviceName, procName) {
673
+ const streamId = (0, import_nanoid2.nanoid)();
674
+ const m = msg(
675
+ transport.clientId,
676
+ serverId,
677
+ streamId,
678
+ input,
679
+ serviceName,
680
+ procName
681
+ );
682
+ m.controlFlags |= 2 /* StreamOpenBit */;
683
+ transport.send(m);
684
+ const outputStream = pushable({ objectMode: true });
685
+ function onMessage(msg2) {
686
+ if (msg2.streamId !== streamId) {
687
+ return;
688
+ }
689
+ if (isStreamClose(msg2.controlFlags)) {
690
+ cleanup();
691
+ } else {
692
+ outputStream.push(msg2.payload);
693
+ }
694
+ }
695
+ function cleanup() {
696
+ outputStream.end();
697
+ transport.removeEventListener("message", onMessage);
698
+ transport.removeEventListener("connectionStatus", onConnectionStatus);
699
+ }
700
+ const closeHandler = () => {
701
+ cleanup();
702
+ transport.send(closeStream(transport.clientId, serverId, streamId));
703
+ };
704
+ const onConnectionStatus = rejectAfterDisconnectGrace(serverId, () => {
705
+ outputStream.push(
706
+ Err({
707
+ code: UNEXPECTED_DISCONNECT,
708
+ message: `${serverId} unexpectedly disconnected`
709
+ })
710
+ );
711
+ cleanup();
712
+ });
713
+ transport.addEventListener("message", onMessage);
714
+ transport.addEventListener("connectionStatus", onConnectionStatus);
715
+ return [outputStream, closeHandler];
716
+ }
717
+ function handleUpload(transport, serverId, input, serviceName, procName) {
718
+ const streamId = (0, import_nanoid2.nanoid)();
719
+ const inputStream = pushable({ objectMode: true });
720
+ let firstMessage = true;
721
+ if (input) {
722
+ const m = msg(
723
+ transport.clientId,
724
+ serverId,
725
+ streamId,
726
+ input,
727
+ serviceName,
728
+ procName
729
+ );
730
+ m.controlFlags = 2 /* StreamOpenBit */;
731
+ transport.send(m);
732
+ firstMessage = false;
733
+ }
734
+ (async () => {
735
+ for await (const rawIn of inputStream) {
736
+ const m = msg(transport.clientId, serverId, streamId, rawIn);
737
+ if (firstMessage) {
738
+ m.controlFlags |= 2 /* StreamOpenBit */;
739
+ m.serviceName = serviceName;
740
+ m.procedureName = procName;
741
+ firstMessage = false;
742
+ }
743
+ transport.send(m);
744
+ }
745
+ transport.send(closeStream(transport.clientId, serverId, streamId));
746
+ })();
747
+ const responsePromise = new Promise((resolve) => {
748
+ const onConnectionStatus = rejectAfterDisconnectGrace(serverId, () => {
749
+ cleanup();
750
+ resolve(
751
+ Err({
752
+ code: UNEXPECTED_DISCONNECT,
753
+ message: `${serverId} unexpectedly disconnected`
754
+ })
755
+ );
756
+ });
757
+ function cleanup() {
758
+ inputStream.end();
759
+ transport.removeEventListener("message", onMessage);
760
+ transport.removeEventListener("connectionStatus", onConnectionStatus);
761
+ }
762
+ function onMessage(msg2) {
763
+ if (msg2.streamId === streamId) {
764
+ cleanup();
765
+ resolve(msg2.payload);
766
+ }
767
+ }
768
+ transport.addEventListener("message", onMessage);
769
+ transport.addEventListener("connectionStatus", onConnectionStatus);
770
+ });
771
+ return [inputStream, responsePromise];
772
+ }
773
+
774
+ // logging/index.ts
775
+ var log;
776
+
777
+ // router/server.ts
778
+ var import_value = require("@sinclair/typebox/value");
779
+ var RiverServer = class {
780
+ transport;
781
+ services;
782
+ contextMap;
783
+ // map of streamId to ProcStream
784
+ streamMap;
785
+ // map of client to their open streams by streamId
786
+ clientStreams;
787
+ constructor(transport, services, extendedContext) {
788
+ this.transport = transport;
789
+ this.services = services;
790
+ this.contextMap = /* @__PURE__ */ new Map();
791
+ for (const service of Object.values(services)) {
792
+ this.contextMap.set(service, {
793
+ ...extendedContext,
794
+ state: service.state
795
+ });
796
+ }
797
+ this.streamMap = /* @__PURE__ */ new Map();
798
+ this.clientStreams = /* @__PURE__ */ new Map();
799
+ this.transport.addEventListener("message", this.handler);
800
+ this.transport.addEventListener("connectionStatus", this.onDisconnect);
801
+ }
802
+ get streams() {
803
+ return this.streamMap;
804
+ }
805
+ handler = async (message) => {
806
+ if (message.to !== this.transport.clientId) {
807
+ log?.info(
808
+ `${this.transport.clientId} -- got msg with destination that isn't the server, ignoring`
809
+ );
810
+ return;
811
+ }
812
+ let procStream = this.streamMap.get(message.streamId);
813
+ const isInitMessage = !procStream;
814
+ procStream ||= this.createNewProcStream(message);
815
+ if (!procStream) {
816
+ return;
817
+ }
818
+ await this.pushToStream(procStream, message, isInitMessage);
819
+ };
820
+ // cleanup streams on unexpected disconnections
821
+ onDisconnect = async (evt) => {
822
+ if (evt.status !== "disconnect") {
823
+ return;
824
+ }
825
+ const disconnectedClientId = evt.conn.connectedTo;
826
+ log?.info(
827
+ `${this.transport.clientId} -- got unexpected disconnect from ${disconnectedClientId}, cleaning up streams`
828
+ );
829
+ const streamsFromThisClient = this.clientStreams.get(disconnectedClientId);
830
+ if (!streamsFromThisClient) {
831
+ return;
832
+ }
833
+ await Promise.all(
834
+ Array.from(streamsFromThisClient).map(this.cleanupStream)
835
+ );
836
+ this.clientStreams.delete(disconnectedClientId);
837
+ };
838
+ async close() {
839
+ this.transport.removeEventListener("message", this.handler);
840
+ this.transport.removeEventListener("connectionStatus", this.onDisconnect);
841
+ await Promise.all([...this.streamMap.keys()].map(this.cleanupStream));
842
+ }
843
+ createNewProcStream(message) {
844
+ if (!isStreamOpen(message.controlFlags)) {
845
+ log?.warn(
846
+ `${this.transport.clientId} -- couldn't find a matching procedure stream for ${message.serviceName}.${message.procedureName}:${message.streamId}`
847
+ );
848
+ return;
849
+ }
850
+ if (!message.serviceName || !(message.serviceName in this.services)) {
851
+ log?.warn(
852
+ `${this.transport.clientId} -- couldn't find service ${message.serviceName}`
853
+ );
854
+ return;
855
+ }
856
+ const service = this.services[message.serviceName];
857
+ const serviceContext = this.getContext(service);
858
+ if (!message.procedureName || !(message.procedureName in service.procedures)) {
859
+ log?.warn(
860
+ `${this.transport.clientId} -- couldn't find a matching procedure for ${message.serviceName}.${message.procedureName}`
861
+ );
862
+ return;
863
+ }
864
+ const procedure = service.procedures[message.procedureName];
865
+ const incoming = pushable({ objectMode: true });
866
+ const outgoing = pushable({ objectMode: true });
867
+ const outputHandler = (
868
+ // sending outgoing messages back to client
869
+ (async () => {
870
+ for await (const response of outgoing) {
871
+ this.transport.send(reply(message, response));
872
+ }
873
+ if (procedure.type === "subscription" || procedure.type === "stream") {
874
+ this.transport.send(
875
+ closeStream(
876
+ this.transport.clientId,
877
+ message.from,
878
+ message.streamId
879
+ )
880
+ );
881
+ }
882
+ })()
883
+ );
884
+ const errorHandler = (err) => {
885
+ const errorMsg = err instanceof Error ? err.message : `[coerced to error] ${err}`;
886
+ log?.error(
887
+ `${this.transport.clientId} -- procedure ${message.serviceName}.${message.procedureName}:${message.streamId} threw an error: ${errorMsg}`
888
+ );
889
+ outgoing.push(
890
+ Err({
891
+ code: UNCAUGHT_ERROR,
892
+ message: errorMsg
893
+ })
894
+ );
895
+ };
896
+ let inputHandler;
897
+ const procHasInitMessage = "init" in procedure;
898
+ if (procedure.type === "stream") {
899
+ if (procHasInitMessage) {
900
+ inputHandler = (async () => {
901
+ const initMessage = await incoming.next();
902
+ if (initMessage.done) {
903
+ return;
904
+ }
905
+ return procedure.handler(serviceContext, initMessage.value, incoming, outgoing).catch(errorHandler);
906
+ })();
907
+ } else {
908
+ inputHandler = procedure.handler(serviceContext, incoming, outgoing).catch(errorHandler);
909
+ }
910
+ } else if (procedure.type === "rpc") {
911
+ inputHandler = (async () => {
912
+ const inputMessage = await incoming.next();
913
+ if (inputMessage.done) {
914
+ return;
915
+ }
916
+ try {
917
+ const outputMessage = await procedure.handler(
918
+ serviceContext,
919
+ inputMessage.value
920
+ );
921
+ outgoing.push(outputMessage);
922
+ } catch (err) {
923
+ errorHandler(err);
924
+ }
925
+ })();
926
+ } else if (procedure.type === "subscription") {
927
+ inputHandler = (async () => {
928
+ const inputMessage = await incoming.next();
929
+ if (inputMessage.done) {
930
+ return;
931
+ }
932
+ try {
933
+ await procedure.handler(serviceContext, inputMessage.value, outgoing);
934
+ } catch (err) {
935
+ errorHandler(err);
936
+ }
937
+ })();
938
+ } else if (procedure.type === "upload") {
939
+ if (procHasInitMessage) {
940
+ inputHandler = (async () => {
941
+ const initMessage = await incoming.next();
942
+ if (initMessage.done) {
943
+ return;
944
+ }
945
+ try {
946
+ const outputMessage = await procedure.handler(
947
+ serviceContext,
948
+ initMessage.value,
949
+ incoming
950
+ );
951
+ outgoing.push(outputMessage);
952
+ } catch (err) {
953
+ errorHandler(err);
954
+ }
955
+ })();
956
+ } else {
957
+ inputHandler = (async () => {
958
+ try {
959
+ const outputMessage = await procedure.handler(
960
+ serviceContext,
961
+ incoming
962
+ );
963
+ outgoing.push(outputMessage);
964
+ } catch (err) {
965
+ errorHandler(err);
966
+ }
967
+ })();
968
+ }
969
+ } else {
970
+ log?.warn(
971
+ `${this.transport.clientId} -- got request for invalid procedure type ${procedure.type} at ${message.serviceName}.${message.procedureName}`
972
+ );
973
+ return;
974
+ }
975
+ const procStream = {
976
+ id: message.streamId,
977
+ incoming,
978
+ outgoing,
979
+ serviceName: message.serviceName,
980
+ procedureName: message.procedureName,
981
+ procedure,
982
+ promises: { inputHandler, outputHandler }
983
+ };
984
+ this.streamMap.set(message.streamId, procStream);
985
+ const streamsFromThisClient = this.clientStreams.get(message.from) ?? /* @__PURE__ */ new Set();
986
+ streamsFromThisClient.add(message.streamId);
987
+ this.clientStreams.set(message.from, streamsFromThisClient);
988
+ return procStream;
989
+ }
990
+ async pushToStream(procStream, message, isInit) {
991
+ const procedure = procStream.procedure;
992
+ const procHasInitMessage = "init" in procedure;
993
+ if (isInit && procHasInitMessage && import_value.Value.Check(procedure.init, message.payload) || import_value.Value.Check(procedure.input, message.payload)) {
994
+ procStream.incoming.push(message.payload);
995
+ } else if (!import_value.Value.Check(ControlMessagePayloadSchema, message.payload)) {
996
+ log?.error(
997
+ `${this.transport.clientId} -- procedure ${procStream.serviceName}.${procStream.procedureName} received invalid payload: ${JSON.stringify(message.payload)}`
998
+ );
999
+ }
1000
+ if (isStreamClose(message.controlFlags)) {
1001
+ await this.cleanupStream(message.streamId);
1002
+ const streamsFromThisClient = this.clientStreams.get(message.from);
1003
+ if (streamsFromThisClient) {
1004
+ streamsFromThisClient.delete(message.streamId);
1005
+ if (streamsFromThisClient.size === 0) {
1006
+ this.clientStreams.delete(message.from);
1007
+ }
1008
+ }
1009
+ }
1010
+ }
1011
+ getContext(service) {
1012
+ const context = this.contextMap.get(service);
1013
+ if (!context) {
1014
+ const err = `${this.transport.clientId} -- no context found for ${service.name}`;
1015
+ log?.error(err);
1016
+ throw new Error(err);
1017
+ }
1018
+ return context;
1019
+ }
1020
+ cleanupStream = async (id) => {
1021
+ const stream = this.streamMap.get(id);
1022
+ if (!stream) {
1023
+ return;
1024
+ }
1025
+ stream.incoming.end();
1026
+ await stream.promises.inputHandler;
1027
+ stream.outgoing.end();
1028
+ await stream.promises.outputHandler;
1029
+ this.streamMap.delete(id);
1030
+ };
1031
+ };
1032
+ function createServer(transport, services, extendedContext) {
1033
+ return new RiverServer(transport, services, extendedContext);
1034
+ }
1035
+ // Annotate the CommonJS export names for ESM import in node:
1036
+ 0 && (module.exports = {
1037
+ Err,
1038
+ Ok,
1039
+ RiverUncaughtSchema,
1040
+ ServiceBuilder,
1041
+ UNCAUGHT_ERROR,
1042
+ buildServiceDefs,
1043
+ createClient,
1044
+ createServer,
1045
+ serializeService
1046
+ });