@replit/river 0.16.1 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +25 -11
  2. package/dist/{chunk-Q6WPGM3K.js → chunk-7IQO434V.js} +11 -3
  3. package/dist/{chunk-7SPCAA6Q.js → chunk-LQMPJI3S.js} +101 -97
  4. package/dist/{chunk-GFRAOY75.js → chunk-VH3NGOXQ.js} +8 -17
  5. package/dist/{chunk-L65XWBX2.js → chunk-VJRLJ3JU.js} +1 -1
  6. package/dist/{chunk-XLJGKNV2.js → chunk-Y6DLSCKU.js} +1 -1
  7. package/dist/{connection-94896f3b.d.ts → connection-0767dc6b.d.ts} +1 -1
  8. package/dist/{connection-99346822.d.ts → connection-f31edbcd.d.ts} +1 -1
  9. package/dist/{index-2e402bb8.d.ts → index-8df0bdfb.d.ts} +27 -31
  10. package/dist/{procedures-f0226890.d.ts → procedures-b5ddb54d.d.ts} +1 -1
  11. package/dist/router/index.cjs +12 -4
  12. package/dist/router/index.d.cts +8 -4
  13. package/dist/router/index.d.ts +8 -4
  14. package/dist/router/index.js +2 -2
  15. package/dist/transport/impls/uds/client.cjs +80 -69
  16. package/dist/transport/impls/uds/client.d.cts +2 -2
  17. package/dist/transport/impls/uds/client.d.ts +2 -2
  18. package/dist/transport/impls/uds/client.js +3 -3
  19. package/dist/transport/impls/uds/server.cjs +82 -94
  20. package/dist/transport/impls/uds/server.d.cts +2 -2
  21. package/dist/transport/impls/uds/server.d.ts +2 -2
  22. package/dist/transport/impls/uds/server.js +3 -3
  23. package/dist/transport/impls/ws/client.cjs +80 -69
  24. package/dist/transport/impls/ws/client.d.cts +2 -2
  25. package/dist/transport/impls/ws/client.d.ts +2 -2
  26. package/dist/transport/impls/ws/client.js +3 -3
  27. package/dist/transport/impls/ws/server.cjs +82 -94
  28. package/dist/transport/impls/ws/server.d.cts +2 -2
  29. package/dist/transport/impls/ws/server.d.ts +2 -2
  30. package/dist/transport/impls/ws/server.js +3 -3
  31. package/dist/transport/index.cjs +107 -115
  32. package/dist/transport/index.d.cts +1 -1
  33. package/dist/transport/index.d.ts +1 -1
  34. package/dist/transport/index.js +2 -2
  35. package/dist/util/testHelpers.cjs +45 -18
  36. package/dist/util/testHelpers.d.cts +4 -9
  37. package/dist/util/testHelpers.d.ts +4 -9
  38. package/dist/util/testHelpers.js +8 -14
  39. package/package.json +1 -1
package/README.md CHANGED
@@ -22,32 +22,46 @@ See [PROTOCOL.md](./PROTOCOL.md) for more information on the protocol.
22
22
 
23
23
  Before proceeding, ensure you have TypeScript 5 installed and configured appropriately:
24
24
 
25
- 1. **Ensure `"moduleResolution": "bundler"` in tsconfig.json**:
25
+ 1. **Ensure your `tsconfig.json` is configured correctly**:
26
26
 
27
- ```json
27
+ You must verify that:
28
+
29
+ - `compilerOptions.moduleResolution` is set to `"bundler"`
30
+ - `compilerOptions.strictFunctionTypes` is set to `true`
31
+ - `compilerOptions.strictNullChecks` is set to `true`
32
+
33
+ or, preferably, that:
34
+
35
+ - `compilerOptions.moduleResolution` is set to `"bundler"`
36
+ - `compilerOptions.strict` is set to `true`
37
+
38
+ Like so:
39
+
40
+ ```jsonc
28
41
  {
29
42
  "compilerOptions": {
30
- "moduleResolution": "bundler"
43
+ "moduleResolution": "bundler",
44
+ "strict": true
31
45
  // Other compiler options...
32
46
  }
33
47
  }
