@replit/river 0.200.0-rc.9 → 0.200.1

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/README.md +8 -8
  2. package/dist/{chunk-42Z2FQIU.js → chunk-6VA5DW7N.js} +21 -13
  3. package/dist/chunk-6VA5DW7N.js.map +1 -0
  4. package/dist/{chunk-4PVU7J25.js → chunk-AJGIY2UB.js} +1 -1
  5. package/dist/chunk-AJGIY2UB.js.map +1 -0
  6. package/dist/chunk-MADS7AI5.js +298 -0
  7. package/dist/chunk-MADS7AI5.js.map +1 -0
  8. package/dist/{chunk-4HT6P2ZG.js → chunk-SONGYR7A.js} +22 -30
  9. package/dist/chunk-SONGYR7A.js.map +1 -0
  10. package/dist/{chunk-EETL2L77.js → chunk-UQHYJZTP.js} +14 -32
  11. package/dist/chunk-UQHYJZTP.js.map +1 -0
  12. package/dist/{chunk-ZXZE253M.js → chunk-YQPJ3HZK.js} +24 -37
  13. package/dist/chunk-YQPJ3HZK.js.map +1 -0
  14. package/dist/{chunk-VXYHC666.js → chunk-YTMS7OP6.js} +1 -1
  15. package/dist/chunk-YTMS7OP6.js.map +1 -0
  16. package/dist/{chunk-I75XYO5W.js → chunk-ZDYZ2FCN.js} +82 -20
  17. package/dist/chunk-ZDYZ2FCN.js.map +1 -0
  18. package/dist/{chunk-GR3AQKHL.js → chunk-ZNJM2HIE.js} +14 -4
  19. package/dist/chunk-ZNJM2HIE.js.map +1 -0
  20. package/dist/{client-22a47343.d.ts → client-095a929e.d.ts} +3 -4
  21. package/dist/codec/index.cjs.map +1 -1
  22. package/dist/codec/index.js +1 -1
  23. package/dist/connection-623d75e9.d.ts +32 -0
  24. package/dist/{context-b4aff18f.d.ts → context-85b8690e.d.ts} +43 -43
  25. package/dist/logging/index.cjs.map +1 -1
  26. package/dist/logging/index.d.cts +1 -1
  27. package/dist/logging/index.d.ts +1 -1
  28. package/dist/logging/index.js +1 -1
  29. package/dist/{message-7d135e38.d.ts → message-57bb8187.d.ts} +5 -3
  30. package/dist/router/index.cjs +600 -681
  31. package/dist/router/index.cjs.map +1 -1
  32. package/dist/router/index.d.cts +22 -12
  33. package/dist/router/index.d.ts +22 -12
  34. package/dist/router/index.js +477 -389
  35. package/dist/router/index.js.map +1 -1
  36. package/dist/{server-dd6a9853.d.ts → server-456bf6cb.d.ts} +5 -5
  37. package/dist/{services-1b5ac5bc.d.ts → services-e4f28470.d.ts} +182 -194
  38. package/dist/transport/impls/ws/client.cjs +129 -62
  39. package/dist/transport/impls/ws/client.cjs.map +1 -1
  40. package/dist/transport/impls/ws/client.d.cts +4 -4
  41. package/dist/transport/impls/ws/client.d.ts +4 -4
  42. package/dist/transport/impls/ws/client.js +7 -7
  43. package/dist/transport/impls/ws/client.js.map +1 -1
  44. package/dist/transport/impls/ws/server.cjs +146 -70
  45. package/dist/transport/impls/ws/server.cjs.map +1 -1
  46. package/dist/transport/impls/ws/server.d.cts +6 -5
  47. package/dist/transport/impls/ws/server.d.ts +6 -5
  48. package/dist/transport/impls/ws/server.js +21 -9
  49. package/dist/transport/impls/ws/server.js.map +1 -1
  50. package/dist/transport/index.cjs +138 -92
  51. package/dist/transport/index.cjs.map +1 -1
  52. package/dist/transport/index.d.cts +4 -4
  53. package/dist/transport/index.d.ts +4 -4
  54. package/dist/transport/index.js +7 -7
  55. package/dist/util/testHelpers.cjs +256 -327
  56. package/dist/util/testHelpers.cjs.map +1 -1
  57. package/dist/util/testHelpers.d.cts +36 -31
  58. package/dist/util/testHelpers.d.ts +36 -31
  59. package/dist/util/testHelpers.js +82 -52
  60. package/dist/util/testHelpers.js.map +1 -1
  61. package/package.json +4 -3
  62. package/dist/chunk-42Z2FQIU.js.map +0 -1
  63. package/dist/chunk-4HT6P2ZG.js.map +0 -1
  64. package/dist/chunk-4PVU7J25.js.map +0 -1
  65. package/dist/chunk-EETL2L77.js.map +0 -1
  66. package/dist/chunk-GR3AQKHL.js.map +0 -1
  67. package/dist/chunk-I75XYO5W.js.map +0 -1
  68. package/dist/chunk-MQ6ANR3H.js +0 -451
  69. package/dist/chunk-MQ6ANR3H.js.map +0 -1
  70. package/dist/chunk-VXYHC666.js.map +0 -1
  71. package/dist/chunk-ZXZE253M.js.map +0 -1
  72. package/dist/connection-260e45a8.d.ts +0 -11
@@ -20,15 +20,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // router/index.ts
21
21
  var router_exports = {};
