@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
@@ -1,39 +1,49 @@
1
1
  import {
2
- ABORT_CODE,
3
2
  AnyResultSchema,
3
+ CANCEL_CODE,
4
4
  Err,
5
5
  ErrResultSchema,
6
- INTERNAL_RIVER_ERROR_CODE,
7
6
  INVALID_REQUEST_CODE,
8
7
  Ok,
9
- Procedure,
10
- ReadStreamImpl,
11
- RequestReaderErrorSchema,
12
- ResponseReaderErrorSchema,
8
+ ReadableImpl,
9
+ ReaderErrorSchema,
13
10
  UNCAUGHT_ERROR_CODE,
14
11
  UNEXPECTED_DISCONNECT_CODE,
15
- WriteStreamImpl
16
- } from "../chunk-MQ6ANR3H.js";
12
+ WritableImpl,
13
+ flattenErrorType,
14
+ unwrapOrThrow
15
+ } from "../chunk-MADS7AI5.js";
17
16
  import {
18
17
  ControlMessageCloseSchema,
19
18
  ControlMessagePayloadSchema,
20
- abortMessage,
19
+ cancelMessage,
21
20
  closeStreamMessage,
22
21
  coerceErrorString,
23
22
  createHandlerSpan,
24
23
  createProcTelemetryInfo,
25
24
  generateId,
26
25
  getPropagationContext,
27
- isStreamAbort,
26
+ isStreamCancel,
28
27
  isStreamClose,
29
- isStreamCloseRequest,
30
28
  isStreamOpen,
31
- requestCloseStreamMessage,
32
29
  version
33
- } from "../chunk-EETL2L77.js";
30
+ } from "../chunk-UQHYJZTP.js";
34
31
 
35
32
  // router/services.ts
36
33
  import { Type } from "@sinclair/typebox";
