@actuallab/rpc 12.3.33 → 12.3.49
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.cjs +419 -230
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +128 -39
- package/dist/index.d.ts +128 -39
- package/dist/index.js +413 -226
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -638,6 +638,11 @@ declare class RpcSystemCallSender {
|
|
|
638
638
|
ackEnd(conn: RpcConnection, format: RpcSerializationFormat, localId: number, hostId: string): void;
|
|
639
639
|
}
|
|
640
640
|
|
|
641
|
+
/** Factory signature shared by all peer lookup/creation methods. Serialization
|
|
642
|
+
* format is encoded in the URL via `?f=...` (see {@link RpcPeerRefBuilder}),
|
|
643
|
+
* so the factory doesn't need an extra parameter for it. `getClientPeer` /
|
|
644
|
+
* `getServerPeer` cast the result, so the factory returns RpcPeer. */
|
|
645
|
+
type RpcPeerFactory = (hub: RpcHub, ref: string) => RpcPeer;
|
|
641
646
|
/** Central RPC coordinator — manages peers, services, and configuration. */
|
|
642
647
|
declare class RpcHub {
|
|
643
648
|
readonly hubId: string;
|
|
@@ -648,15 +653,37 @@ declare class RpcHub {
|
|
|
648
653
|
/** Method registry for compact format hash ↔ name resolution.
|
|
649
654
|
* Created lazily, populated by addService/addClient. */
|
|
650
655
|
readonly registry: RpcMethodRegistry;
|
|
656
|
+
/** Shared reconnect delayer used by every client peer in this hub. Swap in
|
|
657
|
+
* a custom subclass (e.g. app-level signal-gated) before peers start. */
|
|
658
|
+
reconnectDelayer: RpcClientPeerReconnectDelayer;
|
|
659
|
+
/** URL used by {@link defaultPeer} to resolve / create the default client
|
|
660
|
+
* peer. Must be set before the first {@link defaultPeer} access. */
|
|
661
|
+
defaultPeerUrl: string | undefined;
|
|
662
|
+
/** Factory used by {@link defaultPeer} when the peer needs to be created.
|
|
663
|
+
* If left undefined, `getPeer`'s built-in default (RpcClientPeer with
|
|
664
|
+
* format derived from URL or resolver default) is used. */
|
|
665
|
+
defaultPeerFactory: RpcPeerFactory | undefined;
|
|
651
666
|
constructor(hubId?: string);
|
|
667
|
+
/** Shortcut for the hub's default client peer. Fails if
|
|
668
|
+
* {@link defaultPeerUrl} is not set. */
|
|
669
|
+
get defaultPeer(): RpcClientPeer;
|
|
670
|
+
/** Register a peer under its ref. If a different peer is already registered
|
|
671
|
+
* at the same ref, close it first — the hub guarantees at most one live
|
|
672
|
+
* peer per ref, and no peer exists outside the hub. */
|
|
652
673
|
addPeer(peer: RpcPeer): void;
|
|
653
674
|
removePeer(ref: string): void;
|
|
654
|
-
/** Get or create a peer by ref.
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
675
|
+
/** Get or create a peer by ref. If the peer does not exist:
|
|
676
|
+
* - with `factory` provided: it is constructed via `factory(this, ref)`;
|
|
677
|
+
* - otherwise: server peers (ref starts with `server://`) get a plain
|
|
678
|
+
* RpcServerPeer, anything else gets a default-configured RpcClientPeer.
|
|
679
|
+
* The created peer is always registered in this hub. */
|
|
680
|
+
getPeer(ref: string, factory?: RpcPeerFactory): RpcPeer;
|
|
681
|
+
/** Get or create a client peer for the given URL. See {@link getPeer} for
|
|
682
|
+
* the factory semantics. */
|
|
683
|
+
getClientPeer(ref: string, factory?: RpcPeerFactory): RpcClientPeer;
|
|
684
|
+
/** Get or create a server peer for the given ref. See {@link getPeer} for
|
|
685
|
+
* the factory semantics. */
|
|
686
|
+
getServerPeer(ref: string, factory?: RpcPeerFactory): RpcServerPeer;
|
|
660
687
|
/** Register a service with optional server method wrapping for custom call types. */
|
|
661
688
|
addService(defOrContract: RpcServiceDef | (AnyConstructor), impl: RpcServiceImpl): void;
|
|
662
689
|
/** Create a typed client proxy for a service on a remote peer. */
|
|
@@ -712,9 +739,13 @@ declare class RpcSharedObjectTracker {
|
|
|
712
739
|
|
|
713
740
|
/** WebSocket close code sent by the server when the client's serialization format is unsupported. */
|
|
714
741
|
declare const RPC_CLOSE_CODE_UNSUPPORTED_FORMAT = 4001;
|
|
742
|
+
/** Maximum time to wait for the server's handshake response after opening the socket. */
|
|
743
|
+
declare const HANDSHAKE_TIMEOUT_MS = 10000;
|
|
715
744
|
/** Builds the WebSocket connection URL for an RpcClientPeer. */
|
|
716
745
|
type RpcConnectionUrlResolver = (peer: RpcClientPeer) => string;
|
|
717
|
-
/** Default connection URL provider —
|
|
746
|
+
/** Default connection URL provider — sets `clientId` and `f` query parameters,
|
|
747
|
+
* replacing any existing values to keep the wire format consistent with the
|
|
748
|
+
* peer's actual `serializationFormat`. */
|
|
718
749
|
declare const defaultConnectionUrlResolver: RpcConnectionUrlResolver;
|
|
719
750
|
/** Options for RpcPeer.call() — allows custom call types and cancellation. */
|
|
720
751
|
interface RpcCallOptions {
|
|
@@ -736,36 +767,49 @@ interface RemoteHandshake {
|
|
|
736
767
|
}
|
|
737
768
|
/** Base class for RPC peers — handles bidirectional message dispatch. */
|
|
738
769
|
declare abstract class RpcPeer {
|
|
770
|
+
readonly hub: RpcHub;
|
|
739
771
|
/** Routing/addressing key — used as key in hub.peers (URL for clients, "server://{uuid}" for servers). */
|
|
740
772
|
readonly ref: string;
|
|
741
773
|
/** Auto-generated GUID — used in handshakes only. */
|
|
742
774
|
readonly id: string;
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
readonly outbound: RpcOutboundCallTracker;
|
|
746
|
-
readonly inbound: RpcInboundCallTracker;
|
|
775
|
+
readonly outboundCalls: RpcOutboundCallTracker;
|
|
776
|
+
readonly inboundCalls: RpcInboundCallTracker;
|
|
747
777
|
readonly remoteObjects: RpcRemoteObjectTracker;
|
|
748
778
|
readonly sharedObjects: RpcSharedObjectTracker;
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
779
|
+
/** Fired on every state transition with the new value. Initial state is
|
|
780
|
+
* `Disconnected`; `Connecting` is entered when the peer starts an
|
|
781
|
+
* attempt (the reconnect delay is part of this phase); `Connected` is
|
|
782
|
+
* entered only after the handshake has succeeded. */
|
|
783
|
+
readonly connectionStateChanged: EventHandlerSet<RpcConnectionState>;
|
|
784
|
+
protected _connection: RpcConnection | undefined;
|
|
785
|
+
protected _connectionState: RpcConnectionState;
|
|
754
786
|
protected _pendingSends: RpcOutboundCall[];
|
|
755
787
|
private _keepAliveTimer;
|
|
756
|
-
|
|
757
|
-
|
|
788
|
+
private _keepAliveWatchdog;
|
|
789
|
+
/** Wall-clock time of the last inbound `$sys.KeepAlive`, or 0 if none yet
|
|
790
|
+
* for the current connection. Useful for diagnostics. */
|
|
791
|
+
private _lastKeepAliveAt;
|
|
792
|
+
/** Outbound keep-alive send period (per-peer override for tests). */
|
|
793
|
+
keepAlivePeriodMs: number;
|
|
794
|
+
/** Inbound keep-alive silence tolerance (per-peer override for tests). */
|
|
795
|
+
keepAliveTimeoutMs: number;
|
|
796
|
+
protected constructor(hub: RpcHub, ref: string);
|
|
758
797
|
get connection(): RpcConnection | undefined;
|
|
798
|
+
get connectionState(): RpcConnectionState;
|
|
759
799
|
get isConnected(): boolean;
|
|
800
|
+
protected _setConnectionState(value: RpcConnectionState): void;
|
|
801
|
+
/** Resolves on the next transition into `Connected` — or immediately if
|
|
802
|
+
* already in that state. */
|
|
803
|
+
whenConnected(): Promise<void>;
|
|
760
804
|
protected setupConnection(conn: RpcConnection): void;
|
|
761
805
|
/**
|
|
762
806
|
* The serialization format used by this peer for outgoing messages.
|
|
763
807
|
* If not set explicitly, defaults to the resolver's default (JSON /
|
|
764
808
|
* json5np). Subclasses can pre-assign in their constructor.
|
|
765
809
|
*/
|
|
766
|
-
private
|
|
767
|
-
get
|
|
768
|
-
set
|
|
810
|
+
private _serializationFormat;
|
|
811
|
+
get serializationFormat(): RpcSerializationFormat;
|
|
812
|
+
set serializationFormat(value: RpcSerializationFormat);
|
|
769
813
|
call(method: string, args?: unknown[], options?: RpcCallOptions): RpcOutboundCall;
|
|
770
814
|
callNoWait(method: string, args?: unknown[]): void;
|
|
771
815
|
close(): void;
|
|
@@ -777,11 +821,22 @@ declare abstract class RpcPeer {
|
|
|
777
821
|
protected _onHandshakeReceived(_handshake: RemoteHandshake): void;
|
|
778
822
|
private _handleMessage;
|
|
779
823
|
private _handleInbound;
|
|
780
|
-
|
|
781
|
-
|
|
824
|
+
/** Start sending `$sys.KeepAlive` pings and arm the silence watchdog.
|
|
825
|
+
* Called when the peer transitions into `Connected` (after handshake).
|
|
826
|
+
* Each inbound `$sys.KeepAlive` re-arms the watchdog; if it fires, the
|
|
827
|
+
* WebSocket is force-closed so the normal disconnect path runs
|
|
828
|
+
* (`conn.closed` → `connectionState = Disconnected` → UI).
|
|
829
|
+
* Mirrors .NET `RpcObjectTrackers.Maintain`'s `KeepAliveTimeout` branch. */
|
|
830
|
+
private _armKeepAliveWatchdog;
|
|
831
|
+
/** Stop sending keep-alives and clear the silence watchdog. Called when
|
|
832
|
+
* the peer transitions into `Disconnected`. */
|
|
833
|
+
private _disarmKeepAliveWatchdog;
|
|
834
|
+
/** Called by `RpcSystemCallHandler` when a `$sys.KeepAlive` message
|
|
835
|
+
* arrives — records the timestamp and re-arms the silence watchdog. */
|
|
836
|
+
notifyKeepAliveReceived(): void;
|
|
782
837
|
}
|
|
783
838
|
/** Connection state for RpcClientPeer. */
|
|
784
|
-
declare const enum
|
|
839
|
+
declare const enum RpcConnectionState {
|
|
785
840
|
Disconnected = 0,
|
|
786
841
|
Connecting = 1,
|
|
787
842
|
Connected = 2
|
|
@@ -789,7 +844,6 @@ declare const enum RpcPeerConnectionKind {
|
|
|
789
844
|
/** Client-side RPC peer — initiates WebSocket connection. ref = URL. */
|
|
790
845
|
declare class RpcClientPeer extends RpcPeer {
|
|
791
846
|
private _disposed;
|
|
792
|
-
private _connectionKind;
|
|
793
847
|
private _tryIndex;
|
|
794
848
|
private _handshakeIndex;
|
|
795
849
|
/** Index from the MOST RECENTLY RECEIVED server handshake — sent back
|
|
@@ -803,33 +857,58 @@ declare class RpcClientPeer extends RpcPeer {
|
|
|
803
857
|
private _reconnectsAt;
|
|
804
858
|
/** Base64url-encoded peer ID — matches .NET's RpcClientPeer.ClientId (Guid.ToBase64Url). */
|
|
805
859
|
readonly clientId: string;
|
|
806
|
-
/**
|
|
807
|
-
* Serialization format key sent to the server via `f=` query parameter.
|
|
808
|
-
* TS uses plain JSON.stringify (no polymorphic type wrapping), so `json5np`
|
|
809
|
-
* (no-polymorphism) is the correct default.
|
|
810
|
-
*/
|
|
811
|
-
readonly serializationFormat: string;
|
|
812
860
|
/** Builds the WebSocket URL for this peer. Replace to customize URL construction. */
|
|
813
861
|
connectionUrlResolver: RpcConnectionUrlResolver;
|
|
862
|
+
/** Optional WebSocket factory. When set, `run()` uses this instead of the
|
|
863
|
+
* global `new WebSocket(url)` constructor. Used by tests (to inject mock
|
|
864
|
+
* sockets) and by the Node load-test harness (to attach `Session` /
|
|
865
|
+
* `Cookie` headers to the WS upgrade, which the browser `WebSocket`
|
|
866
|
+
* constructor can't do). Must be set before `start()`. */
|
|
867
|
+
webSocketFactory: ((url: string) => WebSocketLike) | undefined;
|
|
868
|
+
/** Max time to wait for the server's handshake response before aborting
|
|
869
|
+
* the connection attempt. Mirrors .NET's `Hub.Limits.HandshakeTimeout`. */
|
|
870
|
+
handshakeTimeoutMs: number;
|
|
814
871
|
readonly peerChanged: EventHandlerSet<void>;
|
|
815
872
|
/** Fired when the server rejects the connection due to an unsupported serialization format (close code 4010). */
|
|
816
873
|
readonly unsupportedFormat: EventHandlerSet<{
|
|
817
874
|
reason: string;
|
|
818
875
|
}>;
|
|
819
|
-
readonly reconnectDelayer: RpcClientPeerReconnectDelayer;
|
|
820
876
|
readonly reconnectsAtChanged: EventHandlerSet<void>;
|
|
821
877
|
get reconnectsAt(): number;
|
|
822
878
|
private _setReconnectsAt;
|
|
823
|
-
|
|
824
|
-
|
|
879
|
+
/** The promise returned by the reconnect loop. `undefined` until
|
|
880
|
+
* `start()` is invoked (which happens automatically when
|
|
881
|
+
* `mustStart = true` is passed to the ctor). */
|
|
882
|
+
whenRunning: Promise<void> | undefined;
|
|
883
|
+
/**
|
|
884
|
+
* @param hub RpcHub instance this peer will be tracked by
|
|
885
|
+
* @param url Full WebSocket URL — the serialization format is taken from
|
|
886
|
+
* the `f=` query parameter (e.g. `wss://host/rpc/ws?f=msgpack6`);
|
|
887
|
+
* falls back to the resolver's default when absent. Use
|
|
888
|
+
* {@link RpcPeerRefBuilder.forClient} to compose URLs with a format.
|
|
889
|
+
* @param mustStart Kick off the reconnect loop automatically at the end of
|
|
890
|
+
* construction (default `true`). Pass `false` if you need to
|
|
891
|
+
* tweak `reconnectDelayer`, `handshakeTimeoutMs`, or similar
|
|
892
|
+
* options before the loop starts — then call `peer.start()`
|
|
893
|
+
* manually.
|
|
894
|
+
*/
|
|
895
|
+
constructor(hub: RpcHub, url: string, mustStart?: boolean);
|
|
825
896
|
/** One-shot connection for tests — no reconnection loop, no handshake.
|
|
897
|
+
* @param conn Rpc connection
|
|
826
898
|
* @param isPeerChanged Whether to treat this as a peer-identity change
|
|
827
899
|
* (default `true` — no handshake was exchanged, so stage-3 compute calls
|
|
828
900
|
* self-invalidate and remote/shared objects are disposed). Pass `false`
|
|
829
901
|
* to simulate a same-peer reconnect in tests. */
|
|
830
902
|
connectWith(conn: RpcConnection, isPeerChanged?: boolean): void;
|
|
831
|
-
/**
|
|
832
|
-
|
|
903
|
+
/** Kick off the reconnect loop. Idempotent — subsequent calls are
|
|
904
|
+
* no-ops; await `peer.whenRunning` if you need the loop's completion
|
|
905
|
+
* promise. Customize `peer.webSocketFactory` first if you need a
|
|
906
|
+
* non-default WebSocket constructor. */
|
|
907
|
+
start(): void;
|
|
908
|
+
/** The reconnect loop itself. Exposed as `protected` so subclasses (and
|
|
909
|
+
* `start()`) can drive it; public callers should use {@link start}. */
|
|
910
|
+
protected run(): Promise<void>;
|
|
911
|
+
private _runImpl;
|
|
833
912
|
/**
|
|
834
913
|
* Reconcile outbound calls after reconnection, then flush pending sends.
|
|
835
914
|
*
|
|
@@ -1121,6 +1200,17 @@ declare class RpcStreamSender<T> implements IRpcObject {
|
|
|
1121
1200
|
private _forceCloseIterator;
|
|
1122
1201
|
}
|
|
1123
1202
|
|
|
1203
|
+
declare class RpcPeerRefBuilder {
|
|
1204
|
+
/** Build a client peer ref from a WebSocket URL, optionally baking in the
|
|
1205
|
+
* serialization format as a `f=` query parameter.
|
|
1206
|
+
* @param url Base WebSocket URL, e.g. `wss://host/rpc/ws`.
|
|
1207
|
+
* @param serializationFormat Optional format key, e.g. `msgpack6`. When
|
|
1208
|
+
* provided, replaces any existing `f=` in the URL. */
|
|
1209
|
+
static forClient(url: string, serializationFormat?: string): string;
|
|
1210
|
+
/** Build a server peer ref from a peer id — returns `server://{id}`. */
|
|
1211
|
+
static forServer(id: string): string;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1124
1214
|
/** Creates a typed RPC client proxy — intercepts method calls and sends them over RPC. */
|
|
1125
1215
|
declare function createRpcClient<T extends object>(peer: RpcPeer, serviceDef: RpcServiceDef): T;
|
|
1126
1216
|
|
|
@@ -1154,8 +1244,7 @@ declare class RpcPeerStateMonitor {
|
|
|
1154
1244
|
private _lastError;
|
|
1155
1245
|
private _state;
|
|
1156
1246
|
private _timer;
|
|
1157
|
-
private
|
|
1158
|
-
private _onDisconnected;
|
|
1247
|
+
private _onConnectionStateChanged;
|
|
1159
1248
|
private _onReconnectsAtChanged;
|
|
1160
1249
|
private _onCancelDelaysChanged;
|
|
1161
1250
|
constructor(peer: RpcClientPeer);
|
|
@@ -1186,4 +1275,4 @@ declare function xxh3_64str(input: string, seed?: bigint): bigint;
|
|
|
1186
1275
|
*/
|
|
1187
1276
|
declare function computeMethodHash(methodName: string): number;
|
|
1188
1277
|
|
|
1189
|
-
export { ARG_DELIMITER, ENVELOPE_DELIMITER, FRAME_DELIMITER, type IRpcObject, IncreasingSeqCompressor, type MethodMeta, RPC_CLOSE_CODE_UNSUPPORTED_FORMAT, type RemoteHandshake, type RpcCallOptions, RpcCallStage, RpcCallTypeId, RpcClientPeer, RpcClientPeerReconnectDelayer, type RpcConnection, type RpcConnectionUrlResolver, type RpcDeserializedMessage, type RpcDispatchContext, RpcHub, RpcInboundCall, RpcInboundCallTracker, RpcJsonSerializationFormat, type RpcLogScope, type RpcMessage, RpcMessageChannelConnection, RpcMessagePackCompactSerializationFormat, RpcMessagePackSerializationFormat, type RpcMethodDef, type RpcMethodDefInput, RpcMethodRegistry, type RpcObjectId, RpcObjectKind, RpcOutboundCall, RpcOutboundCallTracker, RpcPeer,
|
|
1278
|
+
export { ARG_DELIMITER, ENVELOPE_DELIMITER, FRAME_DELIMITER, HANDSHAKE_TIMEOUT_MS, type IRpcObject, IncreasingSeqCompressor, type MethodMeta, RPC_CLOSE_CODE_UNSUPPORTED_FORMAT, type RemoteHandshake, type RpcCallOptions, RpcCallStage, RpcCallTypeId, RpcClientPeer, RpcClientPeerReconnectDelayer, type RpcConnection, RpcConnectionState, type RpcConnectionUrlResolver, type RpcDeserializedMessage, type RpcDispatchContext, RpcHub, RpcInboundCall, RpcInboundCallTracker, RpcJsonSerializationFormat, type RpcLogScope, type RpcMessage, RpcMessageChannelConnection, RpcMessagePackCompactSerializationFormat, RpcMessagePackSerializationFormat, type RpcMethodDef, type RpcMethodDefInput, RpcMethodRegistry, type RpcObjectId, RpcObjectKind, RpcOutboundCall, RpcOutboundCallTracker, RpcPeer, type RpcPeerFactory, RpcPeerRefBuilder, type RpcPeerState, RpcPeerStateKind, RpcPeerStateMonitor, type RpcReceivedMessage, RpcRemoteExecutionMode, RpcRemoteObjectTracker, RpcSerializationFormat, RpcSerializationFormatResolver, RpcServerPeer, type RpcServiceDef, RpcServiceHost, type RpcServiceImpl, RpcSharedObjectTracker, RpcStream, type RpcStreamOptions, type RpcStreamRef, RpcStreamSender, type RpcStreamSource, RpcSystemCallHandler, RpcSystemCallSender, RpcSystemCalls, RpcType, RpcWebSocketConnection, type RpcWireData, type ServiceMeta, type WebSocketLike, type WebSocketServer, WebSocketState, computeMethodHash, createBinaryEncoder, createMessageChannelPair, createRpcClient, defaultBinaryDecoder, defaultBinaryEncoder, defaultConnectionUrlResolver, defineRpcService, deserializeBinaryMessage, deserializeCompactBinaryMessage, deserializeMessage, getLogs, getMethodsMeta, getServiceMeta, getStateDescription, isConnected, likelyConnected, parseStreamRef, resolveStreamRefs, rpcMethod, rpcService, serializeBinaryFrame, serializeBinaryMessage, serializeCompactBinaryMessage, serializeFrame, serializeMessage, splitBinaryFrame, splitCompactBinaryFrame, splitFrame, wireMethodName, xxh3_64, xxh3_64str };
|
package/dist/index.d.ts
CHANGED
|
@@ -638,6 +638,11 @@ declare class RpcSystemCallSender {
|
|
|
638
638
|
ackEnd(conn: RpcConnection, format: RpcSerializationFormat, localId: number, hostId: string): void;
|
|
639
639
|
}
|
|
640
640
|
|
|
641
|
+
/** Factory signature shared by all peer lookup/creation methods. Serialization
|
|
642
|
+
* format is encoded in the URL via `?f=...` (see {@link RpcPeerRefBuilder}),
|
|
643
|
+
* so the factory doesn't need an extra parameter for it. `getClientPeer` /
|
|
644
|
+
* `getServerPeer` cast the result, so the factory returns RpcPeer. */
|
|
645
|
+
type RpcPeerFactory = (hub: RpcHub, ref: string) => RpcPeer;
|
|
641
646
|
/** Central RPC coordinator — manages peers, services, and configuration. */
|
|
642
647
|
declare class RpcHub {
|
|
643
648
|
readonly hubId: string;
|
|
@@ -648,15 +653,37 @@ declare class RpcHub {
|
|
|
648
653
|
/** Method registry for compact format hash ↔ name resolution.
|
|
649
654
|
* Created lazily, populated by addService/addClient. */
|
|
650
655
|
readonly registry: RpcMethodRegistry;
|
|
656
|
+
/** Shared reconnect delayer used by every client peer in this hub. Swap in
|
|
657
|
+
* a custom subclass (e.g. app-level signal-gated) before peers start. */
|
|
658
|
+
reconnectDelayer: RpcClientPeerReconnectDelayer;
|
|
659
|
+
/** URL used by {@link defaultPeer} to resolve / create the default client
|
|
660
|
+
* peer. Must be set before the first {@link defaultPeer} access. */
|
|
661
|
+
defaultPeerUrl: string | undefined;
|
|
662
|
+
/** Factory used by {@link defaultPeer} when the peer needs to be created.
|
|
663
|
+
* If left undefined, `getPeer`'s built-in default (RpcClientPeer with
|
|
664
|
+
* format derived from URL or resolver default) is used. */
|
|
665
|
+
defaultPeerFactory: RpcPeerFactory | undefined;
|
|
651
666
|
constructor(hubId?: string);
|
|
667
|
+
/** Shortcut for the hub's default client peer. Fails if
|
|
668
|
+
* {@link defaultPeerUrl} is not set. */
|
|
669
|
+
get defaultPeer(): RpcClientPeer;
|
|
670
|
+
/** Register a peer under its ref. If a different peer is already registered
|
|
671
|
+
* at the same ref, close it first — the hub guarantees at most one live
|
|
672
|
+
* peer per ref, and no peer exists outside the hub. */
|
|
652
673
|
addPeer(peer: RpcPeer): void;
|
|
653
674
|
removePeer(ref: string): void;
|
|
654
|
-
/** Get or create a peer by ref.
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
675
|
+
/** Get or create a peer by ref. If the peer does not exist:
|
|
676
|
+
* - with `factory` provided: it is constructed via `factory(this, ref)`;
|
|
677
|
+
* - otherwise: server peers (ref starts with `server://`) get a plain
|
|
678
|
+
* RpcServerPeer, anything else gets a default-configured RpcClientPeer.
|
|
679
|
+
* The created peer is always registered in this hub. */
|
|
680
|
+
getPeer(ref: string, factory?: RpcPeerFactory): RpcPeer;
|
|
681
|
+
/** Get or create a client peer for the given URL. See {@link getPeer} for
|
|
682
|
+
* the factory semantics. */
|
|
683
|
+
getClientPeer(ref: string, factory?: RpcPeerFactory): RpcClientPeer;
|
|
684
|
+
/** Get or create a server peer for the given ref. See {@link getPeer} for
|
|
685
|
+
* the factory semantics. */
|
|
686
|
+
getServerPeer(ref: string, factory?: RpcPeerFactory): RpcServerPeer;
|
|
660
687
|
/** Register a service with optional server method wrapping for custom call types. */
|
|
661
688
|
addService(defOrContract: RpcServiceDef | (AnyConstructor), impl: RpcServiceImpl): void;
|
|
662
689
|
/** Create a typed client proxy for a service on a remote peer. */
|
|
@@ -712,9 +739,13 @@ declare class RpcSharedObjectTracker {
|
|
|
712
739
|
|
|
713
740
|
/** WebSocket close code sent by the server when the client's serialization format is unsupported. */
|
|
714
741
|
declare const RPC_CLOSE_CODE_UNSUPPORTED_FORMAT = 4001;
|
|
742
|
+
/** Maximum time to wait for the server's handshake response after opening the socket. */
|
|
743
|
+
declare const HANDSHAKE_TIMEOUT_MS = 10000;
|
|
715
744
|
/** Builds the WebSocket connection URL for an RpcClientPeer. */
|
|
716
745
|
type RpcConnectionUrlResolver = (peer: RpcClientPeer) => string;
|
|
717
|
-
/** Default connection URL provider —
|
|
746
|
+
/** Default connection URL provider — sets `clientId` and `f` query parameters,
|
|
747
|
+
* replacing any existing values to keep the wire format consistent with the
|
|
748
|
+
* peer's actual `serializationFormat`. */
|
|
718
749
|
declare const defaultConnectionUrlResolver: RpcConnectionUrlResolver;
|
|
719
750
|
/** Options for RpcPeer.call() — allows custom call types and cancellation. */
|
|
720
751
|
interface RpcCallOptions {
|
|
@@ -736,36 +767,49 @@ interface RemoteHandshake {
|
|
|
736
767
|
}
|
|
737
768
|
/** Base class for RPC peers — handles bidirectional message dispatch. */
|
|
738
769
|
declare abstract class RpcPeer {
|
|
770
|
+
readonly hub: RpcHub;
|
|
739
771
|
/** Routing/addressing key — used as key in hub.peers (URL for clients, "server://{uuid}" for servers). */
|
|
740
772
|
readonly ref: string;
|
|
741
773
|
/** Auto-generated GUID — used in handshakes only. */
|
|
742
774
|
readonly id: string;
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
readonly outbound: RpcOutboundCallTracker;
|
|
746
|
-
readonly inbound: RpcInboundCallTracker;
|
|
775
|
+
readonly outboundCalls: RpcOutboundCallTracker;
|
|
776
|
+
readonly inboundCalls: RpcInboundCallTracker;
|
|
747
777
|
readonly remoteObjects: RpcRemoteObjectTracker;
|
|
748
778
|
readonly sharedObjects: RpcSharedObjectTracker;
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
779
|
+
/** Fired on every state transition with the new value. Initial state is
|
|
780
|
+
* `Disconnected`; `Connecting` is entered when the peer starts an
|
|
781
|
+
* attempt (the reconnect delay is part of this phase); `Connected` is
|
|
782
|
+
* entered only after the handshake has succeeded. */
|
|
783
|
+
readonly connectionStateChanged: EventHandlerSet<RpcConnectionState>;
|
|
784
|
+
protected _connection: RpcConnection | undefined;
|
|
785
|
+
protected _connectionState: RpcConnectionState;
|
|
754
786
|
protected _pendingSends: RpcOutboundCall[];
|
|
755
787
|
private _keepAliveTimer;
|
|
756
|
-
|
|
757
|
-
|
|
788
|
+
private _keepAliveWatchdog;
|
|
789
|
+
/** Wall-clock time of the last inbound `$sys.KeepAlive`, or 0 if none yet
|
|
790
|
+
* for the current connection. Useful for diagnostics. */
|
|
791
|
+
private _lastKeepAliveAt;
|
|
792
|
+
/** Outbound keep-alive send period (per-peer override for tests). */
|
|
793
|
+
keepAlivePeriodMs: number;
|
|
794
|
+
/** Inbound keep-alive silence tolerance (per-peer override for tests). */
|
|
795
|
+
keepAliveTimeoutMs: number;
|
|
796
|
+
protected constructor(hub: RpcHub, ref: string);
|
|
758
797
|
get connection(): RpcConnection | undefined;
|
|
798
|
+
get connectionState(): RpcConnectionState;
|
|
759
799
|
get isConnected(): boolean;
|
|
800
|
+
protected _setConnectionState(value: RpcConnectionState): void;
|
|
801
|
+
/** Resolves on the next transition into `Connected` — or immediately if
|
|
802
|
+
* already in that state. */
|
|
803
|
+
whenConnected(): Promise<void>;
|
|
760
804
|
protected setupConnection(conn: RpcConnection): void;
|
|
761
805
|
/**
|
|
762
806
|
* The serialization format used by this peer for outgoing messages.
|
|
763
807
|
* If not set explicitly, defaults to the resolver's default (JSON /
|
|
764
808
|
* json5np). Subclasses can pre-assign in their constructor.
|
|
765
809
|
*/
|
|
766
|
-
private
|
|
767
|
-
get
|
|
768
|
-
set
|
|
810
|
+
private _serializationFormat;
|
|
811
|
+
get serializationFormat(): RpcSerializationFormat;
|
|
812
|
+
set serializationFormat(value: RpcSerializationFormat);
|
|
769
813
|
call(method: string, args?: unknown[], options?: RpcCallOptions): RpcOutboundCall;
|
|
770
814
|
callNoWait(method: string, args?: unknown[]): void;
|
|
771
815
|
close(): void;
|
|
@@ -777,11 +821,22 @@ declare abstract class RpcPeer {
|
|
|
777
821
|
protected _onHandshakeReceived(_handshake: RemoteHandshake): void;
|
|
778
822
|
private _handleMessage;
|
|
779
823
|
private _handleInbound;
|
|
780
|
-
|
|
781
|
-
|
|
824
|
+
/** Start sending `$sys.KeepAlive` pings and arm the silence watchdog.
|
|
825
|
+
* Called when the peer transitions into `Connected` (after handshake).
|
|
826
|
+
* Each inbound `$sys.KeepAlive` re-arms the watchdog; if it fires, the
|
|
827
|
+
* WebSocket is force-closed so the normal disconnect path runs
|
|
828
|
+
* (`conn.closed` → `connectionState = Disconnected` → UI).
|
|
829
|
+
* Mirrors .NET `RpcObjectTrackers.Maintain`'s `KeepAliveTimeout` branch. */
|
|
830
|
+
private _armKeepAliveWatchdog;
|
|
831
|
+
/** Stop sending keep-alives and clear the silence watchdog. Called when
|
|
832
|
+
* the peer transitions into `Disconnected`. */
|
|
833
|
+
private _disarmKeepAliveWatchdog;
|
|
834
|
+
/** Called by `RpcSystemCallHandler` when a `$sys.KeepAlive` message
|
|
835
|
+
* arrives — records the timestamp and re-arms the silence watchdog. */
|
|
836
|
+
notifyKeepAliveReceived(): void;
|
|
782
837
|
}
|
|
783
838
|
/** Connection state for RpcClientPeer. */
|
|
784
|
-
declare const enum
|
|
839
|
+
declare const enum RpcConnectionState {
|
|
785
840
|
Disconnected = 0,
|
|
786
841
|
Connecting = 1,
|
|
787
842
|
Connected = 2
|
|
@@ -789,7 +844,6 @@ declare const enum RpcPeerConnectionKind {
|
|
|
789
844
|
/** Client-side RPC peer — initiates WebSocket connection. ref = URL. */
|
|
790
845
|
declare class RpcClientPeer extends RpcPeer {
|
|
791
846
|
private _disposed;
|
|
792
|
-
private _connectionKind;
|
|
793
847
|
private _tryIndex;
|
|
794
848
|
private _handshakeIndex;
|
|
795
849
|
/** Index from the MOST RECENTLY RECEIVED server handshake — sent back
|
|
@@ -803,33 +857,58 @@ declare class RpcClientPeer extends RpcPeer {
|
|
|
803
857
|
private _reconnectsAt;
|
|
804
858
|
/** Base64url-encoded peer ID — matches .NET's RpcClientPeer.ClientId (Guid.ToBase64Url). */
|
|
805
859
|
readonly clientId: string;
|
|
806
|
-
/**
|
|
807
|
-
* Serialization format key sent to the server via `f=` query parameter.
|
|
808
|
-
* TS uses plain JSON.stringify (no polymorphic type wrapping), so `json5np`
|
|
809
|
-
* (no-polymorphism) is the correct default.
|
|
810
|
-
*/
|
|
811
|
-
readonly serializationFormat: string;
|
|
812
860
|
/** Builds the WebSocket URL for this peer. Replace to customize URL construction. */
|
|
813
861
|
connectionUrlResolver: RpcConnectionUrlResolver;
|
|
862
|
+
/** Optional WebSocket factory. When set, `run()` uses this instead of the
|
|
863
|
+
* global `new WebSocket(url)` constructor. Used by tests (to inject mock
|
|
864
|
+
* sockets) and by the Node load-test harness (to attach `Session` /
|
|
865
|
+
* `Cookie` headers to the WS upgrade, which the browser `WebSocket`
|
|
866
|
+
* constructor can't do). Must be set before `start()`. */
|
|
867
|
+
webSocketFactory: ((url: string) => WebSocketLike) | undefined;
|
|
868
|
+
/** Max time to wait for the server's handshake response before aborting
|
|
869
|
+
* the connection attempt. Mirrors .NET's `Hub.Limits.HandshakeTimeout`. */
|
|
870
|
+
handshakeTimeoutMs: number;
|
|
814
871
|
readonly peerChanged: EventHandlerSet<void>;
|
|
815
872
|
/** Fired when the server rejects the connection due to an unsupported serialization format (close code 4010). */
|
|
816
873
|
readonly unsupportedFormat: EventHandlerSet<{
|
|
817
874
|
reason: string;
|
|
818
875
|
}>;
|
|
819
|
-
readonly reconnectDelayer: RpcClientPeerReconnectDelayer;
|
|
820
876
|
readonly reconnectsAtChanged: EventHandlerSet<void>;
|
|
821
877
|
get reconnectsAt(): number;
|
|
822
878
|
private _setReconnectsAt;
|
|
823
|
-
|
|
824
|
-
|
|
879
|
+
/** The promise returned by the reconnect loop. `undefined` until
|
|
880
|
+
* `start()` is invoked (which happens automatically when
|
|
881
|
+
* `mustStart = true` is passed to the ctor). */
|
|
882
|
+
whenRunning: Promise<void> | undefined;
|
|
883
|
+
/**
|
|
884
|
+
* @param hub RpcHub instance this peer will be tracked by
|
|
885
|
+
* @param url Full WebSocket URL — the serialization format is taken from
|
|
886
|
+
* the `f=` query parameter (e.g. `wss://host/rpc/ws?f=msgpack6`);
|
|
887
|
+
* falls back to the resolver's default when absent. Use
|
|
888
|
+
* {@link RpcPeerRefBuilder.forClient} to compose URLs with a format.
|
|
889
|
+
* @param mustStart Kick off the reconnect loop automatically at the end of
|
|
890
|
+
* construction (default `true`). Pass `false` if you need to
|
|
891
|
+
* tweak `reconnectDelayer`, `handshakeTimeoutMs`, or similar
|
|
892
|
+
* options before the loop starts — then call `peer.start()`
|
|
893
|
+
* manually.
|
|
894
|
+
*/
|
|
895
|
+
constructor(hub: RpcHub, url: string, mustStart?: boolean);
|
|
825
896
|
/** One-shot connection for tests — no reconnection loop, no handshake.
|
|
897
|
+
* @param conn Rpc connection
|
|
826
898
|
* @param isPeerChanged Whether to treat this as a peer-identity change
|
|
827
899
|
* (default `true` — no handshake was exchanged, so stage-3 compute calls
|
|
828
900
|
* self-invalidate and remote/shared objects are disposed). Pass `false`
|
|
829
901
|
* to simulate a same-peer reconnect in tests. */
|
|
830
902
|
connectWith(conn: RpcConnection, isPeerChanged?: boolean): void;
|
|
831
|
-
/**
|
|
832
|
-
|
|
903
|
+
/** Kick off the reconnect loop. Idempotent — subsequent calls are
|
|
904
|
+
* no-ops; await `peer.whenRunning` if you need the loop's completion
|
|
905
|
+
* promise. Customize `peer.webSocketFactory` first if you need a
|
|
906
|
+
* non-default WebSocket constructor. */
|
|
907
|
+
start(): void;
|
|
908
|
+
/** The reconnect loop itself. Exposed as `protected` so subclasses (and
|
|
909
|
+
* `start()`) can drive it; public callers should use {@link start}. */
|
|
910
|
+
protected run(): Promise<void>;
|
|
911
|
+
private _runImpl;
|
|
833
912
|
/**
|
|
834
913
|
* Reconcile outbound calls after reconnection, then flush pending sends.
|
|
835
914
|
*
|
|
@@ -1121,6 +1200,17 @@ declare class RpcStreamSender<T> implements IRpcObject {
|
|
|
1121
1200
|
private _forceCloseIterator;
|
|
1122
1201
|
}
|
|
1123
1202
|
|
|
1203
|
+
declare class RpcPeerRefBuilder {
|
|
1204
|
+
/** Build a client peer ref from a WebSocket URL, optionally baking in the
|
|
1205
|
+
* serialization format as a `f=` query parameter.
|
|
1206
|
+
* @param url Base WebSocket URL, e.g. `wss://host/rpc/ws`.
|
|
1207
|
+
* @param serializationFormat Optional format key, e.g. `msgpack6`. When
|
|
1208
|
+
* provided, replaces any existing `f=` in the URL. */
|
|
1209
|
+
static forClient(url: string, serializationFormat?: string): string;
|
|
1210
|
+
/** Build a server peer ref from a peer id — returns `server://{id}`. */
|
|
1211
|
+
static forServer(id: string): string;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1124
1214
|
/** Creates a typed RPC client proxy — intercepts method calls and sends them over RPC. */
|
|
1125
1215
|
declare function createRpcClient<T extends object>(peer: RpcPeer, serviceDef: RpcServiceDef): T;
|
|
1126
1216
|
|
|
@@ -1154,8 +1244,7 @@ declare class RpcPeerStateMonitor {
|
|
|
1154
1244
|
private _lastError;
|
|
1155
1245
|
private _state;
|
|
1156
1246
|
private _timer;
|
|
1157
|
-
private
|
|
1158
|
-
private _onDisconnected;
|
|
1247
|
+
private _onConnectionStateChanged;
|
|
1159
1248
|
private _onReconnectsAtChanged;
|
|
1160
1249
|
private _onCancelDelaysChanged;
|
|
1161
1250
|
constructor(peer: RpcClientPeer);
|
|
@@ -1186,4 +1275,4 @@ declare function xxh3_64str(input: string, seed?: bigint): bigint;
|
|
|
1186
1275
|
*/
|
|
1187
1276
|
declare function computeMethodHash(methodName: string): number;
|
|
1188
1277
|
|
|
1189
|
-
export { ARG_DELIMITER, ENVELOPE_DELIMITER, FRAME_DELIMITER, type IRpcObject, IncreasingSeqCompressor, type MethodMeta, RPC_CLOSE_CODE_UNSUPPORTED_FORMAT, type RemoteHandshake, type RpcCallOptions, RpcCallStage, RpcCallTypeId, RpcClientPeer, RpcClientPeerReconnectDelayer, type RpcConnection, type RpcConnectionUrlResolver, type RpcDeserializedMessage, type RpcDispatchContext, RpcHub, RpcInboundCall, RpcInboundCallTracker, RpcJsonSerializationFormat, type RpcLogScope, type RpcMessage, RpcMessageChannelConnection, RpcMessagePackCompactSerializationFormat, RpcMessagePackSerializationFormat, type RpcMethodDef, type RpcMethodDefInput, RpcMethodRegistry, type RpcObjectId, RpcObjectKind, RpcOutboundCall, RpcOutboundCallTracker, RpcPeer,
|
|
1278
|
+
export { ARG_DELIMITER, ENVELOPE_DELIMITER, FRAME_DELIMITER, HANDSHAKE_TIMEOUT_MS, type IRpcObject, IncreasingSeqCompressor, type MethodMeta, RPC_CLOSE_CODE_UNSUPPORTED_FORMAT, type RemoteHandshake, type RpcCallOptions, RpcCallStage, RpcCallTypeId, RpcClientPeer, RpcClientPeerReconnectDelayer, type RpcConnection, RpcConnectionState, type RpcConnectionUrlResolver, type RpcDeserializedMessage, type RpcDispatchContext, RpcHub, RpcInboundCall, RpcInboundCallTracker, RpcJsonSerializationFormat, type RpcLogScope, type RpcMessage, RpcMessageChannelConnection, RpcMessagePackCompactSerializationFormat, RpcMessagePackSerializationFormat, type RpcMethodDef, type RpcMethodDefInput, RpcMethodRegistry, type RpcObjectId, RpcObjectKind, RpcOutboundCall, RpcOutboundCallTracker, RpcPeer, type RpcPeerFactory, RpcPeerRefBuilder, type RpcPeerState, RpcPeerStateKind, RpcPeerStateMonitor, type RpcReceivedMessage, RpcRemoteExecutionMode, RpcRemoteObjectTracker, RpcSerializationFormat, RpcSerializationFormatResolver, RpcServerPeer, type RpcServiceDef, RpcServiceHost, type RpcServiceImpl, RpcSharedObjectTracker, RpcStream, type RpcStreamOptions, type RpcStreamRef, RpcStreamSender, type RpcStreamSource, RpcSystemCallHandler, RpcSystemCallSender, RpcSystemCalls, RpcType, RpcWebSocketConnection, type RpcWireData, type ServiceMeta, type WebSocketLike, type WebSocketServer, WebSocketState, computeMethodHash, createBinaryEncoder, createMessageChannelPair, createRpcClient, defaultBinaryDecoder, defaultBinaryEncoder, defaultConnectionUrlResolver, defineRpcService, deserializeBinaryMessage, deserializeCompactBinaryMessage, deserializeMessage, getLogs, getMethodsMeta, getServiceMeta, getStateDescription, isConnected, likelyConnected, parseStreamRef, resolveStreamRefs, rpcMethod, rpcService, serializeBinaryFrame, serializeBinaryMessage, serializeCompactBinaryMessage, serializeFrame, serializeMessage, splitBinaryFrame, splitCompactBinaryFrame, splitFrame, wireMethodName, xxh3_64, xxh3_64str };
|