34
48
  ```
35
49
 
36
- If it exists but is set to a different value, modify it to `"bundler"`.
50
+ If these options already exist in your `tsconfig.json` and don't match what is shown above, modify them. River is designed for `"strict": true`, but technically only `strictFunctionTypes` and `strictNullChecks` being set to `true` is required. Failing to set these will cause unresolvable type errors when defining services.
37
51
 
38
52
  2. Install River and Dependencies:
39
53
 
40
- To use River, install the required packages using npm:
54
+ To use River, install the required packages using npm:
41
55
 
42
- ```bash
43
- npm i @replit/river @sinclair/typebox
44
- ```
56
+ ```bash
57
+ npm i @replit/river @sinclair/typebox
58
+ ```
45
59
 
46
60
  3. If you plan on using WebSocket for the underlying transport, also install
47
61
 
48
- ```bash
49
- npm i ws isomorphic-ws
50
- ```
62
+ ```bash
63
+ npm i ws isomorphic-ws
64
+ ```
51
65
 
52
66
  ## Writing services
53
67
 
@@ -3,7 +3,7 @@ import {
3
3
  coerceErrorString,
4
4
  isStreamClose,
5
5
  isStreamOpen
6
- } from "./chunk-GFRAOY75.js";
6
+ } from "./chunk-VH3NGOXQ.js";
7
7
  import {
8
8
  log
9
9
  } from "./chunk-H4BYJELI.js";
@@ -570,8 +570,13 @@ function _createRecursiveProxy(callback, path) {
570
570
  });
571
571
  return proxy;
572
572
  }
573
- var createClient = (transport, serverId, eagerlyConnect = true) => {
574
- if (eagerlyConnect) {
573
+ var defaultClientOptions = {
574
+ connectOnInvoke: true,
575
+ eagerlyConnect: true
576
+ };
577
+ var createClient = (transport, serverId, providedClientOptions = {}) => {
578
+ const options = { ...defaultClientOptions, ...providedClientOptions };
579
+ if (options.eagerlyConnect) {
575
580
  void transport.connect(serverId);
576
581
  }
577
582
  return _createRecursiveProxy(async (opts) => {
@@ -587,6 +592,9 @@ var createClient = (transport, serverId, eagerlyConnect = true) => {
587
592
  input
588
593
  )}`
589
594
  );