34
+ function serializeSchemaV1Compat(services, handshakeSchema) {
35
+ const serializedServiceObject = Object.entries(services).reduce((acc, [name, value]) => {
36
+ acc[name] = value.serializeV1Compat();
37
+ return acc;
38
+ }, {});
39
+ const schema = {
40
+ services: serializedServiceObject
41
+ };
42
+ if (handshakeSchema) {
43
+ schema.handshakeSchema = Type.Strict(handshakeSchema);
44
+ }
45
+ return schema;
46
+ }
37
47
  function serializeSchema(services, handshakeSchema) {
38
48
  const serializedServiceObject = Object.entries(services).reduce((acc, [name, value]) => {
39
49
  acc[name] = value.serialize();
@@ -170,7 +180,7 @@ var ServiceSchema = class _ServiceSchema {
170
180
  * protocol v1. This is useful to be able to continue to generate schemas for older
171
181
  * clients as they are still supported.
172
182
  */
173
- serializeBackwardsCompatible() {
183
+ serializeV1Compat() {
174
184
  return {
175
185
  procedures: Object.fromEntries(
176
186
  Object.entries(this.procedures).map(
@@ -283,9 +293,86 @@ var ServiceScaffold = class {
283
293
  }
284
294
  };
285
295
 
296
+ // router/procedures.ts
297
+ import { Type as Type2 } from "@sinclair/typebox";
298
+ function rpc({
299
+ requestInit,
300
+ responseData,
301
+ responseError = Type2.Never(),
302
+ description,
303
+ handler
304
+ }) {
305
+ return {
306
+ ...description ? { description } : {},
307
+ type: "rpc",
308
+ requestInit,
309
+ responseData,
310
+ responseError,
311
+ handler
312
+ };
313
+ }
314
+ function upload({
315
+ requestInit,
316
+ requestData,
317
+ responseData,
318
+ responseError = Type2.Never(),
319
+ description,
320
+ handler
321
+ }) {
322
+ return {
323
+ type: "upload",
324
+ ...description ? { description } : {},
325
+ requestInit,
326
+ requestData,
327
+ responseData,
328
+ responseError,
329
+ handler
330
+ };
331
+ }
332
+ function subscription({
333
+ requestInit,
334
+ responseData,
335
+ responseError = Type2.Never(),
336
+ description,
337
+ handler
338
+ }) {
339
+ return {
340
+ type: "subscription",
341
+ ...description ? { description } : {},
342
+ requestInit,
343
+ responseData,
344
+ responseError,
345
+ handler
346
+ };
347
+ }
348
+ function stream({
349
+ requestInit,
350
+ requestData,
351
+ responseData,
352
+ responseError = Type2.Never(),
353
+ description,
354
+ handler
355
+ }) {
356
+ return {
357
+ type: "stream",
358
+ ...description ? { description } : {},
359
+ requestInit,
360
+ requestData,
361
+ responseData,
362
+ responseError,
363
+ handler
364
+ };
365
+ }
366
+ var Procedure = {
367
+ rpc,
368
+ upload,
369
+ subscription,
370
+ stream
371
+ };
372
+
286
373
  // router/client.ts
287
374
  import { Value } from "@sinclair/typebox/value";
288
- var OutputErrResultSchema = ErrResultSchema(ResponseReaderErrorSchema);
375
+ var ReaderErrResultSchema = ErrResultSchema(ReaderErrorSchema);
289
376
  var noop = () => {
290
377
  };
291
378
  function _createRecursiveProxy(callback, path) {
@@ -346,6 +433,11 @@ function createClient(transport, serverId, providedClientOptions = {}) {
346
433
  }, []);
347
434
  }
348
435
  function handleProc(procType, transport, serverId, init, serviceName, procedureName, abortSignal) {
436
+ const session = transport.sessions.get(serverId) ?? transport.createUnconnectedSession(serverId);
437
+ const sessionScopedSend = transport.getSessionBoundSendFn(
438
+ serverId,
439
+ session.id
440
+ );
349
441
  const procClosesWithInit = procType === "rpc" || procType === "subscription";
350
442
  const streamId = generateId();
351
443
  const { span, ctx } = createProcTelemetryInfo(
@@ -356,61 +448,61 @@ function handleProc(procType, transport, serverId, init, serviceName, procedureN
356
448
  streamId
357
449
  );
358
450
  let cleanClose = true;
359
- const reqWriter = new WriteStreamImpl((rawIn) => {
360
- transport.send(serverId, {
361
- streamId,
362
- payload: rawIn,
363
- controlFlags: 0,
364
- tracing: getPropagationContext(ctx)
365
- });
366
- });
367
- reqWriter.onClose(() => {
368
- span.addEvent("reqWriter closed");
369
- if (!procClosesWithInit && cleanClose) {
370
- transport.send(serverId, closeStreamMessage(streamId));
371
- }
372
- if (resReader.isClosed()) {
373
- cleanup();
451
+ const reqWritable = new WritableImpl({
452
+ writeCb: (rawIn) => {
453
+ sessionScopedSend({
454
+ streamId,
455
+ payload: rawIn,
456
+ controlFlags: 0
457
+ });
458
+ },
459
+ // close callback
460
+ closeCb: () => {
461
+ span.addEvent("reqWritable closed");
462
+ if (!procClosesWithInit && cleanClose) {
463
+ sessionScopedSend(closeStreamMessage(streamId));
464
+ }
465
+ if (resReadable.isClosed()) {
466
+ cleanup();
467
+ }
374
468
  }
375
469
  });
376
- const resReader = new ReadStreamImpl(() => {
377
- transport.send(serverId, requestCloseStreamMessage(streamId));
378
- });
379
- resReader.onClose(() => {
380
- span.addEvent("resReader closed");
381
- if (reqWriter.isClosed()) {
470
+ const resReadable = new ReadableImpl();
471
+ const closeReadable = () => {
472
+ resReadable._triggerClose();
473
+ span.addEvent("resReadable closed");
474
+ if (reqWritable.isClosed()) {
382
475
  cleanup();
383
476
  }
384
- });
477
+ };
385
478
  function cleanup() {
386
479
  transport.removeEventListener("message", onMessage);
387
480
  transport.removeEventListener("sessionStatus", onSessionStatus);
388
- abortSignal?.removeEventListener("abort", onClientAbort);
481
+ abortSignal?.removeEventListener("abort", onClientCancel);
389
482
  span.end();
390
483
  }
391
- function onClientAbort() {
392
- if (resReader.isClosed() && reqWriter.isClosed()) {
484
+ function onClientCancel() {
485
+ if (resReadable.isClosed() && reqWritable.isClosed()) {
393
486
  return;
394
487
  }
395
- span.addEvent("sending abort");
488
+ span.addEvent("sending cancel");
396
489
  cleanClose = false;
397
- if (!resReader.isClosed()) {
398
- resReader.pushValue(
490
+ if (!resReadable.isClosed()) {
491
+ resReadable._pushValue(
399
492
  Err({
400
- code: ABORT_CODE,
401
- message: "Aborted by client"
493
+ code: CANCEL_CODE,
494
+ message: "cancelled by client"
402
495
  })
403
496
  );
404
- resReader.triggerClose();
497
+ closeReadable();
405
498
  }
406
- reqWriter.close();
407
- transport.send(
408
- serverId,
409
- abortMessage(
499
+ reqWritable.close();
500
+ sessionScopedSend(
501
+ cancelMessage(
410
502
  streamId,
411
503
  Err({
412
- code: ABORT_CODE,
413
- message: "Aborted by client"
504
+ code: CANCEL_CODE,
505
+ message: "cancelled by client"
414
506
  })
415
507
  )
416
508
  );
@@ -419,47 +511,44 @@ function handleProc(procType, transport, serverId, init, serviceName, procedureN
419
511
  if (msg.streamId !== streamId)
420
512
  return;
421
513
  if (msg.to !== transport.clientId) {
422
- transport.log?.error("Got stream message from unexpected client", {
514
+ transport.log?.error("got stream message from unexpected client", {
423
515
  clientId: transport.clientId,
424
516
  transportMessage: msg
425
517
  });
426
518
  return;
427
519
  }
428
- if (isStreamCloseRequest(msg.controlFlags)) {
429
- reqWriter.triggerCloseRequest();
430
- }
431
- if (isStreamAbort(msg.controlFlags)) {
520
+ if (isStreamCancel(msg.controlFlags)) {
432
521
  cleanClose = false;
433
- span.addEvent("received abort");
434
- let abortResult;
435
- if (Value.Check(OutputErrResultSchema, msg.payload)) {
436
- abortResult = msg.payload;
522
+ span.addEvent("received cancel");
523
+ let cancelResult;
524
+ if (Value.Check(ReaderErrResultSchema, msg.payload)) {
525
+ cancelResult = msg.payload;
437
526
  } else {
438
- abortResult = Err({
439
- code: ABORT_CODE,
440
- message: "Stream aborted with invalid payload"
527
+ cancelResult = Err({
528
+ code: CANCEL_CODE,
529
+ message: "stream cancelled with invalid payload"
441
530
  });
442
531
  transport.log?.error(
443
- "Got stream abort without a valid protocol error",
532
+ "got stream cancel without a valid protocol error",
444
533
  {
445
534
  clientId: transport.clientId,
446
535
  transportMessage: msg,
447
536
  validationErrors: [
448
- ...Value.Errors(OutputErrResultSchema, msg.payload)
537
+ ...Value.Errors(ReaderErrResultSchema, msg.payload)
449
538
  ]
450
539
  }
451
540
  );
452
541
  }
453
- if (!resReader.isClosed()) {
454
- resReader.pushValue(abortResult);
455
- resReader.triggerClose();
542
+ if (!resReadable.isClosed()) {
543
+ resReadable._pushValue(cancelResult);
544
+ closeReadable();
456
545
  }
457
- reqWriter.close();
546
+ reqWritable.close();
458
547
  return;
459
548
  }
460
- if (resReader.isClosed()) {
461
- span.recordException("Received message after output stream is closed");
462
- transport.log?.error("Received message after output stream is closed", {
549
+ if (resReadable.isClosed()) {
550
+ span.recordException("received message after response stream is closed");
551
+ transport.log?.error("received message after response stream is closed", {
463
552
  clientId: transport.clientId,
464
553
  transportMessage: msg
465
554
  });
@@ -467,7 +556,7 @@ function handleProc(procType, transport, serverId, init, serviceName, procedureN
467
556
  }
468
557
  if (!Value.Check(ControlMessageCloseSchema, msg.payload)) {
469
558
  if (Value.Check(AnyResultSchema, msg.payload)) {
470
- resReader.pushValue(msg.payload);
559
+ resReadable._pushValue(msg.payload);
471
560
  } else {
472
561
  transport.log?.error(
473
562
  "Got non-control payload, but was not a valid result",
@@ -480,33 +569,36 @@ function handleProc(procType, transport, serverId, init, serviceName, procedureN
480
569
  }
481
570
  }
482
571
  if (isStreamClose(msg.controlFlags)) {
483
- span.addEvent("received output close");
484
- resReader.triggerClose();
572
+ span.addEvent("received response close");
573
+ if (resReadable.isClosed()) {
574
+ transport.log?.error(
575
+ "received stream close but readable was already closed"
576
+ );
577
+ } else {
578
+ closeReadable();
579
+ }
485
580
  }
486
581
  }
487
582
  function onSessionStatus(evt) {
488
- if (evt.status !== "disconnect") {
489
- return;
490
- }
491
- if (evt.session.to !== serverId) {
583
+ if (evt.status !== "disconnect" || evt.session.to !== serverId || session.id !== evt.session.id) {
492
584
  return;
493
585
  }
494
586
  cleanClose = false;
495
- if (!resReader.isClosed()) {
496
- resReader.pushValue(
587
+ if (!resReadable.isClosed()) {
588
+ resReadable._pushValue(
497
589
  Err({
498
590
  code: UNEXPECTED_DISCONNECT_CODE,
499
591
  message: `${serverId} unexpectedly disconnected`
500
592
  })
501
593
  );
594
+ closeReadable();
502
595
  }
503
- reqWriter.close();
504
- resReader.triggerClose();
596
+ reqWritable.close();
505
597
  }
506
- abortSignal?.addEventListener("abort", onClientAbort);
598
+ abortSignal?.addEventListener("abort", onClientCancel);
507
599
  transport.addEventListener("message", onMessage);
508
600
  transport.addEventListener("sessionStatus", onSessionStatus);
509
- transport.send(serverId, {
601
+ sessionScopedSend({
510
602
  streamId,
511
603
  serviceName,
512
604
  procedureName,
@@ -515,34 +607,39 @@ function handleProc(procType, transport, serverId, init, serviceName, procedureN
515
607
  controlFlags: procClosesWithInit ? 2 /* StreamOpenBit */ | 8 /* StreamClosedBit */ : 2 /* StreamOpenBit */
516
608
  });
517
609
  if (procClosesWithInit) {
518
- reqWriter.close();
610
+ reqWritable.close();
519
611
  }
520
612
  if (procType === "subscription") {
521
- return { resReader };
613
+ return {
614
+ resReadable
615
+ };
522
616
  }
523
617
  if (procType === "rpc") {
524
- return getSingleMessage(resReader, transport.log);
618
+ return getSingleMessage(resReadable, transport.log);
525
619
  }
526
620
  if (procType === "upload") {
527
621
  let didFinalize = false;
528
622
  return {
529
- reqWriter,
530
- async finalize() {
623
+ reqWritable,
624
+ finalize: () => {
531
625
  if (didFinalize) {
532
626
  throw new Error("upload stream already finalized");
533
627
  }
534
628
  didFinalize = true;
535
- if (!reqWriter.isClosed()) {
536
- reqWriter.close();
629
+ if (!reqWritable.isClosed()) {
630
+ reqWritable.close();
537
631
  }
538
- return getSingleMessage(resReader, transport.log);
632
+ return getSingleMessage(resReadable, transport.log);
539
633
  }
540
634
  };
541
635
  }
542
- return { reqWriter, resReader };
636
+ return {
637
+ resReadable,
638
+ reqWritable
639
+ };
543
640
  }
544
- async function getSingleMessage(resReader, log) {
545
- const ret = await resReader.asArray();
641
+ async function getSingleMessage(resReadable, log) {
642
+ const ret = await resReadable.collect();
546
643
  if (ret.length > 1) {
547
644
  log?.error("Expected single message from server, got multiple");
548
645
  }
@@ -550,25 +647,31 @@ async function getSingleMessage(resReader, log) {
550
647
  }
551
648
 
552
649
  // router/server.ts
650
+ import { Type as Type3 } from "@sinclair/typebox";
553
651
  import { Value as Value2 } from "@sinclair/typebox/value";
554
652
  import { SpanStatusCode } from "@opentelemetry/api";
555
- var InputErrResultSchema = ErrResultSchema(RequestReaderErrorSchema);
653
+ var CancelResultSchema = ErrResultSchema(
654
+ Type3.Object({
655
+ code: Type3.Literal(CANCEL_CODE),
656
+ message: Type3.String()
657
+ })
658
+ );
556
659
  var RiverServer = class {
557
660
  transport;
558
661
  contextMap;
559
662
  log;
560
663
  /**
561
- * We create a tombstones for streams aborted by the server
664
+ * We create a tombstones for streams cancelled by the server
562
665
  * so that we don't hit errors when the client has inflight
563
- * requests it sent before it saw the abort.
564
- * We track aborted streams for every session separately, so
666
+ * requests it sent before it saw the cancel.
667
+ * We track cancelled streams for every client separately, so
565
668
  * that bad clients don't affect good clients.
566
669
  */
567
- serverAbortedStreams;
568
- maxAbortedStreamTombstonesPerSession;
569
- openStreams;
670
+ serverCancelledStreams;
671
+ maxCancelledStreamTombstonesPerSession;
672
+ streams;
570
673
  services;
571
- constructor(transport, services, handshakeOptions, extendedContext, maxAbortedStreamTombstonesPerSession = 200) {
674
+ constructor(transport, services, handshakeOptions, extendedContext, maxCancelledStreamTombstonesPerSession = 200) {
572
675
  const instances = {};
573
676
  this.services = instances;
574
677
  this.contextMap = /* @__PURE__ */ new Map();
@@ -584,34 +687,40 @@ var RiverServer = class {
584
687
  transport.extendHandshake(handshakeOptions);
585
688
  }
586
689
  this.transport = transport;
587
- this.openStreams = /* @__PURE__ */ new Set();
588
- this.serverAbortedStreams = /* @__PURE__ */ new Map();
589
- this.maxAbortedStreamTombstonesPerSession = maxAbortedStreamTombstonesPerSession;
690
+ this.streams = /* @__PURE__ */ new Map();
691
+ this.serverCancelledStreams = /* @__PURE__ */ new Map();
692
+ this.maxCancelledStreamTombstonesPerSession = maxCancelledStreamTombstonesPerSession;
590
693
  this.log = transport.log;
591
- const handleMessage = (msg) => {
592
- if (msg.to !== this.transport.clientId) {
694
+ const handleCreatingNewStreams = (message) => {
695
+ if (message.to !== this.transport.clientId) {
593
696
  this.log?.info(
594
697
  `got msg with destination that isn't this server, ignoring`,
595
698
  {
596
699
  clientId: this.transport.clientId,
597
- transportMessage: msg
700
+ transportMessage: message
598
701
  }
599
702
  );
600
703
  return;
601
704
  }
602
- if (this.openStreams.has(msg.streamId)) {
705
+ const streamId = message.streamId;
706
+ const stream2 = this.streams.get(streamId);
707
+ if (stream2) {
708
+ stream2.handleMsg(message);
603
709
  return;
604
710
  }
605
- if (this.serverAbortedStreams.get(msg.from)?.has(msg.streamId)) {
711
+ if (this.serverCancelledStreams.get(message.from)?.has(streamId)) {
606
712
  return;
607
713
  }
608
- const validated = this.validateNewProcStream(msg);
609
- if (!validated) {
714
+ const newStreamProps = this.validateNewProcStream(message);
715
+ if (!newStreamProps) {
610
716
  return;
611
717
  }
612
- this.createNewProcStream(validated);
718
+ const newStream = this.createNewProcStream({
719
+ ...newStreamProps,
720
+ ...message
721
+ });
722
+ this.streams.set(streamId, newStream);
613
723
  };
614
- this.transport.addEventListener("message", handleMessage);
615
724
  const handleSessionStatus = (evt) => {
616
725
  if (evt.status !== "disconnect")
617
726
  return;
@@ -620,256 +729,248 @@ var RiverServer = class {
620
729
  `got session disconnect from ${disconnectedClientId}, cleaning up streams`,
621
730
  evt.session.loggingMetadata
622
731
  );
623
- this.serverAbortedStreams.delete(disconnectedClientId);
732
+ for (const stream2 of this.streams.values()) {
733
+ if (stream2.from === disconnectedClientId) {
734
+ stream2.handleSessionDisconnect();
735
+ }
736
+ }
737
+ this.serverCancelledStreams.delete(disconnectedClientId);
624
738
  };
625
- this.transport.addEventListener("sessionStatus", handleSessionStatus);
626
- this.transport.addEventListener("transportStatus", (evt) => {
739
+ const handleTransportStatus = (evt) => {
627
740
  if (evt.status !== "closed")
628
741
  return;
629
- this.transport.removeEventListener("message", handleMessage);
742
+ this.transport.removeEventListener("message", handleCreatingNewStreams);
630
743
  this.transport.removeEventListener("sessionStatus", handleSessionStatus);
631
- });
632
- }
633
- createNewProcStream({
634
- procedure,
635
- procedureName,
636
- service,
637
- serviceName,
638
- sessionMetadata,
639
- loggingMetadata,
640
- streamId,
641
- controlFlags,
642
- initPayload,
643
- from,
644
- sessionId,
645
- tracingCtx,
646
- protocolVersion,
647
- passInitAsDataForBackwardsCompat
648
- }) {
649
- this.openStreams.add(streamId);
650
- let cleanClose = true;
651
- const onServerAbort = (errResult) => {
652
- if (reqReader.isClosed() && resWriter.isClosed()) {
653
- return;
654
- }
655
- cleanClose = false;
656
- if (!reqReader.isClosed()) {
657
- reqReader.pushValue(errResult);
658
- reqReader.triggerClose();
659
- }
660
- resWriter.close();
661
- this.abortStream(from, streamId, errResult);
662
- };
663
- const onHandlerAbort = () => {
664
- onServerAbort(
665
- Err({
666
- code: ABORT_CODE,
667
- message: "Aborted by server procedure handler"
668
- })
744
+ this.transport.removeEventListener(
745
+ "transportStatus",
746
+ handleTransportStatus
669
747
  );
670
748
  };
671
- const handlerAbortController = new AbortController();
672
- handlerAbortController.signal.addEventListener("abort", onHandlerAbort);
673
- const clientAbortController = new AbortController();
674
- const onSessionStatus = (evt) => {
675
- if (evt.status !== "disconnect") {
676
- return;
677
- }
678
- if (evt.session.to !== from) {
679
- return;
680
- }
681
- cleanClose = false;
682
- const errPayload = {
683
- code: UNEXPECTED_DISCONNECT_CODE,
684
- message: `client unexpectedly disconnected`
685
- };
686
- if (!reqReader.isClosed()) {
687
- reqReader.pushValue(Err(errPayload));
688
- reqReader.triggerClose();
689
- }
690
- clientAbortController.abort(errPayload);
691
- resWriter.close();
692
- };
693
- this.transport.addEventListener("sessionStatus", onSessionStatus);
749
+ this.transport.addEventListener("message", handleCreatingNewStreams);
750
+ this.transport.addEventListener("sessionStatus", handleSessionStatus);
751
+ this.transport.addEventListener("transportStatus", handleTransportStatus);
752
+ }
753
+ createNewProcStream(props) {
754
+ const {
755
+ streamId,
756
+ initialSession,
757
+ procedureName,
758
+ serviceName,
759
+ procedure,
760
+ sessionMetadata,
761
+ serviceContext,
762
+ initPayload,
763
+ tracingCtx,
764
+ procClosesWithInit,
765
+ passInitAsDataForBackwardsCompat
766
+ } = props;
767
+ const {
768
+ to: from,
769
+ loggingMetadata,
770
+ protocolVersion,
771
+ id: sessionId
772
+ } = initialSession;
773
+ let cleanClose = true;
694
774
  const onMessage = (msg) => {
695
- if (streamId !== msg.streamId) {
696
- return;
697
- }
698
775
  if (msg.from !== from) {
699
- this.log?.error("Got stream message from unexpected client", {
776
+ this.log?.error("got stream message from unexpected client", {
700
777
  ...loggingMetadata,
701
- clientId: this.transport.clientId,
702
778
  transportMessage: msg,
703
779
  tags: ["invariant-violation"]
704
780
  });
705
781
  return;
706
782
  }
707
- if (isStreamCloseRequest(msg.controlFlags)) {
708
- resWriter.triggerCloseRequest();
709
- }
710
- if (isStreamAbortBackwardsCompat(msg.controlFlags, protocolVersion)) {
711
- let abortResult;
712
- if (Value2.Check(InputErrResultSchema, msg.payload)) {
713
- abortResult = msg.payload;
783
+ if (isStreamCancelBackwardsCompat(msg.controlFlags, protocolVersion)) {
784
+ let cancelResult;
785
+ if (Value2.Check(CancelResultSchema, msg.payload)) {
786
+ cancelResult = msg.payload;
714
787
  } else {
715
- abortResult = Err({
716
- code: ABORT_CODE,
717
- message: "Stream aborted, client sent invalid payload"
788
+ cancelResult = Err({
789
+ code: CANCEL_CODE,
790
+ message: "stream cancelled, client sent invalid payload"
718
791
  });
719
- this.log?.warn("Got stream abort without a valid protocol error", {
792
+ this.log?.warn("got stream cancel without a valid protocol error", {
720
793
  ...loggingMetadata,
721
- clientId: this.transport.clientId,
722
794
  transportMessage: msg,
723
795
  validationErrors: [
724
- ...Value2.Errors(InputErrResultSchema, msg.payload)
796
+ ...Value2.Errors(CancelResultSchema, msg.payload)
725
797
  ],
726
798
  tags: ["invalid-request"]
727
799
  });
728
800
  }
729
- if (!reqReader.isClosed()) {
730
- reqReader.pushValue(abortResult);
731
- reqReader.triggerClose();
801
+ if (!reqReadable.isClosed()) {
802
+ reqReadable._pushValue(cancelResult);
803
+ closeReadable();
732
804
  }
733
- resWriter.close();
734
- clientAbortController.abort(abortResult.payload);
805
+ resWritable.close();
735
806
  return;
736
807
  }
737
- if (reqReader.isClosed()) {
738
- this.log?.warn("Received message after input stream is closed", {
808
+ if (reqReadable.isClosed()) {
809
+ this.log?.warn("received message after request stream is closed", {
739
810
  ...loggingMetadata,
740
- clientId: this.transport.clientId,
741
811
  transportMessage: msg,
742
812
  tags: ["invalid-request"]
743
813
  });
744
- onServerAbort(
745
- Err({
746
- code: INVALID_REQUEST_CODE,
747
- message: "Received message after input stream is closed"
748
- })
749
- );
814
+ onServerCancel({
815
+ code: INVALID_REQUEST_CODE,
816
+ message: "received message after request stream is closed"
817
+ });
750
818
  return;
751
819
  }
752
820
  if ("requestData" in procedure && Value2.Check(procedure.requestData, msg.payload)) {
753
- reqReader.pushValue(Ok(msg.payload));
754
- } else if (!Value2.Check(ControlMessagePayloadSchema, msg.payload)) {
755
- const validationErrors = [
821
+ reqReadable._pushValue(Ok(msg.payload));
822
+ if (isStreamCloseBackwardsCompat(msg.controlFlags, protocolVersion)) {
823
+ closeReadable();
824
+ }
825
+ return;
826
+ }
827
+ if (Value2.Check(ControlMessagePayloadSchema, msg.payload) && isStreamCloseBackwardsCompat(msg.controlFlags, protocolVersion)) {
828
+ closeReadable();
829
+ return;
830
+ }
831
+ let validationErrors;
832
+ let errMessage;
833
+ if ("requestData" in procedure) {
834
+ errMessage = "expected requestData or control payload";
835
+ validationErrors = [
836
+ ...Value2.Errors(procedure.responseData, msg.payload)
837
+ ];
838
+ } else {
839
+ validationErrors = [
756
840
  ...Value2.Errors(ControlMessagePayloadSchema, msg.payload)
757
841
  ];
758
- let errMessage = "Expected control payload for procedure with no input";
759
- if ("requestData" in procedure) {
760
- errMessage = "Expected either control or input payload, validation failed for both";
761
- validationErrors.push(
762
- ...Value2.Errors(procedure.responseData, msg.payload)
763
- );
842
+ errMessage = "expected control payload";
843
+ }
844
+ this.log?.warn(errMessage, {
845
+ ...loggingMetadata,
846
+ transportMessage: msg,
847
+ validationErrors,
848
+ tags: ["invalid-request"]
849
+ });
850
+ onServerCancel({
851
+ code: INVALID_REQUEST_CODE,
852
+ message: errMessage
853
+ });
854
+ };
855
+ const procStream = {
856
+ from,
857
+ streamId,
858
+ procedureName,
859
+ serviceName,
860
+ sessionMetadata,
861
+ procedure,
862
+ handleMsg: onMessage,
863
+ handleSessionDisconnect: () => {
864
+ cleanClose = false;
865
+ const errPayload = {
866
+ code: UNEXPECTED_DISCONNECT_CODE,
867
+ message: "client unexpectedly disconnected"
868
+ };
869
+ if (!reqReadable.isClosed()) {
870
+ reqReadable._pushValue(Err(errPayload));
871
+ closeReadable();
764
872
  }
765
- this.log?.warn(errMessage, {
766
- ...loggingMetadata,
767
- clientId: this.transport.clientId,
768
- transportMessage: msg,
769
- validationErrors,
770
- tags: ["invalid-request"]
771
- });
772
- onServerAbort(
773
- Err({
774
- code: INVALID_REQUEST_CODE,
775
- message: errMessage
776
- })
777
- );
873
+ resWritable.close();
778
874
  }
779
- if (isStreamCloseBackwardsCompat(msg.controlFlags, protocolVersion)) {
780
- reqReader.triggerClose();
875
+ };
876
+ const sessionScopedSend = this.transport.getSessionBoundSendFn(
877
+ from,
878
+ sessionId
879
+ );
880
+ const cancelStream = (streamId2, payload) => {
881
+ this.cancelStream(from, sessionScopedSend, streamId2, payload);
882
+ };
883
+ const onServerCancel = (e) => {
884
+ if (reqReadable.isClosed() && resWritable.isClosed()) {
885
+ return;
781
886
  }
887
+ cleanClose = false;
888
+ const result = Err(e);
889
+ if (!reqReadable.isClosed()) {
890
+ reqReadable._pushValue(result);
891
+ closeReadable();
892
+ }
893
+ resWritable.close();
894
+ cancelStream(streamId, result);
782
895
  };
783
- this.transport.addEventListener("message", onMessage);
784
- const onFinishedCallbacks = [];
896
+ const finishedController = new AbortController();
785
897
  const cleanup = () => {
786
- this.transport.removeEventListener("message", onMessage);
787
- this.transport.removeEventListener("sessionStatus", onSessionStatus);
788
- handlerAbortController.signal.addEventListener("abort", onHandlerAbort);
789
- this.openStreams.delete(streamId);
790
- onFinishedCallbacks.forEach((cb) => {
791
- try {
792
- cb();
793
- } catch {
794
- }
795
- });
796
- onFinishedCallbacks.length = 0;
898
+ finishedController.abort();
899
+ this.streams.delete(streamId);
797
900
  };
798
901
  const procClosesWithResponse = procedure.type === "rpc" || procedure.type === "upload";
799
- const reqReader = new ReadStreamImpl(() => {
800
- this.transport.send(from, requestCloseStreamMessage(streamId));
801
- });
802
- reqReader.onClose(() => {
902
+ const reqReadable = new ReadableImpl();
903
+ const closeReadable = () => {
904
+ reqReadable._triggerClose();
803
905
  if (protocolVersion === "v1.1") {
804
- if (!procClosesWithResponse && !resWriter.isClosed()) {
805
- resWriter.close();
906
+ if (!procClosesWithResponse && !resWritable.isClosed()) {
907
+ resWritable.close();
806
908
  }
807
909
  }
808
- if (resWriter.isClosed()) {
910
+ if (resWritable.isClosed()) {
809
911
  cleanup();
810
912
  }
811
- });
913
+ };
812
914
  if (passInitAsDataForBackwardsCompat) {
813
- reqReader.pushValue(Ok(initPayload));
915
+ reqReadable._pushValue(Ok(initPayload));
814
916
  }
815
- const resWriter = new WriteStreamImpl((response) => {
816
- this.transport.send(from, {
817
- streamId,
818
- controlFlags: procClosesWithResponse ? getStreamCloseBackwardsCompat(protocolVersion) : 0,
819
- payload: response
820
- });
821
- });
822
- resWriter.onClose(() => {
823
- if (!procClosesWithResponse && cleanClose) {
824
- const message = closeStreamMessage(streamId);
825
- message.controlFlags = getStreamCloseBackwardsCompat(protocolVersion);
826
- this.transport.send(from, closeStreamMessage(streamId));
827
- }
828
- if (protocolVersion === "v1.1") {
829
- if (!reqReader.isClosed()) {
830
- reqReader.triggerClose();
917
+ const resWritable = new WritableImpl({
918
+ writeCb: (response) => {
919
+ sessionScopedSend({
920
+ streamId,
921
+ controlFlags: procClosesWithResponse ? getStreamCloseBackwardsCompat(protocolVersion) : 0,
922
+ payload: response
923
+ });
924
+ if (procClosesWithResponse) {
925
+ resWritable.close();
926
+ }
927
+ },
928
+ // close callback
929
+ closeCb: () => {
930
+ if (!procClosesWithResponse && cleanClose) {
931
+ const message = closeStreamMessage(streamId);
932
+ message.controlFlags = getStreamCloseBackwardsCompat(protocolVersion);
933
+ sessionScopedSend(message);
934
+ }
935
+ if (protocolVersion === "v1.1") {
936
+ if (!reqReadable.isClosed()) {
937
+ closeReadable();
938
+ }
939
+ }
940
+ if (reqReadable.isClosed()) {
941
+ cleanup();
831
942
  }
832
- }
833
- if (reqReader.isClosed()) {
834
- cleanup();
835
943
  }
836
944
  });
837
945
  const onHandlerError = (err, span) => {
838
946
  const errorMsg = coerceErrorString(err);
839
947
  span.recordException(err instanceof Error ? err : new Error(errorMsg));
840
948
  span.setStatus({ code: SpanStatusCode.ERROR });
841
- onServerAbort(
842
- Err({
843
- code: UNCAUGHT_ERROR_CODE,
844
- message: errorMsg
845
- })
846
- );
949
+ onServerCancel({
950
+ code: UNCAUGHT_ERROR_CODE,
951
+ message: errorMsg
952
+ });
847
953
  };
848
- if (isStreamCloseBackwardsCompat(controlFlags, protocolVersion)) {
849
- reqReader.triggerClose();
954
+ if (procClosesWithInit) {
955
+ closeReadable();
850
956
  } else if (procedure.type === "rpc" || procedure.type === "subscription") {
851
- this.log?.warn(`${procedure.type} sent an init without a stream close`, {
957
+ this.log?.warn("sent an init without a stream close", {
852
958
  ...loggingMetadata,
853
959
  clientId: this.transport.clientId
854
960
  });
855
961
  }
856
- const serviceContextWithTransportInfo = {
857
- ...this.getContext(service, serviceName),
962
+ const handlerContext = {
963
+ ...serviceContext,
858
964
  from,
859
965
  sessionId,
860
966
  metadata: sessionMetadata,
861
- abortController: handlerAbortController,
862
- clientAbortSignal: clientAbortController.signal,
863
- onRequestFinished: (cb) => {
864
- if (reqReader.isClosed() && resWriter.isClosed()) {
865
- try {
866
- cb();
867
- } catch {
868
- }
869
- return;
870
- }
871
- onFinishedCallbacks.push(cb);
872
- }
967
+ cancel: () => {
968
+ onServerCancel({
969
+ code: CANCEL_CODE,
970
+ message: "cancelled by server procedure handler"
971
+ });
972
+ },
973
+ signal: finishedController.signal
873
974
  };
874
975
  switch (procedure.type) {
875
976
  case "rpc":
@@ -881,15 +982,14 @@ var RiverServer = class {
881
982
  tracingCtx,
882
983
  async (span) => {
883
984
  try {
884
- const outputMessage = await procedure.handler({
885
- ctx: serviceContextWithTransportInfo,
985
+ const responsePayload = await procedure.handler({
986
+ ctx: handlerContext,
886
987
  reqInit: initPayload
887
988
  });
888
- if (resWriter.isClosed()) {
989
+ if (resWritable.isClosed()) {
889
990
  return;
890
991
  }
891
- resWriter.write(outputMessage);
892
- resWriter.close();
992
+ resWritable.write(responsePayload);
893
993
  } catch (err) {
894
994
  onHandlerError(err, span);
895
995
  } finally {
@@ -908,10 +1008,10 @@ var RiverServer = class {
908
1008
  async (span) => {
909
1009
  try {
910
1010
  await procedure.handler({
911
- ctx: serviceContextWithTransportInfo,
1011
+ ctx: handlerContext,
912
1012
  reqInit: initPayload,
913
- reqReader,
914
- resWriter
1013
+ reqReadable,
1014
+ resWritable
915
1015
  });
916
1016
  } catch (err) {
917
1017
  onHandlerError(err, span);
@@ -931,9 +1031,9 @@ var RiverServer = class {
931
1031
  async (span) => {
932
1032
  try {
933
1033
  await procedure.handler({
934
- ctx: serviceContextWithTransportInfo,
935
- reqInit: passInitAsDataForBackwardsCompat ? {} : initPayload,
936
- resWriter
1034
+ ctx: handlerContext,
1035
+ reqInit: initPayload,
1036
+ resWritable
937
1037
  });
938
1038
  } catch (err) {
939
1039
  onHandlerError(err, span);
@@ -952,16 +1052,15 @@ var RiverServer = class {
952
1052
  tracingCtx,
953
1053
  async (span) => {
954
1054
  try {
955
- const outputMessage = await procedure.handler({
956
- ctx: serviceContextWithTransportInfo,
957
- reqInit: passInitAsDataForBackwardsCompat ? {} : initPayload,
958
- reqReader
1055
+ const responsePayload = await procedure.handler({
1056
+ ctx: handlerContext,
1057
+ reqInit: initPayload,
1058
+ reqReadable
959
1059
  });
960
- if (resWriter.isClosed()) {
1060
+ if (resWritable.isClosed()) {
961
1061
  return;
962
1062
  }
963
- resWriter.write(outputMessage);
964
- resWriter.close();
1063
+ resWritable.write(responsePayload);
965
1064
  } catch (err) {
966
1065
  onHandlerError(err, span);
967
1066
  } finally {
@@ -970,16 +1069,8 @@ var RiverServer = class {
970
1069
  }
971
1070
  );
972
1071
  break;
973
- default:
974
- this.log?.error(
975
- `got request for invalid procedure type ${procedure.type} at ${serviceName}.${procedureName}`,
976
- {
977
- ...loggingMetadata,
978
- tags: ["invariant-violation"]
979
- }
980
- );
981
- return;
982
1072
  }
1073
+ return procStream;
983
1074
  }
984
1075
  getContext(service, serviceName) {
985
1076
  const context = this.contextMap.get(service);
@@ -996,22 +1087,20 @@ var RiverServer = class {
996
1087
  validateNewProcStream(initMessage) {
997
1088
  const session = this.transport.sessions.get(initMessage.from);
998
1089
  if (!session) {
999
- const errMessage = `couldn't find a session for ${initMessage.from}`;
1000
1090
  this.log?.error(`couldn't find session for ${initMessage.from}`, {
1001
1091
  clientId: this.transport.clientId,
1002
1092
  transportMessage: initMessage,
1003
1093
  tags: ["invariant-violation"]
1004
1094
  });
1005
- this.abortStream(
1006
- initMessage.from,
1007
- initMessage.streamId,
1008
- Err({
1009
- code: INTERNAL_RIVER_ERROR_CODE,
1010
- message: errMessage
1011
- })
1012
- );
1013
1095
  return null;
1014
1096
  }
1097
+ const sessionScopedSend = this.transport.getSessionBoundSendFn(
1098
+ initMessage.from,
1099
+ session.id
1100
+ );
1101
+ const cancelStream = (streamId, payload) => {
1102
+ this.cancelStream(initMessage.from, sessionScopedSend, streamId, payload);
1103
+ };
1015
1104
  const sessionMetadata = this.transport.sessionHandshakeMetadata.get(
1016
1105
  session.to
1017
1106
  );
@@ -1021,11 +1110,10 @@ var RiverServer = class {
1021
1110
  ...session.loggingMetadata,
1022
1111
  tags: ["invariant-violation"]
1023
1112
  });
1024
- this.abortStream(
1025
- initMessage.from,
1113
+ cancelStream(
1026
1114
  initMessage.streamId,
1027
1115
  Err({
1028
- code: INTERNAL_RIVER_ERROR_CODE,
1116
+ code: UNCAUGHT_ERROR_CODE,
1029
1117
  message: errMessage
1030
1118
  })
1031
1119
  );
@@ -1039,8 +1127,7 @@ var RiverServer = class {
1039
1127
  transportMessage: initMessage,
1040
1128
  tags: ["invalid-request"]
1041
1129
  });
1042
- this.abortStream(
1043
- initMessage.from,
1130
+ cancelStream(
1044
1131
  initMessage.streamId,
1045
1132
  Err({
1046
1133
  code: INVALID_REQUEST_CODE,
@@ -1053,12 +1140,10 @@ var RiverServer = class {
1053
1140
  const errMessage = `missing service name in stream open message`;
1054
1141
  this.log?.warn(errMessage, {
1055
1142
  ...session.loggingMetadata,
1056
- clientId: this.transport.clientId,
1057
1143
  transportMessage: initMessage,
1058
1144
  tags: ["invalid-request"]
1059
1145
  });
1060
- this.abortStream(
1061
- initMessage.from,
1146
+ cancelStream(
1062
1147
  initMessage.streamId,
1063
1148
  Err({
1064
1149
  code: INVALID_REQUEST_CODE,
@@ -1071,12 +1156,10 @@ var RiverServer = class {
1071
1156
  const errMessage = `missing procedure name in stream open message`;
1072
1157
  this.log?.warn(errMessage, {
1073
1158
  ...session.loggingMetadata,
1074
- clientId: this.transport.clientId,
1075
1159
  transportMessage: initMessage,
1076
1160
  tags: ["invalid-request"]
1077
1161
  });
1078
- this.abortStream(
1079
- initMessage.from,
1162
+ cancelStream(
1080
1163
  initMessage.streamId,
1081
1164
  Err({
1082
1165
  code: INVALID_REQUEST_CODE,
@@ -1093,8 +1176,7 @@ var RiverServer = class {
1093
1176
  transportMessage: initMessage,
1094
1177
  tags: ["invalid-request"]
1095
1178
  });
1096
- this.abortStream(
1097
- initMessage.from,
1179
+ cancelStream(
1098
1180
  initMessage.streamId,
1099
1181
  Err({
1100
1182
  code: INVALID_REQUEST_CODE,
@@ -1108,12 +1190,10 @@ var RiverServer = class {
1108
1190
  const errMessage = `couldn't find a matching procedure for ${initMessage.serviceName}.${initMessage.procedureName}`;
1109
1191
  this.log?.warn(errMessage, {
1110
1192
  ...session.loggingMetadata,
1111
- clientId: this.transport.clientId,
1112
1193
  transportMessage: initMessage,
1113
1194
  tags: ["invalid-request"]
1114
1195
  });
1115
- this.abortStream(
1116
- initMessage.from,
1196
+ cancelStream(
1117
1197
  initMessage.streamId,
1118
1198
  Err({
1119
1199
  code: INVALID_REQUEST_CODE,
@@ -1122,7 +1202,19 @@ var RiverServer = class {
1122
1202
  );
1123
1203
  return null;
1124
1204
  }
1205
+ const serviceContext = this.getContext(service, initMessage.serviceName);
1125
1206
  const procedure = service.procedures[initMessage.procedureName];
1207
+ if (!["rpc", "upload", "stream", "subscription"].includes(procedure.type)) {
1208
+ this.log?.error(
1209
+ `got request for invalid procedure type ${procedure.type} at ${initMessage.serviceName}.${initMessage.procedureName}`,
1210
+ {
1211
+ ...session.loggingMetadata,
1212
+ transportMessage: initMessage,
1213
+ tags: ["invariant-violation"]
1214
+ }
1215
+ );
1216
+ return null;
1217
+ }
1126
1218
  let passInitAsDataForBackwardsCompat = false;
1127
1219
  if (session.protocolVersion === "v1.1" && (procedure.type === "upload" || procedure.type === "stream") && Value2.Check(procedure.requestData, initMessage.payload) && Value2.Check(procedure.requestInit, {})) {
1128
1220
  passInitAsDataForBackwardsCompat = true;
@@ -1134,8 +1226,7 @@ var RiverServer = class {
1134
1226
  transportMessage: initMessage,
1135
1227
  tags: ["invalid-request"]
1136
1228
  });
1137
- this.abortStream(
1138
- initMessage.from,
1229
+ cancelStream(
1139
1230
  initMessage.streamId,
1140
1231
  Err({
1141
1232
  code: INVALID_REQUEST_CODE,
@@ -1145,37 +1236,33 @@ var RiverServer = class {
1145
1236
  return null;
1146
1237
  }
1147
1238
  return {
1148
- sessionMetadata,
1149
- procedure,
1239
+ initialSession: session,
1240
+ streamId: initMessage.streamId,
1150
1241
  procedureName: initMessage.procedureName,
1151
- service,
1152
1242
  serviceName: initMessage.serviceName,
1153
- loggingMetadata: {
1154
- ...session.loggingMetadata,
1155
- transportMessage: initMessage
1156
- },
1157
- streamId: initMessage.streamId,
1158
- controlFlags: initMessage.controlFlags,
1159
1243
  tracingCtx: initMessage.tracing,
1160
1244
  initPayload: initMessage.payload,
1161
- from: initMessage.from,
1162
- sessionId: session.id,
1163
- protocolVersion: session.protocolVersion,
1245
+ sessionMetadata,
1246
+ procedure,
1247
+ serviceContext,
1248
+ procClosesWithInit: isStreamCloseBackwardsCompat(
1249
+ initMessage.controlFlags,
1250
+ session.protocolVersion
1251
+ ),
1164
1252
  passInitAsDataForBackwardsCompat
1165
1253
  };
1166
1254
  }
1167
- abortStream(to, streamId, payload) {
1168
- let abortedForSession = this.serverAbortedStreams.get(to);
1169
- if (!abortedForSession) {
1170
- abortedForSession = new LRUSet(this.maxAbortedStreamTombstonesPerSession);
1171
- this.serverAbortedStreams.set(to, abortedForSession);
1255
+ cancelStream(to, sessionScopedSend, streamId, payload) {
1256
+ let cancelledStreamsInSession = this.serverCancelledStreams.get(to);
1257
+ if (!cancelledStreamsInSession) {
1258
+ cancelledStreamsInSession = new LRUSet(
1259
+ this.maxCancelledStreamTombstonesPerSession
1260
+ );
1261
+ this.serverCancelledStreams.set(to, cancelledStreamsInSession);
1172
1262
  }
1173
- abortedForSession.add(streamId);
1174
- this.transport.send(
1175
- to,
1176
- // TODO remove once clients migrate to v2
1177
- this.transport.sessions.get(to)?.protocolVersion === "v1.1" ? closeStreamMessage(streamId) : abortMessage(streamId, payload)
1178
- );
1263
+ cancelledStreamsInSession.add(streamId);
1264
+ const msg = cancelMessage(streamId, payload);
1265
+ sessionScopedSend(msg);
1179
1266
  }
1180
1267
  };
1181
1268
  var LRUSet = class {
@@ -1200,21 +1287,21 @@ var LRUSet = class {
1200
1287
  return this.items.has(item);
1201
1288
  }
1202
1289
  };
1203
- function isStreamAbortBackwardsCompat(controlFlags, protocolVersion) {
1290
+ function isStreamCancelBackwardsCompat(controlFlags, protocolVersion) {
1204
1291
  if (protocolVersion === "v1.1") {
1205
1292
  return false;
1206
1293
  }
1207
- return isStreamAbort(controlFlags);
1294
+ return isStreamCancel(controlFlags);
1208
1295
  }
1209
1296
  function isStreamCloseBackwardsCompat(controlFlags, protocolVersion) {
1210
1297
  if (protocolVersion === "v1.1") {
1211
- return isStreamAbort(controlFlags);
1298
+ return isStreamCancel(controlFlags);
1212
1299
  }
1213
1300
  return isStreamClose(controlFlags);
1214
1301
  }
1215
1302
  function getStreamCloseBackwardsCompat(protocolVersion) {
1216
1303
  if (protocolVersion === "v1.1") {
1217
- return 4 /* StreamAbortBit */;
1304
+ return 4 /* StreamCancelBit */;
1218
1305
  }
1219
1306
  return 8 /* StreamClosedBit */;
1220
1307
  }
@@ -1224,7 +1311,7 @@ function createServer(transport, services, providedServerOptions) {
1224
1311
  services,
1225
1312
  providedServerOptions?.handshakeOptions,
1226
1313
  providedServerOptions?.extendedContext,
1227
- providedServerOptions?.maxAbortedStreamTombstonesPerSession
1314
+ providedServerOptions?.maxCancelledStreamTombstonesPerSession
1228
1315
  );
1229
1316
  }
1230
1317
 
@@ -1236,15 +1323,13 @@ function createServerHandshakeOptions(schema, validate) {
1236
1323
  return { schema, validate };
1237
1324
  }
1238
1325
  export {
1239
- ABORT_CODE,
1326
+ CANCEL_CODE,
1240
1327
  Err,
1241
- INTERNAL_RIVER_ERROR_CODE,
1242
1328
  INVALID_REQUEST_CODE,
1243
1329
  Ok,
1244
1330
  Procedure,
1245
1331
  version as RIVER_VERSION,
1246
- RequestReaderErrorSchema,
1247
- ResponseReaderErrorSchema,
1332
+ ReaderErrorSchema,
1248
1333
  ServiceSchema,
1249
1334
  UNCAUGHT_ERROR_CODE,
1250
1335
  UNEXPECTED_DISCONNECT_CODE,
@@ -1252,6 +1337,9 @@ export {
1252
1337
  createClientHandshakeOptions,
1253
1338
  createServer,
1254
1339
  createServerHandshakeOptions,
1255
- serializeSchema
1340
+ flattenErrorType,
1341
+ serializeSchema,
1342
+ serializeSchemaV1Compat,
1343
+ unwrapOrThrow
1256
1344
  };
1257
1345
  //# sourceMappingURL=index.js.map