22
22
  __export(router_exports, {
23
- ABORT_CODE: () => ABORT_CODE,
23
+ CANCEL_CODE: () => CANCEL_CODE,
24
24
  Err: () => Err,
25
- INTERNAL_RIVER_ERROR_CODE: () => INTERNAL_RIVER_ERROR_CODE,
26
25
  INVALID_REQUEST_CODE: () => INVALID_REQUEST_CODE,
27
26
  Ok: () => Ok,
28
27
  Procedure: () => Procedure,
29
28
  RIVER_VERSION: () => version,
30
- RequestReaderErrorSchema: () => RequestReaderErrorSchema,
31
- ResponseReaderErrorSchema: () => ResponseReaderErrorSchema,
29
+ ReaderErrorSchema: () => ReaderErrorSchema,
32
30
  ServiceSchema: () => ServiceSchema,
33
31
  UNCAUGHT_ERROR_CODE: () => UNCAUGHT_ERROR_CODE,
34
32
  UNEXPECTED_DISCONNECT_CODE: () => UNEXPECTED_DISCONNECT_CODE,
@@ -36,12 +34,28 @@ __export(router_exports, {
36
34
  createClientHandshakeOptions: () => createClientHandshakeOptions,
37
35
  createServer: () => createServer,
38
36
  createServerHandshakeOptions: () => createServerHandshakeOptions,
39
- serializeSchema: () => serializeSchema
37
+ flattenErrorType: () => flattenErrorType,
38
+ serializeSchema: () => serializeSchema,
39
+ serializeSchemaV1Compat: () => serializeSchemaV1Compat,
40
+ unwrapOrThrow: () => unwrapOrThrow
40
41
  });
41
42
  module.exports = __toCommonJS(router_exports);
42
43
 
43
44
  // router/services.ts
44
45
  var import_typebox = require("@sinclair/typebox");
46
+ function serializeSchemaV1Compat(services, handshakeSchema) {
47
+ const serializedServiceObject = Object.entries(services).reduce((acc, [name, value]) => {
48
+ acc[name] = value.serializeV1Compat();
49
+ return acc;
50
+ }, {});
51
+ const schema = {
52
+ services: serializedServiceObject
53
+ };
54
+ if (handshakeSchema) {
55
+ schema.handshakeSchema = import_typebox.Type.Strict(handshakeSchema);
56
+ }
57
+ return schema;
58
+ }
45
59
  function serializeSchema(services, handshakeSchema) {
46
60
  const serializedServiceObject = Object.entries(services).reduce((acc, [name, value]) => {
47
61
  acc[name] = value.serialize();
@@ -178,7 +192,7 @@ var ServiceSchema = class _ServiceSchema {
178
192
  * protocol v1. This is useful to be able to continue to generate schemas for older
179
193
  * clients as they are still supported.
180
194
  */
181
- serializeBackwardsCompatible() {
195
+ serializeV1Compat() {
182
196
  return {
183
197
  procedures: Object.fromEntries(
184
198
  Object.entries(this.procedures).map(
@@ -293,30 +307,6 @@ var ServiceScaffold = class {
293
307
 
294
308
  // router/procedures.ts
295
309
  var import_typebox2 = require("@sinclair/typebox");
296
- var INTERNAL_RIVER_ERROR_CODE = "INTERNAL_RIVER_ERROR";
297
- var UNCAUGHT_ERROR_CODE = "UNCAUGHT_ERROR";
298
- var UNEXPECTED_DISCONNECT_CODE = "UNEXPECTED_DISCONNECT";
299
- var INVALID_REQUEST_CODE = "INVALID_REQUEST";
300
- var ABORT_CODE = "ABORT";
301
- var ResponseReaderErrorSchema = import_typebox2.Type.Object({
302
- code: import_typebox2.Type.Union([
303
- import_typebox2.Type.Literal(INTERNAL_RIVER_ERROR_CODE),
304
- import_typebox2.Type.Literal(UNCAUGHT_ERROR_CODE),
305
- import_typebox2.Type.Literal(UNEXPECTED_DISCONNECT_CODE),
306
- import_typebox2.Type.Literal(INVALID_REQUEST_CODE),
307
- import_typebox2.Type.Literal(ABORT_CODE)
308
- ]),
309
- message: import_typebox2.Type.String()
310
- });
311
- var RequestReaderErrorSchema = import_typebox2.Type.Object({
312
- code: import_typebox2.Type.Union([
313
- import_typebox2.Type.Literal(UNCAUGHT_ERROR_CODE),
314
- import_typebox2.Type.Literal(UNEXPECTED_DISCONNECT_CODE),
315
- import_typebox2.Type.Literal(INVALID_REQUEST_CODE),
316
- import_typebox2.Type.Literal(ABORT_CODE)
317
- ]),
318
- message: import_typebox2.Type.String()
319
- });
320
310
  function rpc({
321
311
  requestInit,
322
312
  responseData,
@@ -392,8 +382,48 @@ var Procedure = {
392
382
  stream
393
383
  };
394
384
 
395
- // transport/message.ts
385
+ // router/errors.ts
396
386
  var import_typebox3 = require("@sinclair/typebox");
387
+ var UNCAUGHT_ERROR_CODE = "UNCAUGHT_ERROR";
388
+ var UNEXPECTED_DISCONNECT_CODE = "UNEXPECTED_DISCONNECT";
389
+ var INVALID_REQUEST_CODE = "INVALID_REQUEST";
390
+ var CANCEL_CODE = "CANCEL";
391
+ var ErrResultSchema = (t) => import_typebox3.Type.Object({
392
+ ok: import_typebox3.Type.Literal(false),
393
+ payload: t
394
+ });
395
+ var ReaderErrorSchema = import_typebox3.Type.Object({
396
+ code: import_typebox3.Type.Union([
397
+ import_typebox3.Type.Literal(UNCAUGHT_ERROR_CODE),
398
+ import_typebox3.Type.Literal(UNEXPECTED_DISCONNECT_CODE),
399
+ import_typebox3.Type.Literal(INVALID_REQUEST_CODE),
400
+ import_typebox3.Type.Literal(CANCEL_CODE)
401
+ ]),
402
+ message: import_typebox3.Type.String()
403
+ });
404
+ function isUnion(schema) {
405
+ return schema[import_typebox3.Kind] === "Union";
406
+ }
407
+ function flattenErrorType(errType) {
408
+ if (!isUnion(errType)) {
409
+ return errType;
410
+ }
411
+ const flattenedTypes = [];
412
+ function flatten(type) {
413
+ if (isUnion(type)) {
414
+ for (const t of type.anyOf) {
415
+ flatten(t);
416
+ }
417
+ } else {
418
+ flattenedTypes.push(type);
419
+ }
420
+ }
421
+ flatten(errType);
422
+ return import_typebox3.Type.Union(flattenedTypes);
423
+ }
424
+
425
+ // transport/message.ts
426
+ var import_typebox4 = require("@sinclair/typebox");
397
427
 
398
428
  // transport/id.ts
399
429
  var import_nanoid = require("nanoid");
@@ -403,95 +433,90 @@ var alphabet = (0, import_nanoid.customAlphabet)(
403
433
  var generateId = () => alphabet(12);
404
434
 
405
435
  // transport/message.ts
406
- var TransportMessageSchema = (t) => import_typebox3.Type.Object({
407
- id: import_typebox3.Type.String(),
408
- from: import_typebox3.Type.String(),
409
- to: import_typebox3.Type.String(),
410
- seq: import_typebox3.Type.Integer(),
411
- ack: import_typebox3.Type.Integer(),
412
- serviceName: import_typebox3.Type.Optional(import_typebox3.Type.String()),
413
- procedureName: import_typebox3.Type.Optional(import_typebox3.Type.String()),
414
- streamId: import_typebox3.Type.String(),
415
- controlFlags: import_typebox3.Type.Integer(),
416
- tracing: import_typebox3.Type.Optional(
417
- import_typebox3.Type.Object({
418
- traceparent: import_typebox3.Type.String(),
419
- tracestate: import_typebox3.Type.String()
436
+ var TransportMessageSchema = (t) => import_typebox4.Type.Object({
437
+ id: import_typebox4.Type.String(),
438
+ from: import_typebox4.Type.String(),
439
+ to: import_typebox4.Type.String(),
440
+ seq: import_typebox4.Type.Integer(),
441
+ ack: import_typebox4.Type.Integer(),
442
+ serviceName: import_typebox4.Type.Optional(import_typebox4.Type.String()),
443
+ procedureName: import_typebox4.Type.Optional(import_typebox4.Type.String()),
444
+ streamId: import_typebox4.Type.String(),
445
+ controlFlags: import_typebox4.Type.Integer(),
446
+ tracing: import_typebox4.Type.Optional(
447
+ import_typebox4.Type.Object({
448
+ traceparent: import_typebox4.Type.String(),
449
+ tracestate: import_typebox4.Type.String()
420
450
  })
421
451
  ),
422
452
  payload: t
423
453
  });
424
- var ControlMessageAckSchema = import_typebox3.Type.Object({
425
- type: import_typebox3.Type.Literal("ACK")
454
+ var ControlMessageAckSchema = import_typebox4.Type.Object({
455
+ type: import_typebox4.Type.Literal("ACK")
426
456
  });
427
- var ControlMessageCloseSchema = import_typebox3.Type.Object({
428
- type: import_typebox3.Type.Literal("CLOSE")
457
+ var ControlMessageCloseSchema = import_typebox4.Type.Object({
458
+ type: import_typebox4.Type.Literal("CLOSE")
429
459
  });
430
- var ControlMessageHandshakeRequestSchema = import_typebox3.Type.Object({
431
- type: import_typebox3.Type.Literal("HANDSHAKE_REQ"),
432
- protocolVersion: import_typebox3.Type.String(),
433
- sessionId: import_typebox3.Type.String(),
460
+ var ControlMessageHandshakeRequestSchema = import_typebox4.Type.Object({
461
+ type: import_typebox4.Type.Literal("HANDSHAKE_REQ"),
462
+ protocolVersion: import_typebox4.Type.String(),
463
+ sessionId: import_typebox4.Type.String(),
434
464
  /**
435
465
  * Specifies what the server's expected session state (from the pov of the client). This can be
436
466
  * used by the server to know whether this is a new or a reestablished connection, and whether it
437
467
  * is compatible with what it already has.
438
468
  */
439
- expectedSessionState: import_typebox3.Type.Object({
469
+ expectedSessionState: import_typebox4.Type.Object({
440
470
  // what the client expects the server to send next
441
- nextExpectedSeq: import_typebox3.Type.Integer(),
442
- // TODO: remove optional once we know all servers
443
- // are nextSentSeq here
444
- // what the server expects the client to send next
445
- nextSentSeq: import_typebox3.Type.Optional(import_typebox3.Type.Integer())
471
+ nextExpectedSeq: import_typebox4.Type.Integer(),
472
+ nextSentSeq: import_typebox4.Type.Integer()
446
473
  }),
447
- metadata: import_typebox3.Type.Optional(import_typebox3.Type.Unknown())
474
+ metadata: import_typebox4.Type.Optional(import_typebox4.Type.Unknown())
448
475
  });
449
- var HandshakeErrorRetriableResponseCodes = import_typebox3.Type.Union([
450
- import_typebox3.Type.Literal("SESSION_STATE_MISMATCH")
476
+ var HandshakeErrorRetriableResponseCodes = import_typebox4.Type.Union([
477
+ import_typebox4.Type.Literal("SESSION_STATE_MISMATCH")
451
478
  ]);
452
- var HandshakeErrorCustomHandlerFatalResponseCodes = import_typebox3.Type.Union([
479
+ var HandshakeErrorCustomHandlerFatalResponseCodes = import_typebox4.Type.Union([
453
480
  // The custom validation handler rejected the handler because the client is unsupported.
454
- import_typebox3.Type.Literal("REJECTED_UNSUPPORTED_CLIENT"),
481
+ import_typebox4.Type.Literal("REJECTED_UNSUPPORTED_CLIENT"),
455
482
  // The custom validation handler rejected the handshake.
456
- import_typebox3.Type.Literal("REJECTED_BY_CUSTOM_HANDLER")
483
+ import_typebox4.Type.Literal("REJECTED_BY_CUSTOM_HANDLER")
457
484
  ]);
458
- var HandshakeErrorFatalResponseCodes = import_typebox3.Type.Union([
485
+ var HandshakeErrorFatalResponseCodes = import_typebox4.Type.Union([
459
486
  HandshakeErrorCustomHandlerFatalResponseCodes,
460
487
  // The ciient sent a handshake that doesn't comply with the extended handshake metadata.
461
- import_typebox3.Type.Literal("MALFORMED_HANDSHAKE_META"),
488
+ import_typebox4.Type.Literal("MALFORMED_HANDSHAKE_META"),
462
489
  // The ciient sent a handshake that doesn't comply with ControlMessageHandshakeRequestSchema.
463
- import_typebox3.Type.Literal("MALFORMED_HANDSHAKE"),
490
+ import_typebox4.Type.Literal("MALFORMED_HANDSHAKE"),
464
491
  // The client's protocol version does not match the server's.
465
- import_typebox3.Type.Literal("PROTOCOL_VERSION_MISMATCH")
492
+ import_typebox4.Type.Literal("PROTOCOL_VERSION_MISMATCH")
466
493
  ]);
467
- var HandshakeErrorResponseCodes = import_typebox3.Type.Union([
494
+ var HandshakeErrorResponseCodes = import_typebox4.Type.Union([
468
495
  HandshakeErrorRetriableResponseCodes,
469
496
  HandshakeErrorFatalResponseCodes
470
497
  ]);
471
- var ControlMessageHandshakeResponseSchema = import_typebox3.Type.Object({
472
- type: import_typebox3.Type.Literal("HANDSHAKE_RESP"),
473
- status: import_typebox3.Type.Union([
474
- import_typebox3.Type.Object({
475
- ok: import_typebox3.Type.Literal(true),
476
- sessionId: import_typebox3.Type.String()
498
+ var ControlMessageHandshakeResponseSchema = import_typebox4.Type.Object({
499
+ type: import_typebox4.Type.Literal("HANDSHAKE_RESP"),
500
+ status: import_typebox4.Type.Union([
501
+ import_typebox4.Type.Object({
502
+ ok: import_typebox4.Type.Literal(true),
503
+ sessionId: import_typebox4.Type.String()
477
504
  }),
478
- import_typebox3.Type.Object({
479
- ok: import_typebox3.Type.Literal(false),
480
- reason: import_typebox3.Type.String(),
481
- // TODO: remove optional once we know all servers
482
- // are sending code here
483
- code: import_typebox3.Type.Optional(HandshakeErrorResponseCodes)
505
+ import_typebox4.Type.Object({
506
+ ok: import_typebox4.Type.Literal(false),
507
+ reason: import_typebox4.Type.String(),
508
+ code: HandshakeErrorResponseCodes
484
509
  })
485
510
  ])
486
511
  });
487
- var ControlMessagePayloadSchema = import_typebox3.Type.Union([
512
+ var ControlMessagePayloadSchema = import_typebox4.Type.Union([
488
513
  ControlMessageCloseSchema,
489
514
  ControlMessageAckSchema,
490
515
  ControlMessageHandshakeRequestSchema,
491
516
  ControlMessageHandshakeResponseSchema
492
517
  ]);
493
518
  var OpaqueTransportMessageSchema = TransportMessageSchema(
494
- import_typebox3.Type.Unknown()
519
+ import_typebox4.Type.Unknown()
495
520
  );
496
521
  function closeStreamMessage(streamId) {
497
522
  return {
@@ -502,19 +527,10 @@ function closeStreamMessage(streamId) {
502
527
  }
503
528
  };
504
529
  }
505
- function requestCloseStreamMessage(streamId) {
530
+ function cancelMessage(streamId, payload) {
506
531
  return {
507
532
  streamId,
508
- controlFlags: 16 /* StreamCloseRequestBit */,
509
- payload: {
510
- type: "CLOSE"
511
- }
512
- };
513
- }
514
- function abortMessage(streamId, payload) {
515
- return {
516
- streamId,
517
- controlFlags: 4 /* StreamAbortBit */,
533
+ controlFlags: 4 /* StreamCancelBit */,
518
534
  payload
519
535
  };
520
536
  }
@@ -530,37 +546,27 @@ function isStreamClose(controlFlag) {
530
546
  (controlFlag & 8 /* StreamClosedBit */) === 8 /* StreamClosedBit */
531
547
  );
532
548
  }
533
- function isStreamCloseRequest(controlFlag) {
534
- return (
535
- /* eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison */
536
- (controlFlag & 16 /* StreamCloseRequestBit */) === 16 /* StreamCloseRequestBit */
537
- );
538
- }
539
- function isStreamAbort(controlFlag) {
549
+ function isStreamCancel(controlFlag) {
540
550
  return (
541
551
  /* eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison */
542
- (controlFlag & 4 /* StreamAbortBit */) === 4 /* StreamAbortBit */
552
+ (controlFlag & 4 /* StreamCancelBit */) === 4 /* StreamCancelBit */
543
553
  );
544
554
  }
545
555
 
546
556
  // router/result.ts
547
- var import_typebox4 = require("@sinclair/typebox");
548
- var ErrResultSchema = (t) => import_typebox4.Type.Object({
549
- ok: import_typebox4.Type.Literal(false),
550
- payload: t
551
- });
552
- var AnyResultSchema = import_typebox4.Type.Union([
553
- import_typebox4.Type.Object({
554
- ok: import_typebox4.Type.Literal(false),
555
- payload: import_typebox4.Type.Object({
556
- code: import_typebox4.Type.String(),
557
- message: import_typebox4.Type.String(),
558
- extras: import_typebox4.Type.Optional(import_typebox4.Type.Unknown())
557
+ var import_typebox5 = require("@sinclair/typebox");
558
+ var AnyResultSchema = import_typebox5.Type.Union([
559
+ import_typebox5.Type.Object({
560
+ ok: import_typebox5.Type.Literal(false),
561
+ payload: import_typebox5.Type.Object({
562
+ code: import_typebox5.Type.String(),
563
+ message: import_typebox5.Type.String(),
564
+ extras: import_typebox5.Type.Optional(import_typebox5.Type.Unknown())
559
565
  })
560
566
  }),
561
- import_typebox4.Type.Object({
562
- ok: import_typebox4.Type.Literal(true),
563
- payload: import_typebox4.Type.Unknown()
567
+ import_typebox5.Type.Object({
568
+ ok: import_typebox5.Type.Literal(true),
569
+ payload: import_typebox5.Type.Unknown()
564
570
  })
565
571
  ]);
566
572
  function Ok(payload) {
@@ -575,12 +581,20 @@ function Err(error) {
575
581
  payload: error
576
582
  };
577
583
  }
584
+ function unwrapOrThrow(result) {
585
+ if (result.ok) {
586
+ return result.payload;
587
+ }
588
+ throw new Error(
589
+ `Cannot non-ok result, got: ${result.payload.code} - ${result.payload.message}`
590
+ );
591
+ }
578
592
 
579
593
  // tracing/index.ts
580
594
  var import_api = require("@opentelemetry/api");
581
595
 
582
596
  // package.json
583
- var version = "0.200.0-rc.9";
597
+ var version = "0.200.1";
584
598
 
585
599
  // tracing/index.ts
586
600
  function getPropagationContext(ctx) {
@@ -644,306 +658,210 @@ function createHandlerSpan(kind, serviceName, procedureName, streamId, tracing,
644
658
  var tracer = import_api.trace.getTracer("river", version);
645
659
 
646
660
  // router/streams.ts
647
- var StreamDrainedError = {
648
- code: "STREAM_DRAINED",
649
- message: "Stream was drained"
661
+ var ReadableBrokenError = {
662
+ code: "READABLE_BROKEN",
663
+ message: "Readable was broken before it is fully consumed"
650
664
  };
651
- var ReadStreamImpl = class {
665
+ function createPromiseWithResolvers() {
666
+ let resolve;
667
+ let reject;
668
+ const promise = new Promise((res, rej) => {
669
+ resolve = res;
670
+ reject = rej;
671
+ });
672
+ return {
673
+ promise,
674
+ // @ts-expect-error promise callbacks are sync
675
+ resolve,
676
+ // @ts-expect-error promise callbacks are sync
677
+ reject
678
+ };
679
+ }
680
+ var ReadableImpl = class {
652
681
  /**
653
- * Whether the stream is closed.
682
+ * Whether the {@link Readable} is closed.
683
+ *
684
+ * Closed {@link Readable}s are done receiving values, but that doesn't affect
685
+ * any other aspect of the {@link Readable} such as it's consumability.
654
686
  */
655
687
  closed = false;
656
688
  /**
657
- * A list of listeners that will be called when the stream is closed.
658
- */
659
- onCloseListeners;
660
- /**
661
- * Whether the user has requested to close the stream.
662
- */
663
- closeRequested = false;
664
- /**
665
- * Used to signal to the outside world that the user has requested to close the stream.
666
- */
667
- closeRequestCallback;
668
- /**
669
- * Whether the stream is locked.
689
+ * Whether the {@link Readable} is locked.
690
+ *
691
+ * @see {@link Readable}'s typedoc to understand locking
670
692
  */
671
693
  locked = false;
672
694
  /**
673
- * Whether drain was called.
695
+ * Whether {@link break} was called.
696
+ *
697
+ * @see {@link break} for more information
674
698
  */
675
- drained = false;
699
+ broken = false;
676
700
  /**
677
- * This flag allows us to avoid cases where drain was called,
678
- * but the stream is fully consumed and closed. We don't need
679
- * to signal that drain was called.
701
+ * This flag allows us to avoid emitting a {@link ReadableBrokenError} after {@link break} was called
702
+ * in cases where the {@link queue} is fully consumed and {@link ReadableImpl} is {@link closed}. This is just an
703
+ * ergonomic feature to avoid emitting an error in our iteration when we don't have to.
680
704
  */
681
- didDrainDisposeValues = false;
705
+ brokenWithValuesLeftToRead = false;
682
706
  /**
683
- * A list of values that have been pushed to the stream but not yet emitted to the user.
707
+ * A list of values that have been pushed to the {@link ReadableImpl} but not yet emitted to the user.
684
708
  */
685
709
  queue = [];
686
710
  /**
687
711
  * Used by methods in the class to signal to the iterator that it
688
712
  * should check for the next value.
689
713
  */
690
- nextPromise = null;
691
- /**
692
- * Resolves nextPromise
693
- */
694
- resolveNextPromise = null;
695
- constructor(closeRequestCallback) {
696
- this.closeRequestCallback = closeRequestCallback;
697
- this.onCloseListeners = /* @__PURE__ */ new Set();
698
- }
714
+ next = null;
699
715
  [Symbol.asyncIterator]() {
700
- if (this.isLocked()) {
701
- throw new TypeError("ReadStream is already locked");
716
+ if (this.locked) {
717
+ throw new TypeError("Readable is already locked");
702
718
  }
703
- let didSignalDrain = false;
704
719
  this.locked = true;
720
+ let didSignalBreak = false;
705
721
  return {
706
722
  next: async () => {
707
- if (this.drained && didSignalDrain) {
723
+ if (didSignalBreak) {
708
724
  return {
709
725
  done: true,
710
726
  value: void 0
711
727
  };
712
728
  }
713
729
  while (this.queue.length === 0) {
714
- if (this.isClosed() && !this.didDrainDisposeValues) {
730
+ if (this.closed && !this.brokenWithValuesLeftToRead) {
715
731
  return {
716
732
  done: true,
717
733
  value: void 0
718
734
  };
719
735
  }
720
- if (this.drained) {
721
- didSignalDrain = true;
736
+ if (this.broken) {
737
+ didSignalBreak = true;
722
738
  return {
723
739
  done: false,
724
- value: Err(StreamDrainedError)
740
+ value: Err(ReadableBrokenError)
725
741
  };
726
742
  }
727
- if (!this.nextPromise) {
728
- this.nextPromise = new Promise((resolve) => {
729
- this.resolveNextPromise = resolve;
730
- });
743
+ if (!this.next) {
744
+ this.next = createPromiseWithResolvers();
731
745
  }
732
- await this.nextPromise;
733
- this.nextPromise = null;
734
- this.resolveNextPromise = null;
746
+ await this.next.promise;
747
+ this.next = null;
735
748
  }
736
749
  const value = this.queue.shift();
737
750
  return { done: false, value };
738
751
  },
739
752
  return: () => {
740
- this.drain();
753
+ this.break();
741
754
  return { done: true, value: void 0 };
742
755
  }
743
756
  };
744
757
  }
745
- unwrappedIter() {
746
- const iterator = this[Symbol.asyncIterator]();
747
- let unwrappedLock = false;
748
- return {
749
- [Symbol.asyncIterator]() {
750
- if (unwrappedLock) {
751
- throw new TypeError("ReadStream is already locked");
752
- }
753
- unwrappedLock = true;
754
- return {
755
- next: async () => {
756
- const next = await iterator.next();
757
- if (next.done) {
758
- return next;
759
- }
760
- if (next.value.ok) {
761
- return { done: false, value: next.value.payload };
762
- }
763
- iterator.return();
764
- throw new Error(
765
- `Got err result in unwrappedIter: ${next.value.payload.code} - ${next.value.payload.message}`
766
- );
767
- },
768
- return: () => iterator.return()
769
- };
770
- }
771
- };
772
- }
773
- async asArray() {
758
+ async collect() {
774
759
  const array = [];
775
760
  for await (const value of this) {
776
761
  array.push(value);
777
762
  }
778
763
  return array;
779
764
  }
780
- drain() {
781
- if (this.drained) {
765
+ break() {
766
+ if (this.broken) {
782
767
  return;
783
768
  }
784
769
  this.locked = true;
785
- this.drained = true;
786
- this.didDrainDisposeValues = this.queue.length > 0;
770
+ this.broken = true;
771
+ this.brokenWithValuesLeftToRead = this.queue.length > 0;
787
772
  this.queue.length = 0;
788
- this.resolveNextPromise?.();
789
- }
790
- isClosed() {
791
- return this.closed;
792
- }
793
- isLocked() {
794
- return this.locked;
795
- }
796
- onClose(cb) {
797
- if (this.isClosed()) {
798
- throw new Error("Stream is already closed");
799
- }
800
- this.onCloseListeners.add(cb);
801
- return () => {
802
- this.onCloseListeners.delete(cb);
803
- };
804
- }
805
- requestClose() {
806
- if (this.isClosed()) {
807
- throw new Error("Cannot request close after stream already closed");
808
- }
809
- if (!this.closeRequested) {
810
- this.closeRequested = true;
811
- this.closeRequestCallback();
812
- }
813
- return new Promise((resolve) => {
814
- this.onClose(() => {
815
- resolve(void 0);
816
- });
817
- });
773
+ this.next?.resolve();
818
774
  }
819
- isCloseRequested() {
820
- return this.closeRequested;
775
+ isReadable() {
776
+ return !this.locked && !this.broken;
821
777
  }
822
778
  /**
823
779
  * @internal meant for use within river, not exposed as a public API
824
780
  *
825
- * Pushes a value to the stream.
781
+ * Pushes a value to be read.
826
782
  */
827
- pushValue(value) {
828
- if (this.drained) {
783
+ _pushValue(value) {
784
+ if (this.broken) {
829
785
  return;
830
786
  }
831
787
  if (this.closed) {
832
- throw new Error("Cannot push to closed stream");
788
+ throw new Error("Cannot push to closed Readable");
833
789
  }
834
790
  this.queue.push(value);
835
- this.resolveNextPromise?.();
791
+ this.next?.resolve();
836
792
  }
837
793
  /**
838
794
  * @internal meant for use within river, not exposed as a public API
839
795
  *
840
- * Triggers the close of the stream. Make sure to push all remaining
796
+ * Triggers the close of the {@link Readable}. Make sure to push all remaining
841
797
  * values before calling this method.
842
798
  */
843
- triggerClose() {
844
- if (this.isClosed()) {
799
+ _triggerClose() {
800
+ if (this.closed) {
845
801
  throw new Error("Unexpected closing multiple times");
846
802
  }
847
803
  this.closed = true;
848
- this.resolveNextPromise?.();
849
- this.onCloseListeners.forEach((cb) => cb());
850
- this.onCloseListeners.clear();
804
+ this.next?.resolve();
851
805
  }
852
806
  /**
853
807
  * @internal meant for use within river, not exposed as a public API
854
808
  */
855
- hasValuesInQueue() {
809
+ _hasValuesInQueue() {
856
810
  return this.queue.length > 0;
857
811
  }
858
- };
859
- var WriteStreamImpl = class {
860
- /**
861
- * Passed via constructor to pass on write requests
862
- */
863
- writeCb;
864
812
  /**
865
- * Whether the stream is closed.
813
+ * @internal meant for use within river, not exposed as a public API
866
814
  */
867
- closed = false;
815
+ isClosed() {
816
+ return this.closed;
817
+ }
818
+ };
819
+ var WritableImpl = class {
868
820
  /**
869
- * A list of listeners that will be called when the stream is closed.
821
+ * Passed via constructor to pass on calls to {@link write}
870
822
  */
871
- onCloseListeners;
823
+ writeCb;
872
824
  /**
873
- * Whether the reader has requested to close the stream.
825
+ * Passed via constructor to pass on calls to {@link close}
874
826
  */
875
- closeRequested = false;
827
+ closeCb;
876
828
  /**
877
- * A list of listeners that will be called when a close request is triggered.
829
+ * Whether {@link close} was called, and {@link Writable} is not writable anymore.
878
830
  */
879
- onCloseRequestListeners;
880
- constructor(writeCb) {
881
- this.writeCb = writeCb;
882
- this.onCloseListeners = /* @__PURE__ */ new Set();
883
- this.onCloseRequestListeners = /* @__PURE__ */ new Set();
831
+ closed = false;
832
+ constructor(callbacks) {
833
+ this.writeCb = callbacks.writeCb;
834
+ this.closeCb = callbacks.closeCb;
884
835
  }
885
836
  write(value) {
886
- if (this.isClosed()) {
887
- throw new Error("Cannot write to closed stream");
837
+ if (this.closed) {
838
+ throw new Error("Cannot write to closed Writable");
888
839
  }
889
840
  this.writeCb(value);
890
841
  }
891
- isClosed() {
892
- return this.closed;
893
- }
894
- onClose(cb) {
895
- if (this.isClosed()) {
896
- cb();
897
- return () => void 0;
898
- }
899
- this.onCloseListeners.add(cb);
900
- return () => this.onCloseListeners.delete(cb);
842
+ isWritable() {
843
+ return !this.closed;
901
844
  }
902
845
  close() {
903
- if (this.isClosed()) {
846
+ if (this.closed) {
904
847
  return;
905
848
  }
906
849
  this.closed = true;
907
- this.onCloseListeners.forEach((cb) => cb());
908
- this.onCloseListeners.clear();
909
- this.onCloseRequestListeners.clear();
910
850
  this.writeCb = () => void 0;
911
- }
912
- isCloseRequested() {
913
- return this.closeRequested;
914
- }
915
- onCloseRequest(cb) {
916
- if (this.isClosed()) {
917
- throw new Error("Stream is already closed");
918
- }
919
- if (this.isCloseRequested()) {
920
- cb();
921
- return () => void 0;
922
- }
923
- this.onCloseRequestListeners.add(cb);
924
- return () => this.onCloseRequestListeners.delete(cb);
851
+ this.closeCb();
852
+ this.closeCb = () => void 0;
925
853
  }
926
854
  /**
927
855
  * @internal meant for use within river, not exposed as a public API
928
- *
929
- * Triggers a close request.
930
856
  */
931
- triggerCloseRequest() {
932
- if (this.isCloseRequested()) {
933
- throw new Error("Cannot trigger close request multiple times");
934
- }
935
- if (this.isClosed()) {
936
- throw new Error("Cannot trigger close request on closed stream");
937
- }
938
- this.closeRequested = true;
939
- this.onCloseRequestListeners.forEach((cb) => cb());
940
- this.onCloseRequestListeners.clear();
857
+ isClosed() {
858
+ return this.closed;
941
859
  }
942
860
  };
943
861
 
944
862
  // router/client.ts
945
863
  var import_value = require("@sinclair/typebox/value");
946
- var OutputErrResultSchema = ErrResultSchema(ResponseReaderErrorSchema);
864
+ var ReaderErrResultSchema = ErrResultSchema(ReaderErrorSchema);
947
865
  var noop = () => {
948
866
  };
949
867
  function _createRecursiveProxy(callback, path) {
@@ -1004,6 +922,11 @@ function createClient(transport, serverId, providedClientOptions = {}) {
1004
922
  }, []);
1005
923
  }
1006
924
  function handleProc(procType, transport, serverId, init, serviceName, procedureName, abortSignal) {
925
+ const session = transport.sessions.get(serverId) ?? transport.createUnconnectedSession(serverId);
926
+ const sessionScopedSend = transport.getSessionBoundSendFn(
927
+ serverId,
928
+ session.id
929
+ );
1007
930
  const procClosesWithInit = procType === "rpc" || procType === "subscription";
1008
931
  const streamId = generateId();
1009
932
  const { span, ctx } = createProcTelemetryInfo(
@@ -1014,61 +937,61 @@ function handleProc(procType, transport, serverId, init, serviceName, procedureN
1014
937
  streamId
1015
938
  );
1016
939
  let cleanClose = true;
1017
- const reqWriter = new WriteStreamImpl((rawIn) => {
1018
- transport.send(serverId, {
1019
- streamId,
1020
- payload: rawIn,
1021
- controlFlags: 0,
1022
- tracing: getPropagationContext(ctx)
1023
- });
1024
- });
1025
- reqWriter.onClose(() => {
1026
- span.addEvent("reqWriter closed");
1027
- if (!procClosesWithInit && cleanClose) {
1028
- transport.send(serverId, closeStreamMessage(streamId));
1029
- }
1030
- if (resReader.isClosed()) {
1031
- cleanup();
940
+ const reqWritable = new WritableImpl({
941
+ writeCb: (rawIn) => {
942
+ sessionScopedSend({
943
+ streamId,
944
+ payload: rawIn,
945
+ controlFlags: 0
946
+ });
947
+ },
948
+ // close callback
949
+ closeCb: () => {
950
+ span.addEvent("reqWritable closed");
951
+ if (!procClosesWithInit && cleanClose) {
952
+ sessionScopedSend(closeStreamMessage(streamId));
953
+ }
954
+ if (resReadable.isClosed()) {
955
+ cleanup();
956
+ }
1032
957
  }
1033
958
  });
1034
- const resReader = new ReadStreamImpl(() => {
1035
- transport.send(serverId, requestCloseStreamMessage(streamId));
1036
- });
1037
- resReader.onClose(() => {
1038
- span.addEvent("resReader closed");
1039
- if (reqWriter.isClosed()) {
959
+ const resReadable = new ReadableImpl();
960
+ const closeReadable = () => {
961
+ resReadable._triggerClose();
962
+ span.addEvent("resReadable closed");
963
+ if (reqWritable.isClosed()) {
1040
964
  cleanup();
1041
965
  }
1042
- });
966
+ };
1043
967
  function cleanup() {
1044
968
  transport.removeEventListener("message", onMessage);
1045
969
  transport.removeEventListener("sessionStatus", onSessionStatus);
1046
- abortSignal?.removeEventListener("abort", onClientAbort);
970
+ abortSignal?.removeEventListener("abort", onClientCancel);
1047
971
  span.end();
1048
972
  }
1049
- function onClientAbort() {
1050
- if (resReader.isClosed() && reqWriter.isClosed()) {
973
+ function onClientCancel() {
974
+ if (resReadable.isClosed() && reqWritable.isClosed()) {
1051
975
  return;
1052
976
  }
1053
- span.addEvent("sending abort");
977
+ span.addEvent("sending cancel");
1054
978
  cleanClose = false;
1055
- if (!resReader.isClosed()) {
1056
- resReader.pushValue(
979
+ if (!resReadable.isClosed()) {
980
+ resReadable._pushValue(
1057
981
  Err({
1058
- code: ABORT_CODE,
1059
- message: "Aborted by client"
982
+ code: CANCEL_CODE,
983
+ message: "cancelled by client"
1060
984
  })
1061
985
  );
1062
- resReader.triggerClose();
986
+ closeReadable();
1063
987
  }
1064
- reqWriter.close();
1065
- transport.send(
1066
- serverId,
1067
- abortMessage(
988
+ reqWritable.close();
989
+ sessionScopedSend(
990
+ cancelMessage(
1068
991
  streamId,
1069
992
  Err({
1070
- code: ABORT_CODE,
1071
- message: "Aborted by client"
993
+ code: CANCEL_CODE,
994
+ message: "cancelled by client"
1072
995
  })
1073
996
  )
1074
997
  );
@@ -1077,47 +1000,44 @@ function handleProc(procType, transport, serverId, init, serviceName, procedureN
1077
1000
  if (msg.streamId !== streamId)
1078
1001
  return;
1079
1002
  if (msg.to !== transport.clientId) {
1080
- transport.log?.error("Got stream message from unexpected client", {
1003
+ transport.log?.error("got stream message from unexpected client", {
1081
1004
  clientId: transport.clientId,
1082
1005
  transportMessage: msg
1083
1006
  });
1084
1007
  return;
1085
1008
  }
1086
- if (isStreamCloseRequest(msg.controlFlags)) {
1087
- reqWriter.triggerCloseRequest();
1088
- }
1089
- if (isStreamAbort(msg.controlFlags)) {
1009
+ if (isStreamCancel(msg.controlFlags)) {
1090
1010
  cleanClose = false;
1091
- span.addEvent("received abort");
1092
- let abortResult;
1093
- if (import_value.Value.Check(OutputErrResultSchema, msg.payload)) {
1094
- abortResult = msg.payload;
1011
+ span.addEvent("received cancel");
1012
+ let cancelResult;
1013
+ if (import_value.Value.Check(ReaderErrResultSchema, msg.payload)) {
1014
+ cancelResult = msg.payload;
1095
1015
  } else {
1096
- abortResult = Err({
1097
- code: ABORT_CODE,
1098
- message: "Stream aborted with invalid payload"
1016
+ cancelResult = Err({
1017
+ code: CANCEL_CODE,
1018
+ message: "stream cancelled with invalid payload"
1099
1019
  });
1100
1020
  transport.log?.error(
1101
- "Got stream abort without a valid protocol error",
1021
+ "got stream cancel without a valid protocol error",
1102
1022
  {
1103
1023
  clientId: transport.clientId,
1104
1024
  transportMessage: msg,
1105
1025
  validationErrors: [
1106
- ...import_value.Value.Errors(OutputErrResultSchema, msg.payload)
1026
+ ...import_value.Value.Errors(ReaderErrResultSchema, msg.payload)
1107
1027
  ]
1108
1028
  }
1109
1029
  );
1110
1030
  }
1111
- if (!resReader.isClosed()) {
1112
- resReader.pushValue(abortResult);
1113
- resReader.triggerClose();
1031
+ if (!resReadable.isClosed()) {
1032
+ resReadable._pushValue(cancelResult);
1033
+ closeReadable();
1114
1034
  }
1115
- reqWriter.close();
1035
+ reqWritable.close();
1116
1036
  return;
1117
1037
  }
1118
- if (resReader.isClosed()) {
1119
- span.recordException("Received message after output stream is closed");
1120
- transport.log?.error("Received message after output stream is closed", {
1038
+ if (resReadable.isClosed()) {
1039
+ span.recordException("received message after response stream is closed");
1040
+ transport.log?.error("received message after response stream is closed", {
1121
1041
  clientId: transport.clientId,
1122
1042
  transportMessage: msg
1123
1043
  });
@@ -1125,7 +1045,7 @@ function handleProc(procType, transport, serverId, init, serviceName, procedureN
1125
1045
  }
1126
1046
  if (!import_value.Value.Check(ControlMessageCloseSchema, msg.payload)) {
1127
1047
  if (import_value.Value.Check(AnyResultSchema, msg.payload)) {
1128
- resReader.pushValue(msg.payload);
1048
+ resReadable._pushValue(msg.payload);
1129
1049
  } else {
1130
1050
  transport.log?.error(
1131
1051
  "Got non-control payload, but was not a valid result",
@@ -1138,33 +1058,36 @@ function handleProc(procType, transport, serverId, init, serviceName, procedureN
1138
1058
  }
1139
1059
  }
1140
1060
  if (isStreamClose(msg.controlFlags)) {
1141
- span.addEvent("received output close");
1142
- resReader.triggerClose();
1061
+ span.addEvent("received response close");
1062
+ if (resReadable.isClosed()) {
1063
+ transport.log?.error(
1064
+ "received stream close but readable was already closed"
1065
+ );
1066
+ } else {
1067
+ closeReadable();
1068
+ }
1143
1069
  }
1144
1070
  }
1145
1071
  function onSessionStatus(evt) {
1146
- if (evt.status !== "disconnect") {
1147
- return;
1148
- }
1149
- if (evt.session.to !== serverId) {
1072
+ if (evt.status !== "disconnect" || evt.session.to !== serverId || session.id !== evt.session.id) {
1150
1073
  return;
1151
1074
  }
1152
1075
  cleanClose = false;
1153
- if (!resReader.isClosed()) {
1154
- resReader.pushValue(
1076
+ if (!resReadable.isClosed()) {
1077
+ resReadable._pushValue(
1155
1078
  Err({
1156
1079
  code: UNEXPECTED_DISCONNECT_CODE,
1157
1080
  message: `${serverId} unexpectedly disconnected`
1158
1081
  })
1159
1082
  );
1083
+ closeReadable();
1160
1084
  }
1161
- reqWriter.close();
1162
- resReader.triggerClose();
1085
+ reqWritable.close();
1163
1086
  }
1164
- abortSignal?.addEventListener("abort", onClientAbort);
1087
+ abortSignal?.addEventListener("abort", onClientCancel);
1165
1088
  transport.addEventListener("message", onMessage);
1166
1089
  transport.addEventListener("sessionStatus", onSessionStatus);
1167
- transport.send(serverId, {
1090
+ sessionScopedSend({
1168
1091
  streamId,
1169
1092
  serviceName,
1170
1093
  procedureName,
@@ -1173,34 +1096,39 @@ function handleProc(procType, transport, serverId, init, serviceName, procedureN
1173
1096
  controlFlags: procClosesWithInit ? 2 /* StreamOpenBit */ | 8 /* StreamClosedBit */ : 2 /* StreamOpenBit */
1174
1097
  });
1175
1098
  if (procClosesWithInit) {
1176
- reqWriter.close();
1099
+ reqWritable.close();
1177
1100
  }
1178
1101
  if (procType === "subscription") {
1179
- return { resReader };
1102
+ return {
1103
+ resReadable
1104
+ };
1180
1105
  }
1181
1106
  if (procType === "rpc") {
1182
- return getSingleMessage(resReader, transport.log);
1107
+ return getSingleMessage(resReadable, transport.log);
1183
1108
  }
1184
1109
  if (procType === "upload") {
1185
1110
  let didFinalize = false;
1186
1111
  return {
1187
- reqWriter,
1188
- async finalize() {
1112
+ reqWritable,
1113
+ finalize: () => {
1189
1114
  if (didFinalize) {
1190
1115
  throw new Error("upload stream already finalized");
1191
1116
  }
1192
1117
  didFinalize = true;
1193
- if (!reqWriter.isClosed()) {
1194
- reqWriter.close();
1118
+ if (!reqWritable.isClosed()) {
1119
+ reqWritable.close();
1195
1120
  }
1196
- return getSingleMessage(resReader, transport.log);
1121
+ return getSingleMessage(resReadable, transport.log);
1197
1122
  }
1198
1123
  };
1199
1124
  }
1200
- return { reqWriter, resReader };
1125
+ return {
1126
+ resReadable,
1127
+ reqWritable
1128
+ };
1201
1129
  }
1202
- async function getSingleMessage(resReader, log) {
1203
- const ret = await resReader.asArray();
1130
+ async function getSingleMessage(resReadable, log) {
1131
+ const ret = await resReadable.collect();
1204
1132
  if (ret.length > 1) {
1205
1133
  log?.error("Expected single message from server, got multiple");
1206
1134
  }
@@ -1208,6 +1136,7 @@ async function getSingleMessage(resReader, log) {
1208
1136
  }
1209
1137
 
1210
1138
  // router/server.ts
1139
+ var import_typebox6 = require("@sinclair/typebox");
1211
1140
  var import_value2 = require("@sinclair/typebox/value");
1212
1141
 
1213
1142
  // util/stringify.ts
@@ -1220,23 +1149,28 @@ function coerceErrorString(err) {
1220
1149
 
1221
1150
  // router/server.ts
1222
1151
  var import_api2 = require("@opentelemetry/api");
1223
- var InputErrResultSchema = ErrResultSchema(RequestReaderErrorSchema);
1152
+ var CancelResultSchema = ErrResultSchema(
1153
+ import_typebox6.Type.Object({
1154
+ code: import_typebox6.Type.Literal(CANCEL_CODE),
1155
+ message: import_typebox6.Type.String()
1156
+ })
1157
+ );
1224
1158
  var RiverServer = class {
1225
1159
  transport;
1226
1160
  contextMap;
1227
1161
  log;
1228
1162
  /**
1229
- * We create a tombstones for streams aborted by the server
1163
+ * We create a tombstones for streams cancelled by the server
1230
1164
  * so that we don't hit errors when the client has inflight
1231
- * requests it sent before it saw the abort.
1232
- * We track aborted streams for every session separately, so
1165
+ * requests it sent before it saw the cancel.
1166
+ * We track cancelled streams for every client separately, so
1233
1167
  * that bad clients don't affect good clients.
1234
1168
  */
1235
- serverAbortedStreams;
1236
- maxAbortedStreamTombstonesPerSession;
1237
- openStreams;
1169
+ serverCancelledStreams;
1170
+ maxCancelledStreamTombstonesPerSession;
1171
+ streams;
1238
1172
  services;
1239
- constructor(transport, services, handshakeOptions, extendedContext, maxAbortedStreamTombstonesPerSession = 200) {
1173
+ constructor(transport, services, handshakeOptions, extendedContext, maxCancelledStreamTombstonesPerSession = 200) {
1240
1174
  const instances = {};
1241
1175
  this.services = instances;
1242
1176
  this.contextMap = /* @__PURE__ */ new Map();
@@ -1252,34 +1186,40 @@ var RiverServer = class {
1252
1186
  transport.extendHandshake(handshakeOptions);
1253
1187
  }
1254
1188
  this.transport = transport;
1255
- this.openStreams = /* @__PURE__ */ new Set();
1256
- this.serverAbortedStreams = /* @__PURE__ */ new Map();
1257
- this.maxAbortedStreamTombstonesPerSession = maxAbortedStreamTombstonesPerSession;
1189
+ this.streams = /* @__PURE__ */ new Map();
1190
+ this.serverCancelledStreams = /* @__PURE__ */ new Map();
1191
+ this.maxCancelledStreamTombstonesPerSession = maxCancelledStreamTombstonesPerSession;
1258
1192
  this.log = transport.log;
1259
- const handleMessage = (msg) => {
1260
- if (msg.to !== this.transport.clientId) {
1193
+ const handleCreatingNewStreams = (message) => {
1194
+ if (message.to !== this.transport.clientId) {
1261
1195
  this.log?.info(
1262
1196
  `got msg with destination that isn't this server, ignoring`,
1263
1197
  {
1264
1198
  clientId: this.transport.clientId,
1265
- transportMessage: msg
1199
+ transportMessage: message
1266
1200
  }
1267
1201
  );
1268
1202
  return;
1269
1203
  }
1270
- if (this.openStreams.has(msg.streamId)) {
1204
+ const streamId = message.streamId;
1205
+ const stream2 = this.streams.get(streamId);
1206
+ if (stream2) {
1207
+ stream2.handleMsg(message);
1271
1208
  return;
1272
1209
  }
1273
- if (this.serverAbortedStreams.get(msg.from)?.has(msg.streamId)) {
1210
+ if (this.serverCancelledStreams.get(message.from)?.has(streamId)) {
1274
1211
  return;
1275
1212
  }
1276
- const validated = this.validateNewProcStream(msg);
1277
- if (!validated) {
1213
+ const newStreamProps = this.validateNewProcStream(message);
1214
+ if (!newStreamProps) {
1278
1215
  return;
1279
1216
  }
1280
- this.createNewProcStream(validated);
1217
+ const newStream = this.createNewProcStream({
1218
+ ...newStreamProps,
1219
+ ...message
1220
+ });
1221
+ this.streams.set(streamId, newStream);
1281
1222
  };
1282
- this.transport.addEventListener("message", handleMessage);
1283
1223
  const handleSessionStatus = (evt) => {
1284
1224
  if (evt.status !== "disconnect")
1285
1225
  return;
@@ -1288,256 +1228,248 @@ var RiverServer = class {
1288
1228
  `got session disconnect from ${disconnectedClientId}, cleaning up streams`,
1289
1229
  evt.session.loggingMetadata
1290
1230
  );
1291
- this.serverAbortedStreams.delete(disconnectedClientId);
1231
+ for (const stream2 of this.streams.values()) {
1232
+ if (stream2.from === disconnectedClientId) {
1233
+ stream2.handleSessionDisconnect();
1234
+ }
1235
+ }
1236
+ this.serverCancelledStreams.delete(disconnectedClientId);
1292
1237
  };
1293
- this.transport.addEventListener("sessionStatus", handleSessionStatus);
1294
- this.transport.addEventListener("transportStatus", (evt) => {
1238
+ const handleTransportStatus = (evt) => {
1295
1239
  if (evt.status !== "closed")
1296
1240
  return;
1297
- this.transport.removeEventListener("message", handleMessage);
1241
+ this.transport.removeEventListener("message", handleCreatingNewStreams);
1298
1242
  this.transport.removeEventListener("sessionStatus", handleSessionStatus);
1299
- });
1300
- }
1301
- createNewProcStream({
1302
- procedure,
1303
- procedureName,
1304
- service,
1305
- serviceName,
1306
- sessionMetadata,
1307
- loggingMetadata,
1308
- streamId,
1309
- controlFlags,
1310
- initPayload,
1311
- from,
1312
- sessionId,
1313
- tracingCtx,
1314
- protocolVersion,
1315
- passInitAsDataForBackwardsCompat
1316
- }) {
1317
- this.openStreams.add(streamId);
1318
- let cleanClose = true;
1319
- const onServerAbort = (errResult) => {
1320
- if (reqReader.isClosed() && resWriter.isClosed()) {
1321
- return;
1322
- }
1323
- cleanClose = false;
1324
- if (!reqReader.isClosed()) {
1325
- reqReader.pushValue(errResult);
1326
- reqReader.triggerClose();
1327
- }
1328
- resWriter.close();
1329
- this.abortStream(from, streamId, errResult);
1330
- };
1331
- const onHandlerAbort = () => {
1332
- onServerAbort(
1333
- Err({
1334
- code: ABORT_CODE,
1335
- message: "Aborted by server procedure handler"
1336
- })
1243
+ this.transport.removeEventListener(
1244
+ "transportStatus",
1245
+ handleTransportStatus
1337
1246
  );
1338
1247
  };
1339
- const handlerAbortController = new AbortController();
1340
- handlerAbortController.signal.addEventListener("abort", onHandlerAbort);
1341
- const clientAbortController = new AbortController();
1342
- const onSessionStatus = (evt) => {
1343
- if (evt.status !== "disconnect") {
1344
- return;
1345
- }
1346
- if (evt.session.to !== from) {
1347
- return;
1348
- }
1349
- cleanClose = false;
1350
- const errPayload = {
1351
- code: UNEXPECTED_DISCONNECT_CODE,
1352
- message: `client unexpectedly disconnected`
1353
- };
1354
- if (!reqReader.isClosed()) {
1355
- reqReader.pushValue(Err(errPayload));
1356
- reqReader.triggerClose();
1357
- }
1358
- clientAbortController.abort(errPayload);
1359
- resWriter.close();
1360
- };
1361
- this.transport.addEventListener("sessionStatus", onSessionStatus);
1248
+ this.transport.addEventListener("message", handleCreatingNewStreams);
1249
+ this.transport.addEventListener("sessionStatus", handleSessionStatus);
1250
+ this.transport.addEventListener("transportStatus", handleTransportStatus);
1251
+ }
1252
+ createNewProcStream(props) {
1253
+ const {
1254
+ streamId,
1255
+ initialSession,
1256
+ procedureName,
1257
+ serviceName,
1258
+ procedure,
1259
+ sessionMetadata,
1260
+ serviceContext,
1261
+ initPayload,
1262
+ tracingCtx,
1263
+ procClosesWithInit,
1264
+ passInitAsDataForBackwardsCompat
1265
+ } = props;
1266
+ const {
1267
+ to: from,
1268
+ loggingMetadata,
1269
+ protocolVersion,
1270
+ id: sessionId
1271
+ } = initialSession;
1272
+ let cleanClose = true;
1362
1273
  const onMessage = (msg) => {
1363
- if (streamId !== msg.streamId) {
1364
- return;
1365
- }
1366
1274
  if (msg.from !== from) {
1367
- this.log?.error("Got stream message from unexpected client", {
1275
+ this.log?.error("got stream message from unexpected client", {
1368
1276
  ...loggingMetadata,
1369
- clientId: this.transport.clientId,
1370
1277
  transportMessage: msg,
1371
1278
  tags: ["invariant-violation"]
1372
1279
  });
1373
1280
  return;
1374
1281
  }
1375
- if (isStreamCloseRequest(msg.controlFlags)) {
1376
- resWriter.triggerCloseRequest();
1377
- }
1378
- if (isStreamAbortBackwardsCompat(msg.controlFlags, protocolVersion)) {
1379
- let abortResult;
1380
- if (import_value2.Value.Check(InputErrResultSchema, msg.payload)) {
1381
- abortResult = msg.payload;
1282
+ if (isStreamCancelBackwardsCompat(msg.controlFlags, protocolVersion)) {
1283
+ let cancelResult;
1284
+ if (import_value2.Value.Check(CancelResultSchema, msg.payload)) {
1285
+ cancelResult = msg.payload;
1382
1286
  } else {
1383
- abortResult = Err({
1384
- code: ABORT_CODE,
1385
- message: "Stream aborted, client sent invalid payload"
1287
+ cancelResult = Err({
1288
+ code: CANCEL_CODE,
1289
+ message: "stream cancelled, client sent invalid payload"
1386
1290
  });
1387
- this.log?.warn("Got stream abort without a valid protocol error", {
1291
+ this.log?.warn("got stream cancel without a valid protocol error", {
1388
1292
  ...loggingMetadata,
1389
- clientId: this.transport.clientId,
1390
1293
  transportMessage: msg,
1391
1294
  validationErrors: [
1392
- ...import_value2.Value.Errors(InputErrResultSchema, msg.payload)
1295
+ ...import_value2.Value.Errors(CancelResultSchema, msg.payload)
1393
1296
  ],
1394
1297
  tags: ["invalid-request"]
1395
1298
  });
1396
1299
  }
1397
- if (!reqReader.isClosed()) {
1398
- reqReader.pushValue(abortResult);
1399
- reqReader.triggerClose();
1300
+ if (!reqReadable.isClosed()) {
1301
+ reqReadable._pushValue(cancelResult);
1302
+ closeReadable();
1400
1303
  }
1401
- resWriter.close();
1402
- clientAbortController.abort(abortResult.payload);
1304
+ resWritable.close();
1403
1305
  return;
1404
1306
  }
1405
- if (reqReader.isClosed()) {
1406
- this.log?.warn("Received message after input stream is closed", {
1307
+ if (reqReadable.isClosed()) {
1308
+ this.log?.warn("received message after request stream is closed", {
1407
1309
  ...loggingMetadata,
1408
- clientId: this.transport.clientId,
1409
1310
  transportMessage: msg,
1410
1311
  tags: ["invalid-request"]
1411
1312
  });
1412
- onServerAbort(
1413
- Err({
1414
- code: INVALID_REQUEST_CODE,
1415
- message: "Received message after input stream is closed"
1416
- })
1417
- );
1313
+ onServerCancel({
1314
+ code: INVALID_REQUEST_CODE,
1315
+ message: "received message after request stream is closed"
1316
+ });
1418
1317
  return;
1419
1318
  }
1420
1319
  if ("requestData" in procedure && import_value2.Value.Check(procedure.requestData, msg.payload)) {
1421
- reqReader.pushValue(Ok(msg.payload));
1422
- } else if (!import_value2.Value.Check(ControlMessagePayloadSchema, msg.payload)) {
1423
- const validationErrors = [
1320
+ reqReadable._pushValue(Ok(msg.payload));
1321
+ if (isStreamCloseBackwardsCompat(msg.controlFlags, protocolVersion)) {
1322
+ closeReadable();
1323
+ }
1324
+ return;
1325
+ }
1326
+ if (import_value2.Value.Check(ControlMessagePayloadSchema, msg.payload) && isStreamCloseBackwardsCompat(msg.controlFlags, protocolVersion)) {
1327
+ closeReadable();
1328
+ return;
1329
+ }
1330
+ let validationErrors;
1331
+ let errMessage;
1332
+ if ("requestData" in procedure) {
1333
+ errMessage = "expected requestData or control payload";
1334
+ validationErrors = [
1335
+ ...import_value2.Value.Errors(procedure.responseData, msg.payload)
1336
+ ];
1337
+ } else {
1338
+ validationErrors = [
1424
1339
  ...import_value2.Value.Errors(ControlMessagePayloadSchema, msg.payload)
1425
1340
  ];
1426
- let errMessage = "Expected control payload for procedure with no input";
1427
- if ("requestData" in procedure) {
1428
- errMessage = "Expected either control or input payload, validation failed for both";
1429
- validationErrors.push(
1430
- ...import_value2.Value.Errors(procedure.responseData, msg.payload)
1431
- );
1341
+ errMessage = "expected control payload";
1342
+ }
1343
+ this.log?.warn(errMessage, {
1344
+ ...loggingMetadata,
1345
+ transportMessage: msg,
1346
+ validationErrors,
1347
+ tags: ["invalid-request"]
1348
+ });
1349
+ onServerCancel({
1350
+ code: INVALID_REQUEST_CODE,
1351
+ message: errMessage
1352
+ });
1353
+ };
1354
+ const procStream = {
1355
+ from,
1356
+ streamId,
1357
+ procedureName,
1358
+ serviceName,
1359
+ sessionMetadata,
1360
+ procedure,
1361
+ handleMsg: onMessage,
1362
+ handleSessionDisconnect: () => {
1363
+ cleanClose = false;
1364
+ const errPayload = {
1365
+ code: UNEXPECTED_DISCONNECT_CODE,
1366
+ message: "client unexpectedly disconnected"
1367
+ };
1368
+ if (!reqReadable.isClosed()) {
1369
+ reqReadable._pushValue(Err(errPayload));
1370
+ closeReadable();
1432
1371
  }
1433
- this.log?.warn(errMessage, {
1434
- ...loggingMetadata,
1435
- clientId: this.transport.clientId,
1436
- transportMessage: msg,
1437
- validationErrors,
1438
- tags: ["invalid-request"]
1439
- });
1440
- onServerAbort(
1441
- Err({
1442
- code: INVALID_REQUEST_CODE,
1443
- message: errMessage
1444
- })
1445
- );
1372
+ resWritable.close();
1446
1373
  }
1447
- if (isStreamCloseBackwardsCompat(msg.controlFlags, protocolVersion)) {
1448
- reqReader.triggerClose();
1374
+ };
1375
+ const sessionScopedSend = this.transport.getSessionBoundSendFn(
1376
+ from,
1377
+ sessionId
1378
+ );
1379
+ const cancelStream = (streamId2, payload) => {
1380
+ this.cancelStream(from, sessionScopedSend, streamId2, payload);
1381
+ };
1382
+ const onServerCancel = (e) => {
1383
+ if (reqReadable.isClosed() && resWritable.isClosed()) {
1384
+ return;
1385
+ }
1386
+ cleanClose = false;
1387
+ const result = Err(e);
1388
+ if (!reqReadable.isClosed()) {
1389
+ reqReadable._pushValue(result);
1390
+ closeReadable();
1449
1391
  }
1392
+ resWritable.close();
1393
+ cancelStream(streamId, result);
1450
1394
  };
1451
- this.transport.addEventListener("message", onMessage);
1452
- const onFinishedCallbacks = [];
1395
+ const finishedController = new AbortController();
1453
1396
  const cleanup = () => {
1454
- this.transport.removeEventListener("message", onMessage);
1455
- this.transport.removeEventListener("sessionStatus", onSessionStatus);
1456
- handlerAbortController.signal.addEventListener("abort", onHandlerAbort);
1457
- this.openStreams.delete(streamId);
1458
- onFinishedCallbacks.forEach((cb) => {
1459
- try {
1460
- cb();
1461
- } catch {
1462
- }
1463
- });
1464
- onFinishedCallbacks.length = 0;
1397
+ finishedController.abort();
1398
+ this.streams.delete(streamId);
1465
1399
  };
1466
1400
  const procClosesWithResponse = procedure.type === "rpc" || procedure.type === "upload";
1467
- const reqReader = new ReadStreamImpl(() => {
1468
- this.transport.send(from, requestCloseStreamMessage(streamId));
1469
- });
1470
- reqReader.onClose(() => {
1401
+ const reqReadable = new ReadableImpl();
1402
+ const closeReadable = () => {
1403
+ reqReadable._triggerClose();
1471
1404
  if (protocolVersion === "v1.1") {
1472
- if (!procClosesWithResponse && !resWriter.isClosed()) {
1473
- resWriter.close();
1405
+ if (!procClosesWithResponse && !resWritable.isClosed()) {
1406
+ resWritable.close();
1474
1407
  }
1475
1408
  }
1476
- if (resWriter.isClosed()) {
1409
+ if (resWritable.isClosed()) {
1477
1410
  cleanup();
1478
1411
  }
1479
- });
1412
+ };
1480
1413
  if (passInitAsDataForBackwardsCompat) {
1481
- reqReader.pushValue(Ok(initPayload));
1414
+ reqReadable._pushValue(Ok(initPayload));
1482
1415
  }
1483
- const resWriter = new WriteStreamImpl((response) => {
1484
- this.transport.send(from, {
1485
- streamId,
1486
- controlFlags: procClosesWithResponse ? getStreamCloseBackwardsCompat(protocolVersion) : 0,
1487
- payload: response
1488
- });
1489
- });
1490
- resWriter.onClose(() => {
1491
- if (!procClosesWithResponse && cleanClose) {
1492
- const message = closeStreamMessage(streamId);
1493
- message.controlFlags = getStreamCloseBackwardsCompat(protocolVersion);
1494
- this.transport.send(from, closeStreamMessage(streamId));
1495
- }
1496
- if (protocolVersion === "v1.1") {
1497
- if (!reqReader.isClosed()) {
1498
- reqReader.triggerClose();
1416
+ const resWritable = new WritableImpl({
1417
+ writeCb: (response) => {
1418
+ sessionScopedSend({
1419
+ streamId,
1420
+ controlFlags: procClosesWithResponse ? getStreamCloseBackwardsCompat(protocolVersion) : 0,
1421
+ payload: response
1422
+ });
1423
+ if (procClosesWithResponse) {
1424
+ resWritable.close();
1425
+ }
1426
+ },
1427
+ // close callback
1428
+ closeCb: () => {
1429
+ if (!procClosesWithResponse && cleanClose) {
1430
+ const message = closeStreamMessage(streamId);
1431
+ message.controlFlags = getStreamCloseBackwardsCompat(protocolVersion);
1432
+ sessionScopedSend(message);
1433
+ }
1434
+ if (protocolVersion === "v1.1") {
1435
+ if (!reqReadable.isClosed()) {
1436
+ closeReadable();
1437
+ }
1438
+ }
1439
+ if (reqReadable.isClosed()) {
1440
+ cleanup();
1499
1441
  }
1500
- }
1501
- if (reqReader.isClosed()) {
1502
- cleanup();
1503
1442
  }
1504
1443
  });
1505
1444
  const onHandlerError = (err, span) => {
1506
1445
  const errorMsg = coerceErrorString(err);
1507
1446
  span.recordException(err instanceof Error ? err : new Error(errorMsg));
1508
1447
  span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
1509
- onServerAbort(
1510
- Err({
1511
- code: UNCAUGHT_ERROR_CODE,
1512
- message: errorMsg
1513
- })
1514
- );
1448
+ onServerCancel({
1449
+ code: UNCAUGHT_ERROR_CODE,
1450
+ message: errorMsg
1451
+ });
1515
1452
  };
1516
- if (isStreamCloseBackwardsCompat(controlFlags, protocolVersion)) {
1517
- reqReader.triggerClose();
1453
+ if (procClosesWithInit) {
1454
+ closeReadable();
1518
1455
  } else if (procedure.type === "rpc" || procedure.type === "subscription") {
1519
- this.log?.warn(`${procedure.type} sent an init without a stream close`, {
1456
+ this.log?.warn("sent an init without a stream close", {
1520
1457
  ...loggingMetadata,
1521
1458
  clientId: this.transport.clientId
1522
1459
  });
1523
1460
  }
1524
- const serviceContextWithTransportInfo = {
1525
- ...this.getContext(service, serviceName),
1461
+ const handlerContext = {
1462
+ ...serviceContext,
1526
1463
  from,
1527
1464
  sessionId,
1528
1465
  metadata: sessionMetadata,
1529
- abortController: handlerAbortController,
1530
- clientAbortSignal: clientAbortController.signal,
1531
- onRequestFinished: (cb) => {
1532
- if (reqReader.isClosed() && resWriter.isClosed()) {
1533
- try {
1534
- cb();
1535
- } catch {
1536
- }
1537
- return;
1538
- }
1539
- onFinishedCallbacks.push(cb);
1540
- }
1466
+ cancel: () => {
1467
+ onServerCancel({
1468
+ code: CANCEL_CODE,
1469
+ message: "cancelled by server procedure handler"
1470
+ });
1471
+ },
1472
+ signal: finishedController.signal
1541
1473
  };
1542
1474
  switch (procedure.type) {
1543
1475
  case "rpc":
@@ -1549,15 +1481,14 @@ var RiverServer = class {
1549
1481
  tracingCtx,
1550
1482
  async (span) => {
1551
1483
  try {
1552
- const outputMessage = await procedure.handler({
1553
- ctx: serviceContextWithTransportInfo,
1484
+ const responsePayload = await procedure.handler({
1485
+ ctx: handlerContext,
1554
1486
  reqInit: initPayload
1555
1487
  });
1556
- if (resWriter.isClosed()) {
1488
+ if (resWritable.isClosed()) {
1557
1489
  return;
1558
1490
  }
1559
- resWriter.write(outputMessage);
1560
- resWriter.close();
1491
+ resWritable.write(responsePayload);
1561
1492
  } catch (err) {
1562
1493
  onHandlerError(err, span);
1563
1494
  } finally {
@@ -1576,10 +1507,10 @@ var RiverServer = class {
1576
1507
  async (span) => {
1577
1508
  try {
1578
1509
  await procedure.handler({
1579
- ctx: serviceContextWithTransportInfo,
1510
+ ctx: handlerContext,
1580
1511
  reqInit: initPayload,
1581
- reqReader,
1582
- resWriter
1512
+ reqReadable,
1513
+ resWritable
1583
1514
  });
1584
1515
  } catch (err) {
1585
1516
  onHandlerError(err, span);
@@ -1599,9 +1530,9 @@ var RiverServer = class {
1599
1530
  async (span) => {
1600
1531
  try {
1601
1532
  await procedure.handler({
1602
- ctx: serviceContextWithTransportInfo,
1603
- reqInit: passInitAsDataForBackwardsCompat ? {} : initPayload,
1604
- resWriter
1533
+ ctx: handlerContext,
1534
+ reqInit: initPayload,
1535
+ resWritable
1605
1536
  });
1606
1537
  } catch (err) {
1607
1538
  onHandlerError(err, span);
@@ -1620,16 +1551,15 @@ var RiverServer = class {
1620
1551
  tracingCtx,
1621
1552
  async (span) => {
1622
1553
  try {
1623
- const outputMessage = await procedure.handler({
1624
- ctx: serviceContextWithTransportInfo,
1625
- reqInit: passInitAsDataForBackwardsCompat ? {} : initPayload,
1626
- reqReader
1554
+ const responsePayload = await procedure.handler({
1555
+ ctx: handlerContext,
1556
+ reqInit: initPayload,
1557
+ reqReadable
1627
1558
  });
1628
- if (resWriter.isClosed()) {
1559
+ if (resWritable.isClosed()) {
1629
1560
  return;
1630
1561
  }
1631
- resWriter.write(outputMessage);
1632
- resWriter.close();
1562
+ resWritable.write(responsePayload);
1633
1563
  } catch (err) {
1634
1564
  onHandlerError(err, span);
1635
1565
  } finally {
@@ -1638,16 +1568,8 @@ var RiverServer = class {
1638
1568
  }
1639
1569
  );
1640
1570
  break;
1641
- default:
1642
- this.log?.error(
1643
- `got request for invalid procedure type ${procedure.type} at ${serviceName}.${procedureName}`,
1644
- {
1645
- ...loggingMetadata,
1646
- tags: ["invariant-violation"]
1647
- }
1648
- );
1649
- return;
1650
1571
  }
1572
+ return procStream;
1651
1573
  }
1652
1574
  getContext(service, serviceName) {
1653
1575
  const context2 = this.contextMap.get(service);
@@ -1664,22 +1586,20 @@ var RiverServer = class {
1664
1586
  validateNewProcStream(initMessage) {
1665
1587
  const session = this.transport.sessions.get(initMessage.from);
1666
1588
  if (!session) {
1667
- const errMessage = `couldn't find a session for ${initMessage.from}`;
1668
1589
  this.log?.error(`couldn't find session for ${initMessage.from}`, {
1669
1590
  clientId: this.transport.clientId,
1670
1591
  transportMessage: initMessage,
1671
1592
  tags: ["invariant-violation"]
1672
1593
  });
1673
- this.abortStream(
1674
- initMessage.from,
1675
- initMessage.streamId,
1676
- Err({
1677
- code: INTERNAL_RIVER_ERROR_CODE,
1678
- message: errMessage
1679
- })
1680
- );
1681
1594
  return null;
1682
1595
  }
1596
+ const sessionScopedSend = this.transport.getSessionBoundSendFn(
1597
+ initMessage.from,
1598
+ session.id
1599
+ );
1600
+ const cancelStream = (streamId, payload) => {
1601
+ this.cancelStream(initMessage.from, sessionScopedSend, streamId, payload);
1602
+ };
1683
1603
  const sessionMetadata = this.transport.sessionHandshakeMetadata.get(
1684
1604
  session.to
1685
1605
  );
@@ -1689,11 +1609,10 @@ var RiverServer = class {
1689
1609
  ...session.loggingMetadata,
1690
1610
  tags: ["invariant-violation"]
1691
1611
  });
1692
- this.abortStream(
1693
- initMessage.from,
1612
+ cancelStream(
1694
1613
  initMessage.streamId,
1695
1614
  Err({
1696
- code: INTERNAL_RIVER_ERROR_CODE,
1615
+ code: UNCAUGHT_ERROR_CODE,
1697
1616
  message: errMessage
1698
1617
  })
1699
1618
  );
@@ -1707,8 +1626,7 @@ var RiverServer = class {
1707
1626
  transportMessage: initMessage,
1708
1627
  tags: ["invalid-request"]
1709
1628
  });
1710
- this.abortStream(
1711
- initMessage.from,
1629
+ cancelStream(
1712
1630
  initMessage.streamId,
1713
1631
  Err({
1714
1632
  code: INVALID_REQUEST_CODE,
@@ -1721,12 +1639,10 @@ var RiverServer = class {
1721
1639
  const errMessage = `missing service name in stream open message`;
1722
1640
  this.log?.warn(errMessage, {
1723
1641
  ...session.loggingMetadata,
1724
- clientId: this.transport.clientId,
1725
1642
  transportMessage: initMessage,
1726
1643
  tags: ["invalid-request"]
1727
1644
  });
1728
- this.abortStream(
1729
- initMessage.from,
1645
+ cancelStream(
1730
1646
  initMessage.streamId,
1731
1647
  Err({
1732
1648
  code: INVALID_REQUEST_CODE,
@@ -1739,12 +1655,10 @@ var RiverServer = class {
1739
1655
  const errMessage = `missing procedure name in stream open message`;
1740
1656
  this.log?.warn(errMessage, {
1741
1657
  ...session.loggingMetadata,
1742
- clientId: this.transport.clientId,
1743
1658
  transportMessage: initMessage,
1744
1659
  tags: ["invalid-request"]
1745
1660
  });
1746
- this.abortStream(
1747
- initMessage.from,
1661
+ cancelStream(
1748
1662
  initMessage.streamId,
1749
1663
  Err({
1750
1664
  code: INVALID_REQUEST_CODE,
@@ -1761,8 +1675,7 @@ var RiverServer = class {
1761
1675
  transportMessage: initMessage,
1762
1676
  tags: ["invalid-request"]
1763
1677
  });
1764
- this.abortStream(
1765
- initMessage.from,
1678
+ cancelStream(
1766
1679
  initMessage.streamId,
1767
1680
  Err({
1768
1681
  code: INVALID_REQUEST_CODE,
@@ -1776,12 +1689,10 @@ var RiverServer = class {
1776
1689
  const errMessage = `couldn't find a matching procedure for ${initMessage.serviceName}.${initMessage.procedureName}`;
1777
1690
  this.log?.warn(errMessage, {
1778
1691
  ...session.loggingMetadata,
1779
- clientId: this.transport.clientId,
1780
1692
  transportMessage: initMessage,
1781
1693
  tags: ["invalid-request"]
1782
1694
  });
1783
- this.abortStream(
1784
- initMessage.from,
1695
+ cancelStream(
1785
1696
  initMessage.streamId,
1786
1697
  Err({
1787
1698
  code: INVALID_REQUEST_CODE,
@@ -1790,7 +1701,19 @@ var RiverServer = class {
1790
1701
  );
1791
1702
  return null;
1792
1703
  }
1704
+ const serviceContext = this.getContext(service, initMessage.serviceName);
1793
1705
  const procedure = service.procedures[initMessage.procedureName];
1706
+ if (!["rpc", "upload", "stream", "subscription"].includes(procedure.type)) {
1707
+ this.log?.error(
1708
+ `got request for invalid procedure type ${procedure.type} at ${initMessage.serviceName}.${initMessage.procedureName}`,
1709
+ {
1710
+ ...session.loggingMetadata,
1711
+ transportMessage: initMessage,
1712
+ tags: ["invariant-violation"]
1713
+ }
1714
+ );
1715
+ return null;
1716
+ }
1794
1717
  let passInitAsDataForBackwardsCompat = false;
1795
1718
  if (session.protocolVersion === "v1.1" && (procedure.type === "upload" || procedure.type === "stream") && import_value2.Value.Check(procedure.requestData, initMessage.payload) && import_value2.Value.Check(procedure.requestInit, {})) {
1796
1719
  passInitAsDataForBackwardsCompat = true;
@@ -1802,8 +1725,7 @@ var RiverServer = class {
1802
1725
  transportMessage: initMessage,
1803
1726
  tags: ["invalid-request"]
1804
1727
  });
1805
- this.abortStream(
1806
- initMessage.from,
1728
+ cancelStream(
1807
1729
  initMessage.streamId,
1808
1730
  Err({
1809
1731
  code: INVALID_REQUEST_CODE,
@@ -1813,37 +1735,33 @@ var RiverServer = class {
1813
1735
  return null;
1814
1736
  }
1815
1737
  return {
1816
- sessionMetadata,
1817
- procedure,
1738
+ initialSession: session,
1739
+ streamId: initMessage.streamId,
1818
1740
  procedureName: initMessage.procedureName,
1819
- service,
1820
1741
  serviceName: initMessage.serviceName,
1821
- loggingMetadata: {
1822
- ...session.loggingMetadata,
1823
- transportMessage: initMessage
1824
- },
1825
- streamId: initMessage.streamId,
1826
- controlFlags: initMessage.controlFlags,
1827
1742
  tracingCtx: initMessage.tracing,
1828
1743
  initPayload: initMessage.payload,
1829
- from: initMessage.from,
1830
- sessionId: session.id,
1831
- protocolVersion: session.protocolVersion,
1744
+ sessionMetadata,
1745
+ procedure,
1746
+ serviceContext,
1747
+ procClosesWithInit: isStreamCloseBackwardsCompat(
1748
+ initMessage.controlFlags,
1749
+ session.protocolVersion
1750
+ ),
1832
1751
  passInitAsDataForBackwardsCompat
1833
1752
  };
1834
1753
  }
1835
- abortStream(to, streamId, payload) {
1836
- let abortedForSession = this.serverAbortedStreams.get(to);
1837
- if (!abortedForSession) {
1838
- abortedForSession = new LRUSet(this.maxAbortedStreamTombstonesPerSession);
1839
- this.serverAbortedStreams.set(to, abortedForSession);
1754
+ cancelStream(to, sessionScopedSend, streamId, payload) {
1755
+ let cancelledStreamsInSession = this.serverCancelledStreams.get(to);
1756
+ if (!cancelledStreamsInSession) {
1757
+ cancelledStreamsInSession = new LRUSet(
1758
+ this.maxCancelledStreamTombstonesPerSession
1759
+ );
1760
+ this.serverCancelledStreams.set(to, cancelledStreamsInSession);
1840
1761
  }
1841
- abortedForSession.add(streamId);
1842
- this.transport.send(
1843
- to,
1844
- // TODO remove once clients migrate to v2
1845
- this.transport.sessions.get(to)?.protocolVersion === "v1.1" ? closeStreamMessage(streamId) : abortMessage(streamId, payload)
1846
- );
1762
+ cancelledStreamsInSession.add(streamId);
1763
+ const msg = cancelMessage(streamId, payload);
1764
+ sessionScopedSend(msg);
1847
1765
  }
1848
1766
  };
1849
1767
  var LRUSet = class {
@@ -1868,21 +1786,21 @@ var LRUSet = class {
1868
1786
  return this.items.has(item);
1869
1787
  }
1870
1788
  };
1871
- function isStreamAbortBackwardsCompat(controlFlags, protocolVersion) {
1789
+ function isStreamCancelBackwardsCompat(controlFlags, protocolVersion) {
1872
1790
  if (protocolVersion === "v1.1") {
1873
1791
  return false;
1874
1792
  }
1875
- return isStreamAbort(controlFlags);
1793
+ return isStreamCancel(controlFlags);
1876
1794
  }
1877
1795
  function isStreamCloseBackwardsCompat(controlFlags, protocolVersion) {
1878
1796
  if (protocolVersion === "v1.1") {
1879
- return isStreamAbort(controlFlags);
1797
+ return isStreamCancel(controlFlags);
1880
1798
  }
1881
1799
  return isStreamClose(controlFlags);
1882
1800
  }
1883
1801
  function getStreamCloseBackwardsCompat(protocolVersion) {
1884
1802
  if (protocolVersion === "v1.1") {
1885
- return 4 /* StreamAbortBit */;
1803
+ return 4 /* StreamCancelBit */;
1886
1804
  }
1887
1805
  return 8 /* StreamClosedBit */;
1888
1806
  }
@@ -1892,7 +1810,7 @@ function createServer(transport, services, providedServerOptions) {
1892
1810
  services,
1893
1811
  providedServerOptions?.handshakeOptions,
1894
1812
  providedServerOptions?.extendedContext,
1895
- providedServerOptions?.maxAbortedStreamTombstonesPerSession
1813
+ providedServerOptions?.maxCancelledStreamTombstonesPerSession
1896
1814
  );
1897
1815
  }
1898
1816
 
@@ -1905,15 +1823,13 @@ function createServerHandshakeOptions(schema, validate) {
1905
1823
  }
1906
1824
  // Annotate the CommonJS export names for ESM import in node:
1907
1825
  0 && (module.exports = {
1908
- ABORT_CODE,
1826
+ CANCEL_CODE,
1909
1827
  Err,
1910
- INTERNAL_RIVER_ERROR_CODE,
1911
1828
  INVALID_REQUEST_CODE,
1912
1829
  Ok,
1913
1830
  Procedure,
1914
1831
  RIVER_VERSION,
1915
- RequestReaderErrorSchema,
1916
- ResponseReaderErrorSchema,
1832
+ ReaderErrorSchema,
1917
1833
  ServiceSchema,
1918
1834
  UNCAUGHT_ERROR_CODE,
1919
1835
  UNEXPECTED_DISCONNECT_CODE,
@@ -1921,6 +1837,9 @@ function createServerHandshakeOptions(schema, validate) {
1921
1837
  createClientHandshakeOptions,
1922
1838
  createServer,
1923
1839
  createServerHandshakeOptions,
1924
- serializeSchema
1840
+ flattenErrorType,
1841
+ serializeSchema,
1842
+ serializeSchemaV1Compat,
1843
+ unwrapOrThrow
1925
1844
  });
1926
1845
  //# sourceMappingURL=index.cjs.map