@actuallab/rpc 12.1.69 → 12.1.115

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.
package/dist/index.d.cts CHANGED
@@ -272,6 +272,7 @@ type RpcObjectKind = (typeof RpcObjectKind)[keyof typeof RpcObjectKind];
272
272
  interface IRpcObject {
273
273
  readonly id: RpcObjectId;
274
274
  readonly kind: RpcObjectKind;
275
+ readonly allowReconnect: boolean;
275
276
  reconnect(): void;
276
277
  disconnect(): void;
277
278
  }
@@ -301,6 +302,8 @@ declare class RpcSharedObjectTracker {
301
302
  * so "json5np" (System.Text.Json, no polymorphism) is the correct match.
302
303
  */
303
304
  declare const DEFAULT_SERIALIZATION_FORMAT = "json5np";
305
+ /** WebSocket close code sent by the server when the client's serialization format is unsupported. */
306
+ declare const RPC_CLOSE_CODE_UNSUPPORTED_FORMAT = 4001;
304
307
  /** Builds the WebSocket connection URL for an RpcClientPeer. */
305
308
  type RpcConnectionUrlResolver = (peer: RpcClientPeer) => string;
306
309
  /** Default connection URL provider — appends `clientId` and `f` query parameters. */
@@ -383,6 +386,10 @@ declare class RpcClientPeer extends RpcPeer {
383
386
  /** Builds the WebSocket URL for this peer. Replace to customize URL construction. */
384
387
  connectionUrlResolver: RpcConnectionUrlResolver;
385
388
  readonly peerChanged: EventHandlerSet<void>;
389
+ /** Fired when the server rejects the connection due to an unsupported serialization format (close code 4010). */
390
+ readonly unsupportedFormat: EventHandlerSet<{
391
+ reason: string;
392
+ }>;
386
393
  readonly reconnectDelayer: RpcClientPeerReconnectDelayer;
387
394
  readonly reconnectsAtChanged: EventHandlerSet<void>;
388
395
  get reconnectsAt(): number;
@@ -423,6 +430,7 @@ interface RpcStreamRef {
423
430
  readonly localId: number;
424
431
  readonly ackPeriod: number;
425
432
  readonly ackAdvance: number;
433
+ readonly allowReconnect: boolean;
426
434
  }
427
435
  /**
428
436
  * Parses a stream reference string of the form "{hostId},{localId},{ackPeriod},{ackAdvance}".
@@ -443,6 +451,7 @@ declare function parseStreamRef(value: unknown): RpcStreamRef | null;
443
451
  declare class RpcStream<T> implements AsyncIterable<T>, IRpcObject {
444
452
  readonly id: RpcObjectId;
445
453
  readonly kind: 1;
454
+ readonly allowReconnect: boolean;
446
455
  readonly peer: RpcPeer;
447
456
  readonly ackPeriod: number;
448
457
  readonly ackAdvance: number;
@@ -494,13 +503,14 @@ declare function resolveStreamRefs(value: unknown, peer: RpcPeer): unknown;
494
503
  declare class RpcStreamSender<T> implements IRpcObject {
495
504
  readonly id: RpcObjectId;
496
505
  readonly kind: 0;
506
+ readonly allowReconnect: boolean;
497
507
  readonly peer: RpcPeer;
498
508
  readonly ackPeriod: number;
499
509
  readonly ackAdvance: number;
500
510
  private _nextIndex;
501
511
  private _ended;
502
512
  private _started;
503
- constructor(peer: RpcPeer, ackPeriod?: number, ackAdvance?: number);
513
+ constructor(peer: RpcPeer, ackPeriod?: number, ackAdvance?: number, allowReconnect?: boolean);
504
514
  /** Returns the stream reference string for the $sys.Ok response. */
505
515
  toRef(): string;
506
516
  /** Called by system call handler when $sys.Ack is received from the client. */
@@ -586,4 +596,4 @@ declare class RpcPeerStateMonitor {
586
596
  private _scheduleRecompute;
587
597
  }
588
598
 
589
- export { ARG_DELIMITER, DEFAULT_SERIALIZATION_FORMAT, ENVELOPE_DELIMITER, FRAME_DELIMITER, type IRpcObject, type MethodMeta, type RemoteHandshake, type RpcCallOptions, RpcCallTypeId, RpcClientPeer, RpcClientPeerReconnectDelayer, type RpcConnection, type RpcConnectionUrlResolver, type RpcDispatchContext, RpcHub, RpcInboundCall, RpcInboundCallTracker, type RpcMessage, RpcMessageChannelConnection, type RpcMethodDef, type RpcMethodDefInput, type RpcObjectId, RpcObjectKind, RpcOutboundCall, RpcOutboundCallTracker, RpcPeer, RpcPeerConnectionKind, type RpcPeerState, RpcPeerStateKind, RpcPeerStateMonitor, RpcRemoteObjectTracker, RpcServerPeer, type RpcServiceDef, RpcServiceHost, type RpcServiceImpl, RpcSharedObjectTracker, RpcStream, type RpcStreamRef, RpcStreamSender, RpcSystemCallHandler, RpcSystemCallSender, RpcSystemCalls, RpcType, RpcWebSocketConnection, type ServiceMeta, type WebSocketLike, type WebSocketServer, WebSocketState, createMessageChannelPair, createRpcClient, defaultConnectionUrlResolver, defineRpcService, deserializeMessage, getMethodsMeta, getServiceMeta, getStateDescription, isConnected, likelyConnected, parseStreamRef, resolveStreamRefs, rpcMethod, rpcService, serializeFrame, serializeMessage, splitFrame, wireMethodName };
599
+ export { ARG_DELIMITER, DEFAULT_SERIALIZATION_FORMAT, ENVELOPE_DELIMITER, FRAME_DELIMITER, type IRpcObject, type MethodMeta, RPC_CLOSE_CODE_UNSUPPORTED_FORMAT, type RemoteHandshake, type RpcCallOptions, RpcCallTypeId, RpcClientPeer, RpcClientPeerReconnectDelayer, type RpcConnection, type RpcConnectionUrlResolver, type RpcDispatchContext, RpcHub, RpcInboundCall, RpcInboundCallTracker, type RpcMessage, RpcMessageChannelConnection, type RpcMethodDef, type RpcMethodDefInput, type RpcObjectId, RpcObjectKind, RpcOutboundCall, RpcOutboundCallTracker, RpcPeer, RpcPeerConnectionKind, type RpcPeerState, RpcPeerStateKind, RpcPeerStateMonitor, RpcRemoteObjectTracker, RpcServerPeer, type RpcServiceDef, RpcServiceHost, type RpcServiceImpl, RpcSharedObjectTracker, RpcStream, type RpcStreamRef, RpcStreamSender, RpcSystemCallHandler, RpcSystemCallSender, RpcSystemCalls, RpcType, RpcWebSocketConnection, type ServiceMeta, type WebSocketLike, type WebSocketServer, WebSocketState, createMessageChannelPair, createRpcClient, defaultConnectionUrlResolver, defineRpcService, deserializeMessage, getMethodsMeta, getServiceMeta, getStateDescription, isConnected, likelyConnected, parseStreamRef, resolveStreamRefs, rpcMethod, rpcService, serializeFrame, serializeMessage, splitFrame, wireMethodName };
package/dist/index.d.ts CHANGED
@@ -272,6 +272,7 @@ type RpcObjectKind = (typeof RpcObjectKind)[keyof typeof RpcObjectKind];
272
272
  interface IRpcObject {
273
273
  readonly id: RpcObjectId;
274
274
  readonly kind: RpcObjectKind;
275
+ readonly allowReconnect: boolean;
275
276
  reconnect(): void;
276
277
  disconnect(): void;
277
278
  }
@@ -301,6 +302,8 @@ declare class RpcSharedObjectTracker {
301
302
  * so "json5np" (System.Text.Json, no polymorphism) is the correct match.
302
303
  */
303
304
  declare const DEFAULT_SERIALIZATION_FORMAT = "json5np";
305
+ /** WebSocket close code sent by the server when the client's serialization format is unsupported. */
306
+ declare const RPC_CLOSE_CODE_UNSUPPORTED_FORMAT = 4001;
304
307
  /** Builds the WebSocket connection URL for an RpcClientPeer. */
305
308
  type RpcConnectionUrlResolver = (peer: RpcClientPeer) => string;
306
309
  /** Default connection URL provider — appends `clientId` and `f` query parameters. */
@@ -383,6 +386,10 @@ declare class RpcClientPeer extends RpcPeer {
383
386
  /** Builds the WebSocket URL for this peer. Replace to customize URL construction. */
384
387
  connectionUrlResolver: RpcConnectionUrlResolver;
385
388
  readonly peerChanged: EventHandlerSet<void>;
389
+ /** Fired when the server rejects the connection due to an unsupported serialization format (close code 4010). */
390
+ readonly unsupportedFormat: EventHandlerSet<{
391
+ reason: string;
392
+ }>;
386
393
  readonly reconnectDelayer: RpcClientPeerReconnectDelayer;
387
394
  readonly reconnectsAtChanged: EventHandlerSet<void>;
388
395
  get reconnectsAt(): number;
@@ -423,6 +430,7 @@ interface RpcStreamRef {
423
430
  readonly localId: number;
424
431
  readonly ackPeriod: number;
425
432
  readonly ackAdvance: number;
433
+ readonly allowReconnect: boolean;
426
434
  }
427
435
  /**
428
436
  * Parses a stream reference string of the form "{hostId},{localId},{ackPeriod},{ackAdvance}".
@@ -443,6 +451,7 @@ declare function parseStreamRef(value: unknown): RpcStreamRef | null;
443
451
  declare class RpcStream<T> implements AsyncIterable<T>, IRpcObject {
444
452
  readonly id: RpcObjectId;
445
453
  readonly kind: 1;
454
+ readonly allowReconnect: boolean;
446
455
  readonly peer: RpcPeer;
447
456
  readonly ackPeriod: number;
448
457
  readonly ackAdvance: number;
@@ -494,13 +503,14 @@ declare function resolveStreamRefs(value: unknown, peer: RpcPeer): unknown;
494
503
  declare class RpcStreamSender<T> implements IRpcObject {
495
504
  readonly id: RpcObjectId;
496
505
  readonly kind: 0;
506
+ readonly allowReconnect: boolean;
497
507
  readonly peer: RpcPeer;
498
508
  readonly ackPeriod: number;
499
509
  readonly ackAdvance: number;
500
510
  private _nextIndex;
501
511
  private _ended;
502
512
  private _started;
503
- constructor(peer: RpcPeer, ackPeriod?: number, ackAdvance?: number);
513
+ constructor(peer: RpcPeer, ackPeriod?: number, ackAdvance?: number, allowReconnect?: boolean);
504
514
  /** Returns the stream reference string for the $sys.Ok response. */
505
515
  toRef(): string;
506
516
  /** Called by system call handler when $sys.Ack is received from the client. */
@@ -586,4 +596,4 @@ declare class RpcPeerStateMonitor {
586
596
  private _scheduleRecompute;
587
597
  }
588
598
 
589
- export { ARG_DELIMITER, DEFAULT_SERIALIZATION_FORMAT, ENVELOPE_DELIMITER, FRAME_DELIMITER, type IRpcObject, type MethodMeta, type RemoteHandshake, type RpcCallOptions, RpcCallTypeId, RpcClientPeer, RpcClientPeerReconnectDelayer, type RpcConnection, type RpcConnectionUrlResolver, type RpcDispatchContext, RpcHub, RpcInboundCall, RpcInboundCallTracker, type RpcMessage, RpcMessageChannelConnection, type RpcMethodDef, type RpcMethodDefInput, type RpcObjectId, RpcObjectKind, RpcOutboundCall, RpcOutboundCallTracker, RpcPeer, RpcPeerConnectionKind, type RpcPeerState, RpcPeerStateKind, RpcPeerStateMonitor, RpcRemoteObjectTracker, RpcServerPeer, type RpcServiceDef, RpcServiceHost, type RpcServiceImpl, RpcSharedObjectTracker, RpcStream, type RpcStreamRef, RpcStreamSender, RpcSystemCallHandler, RpcSystemCallSender, RpcSystemCalls, RpcType, RpcWebSocketConnection, type ServiceMeta, type WebSocketLike, type WebSocketServer, WebSocketState, createMessageChannelPair, createRpcClient, defaultConnectionUrlResolver, defineRpcService, deserializeMessage, getMethodsMeta, getServiceMeta, getStateDescription, isConnected, likelyConnected, parseStreamRef, resolveStreamRefs, rpcMethod, rpcService, serializeFrame, serializeMessage, splitFrame, wireMethodName };
599
+ export { ARG_DELIMITER, DEFAULT_SERIALIZATION_FORMAT, ENVELOPE_DELIMITER, FRAME_DELIMITER, type IRpcObject, type MethodMeta, RPC_CLOSE_CODE_UNSUPPORTED_FORMAT, type RemoteHandshake, type RpcCallOptions, RpcCallTypeId, RpcClientPeer, RpcClientPeerReconnectDelayer, type RpcConnection, type RpcConnectionUrlResolver, type RpcDispatchContext, RpcHub, RpcInboundCall, RpcInboundCallTracker, type RpcMessage, RpcMessageChannelConnection, type RpcMethodDef, type RpcMethodDefInput, type RpcObjectId, RpcObjectKind, RpcOutboundCall, RpcOutboundCallTracker, RpcPeer, RpcPeerConnectionKind, type RpcPeerState, RpcPeerStateKind, RpcPeerStateMonitor, RpcRemoteObjectTracker, RpcServerPeer, type RpcServiceDef, RpcServiceHost, type RpcServiceImpl, RpcSharedObjectTracker, RpcStream, type RpcStreamRef, RpcStreamSender, RpcSystemCallHandler, RpcSystemCallSender, RpcSystemCalls, RpcType, RpcWebSocketConnection, type ServiceMeta, type WebSocketLike, type WebSocketServer, WebSocketState, createMessageChannelPair, createRpcClient, defaultConnectionUrlResolver, defineRpcService, deserializeMessage, getMethodsMeta, getServiceMeta, getStateDescription, isConnected, likelyConnected, parseStreamRef, resolveStreamRefs, rpcMethod, rpcService, serializeFrame, serializeMessage, splitFrame, wireMethodName };
package/dist/index.js CHANGED
@@ -310,17 +310,19 @@ var RpcObjectKind = { Local: 0, Remote: 1 };
310
310
  function parseStreamRef(value) {
311
311
  if (typeof value !== "string") return null;
312
312
  const parts = value.split(",");
313
- if (parts.length !== 4) return null;
313
+ if (parts.length < 4 || parts.length > 5) return null;
314
314
  const hostId = parts[0];
315
315
  const localId = parseInt(parts[1], 10);
316
316
  const ackPeriod = parseInt(parts[2], 10);
317
317
  const ackAdvance = parseInt(parts[3], 10);
318
318
  if (isNaN(localId) || isNaN(ackPeriod) || isNaN(ackAdvance)) return null;
319
- return { hostId, localId, ackPeriod, ackAdvance };
319
+ const allowReconnect = parts.length < 5 || parts[4] !== "0";
320
+ return { hostId, localId, ackPeriod, ackAdvance, allowReconnect };
320
321
  }
321
322
  var RpcStream = class {
322
323
  id;
323
324
  kind = RpcObjectKind.Remote;
325
+ allowReconnect;
324
326
  peer;
325
327
  ackPeriod;
326
328
  ackAdvance;
@@ -335,6 +337,7 @@ var RpcStream = class {
335
337
  _ackSentUpTo = 0;
336
338
  constructor(ref, peer) {
337
339
  this.id = { hostId: ref.hostId, localId: ref.localId };
340
+ this.allowReconnect = ref.allowReconnect;
338
341
  this.peer = peer;
339
342
  this.ackPeriod = ref.ackPeriod;
340
343
  this.ackAdvance = ref.ackAdvance;
@@ -380,7 +383,11 @@ var RpcStream = class {
380
383
  }
381
384
  // -- IRpcObject --
382
385
  reconnect() {
383
- this._sendAck(this._nextExpectedIndex, true);
386
+ if (this.allowReconnect) {
387
+ this._sendAck(this._nextExpectedIndex, true);
388
+ } else {
389
+ this.disconnect();
390
+ }
384
391
  }
385
392
  disconnect() {
386
393
  if (this._completed) return;
@@ -633,22 +640,24 @@ var DEFAULT_ACK_ADVANCE = 128;
633
640
  var RpcStreamSender = class {
634
641
  id;
635
642
  kind = RpcObjectKind.Local;
643
+ allowReconnect;
636
644
  peer;
637
645
  ackPeriod;
638
646
  ackAdvance;
639
647
  _nextIndex = 0;
640
648
  _ended = false;
641
649
  _started = new PromiseSource4();
642
- constructor(peer, ackPeriod = DEFAULT_ACK_PERIOD, ackAdvance = DEFAULT_ACK_ADVANCE) {
650
+ constructor(peer, ackPeriod = DEFAULT_ACK_PERIOD, ackAdvance = DEFAULT_ACK_ADVANCE, allowReconnect = true) {
643
651
  const localId = peer.sharedObjects.nextId();
644
652
  this.id = { hostId: peer.hub.hubId, localId };
653
+ this.allowReconnect = allowReconnect;
645
654
  this.peer = peer;
646
655
  this.ackPeriod = ackPeriod;
647
656
  this.ackAdvance = ackAdvance;
648
657
  }
649
658
  /** Returns the stream reference string for the $sys.Ok response. */
650
659
  toRef() {
651
- return `${this.id.hostId},${this.id.localId},${this.ackPeriod},${this.ackAdvance}`;
660
+ return `${this.id.hostId},${this.id.localId},${this.ackPeriod},${this.ackAdvance},${this.allowReconnect ? "1" : "0"}`;
652
661
  }
653
662
  /** Called by system call handler when $sys.Ack is received from the client. */
654
663
  onAck(_nextIndex, _hostId) {
@@ -738,7 +747,10 @@ var RpcRemoteObjectTracker = class {
738
747
  }
739
748
  reconnectAll() {
740
749
  for (const obj of this._objects.values()) {
741
- obj.reconnect();
750
+ if (obj.allowReconnect)
751
+ obj.reconnect();
752
+ else
753
+ obj.disconnect();
742
754
  }
743
755
  }
744
756
  };
@@ -781,6 +793,7 @@ var RpcClientPeerReconnectDelayer = class extends RetryDelayer {
781
793
 
782
794
  // src/rpc-peer.ts
783
795
  var DEFAULT_SERIALIZATION_FORMAT = "json5np";
796
+ var RPC_CLOSE_CODE_UNSUPPORTED_FORMAT = 4001;
784
797
  var defaultConnectionUrlResolver = (peer) => {
785
798
  const sep = peer.ref.includes("?") ? "&" : "?";
786
799
  return peer.ref + sep + `clientId=${peer.clientId}&f=${peer.serializationFormat}`;
@@ -986,6 +999,8 @@ var RpcClientPeer = class extends RpcPeer {
986
999
  /** Builds the WebSocket URL for this peer. Replace to customize URL construction. */
987
1000
  connectionUrlResolver = defaultConnectionUrlResolver;
988
1001
  peerChanged = new EventHandlerSet3();
1002
+ /** Fired when the server rejects the connection due to an unsupported serialization format (close code 4010). */
1003
+ unsupportedFormat = new EventHandlerSet3();
989
1004
  reconnectDelayer = new RpcClientPeerReconnectDelayer();
990
1005
  reconnectsAtChanged = new EventHandlerSet3();
991
1006
  get reconnectsAt() {
@@ -1013,10 +1028,16 @@ var RpcClientPeer = class extends RpcPeer {
1013
1028
  async run(wsFactory) {
1014
1029
  const connUrl = this.connectionUrlResolver(this);
1015
1030
  while (!this._disposed) {
1031
+ let lastCloseCode = 0;
1032
+ let lastCloseReason = "";
1016
1033
  try {
1017
1034
  const ws = wsFactory?.(connUrl) ?? new WebSocket(connUrl);
1018
1035
  const conn = new RpcWebSocketConnection(ws);
1019
1036
  this._connectionKind = 1 /* Connecting */;
1037
+ conn.closed.add((ev) => {
1038
+ lastCloseCode = ev.code;
1039
+ lastCloseReason = ev.reason;
1040
+ });
1020
1041
  this._pendingHandshake = new PromiseSource5();
1021
1042
  this.setupConnection(conn);
1022
1043
  this._connection = void 0;
@@ -1049,6 +1070,11 @@ var RpcClientPeer = class extends RpcPeer {
1049
1070
  }
1050
1071
  this._connectionKind = 0 /* Disconnected */;
1051
1072
  if (this._disposed) break;
1073
+ if (lastCloseCode === RPC_CLOSE_CODE_UNSUPPORTED_FORMAT) {
1074
+ this.unsupportedFormat.trigger({ reason: lastCloseReason });
1075
+ this._disposed = true;
1076
+ break;
1077
+ }
1052
1078
  this._tryIndex++;
1053
1079
  const delay = this.reconnectDelayer.getDelay(this._tryIndex);
1054
1080
  if (delay.isLimitExceeded) {
@@ -1519,6 +1545,7 @@ export {
1519
1545
  DEFAULT_SERIALIZATION_FORMAT,
1520
1546
  ENVELOPE_DELIMITER,
1521
1547
  FRAME_DELIMITER,
1548
+ RPC_CLOSE_CODE_UNSUPPORTED_FORMAT,
1522
1549
  RpcCallTypeId,
1523
1550
  RpcClientPeer,
1524
1551
  RpcClientPeerReconnectDelayer,