595
+ if (options.connectOnInvoke && !transport.connections.has(serverId)) {
596
+ void transport.connect(serverId);
597
+ }
590
598
  if (procType === "rpc") {
591
599
  return handleRpc(
592
600
  transport,
@@ -7,7 +7,7 @@ import {
7
7
  handshakeRequestMessage,
8
8
  handshakeResponseMessage,
9
9
  isAck
10
- } from "./chunk-GFRAOY75.js";
10
+ } from "./chunk-VH3NGOXQ.js";
11
11
  import {
12
12
  log
13
13
  } from "./chunk-H4BYJELI.js";
@@ -19,7 +19,8 @@ import {
19
19
  var ProtocolError = {
20
20
  RetriesExceeded: "conn_retry_exceeded",
21
21
  HandshakeFailed: "handshake_failed",
22
- UseAfterDestroy: "use_after_destroy"
22
+ UseAfterDestroy: "use_after_destroy",
23
+ MessageOrderingViolated: "message_ordering_violated"
23
24
  };
24
25
  var EventDispatcher = class {
25
26
  eventListeners = {};
@@ -74,7 +75,12 @@ var Session = class {
74
75
  /**
75
76
  * The unique ID of this session.
76
77
  */
77
- debugId;
78
+ id;
79
+ /**
80
+ * What the other side advertised as their session ID
81
+ * for this session.
82
+ */
83
+ advertisedSessionId;
78
84
  /**
79
85
  * Number of messages we've sent along this session (excluding handshake and acks)
80
86
  */
@@ -96,11 +102,11 @@ var Session = class {
96
102
  * The interval for sending heartbeats.
97
103
  */
98
104
  heartbeat;
99
- constructor(from, connectedTo, conn, options) {
105
+ constructor(conn, from, to, options) {
106
+ this.id = `session-${nanoid(12)}`;
100
107
  this.options = options;
101
- this.debugId = `sess-${unsafeId()}`;
102
108
  this.from = from;
103
- this.to = connectedTo;
109
+ this.to = to;
104
110
  this.connection = conn;
105
111
  this.codec = options.codec;
106
112
  this.heartbeatMisses = 0;
@@ -140,7 +146,7 @@ var Session = class {
140
146
  log?.info(
141
147
  `${this.from} -- closing connection (id: ${this.connection.debugId}) to ${this.to} due to inactivity`
142
148
  );
143
- this.closeStaleConnection(this.connection);
149
+ this.closeStaleConnection();
144
150
  }
145
151
  return;
146
152
  }
@@ -171,33 +177,37 @@ var Session = class {
171
177
  log?.debug(`${this.from} -- resending ${msg.id} (seq: ${msg.seq})`);
172
178
  const ok = this.connection.send(this.codec.toBuffer(msg));
173
179
  if (!ok) {
174
- const msg2 = `${this.from} -- failed to send buffered message to ${this.to} in session (id: ${this.debugId}) (if you hit this code path something is seriously wrong)`;
180
+ const msg2 = `${this.from} -- failed to send buffered message to ${this.to} in session (id: ${this.id}) (if you hit this code path something is seriously wrong)`;
175
181
  log?.error(msg2);
176
182
  throw new Error(msg2);
177
183
  }
178
184
  }
179
185
  }
180
186
  updateBookkeeping(ack, seq) {
187
+ if (seq + 1 < this.ack) {
188
+ log?.error(`${this.from} -- received stale seq ${seq} + 1 < ${this.ack}`);
189
+ return;
190
+ }
181
191
  this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq > ack);
182
192
  this.ack = seq + 1;
183
193
  }
184
194
  closeStaleConnection(conn) {
185
- if (!this.connection || this.connection !== conn)
195
+ if (this.connection === void 0 || this.connection === conn)
186
196
  return;
187
197
  log?.info(
188
- `${this.from} -- closing old inner connection (id: ${this.connection.debugId}) from session (id: ${this.debugId}) to ${this.to}`
198
+ `${this.from} -- closing old inner connection (id: ${this.connection.debugId}) from session (id: ${this.id}) to ${this.to}`
189
199
  );
190
200
  this.connection.close();
191
201
  this.connection = void 0;
192
202
  }
193
203
  replaceWithNewConnection(newConn) {
194
- this.closeStaleConnection(this.connection);
204
+ this.closeStaleConnection(newConn);
195
205
  this.cancelGrace();
196
206
  this.connection = newConn;
197
207
  }
198
208
  beginGrace(cb) {
199
209
  log?.info(
200
- `${this.from} -- starting ${this.options.sessionDisconnectGraceMs}ms grace period until session (id: ${this.debugId}) to ${this.to} is closed`
210
+ `${this.from} -- starting ${this.options.sessionDisconnectGraceMs}ms grace period until session (id: ${this.id}) to ${this.to} is closed`
201
211
  );
202
212
  this.disconnectionGrace = setTimeout(() => {
203
213
  this.close();
@@ -208,11 +218,12 @@ var Session = class {
208
218
  cancelGrace() {
209
219
  this.heartbeatMisses = 0;
210
220
  clearTimeout(this.disconnectionGrace);
221
+ this.disconnectionGrace = void 0;
211
222
  }
212
223
  // closed when we want to discard the whole session
213
224
  // (i.e. shutdown or session disconnect)
214
225
  close() {
215
- this.closeStaleConnection(this.connection);
226
+ this.closeStaleConnection();
216
227
  this.cancelGrace();
217
228
  this.resetBufferedMessages();
218
229
  clearInterval(this.heartbeat);
@@ -243,7 +254,6 @@ var Session = class {
243
254
 
244
255
  // transport/transport.ts
245
256
  import { Value } from "@sinclair/typebox/value";
246
- import { nanoid as nanoid2 } from "nanoid";
247
257
 
248
258
  // transport/rateLimit.ts
249
259
  var LeakyBucketRateLimit = class {
@@ -331,17 +341,10 @@ var defaultConnectionRetryOptions = {
331
341
  budgetRestoreIntervalMs: 200
332
342
  };
333
343
  var defaultClientTransportOptions = {
334
- connectionRetryOptions: defaultConnectionRetryOptions,
335
- ...defaultTransportOptions
344
+ ...defaultTransportOptions,
345
+ ...defaultConnectionRetryOptions
336
346
  };
337
347
  var Transport = class {
338
- /**
339
- * Unique per instance of the transport.
340
- * This allows us to distinguish reconnects to different
341
- * transports.
342
- */
343
- instanceId = nanoid2();
344
- connectedInstanceIds = /* @__PURE__ */ new Map();
345
348
  /**
346
349
  * A flag indicating whether the transport has been destroyed.
347
350
  * A destroyed transport will not attempt to reconnect and cannot be used again.
@@ -394,41 +397,41 @@ var Transport = class {
394
397
  * and we know the identity of the connected client.
395
398
  * @param conn The connection object.
396
399
  */
397
- onConnect(conn, connectedTo, instanceId) {
400
+ onConnect(conn, connectedTo, advertisedSessionId) {
398
401
  this.eventDispatcher.dispatchEvent("connectionStatus", {
399
402
  status: "connect",
400
403
  conn
401
404
  });
402
405
  let oldSession = this.sessions.get(connectedTo);
403
- const lastInstanceId = this.connectedInstanceIds.get(connectedTo);
404
- if (oldSession && lastInstanceId !== void 0 && lastInstanceId !== instanceId) {
406
+ if (oldSession?.advertisedSessionId && oldSession.advertisedSessionId !== advertisedSessionId) {
405
407
  log?.warn(
406
- `${this.clientId} -- connection from ${connectedTo} is a different instance (got: ${instanceId}, last connected to: ${lastInstanceId}), starting a new session`
408
+ `${this.clientId} -- connection from ${connectedTo} is a different session (id: ${advertisedSessionId}, last connected to: ${oldSession.advertisedSessionId}), starting a new session`
407
409
  );
408
410
  oldSession.close();
409
411
  this.deleteSession(oldSession);
410
412
  oldSession = void 0;
411
413
  }
412
- this.connectedInstanceIds.set(connectedTo, instanceId);
413
414
  if (oldSession === void 0) {
414
415
  const newSession = this.createSession(connectedTo, conn);
416
+ newSession.advertisedSessionId = advertisedSessionId;
415
417
  log?.info(
416
- `${this.clientId} -- new connection (id: ${conn.debugId}) for new session (id: ${newSession.debugId}) to ${connectedTo}`
418
+ `${this.clientId} -- new connection (id: ${conn.debugId}) for new session (id: ${newSession.id}) to ${connectedTo}`
417
419
  );
418
420
  return newSession;
419
421
  }
420
422
  log?.info(
421
- `${this.clientId} -- new connection (id: ${conn.debugId}) for existing session (id: ${oldSession.debugId}) to ${connectedTo}`
423
+ `${this.clientId} -- new connection (id: ${conn.debugId}) for existing session (id: ${oldSession.id}) to ${connectedTo}`
422
424
  );
423
425
  oldSession.replaceWithNewConnection(conn);
424
426
  oldSession.sendBufferedMessages();
427
+ oldSession.advertisedSessionId = advertisedSessionId;
425
428
  return oldSession;
426
429
  }
427
- createSession(connectedTo, conn) {
430
+ createSession(to, conn) {
428
431
  const session = new Session(
429
- this.clientId,
430
- connectedTo,
431
432
  conn,
433
+ this.clientId,
434
+ to,
432
435
  this.options
433
436
  );
434
437
  this.sessions.set(session.to, session);
@@ -438,10 +441,20 @@ var Transport = class {
438
441
  });
439
442
  return session;
440
443
  }
444
+ getOrCreateSession(to, conn) {
445
+ let session = this.sessions.get(to);
446
+ if (!session) {
447
+ session = this.createSession(to, conn);
448
+ log?.info(
449
+ `${this.clientId} -- no session for ${to}, created a new one (id: ${session.id})`
450
+ );
451
+ }
452
+ return session;
453
+ }
441
454
  deleteSession(session) {
442
455
  this.sessions.delete(session.to);
443
456
  log?.info(
444
- `${this.clientId} -- session ${session.debugId} disconnect from ${session.to}`
457
+ `${this.clientId} -- session ${session.id} disconnect from ${session.to}`
445
458
  );
446
459
  this.eventDispatcher.dispatchEvent("sessionStatus", {
447
460
  status: "disconnect",
@@ -509,11 +522,14 @@ var Transport = class {
509
522
  )}`
510
523
  );
511
524
  } else {
525
+ const errMsg = `received out-of-order msg (got seq: ${msg.seq}, wanted seq: ${session.nextExpectedSeq})`;
512
526
  log?.error(
513
- `${this.clientId} -- received out-of-order msg (got: ${msg.seq}, wanted: ${session.nextExpectedSeq}), marking connection as dead: ${JSON.stringify(msg)}`
527
+ `${this.clientId} -- fatal: ${errMsg}, marking connection as dead: ${JSON.stringify(
528
+ msg
529
+ )}`
514
530
  );
531
+ this.protocolError(ProtocolError.MessageOrderingViolated, errMsg);
515
532
  session.close();
516
- this.deleteSession(session);
517
533
  }
518
534
  return;
519
535
  }
@@ -560,14 +576,7 @@ var Transport = class {
560
576
  );
561
577
  return void 0;
562
578
  }
563
- let session = this.sessions.get(to);
564
- if (!session) {
565
- session = this.createSession(to, void 0);
566
- log?.info(
567
- `${this.clientId} -- no session for ${to}, created a new one (id: ${session.debugId})`
568
- );
569
- }
570
- return session.send(msg);
579
+ return this.getOrCreateSession(to).send(msg);
571
580
  }
572
581
  // control helpers
573
582
  sendCloseStream(to, streamId) {
@@ -619,7 +628,13 @@ var ClientTransport = class extends Transport {
619
628
  */
620
629
  inflightConnectionPromises;
621
630
  retryBudget;
622
- tryReconnecting = true;
631
+ /**
632
+ * A flag indicating whether the transport should automatically reconnect
633
+ * when a connection is dropped.
634
+ * Realistically, this should always be true for clients unless you are writing
635
+ * tests or a special case where you don't want to reconnect.
636
+ */
637
+ reconnectOnConnectionDrop = true;
623
638
  constructor(clientId, providedOptions) {
624
639
  super(clientId, providedOptions);
625
640
  this.options = {
@@ -627,21 +642,20 @@ var ClientTransport = class extends Transport {
627
642
  ...providedOptions
628
643
  };
629
644
  this.inflightConnectionPromises = /* @__PURE__ */ new Map();
630
- this.retryBudget = new LeakyBucketRateLimit(
631
- this.options.connectionRetryOptions
632
- );
645
+ this.retryBudget = new LeakyBucketRateLimit(this.options);
633
646
  }
634
647
  handleConnection(conn, to) {
635
648
  if (this.state !== "open")
636
649
  return;
637
650
  let session = void 0;
638
651
  const handshakeHandler = (data) => {
639
- const handshake = this.receiveHandshakeResponseMessage(data);
640
- if (!handshake) {
652
+ const maybeSession = this.receiveHandshakeResponseMessage(data, conn);
653
+ if (!maybeSession) {
641
654
  conn.close();
642
655
  return;
656
+ } else {
657
+ session = maybeSession;
643
658
  }
644
- session = this.onConnect(conn, handshake.from, handshake.instanceId);
645
659
  conn.removeDataListener(handshakeHandler);
646
660
  conn.addDataListener((data2) => {
647
661
  const parsed = this.parseMsg(data2);
@@ -661,7 +675,7 @@ var ClientTransport = class extends Transport {
661
675
  `${this.clientId} -- connection (id: ${conn.debugId}) to ${to} disconnected`
662
676
  );
663
677
  this.inflightConnectionPromises.delete(to);
664
- if (this.tryReconnecting) {
678
+ if (this.reconnectOnConnectionDrop) {
665
679
  void this.connect(to);
666
680
  }
667
681
  });
@@ -671,7 +685,7 @@ var ClientTransport = class extends Transport {
671
685
  );
672
686
  });
673
687
  }
674
- receiveHandshakeResponseMessage(data) {
688
+ receiveHandshakeResponseMessage(data, conn) {
675
689
  const parsed = this.parseMsg(data);
676
690
  if (!parsed) {
677
691
  this.protocolError(
@@ -704,12 +718,14 @@ var ClientTransport = class extends Transport {
704
718
  );
705
719
  return false;
706
720
  }
707
- const instanceId = parsed.payload.status.instanceId;
708
- log?.debug(
709
- `${this.clientId} -- handshake from ${parsed.from} ok (instance: ${instanceId})`
721
+ log?.debug(`${this.clientId} -- handshake from ${parsed.from} ok`);
722
+ const session = this.onConnect(
723
+ conn,
724
+ parsed.from,
725
+ parsed.payload.status.sessionId
710
726
  );
711
727
  this.retryBudget.startRestoringBudget(parsed.from);
712
- return { instanceId, from: parsed.from };
728
+ return session;
713
729
  }
714
730
  /**
715
731
  * Manually attempts to connect to a client.
@@ -767,7 +783,7 @@ var ClientTransport = class extends Transport {
767
783
  } catch (error) {
768
784
  this.inflightConnectionPromises.delete(to);
769
785
  const errStr = coerceErrorString(error);
770
- if (!this.tryReconnecting || !canProceedWithConnection()) {
786
+ if (!this.reconnectOnConnectionDrop || !canProceedWithConnection()) {
771
787
  log?.warn(`${this.clientId} -- connection to ${to} failed (${errStr})`);
772
788
  } else {
773
789
  log?.warn(
@@ -778,11 +794,8 @@ var ClientTransport = class extends Transport {
778
794
  }
779
795
  }
780
796
  sendHandshake(to, conn) {
781
- const requestMsg = handshakeRequestMessage(
782
- this.clientId,
783
- to,
784
- this.instanceId
785
- );
797
+ const session = this.getOrCreateSession(to, conn);
798
+ const requestMsg = handshakeRequestMessage(this.clientId, to, session.id);
786
799
  log?.debug(`${this.clientId} -- sending handshake request to ${to}`);
787
800
  conn.send(this.codec.toBuffer(requestMsg));
788
801
  }
@@ -795,7 +808,7 @@ var ServerTransport = class extends Transport {
795
808
  constructor(clientId, providedOptions) {
796
809
  super(clientId, providedOptions);
797
810
  log?.info(
798
- `${this.clientId} -- initiated server transport (instance id: ${this.instanceId}, protocol: ${PROTOCOL_VERSION})`
811
+ `${this.clientId} -- initiated server transport (protocol: ${PROTOCOL_VERSION})`
799
812
  );
800
813
  }
801
814
  handleConnection(conn) {
@@ -807,12 +820,13 @@ var ServerTransport = class extends Transport {
807
820
  let session = void 0;
808
821
  const client = () => session?.to ?? "unknown";
809
822
  const handshakeHandler = (data) => {
810
- const handshake = this.receiveHandshakeRequestMessage(data, conn);
811
- if (!handshake) {
823
+ const maybeSession = this.receiveHandshakeRequestMessage(data, conn);
824
+ if (!maybeSession) {
812
825
  conn.close();
813
826
  return;
827
+ } else {
828
+ session = maybeSession;
814
829
  }
815
- session = this.onConnect(conn, handshake.from, handshake.instanceId);
816
830
  conn.removeDataListener(handshakeHandler);
817
831
  conn.addDataListener((data2) => {
818
832
  const parsed = this.parseMsg(data2);
@@ -850,18 +864,13 @@ var ServerTransport = class extends Transport {
850
864
  return false;
851
865
  }
852
866
  if (!Value.Check(ControlMessageHandshakeRequestSchema, parsed.payload)) {
853
- const responseMsg2 = handshakeResponseMessage(
854
- this.clientId,
855
- this.instanceId,
856
- parsed.from,
857
- false
858
- );
867
+ const reason = "received invalid handshake msg";
868
+ const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
869
+ ok: false,
870
+ reason
871
+ });
859
872
  conn.send(this.codec.toBuffer(responseMsg2));
860
- log?.warn(
861
- `${this.clientId} -- received invalid handshake msg: ${JSON.stringify(
862
- parsed
863
- )}`
864
- );
873
+ log?.warn(`${this.clientId} -- ${reason}: ${JSON.stringify(parsed)}`);
865
874
  this.protocolError(
866
875
  ProtocolError.HandshakeFailed,
867
876
  "invalid handshake request"
@@ -870,34 +879,28 @@ var ServerTransport = class extends Transport {
870
879
  }
871
880
  const gotVersion = parsed.payload.protocolVersion;
872
881
  if (gotVersion !== PROTOCOL_VERSION) {
873
- const responseMsg2 = handshakeResponseMessage(
874
- this.clientId,
875
- this.instanceId,
876
- parsed.from,
877
- false
878
- );
882
+ const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
883
+ const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
884
+ ok: false,
885
+ reason
886
+ });
879
887
  conn.send(this.codec.toBuffer(responseMsg2));
880
888
  log?.warn(
881
889
  `${this.clientId} -- received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`
882
890
  );
883
- this.protocolError(
884
- ProtocolError.HandshakeFailed,
885
- `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`
886
- );
891
+ this.protocolError(ProtocolError.HandshakeFailed, reason);
887
892
  return false;
888
893
  }
889
- const instanceId = parsed.payload.instanceId;
894
+ const session = this.getOrCreateSession(parsed.from, conn);
890
895
  log?.debug(
891
- `${this.clientId} -- handshake from ${parsed.from} ok (instance id: ${instanceId}), responding with handshake success`
892
- );
893
- const responseMsg = handshakeResponseMessage(
894
- this.clientId,
895
- this.instanceId,
896
- parsed.from,
897
- true
896
+ `${this.clientId} -- handshake from ${parsed.from} ok, responding with handshake success`
898
897
  );
898
+ const responseMsg = handshakeResponseMessage(this.clientId, parsed.from, {
899
+ ok: true,
900
+ sessionId: session.id
901
+ });
899
902
  conn.send(this.codec.toBuffer(responseMsg));
900
- return { instanceId, from: parsed.from };
903
+ return this.onConnect(conn, parsed.from, parsed.payload.sessionId);
901
904
  }
902
905
  };
903
906
 
@@ -905,6 +908,7 @@ export {
905
908
  ProtocolError,
906
909
  Connection,
907
910
  Session,
911
+ defaultTransportOptions,
908
912
  Transport,
909
913
  ClientTransport,
910
914
  ServerTransport
@@ -19,18 +19,18 @@ var ControlMessageAckSchema = Type.Object({
19
19
  var ControlMessageCloseSchema = Type.Object({
20
20
  type: Type.Literal("CLOSE")
21
21
  });
22
- var PROTOCOL_VERSION = "v1";
22
+ var PROTOCOL_VERSION = "v1.1";
23
23
  var ControlMessageHandshakeRequestSchema = Type.Object({
24
24
  type: Type.Literal("HANDSHAKE_REQ"),
25
25
  protocolVersion: Type.String(),
26
- instanceId: Type.String()
26
+ sessionId: Type.String()
27
27
  });
28
28
  var ControlMessageHandshakeResponseSchema = Type.Object({
29
29
  type: Type.Literal("HANDSHAKE_RESP"),
30
30
  status: Type.Union([
31
31
  Type.Object({
32
32
  ok: Type.Literal(true),
33
- instanceId: Type.String()
33
+ sessionId: Type.String()
34
34
  }),
35
35
  Type.Object({
36
36
  ok: Type.Literal(false),
@@ -47,7 +47,7 @@ var ControlMessagePayloadSchema = Type.Union([
47
47
  var OpaqueTransportMessageSchema = TransportMessageSchema(
48
48
  Type.Unknown()
49
49
  );
50
- function handshakeRequestMessage(from, to, instanceId) {
50
+ function handshakeRequestMessage(from, to, sessionId) {
51
51
  return {
52
52
  id: nanoid(),
53
53
  from,
@@ -59,11 +59,11 @@ function handshakeRequestMessage(from, to, instanceId) {
59
59
  payload: {
60
60
  type: "HANDSHAKE_REQ",
61
61
  protocolVersion: PROTOCOL_VERSION,
62
- instanceId
62
+ sessionId
63
63
  }
64
64
  };
65
65
  }
66
- function handshakeResponseMessage(from, instanceId, to, ok, reason) {
66
+ function handshakeResponseMessage(from, to, status) {
67
67
  return {
68
68
  id: nanoid(),
69
69
  from,
@@ -72,18 +72,9 @@ function handshakeResponseMessage(from, instanceId, to, ok, reason) {
72
72
  ack: 0,
73
73
  streamId: nanoid(),
74
74
  controlFlags: 0,
75
- payload: ok ? {
76
- type: "HANDSHAKE_RESP",
77
- status: {
78
- ok: true,
79
- instanceId
80
- }
81
- } : {
75
+ payload: {
82
76
  type: "HANDSHAKE_RESP",
83
- status: {
84
- ok: false,
85
- reason: reason ?? "Unknown reason"
86
- }
77
+ status
87
78
  }
88
79
  };
89
80
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Connection
3
- } from "./chunk-7SPCAA6Q.js";
3
+ } from "./chunk-LQMPJI3S.js";
4
4
 
5
5
  // transport/transforms/messageFraming.ts
6
6
  import { Transform } from "node:stream";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Connection
3
- } from "./chunk-7SPCAA6Q.js";
3
+ } from "./chunk-LQMPJI3S.js";
4
4
 
5
5
  // transport/impls/ws/connection.ts
6
6
  var WebSocketConnection = class extends Connection {
@@ -1,4 +1,4 @@
1
- import { C as Connection } from './index-2e402bb8.js';
1
+ import { C as Connection } from './index-8df0bdfb.js';
2
2
  import { Socket } from 'node:net';
3
3
  import stream, { Transform, TransformCallback, TransformOptions } from 'node:stream';
4
4
 
@@ -1,5 +1,5 @@
1
1
  import WebSocket from 'isomorphic-ws';
2
- import { C as Connection } from './index-2e402bb8.js';
2
+ import { C as Connection } from './index-8df0bdfb.js';
3
3
 
4
4
  declare class WebSocketConnection extends Connection {
5
5
  ws: WebSocket;