@actuallab/rpc 12.1.62 → 12.1.100

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
@@ -13,6 +13,11 @@ declare const RpcSystemCalls: {
13
13
  readonly cancel: "$sys.Cancel:0";
14
14
  readonly keepAlive: "$sys.KeepAlive:1";
15
15
  readonly reconnect: "$sys.Reconnect:3";
16
+ readonly ack: "$sys.Ack:2";
17
+ readonly ackEnd: "$sys.AckEnd:1";
18
+ readonly item: "$sys.I:2";
19
+ readonly batch: "$sys.B:2";
20
+ readonly end: "$sys.End:2";
16
21
  };
17
22
  /** Wire-format RPC message envelope. */
18
23
  interface RpcMessage {
@@ -127,20 +132,18 @@ interface RpcMethodDefInput {
127
132
  args: unknown[];
128
133
  returns?: symbol;
129
134
  callTypeId?: number;
130
- stream?: boolean;
131
- noWait?: boolean;
135
+ /** Override for wireArgCount. Default: args.length + 1 (assumes a CancellationToken slot). */
136
+ wireArgCount?: number;
132
137
  }
133
138
  declare const RpcType: {
134
139
  readonly object: symbol;
135
140
  readonly stream: symbol;
141
+ readonly noWait: symbol;
136
142
  readonly void: symbol;
137
143
  };
138
- interface RpcServiceDefOptions {
139
- ctOffset?: number;
140
- }
141
144
  /** Returns the full wire method name: "ServiceName.MethodName:wireArgCount". */
142
145
  declare function wireMethodName(def: RpcMethodDef): string;
143
- declare function defineRpcService(name: string, methods: Record<string, RpcMethodDefInput>, options?: RpcServiceDefOptions): RpcServiceDef;
146
+ declare function defineRpcService(name: string, methods: Record<string, RpcMethodDefInput>): RpcServiceDef;
144
147
 
145
148
  /** Tracks a pending outbound RPC call. */
146
149
  declare class RpcOutboundCall {
@@ -191,18 +194,6 @@ declare class RpcInboundCallTracker {
191
194
  clear(): void;
192
195
  }
193
196
 
194
- /** Handles an incoming system call message and dispatches to the appropriate tracker. */
195
- declare function handleSystemCall(message: RpcMessage, args: unknown[], outboundTracker: RpcOutboundCallTracker, inboundTracker: RpcInboundCallTracker): void;
196
-
197
- /** Sends system RPC messages — like .NET's RpcSystemCallSender. */
198
- declare class RpcSystemCallSender {
199
- handshake(conn: RpcConnection, peerId: string, hubId: string, index: number): void;
200
- ok(conn: RpcConnection, relatedId: number, result: unknown): void;
201
- error(conn: RpcConnection, relatedId: number, error: unknown): void;
202
- cancel(conn: RpcConnection, relatedId: number): void;
203
- keepAlive(conn: RpcConnection, activeCallIds: number[]): void;
204
- }
205
-
206
197
  declare class RpcClientPeerReconnectDelayer extends RetryDelayer {
207
198
  constructor();
208
199
  }
@@ -222,12 +213,29 @@ declare class RpcServiceHost {
222
213
  getMethodDef(wireMethod: string): RpcMethodDef | undefined;
223
214
  }
224
215
 
216
+ /** Sends system RPC messages — like .NET's RpcSystemCallSender. */
217
+ declare class RpcSystemCallSender {
218
+ handshake(conn: RpcConnection, peerId: string, hubId: string, index: number): void;
219
+ ok(conn: RpcConnection, relatedId: number, result: unknown): void;
220
+ error(conn: RpcConnection, relatedId: number, error: unknown): void;
221
+ cancel(conn: RpcConnection, relatedId: number): void;
222
+ keepAlive(conn: RpcConnection, activeCallIds: number[]): void;
223
+ item(conn: RpcConnection, localId: number, index: number, item: unknown): void;
224
+ batch(conn: RpcConnection, localId: number, index: number, items: unknown[]): void;
225
+ end(conn: RpcConnection, localId: number, index: number, error?: {
226
+ Message: string;
227
+ } | null): void;
228
+ ack(conn: RpcConnection, localId: number, nextIndex: number, hostId: string): void;
229
+ ackEnd(conn: RpcConnection, localId: number, hostId: string): void;
230
+ }
231
+
225
232
  /** Central RPC coordinator — manages peers, services, and configuration. */
226
233
  declare class RpcHub {
227
234
  readonly hubId: string;
228
235
  readonly peers: Map<string, RpcPeer>;
229
236
  readonly serviceHost: RpcServiceHost;
230
237
  readonly systemCallSender: RpcSystemCallSender;
238
+ systemCallHandler: RpcSystemCallHandler;
231
239
  constructor(hubId?: string);
232
240
  addPeer(peer: RpcPeer): void;
233
241
  removePeer(ref: string): void;
@@ -242,8 +250,6 @@ declare class RpcHub {
242
250
  /** Create a typed client proxy for a service on a remote peer. */
243
251
  addClient<T extends object>(peer: RpcPeer, defOrContract: RpcServiceDef | (abstract new (...args: any[]) => any)): T;
244
252
  close(): void;
245
- /** Dispatch an inbound system call. Override in FusionHub to handle compute-specific system calls. */
246
- handleSystemCall(message: RpcMessage, args: unknown[], outbound: RpcOutboundCallTracker, inbound: RpcInboundCallTracker): void;
247
253
  /** Build an RpcServiceDef from decorator metadata on a contract class. Override in FusionHub for compute support. */
248
254
  protected _buildServiceDef(cls: abstract new (...args: any[]) => any): RpcServiceDef;
249
255
  /** Resolve a service def from either a plain RpcServiceDef or a contract class. */
@@ -254,6 +260,42 @@ declare class RpcHub {
254
260
  protected _createClientMethod(peer: RpcPeer, methodDef: RpcMethodDef): (...args: unknown[]) => unknown;
255
261
  }
256
262
 
263
+ interface RpcObjectId {
264
+ readonly hostId: string;
265
+ readonly localId: number;
266
+ }
267
+ declare const RpcObjectKind: {
268
+ readonly Local: 0;
269
+ readonly Remote: 1;
270
+ };
271
+ type RpcObjectKind = (typeof RpcObjectKind)[keyof typeof RpcObjectKind];
272
+ interface IRpcObject {
273
+ readonly id: RpcObjectId;
274
+ readonly kind: RpcObjectKind;
275
+ readonly allowReconnect: boolean;
276
+ reconnect(): void;
277
+ disconnect(): void;
278
+ }
279
+
280
+ declare class RpcRemoteObjectTracker {
281
+ private _objects;
282
+ register(obj: IRpcObject): void;
283
+ get(localId: number): IRpcObject | undefined;
284
+ unregister(obj: IRpcObject): void;
285
+ disconnectAll(): void;
286
+ reconnectAll(): void;
287
+ }
288
+
289
+ declare class RpcSharedObjectTracker {
290
+ private _nextId;
291
+ private _objects;
292
+ nextId(): number;
293
+ register(obj: IRpcObject): void;
294
+ get(localId: number): IRpcObject | undefined;
295
+ unregister(obj: IRpcObject): void;
296
+ disconnectAll(): void;
297
+ }
298
+
257
299
  /**
258
300
  * Default serialization format for RpcClientPeer connections.
259
301
  * TS uses plain JSON.stringify without polymorphic type wrapping,
@@ -290,6 +332,8 @@ declare abstract class RpcPeer {
290
332
  protected _connection: RpcConnection | undefined;
291
333
  readonly outbound: RpcOutboundCallTracker;
292
334
  readonly inbound: RpcInboundCallTracker;
335
+ readonly remoteObjects: RpcRemoteObjectTracker;
336
+ readonly sharedObjects: RpcSharedObjectTracker;
293
337
  readonly connected: EventHandlerSet<void>;
294
338
  readonly disconnected: EventHandlerSet<{
295
339
  code: number;
@@ -298,6 +342,7 @@ declare abstract class RpcPeer {
298
342
  protected _pendingSends: RpcOutboundCall[];
299
343
  private _keepAliveTimer;
300
344
  constructor(ref: string, hub: RpcHub);
345
+ get hub(): RpcHub;
301
346
  get connection(): RpcConnection | undefined;
302
347
  get isConnected(): boolean;
303
348
  protected setupConnection(conn: RpcConnection): void;
@@ -368,6 +413,119 @@ declare class RpcServerPeer extends RpcPeer {
368
413
  protected _onHandshakeReceived(_handshake: RemoteHandshake): void;
369
414
  }
370
415
 
416
+ /** Handles incoming system call messages — class-based equivalent of the former standalone function. */
417
+ declare class RpcSystemCallHandler {
418
+ handle(message: RpcMessage, args: unknown[], peer: RpcPeer): void;
419
+ }
420
+
421
+ /** Parsed stream reference from the server's result payload. */
422
+ interface RpcStreamRef {
423
+ readonly hostId: string;
424
+ readonly localId: number;
425
+ readonly ackPeriod: number;
426
+ readonly ackAdvance: number;
427
+ readonly allowReconnect: boolean;
428
+ }
429
+ /**
430
+ * Parses a stream reference string of the form "{hostId},{localId},{ackPeriod},{ackAdvance}".
431
+ * Returns null if the value is not a valid stream reference.
432
+ */
433
+ declare function parseStreamRef(value: unknown): RpcStreamRef | null;
434
+ /**
435
+ * Client-side RPC stream — consumes items sent by the server via system calls
436
+ * ($sys.I, $sys.B, $sys.End) and implements AsyncIterable<T> for for-await-of consumption.
437
+ *
438
+ * Wire protocol:
439
+ * - Client sends Ack(0, hostId) to start the stream
440
+ * - Server sends I (single item) / B (batch) messages
441
+ * - Client acks every ackPeriod items for flow control
442
+ * - Server sends End to signal completion (with optional error)
443
+ * - Client sends AckEnd to acknowledge completion
444
+ */
445
+ declare class RpcStream<T> implements AsyncIterable<T>, IRpcObject {
446
+ readonly id: RpcObjectId;
447
+ readonly kind: 1;
448
+ readonly allowReconnect: boolean;
449
+ readonly peer: RpcPeer;
450
+ readonly ackPeriod: number;
451
+ readonly ackAdvance: number;
452
+ private _buffer;
453
+ private _nextExpectedIndex;
454
+ private _consumerWaiting;
455
+ private _completed;
456
+ private _completionError;
457
+ private _disposed;
458
+ private _started;
459
+ private _iterating;
460
+ private _ackSentUpTo;
461
+ constructor(ref: RpcStreamRef, peer: RpcPeer);
462
+ /** Called by system call handler when a single item arrives ($sys.I). */
463
+ onItem(index: number, item: T): void;
464
+ /** Called by system call handler when a batch arrives ($sys.B). */
465
+ onBatch(index: number, items: T[]): void;
466
+ /** Called by system call handler when the stream ends ($sys.End). */
467
+ onEnd(index: number, error: Error | null): void;
468
+ reconnect(): void;
469
+ disconnect(): void;
470
+ [Symbol.asyncIterator](): AsyncIterator<T>;
471
+ dispose(): void;
472
+ private _notifyConsumer;
473
+ private _maybeSendAck;
474
+ private _sendAck;
475
+ private _sendAckEnd;
476
+ }
477
+ /**
478
+ * Recursively walks a deserialized value and replaces any stream ref strings
479
+ * with live RpcStream<unknown> instances registered on the given peer.
480
+ * This handles nested stream refs inside complex return types (e.g. Table<T>
481
+ * containing RpcStream<Row<T>> fields serialized as "{hostId},{localId},{ackPeriod},{ackAdvance}").
482
+ */
483
+ declare function resolveStreamRefs(value: unknown, peer: RpcPeer): unknown;
484
+
485
+ /**
486
+ * Server-side RPC stream producer — sends items to a remote consumer via
487
+ * $sys.I / $sys.B / $sys.End system calls.
488
+ *
489
+ * Wire protocol (server perspective):
490
+ * - Server returns the stream reference string as $sys.Ok
491
+ * - Client sends Ack(0, hostId) to start the stream
492
+ * - Server sends I (single item) / B (batch) messages
493
+ * - Client acks every ackPeriod items for flow control
494
+ * - Server sends End to signal completion (with optional error)
495
+ * - Client sends AckEnd to acknowledge completion
496
+ */
497
+ declare class RpcStreamSender<T> implements IRpcObject {
498
+ readonly id: RpcObjectId;
499
+ readonly kind: 0;
500
+ readonly allowReconnect: boolean;
501
+ readonly peer: RpcPeer;
502
+ readonly ackPeriod: number;
503
+ readonly ackAdvance: number;
504
+ private _nextIndex;
505
+ private _ended;
506
+ private _started;
507
+ constructor(peer: RpcPeer, ackPeriod?: number, ackAdvance?: number, allowReconnect?: boolean);
508
+ /** Returns the stream reference string for the $sys.Ok response. */
509
+ toRef(): string;
510
+ /** Called by system call handler when $sys.Ack is received from the client. */
511
+ onAck(_nextIndex: number, _hostId: string): void;
512
+ /** Called by system call handler when $sys.AckEnd is received from the client. */
513
+ onAckEnd(_hostId: string): void;
514
+ /** Send a single item to the client. */
515
+ sendItem(item: T): void;
516
+ /** Send a batch of items to the client. */
517
+ sendBatch(items: T[]): void;
518
+ /** Signal stream completion to the client. */
519
+ sendEnd(error?: Error | null): void;
520
+ /**
521
+ * Consume an AsyncIterable and send all items to the client.
522
+ * Waits for the client's initial Ack before starting to pump items.
523
+ */
524
+ writeFrom(source: AsyncIterable<T>): Promise<void>;
525
+ reconnect(): void;
526
+ disconnect(): void;
527
+ }
528
+
371
529
  /** Creates a typed RPC client proxy — intercepts method calls and sends them over RPC. */
372
530
  declare function createRpcClient<T extends object>(peer: RpcPeer, serviceDef: RpcServiceDef): T;
373
531
 
@@ -379,26 +537,21 @@ interface WebSocketServer {
379
537
 
380
538
  interface MethodMeta {
381
539
  argCount: number;
382
- stream?: boolean;
383
- noWait?: boolean;
540
+ returns?: symbol;
384
541
  [key: symbol]: unknown;
385
542
  }
386
543
  interface ServiceMeta {
387
544
  name: string;
388
- ctOffset?: number;
389
545
  }
390
546
  /** Read method metadata from a decorated class. */
391
547
  declare function getMethodsMeta(cls: abstract new (...args: any[]) => any): Record<string, MethodMeta> | undefined;
392
548
  /** Read service metadata from a decorated class. */
393
549
  declare function getServiceMeta(cls: abstract new (...args: any[]) => any): ServiceMeta | undefined;
394
- /** Class decorator — stores the RPC service wire name and optional ctOffset. */
395
- declare function rpcService(serviceName: string, options?: {
396
- ctOffset?: number;
397
- }): <T extends abstract new (...args: any[]) => any>(_target: T, context: ClassDecoratorContext<T>) => void;
398
- /** Method decorator — stores RPC method metadata (argCount, stream, noWait). Does NOT wrap the method. */
550
+ /** Class decorator — stores the RPC service wire name. */
551
+ declare function rpcService(serviceName: string): <T extends abstract new (...args: any[]) => any>(_target: T, context: ClassDecoratorContext<T>) => void;
552
+ /** Method decorator — stores RPC method metadata (argCount, returns). Does NOT wrap the method. */
399
553
  declare function rpcMethod(options?: {
400
- stream?: boolean;
401
- noWait?: boolean;
554
+ returns?: symbol;
402
555
  }): <This, Args extends unknown[], Return>(target: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>) => (this: This, ...args: Args) => Return;
403
556
 
404
557
  declare const enum RpcPeerStateKind {
@@ -437,4 +590,4 @@ declare class RpcPeerStateMonitor {
437
590
  private _scheduleRecompute;
438
591
  }
439
592
 
440
- export { ARG_DELIMITER, DEFAULT_SERIALIZATION_FORMAT, ENVELOPE_DELIMITER, FRAME_DELIMITER, 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, RpcOutboundCall, RpcOutboundCallTracker, RpcPeer, RpcPeerConnectionKind, type RpcPeerState, RpcPeerStateKind, RpcPeerStateMonitor, RpcServerPeer, type RpcServiceDef, type RpcServiceDefOptions, RpcServiceHost, type RpcServiceImpl, RpcSystemCallSender, RpcSystemCalls, RpcType, RpcWebSocketConnection, type ServiceMeta, type WebSocketLike, type WebSocketServer, WebSocketState, createMessageChannelPair, createRpcClient, defaultConnectionUrlResolver, defineRpcService, deserializeMessage, getMethodsMeta, getServiceMeta, getStateDescription, handleSystemCall, isConnected, likelyConnected, rpcMethod, rpcService, serializeFrame, serializeMessage, splitFrame, wireMethodName };
593
+ 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 };
package/dist/index.d.ts CHANGED
@@ -13,6 +13,11 @@ declare const RpcSystemCalls: {
13
13
  readonly cancel: "$sys.Cancel:0";
14
14
  readonly keepAlive: "$sys.KeepAlive:1";
15
15
  readonly reconnect: "$sys.Reconnect:3";
16
+ readonly ack: "$sys.Ack:2";
17
+ readonly ackEnd: "$sys.AckEnd:1";
18
+ readonly item: "$sys.I:2";
19
+ readonly batch: "$sys.B:2";
20
+ readonly end: "$sys.End:2";
16
21
  };
17
22
  /** Wire-format RPC message envelope. */
18
23
  interface RpcMessage {
@@ -127,20 +132,18 @@ interface RpcMethodDefInput {
127
132
  args: unknown[];
128
133
  returns?: symbol;
129
134
  callTypeId?: number;
130
- stream?: boolean;
131
- noWait?: boolean;
135
+ /** Override for wireArgCount. Default: args.length + 1 (assumes a CancellationToken slot). */
136
+ wireArgCount?: number;
132
137
  }
133
138
  declare const RpcType: {
134
139
  readonly object: symbol;
135
140
  readonly stream: symbol;
141
+ readonly noWait: symbol;
136
142
  readonly void: symbol;
137
143
  };
138
- interface RpcServiceDefOptions {
139
- ctOffset?: number;
140
- }
141
144
  /** Returns the full wire method name: "ServiceName.MethodName:wireArgCount". */
142
145
  declare function wireMethodName(def: RpcMethodDef): string;
143
- declare function defineRpcService(name: string, methods: Record<string, RpcMethodDefInput>, options?: RpcServiceDefOptions): RpcServiceDef;
146
+ declare function defineRpcService(name: string, methods: Record<string, RpcMethodDefInput>): RpcServiceDef;
144
147
 
145
148
  /** Tracks a pending outbound RPC call. */
146
149
  declare class RpcOutboundCall {
@@ -191,18 +194,6 @@ declare class RpcInboundCallTracker {
191
194
  clear(): void;
192
195
  }
193
196
 
194
- /** Handles an incoming system call message and dispatches to the appropriate tracker. */
195
- declare function handleSystemCall(message: RpcMessage, args: unknown[], outboundTracker: RpcOutboundCallTracker, inboundTracker: RpcInboundCallTracker): void;
196
-
197
- /** Sends system RPC messages — like .NET's RpcSystemCallSender. */
198
- declare class RpcSystemCallSender {
199
- handshake(conn: RpcConnection, peerId: string, hubId: string, index: number): void;
200
- ok(conn: RpcConnection, relatedId: number, result: unknown): void;
201
- error(conn: RpcConnection, relatedId: number, error: unknown): void;
202
- cancel(conn: RpcConnection, relatedId: number): void;
203
- keepAlive(conn: RpcConnection, activeCallIds: number[]): void;
204
- }
205
-
206
197
  declare class RpcClientPeerReconnectDelayer extends RetryDelayer {
207
198
  constructor();
208
199
  }
@@ -222,12 +213,29 @@ declare class RpcServiceHost {
222
213
  getMethodDef(wireMethod: string): RpcMethodDef | undefined;
223
214
  }
224
215
 
216
+ /** Sends system RPC messages — like .NET's RpcSystemCallSender. */
217
+ declare class RpcSystemCallSender {
218
+ handshake(conn: RpcConnection, peerId: string, hubId: string, index: number): void;
219
+ ok(conn: RpcConnection, relatedId: number, result: unknown): void;
220
+ error(conn: RpcConnection, relatedId: number, error: unknown): void;
221
+ cancel(conn: RpcConnection, relatedId: number): void;
222
+ keepAlive(conn: RpcConnection, activeCallIds: number[]): void;
223
+ item(conn: RpcConnection, localId: number, index: number, item: unknown): void;
224
+ batch(conn: RpcConnection, localId: number, index: number, items: unknown[]): void;
225
+ end(conn: RpcConnection, localId: number, index: number, error?: {
226
+ Message: string;
227
+ } | null): void;
228
+ ack(conn: RpcConnection, localId: number, nextIndex: number, hostId: string): void;
229
+ ackEnd(conn: RpcConnection, localId: number, hostId: string): void;
230
+ }
231
+
225
232
  /** Central RPC coordinator — manages peers, services, and configuration. */
226
233
  declare class RpcHub {
227
234
  readonly hubId: string;
228
235
  readonly peers: Map<string, RpcPeer>;
229
236
  readonly serviceHost: RpcServiceHost;
230
237
  readonly systemCallSender: RpcSystemCallSender;
238
+ systemCallHandler: RpcSystemCallHandler;
231
239
  constructor(hubId?: string);
232
240
  addPeer(peer: RpcPeer): void;
233
241
  removePeer(ref: string): void;
@@ -242,8 +250,6 @@ declare class RpcHub {
242
250
  /** Create a typed client proxy for a service on a remote peer. */
243
251
  addClient<T extends object>(peer: RpcPeer, defOrContract: RpcServiceDef | (abstract new (...args: any[]) => any)): T;
244
252
  close(): void;
245
- /** Dispatch an inbound system call. Override in FusionHub to handle compute-specific system calls. */
246
- handleSystemCall(message: RpcMessage, args: unknown[], outbound: RpcOutboundCallTracker, inbound: RpcInboundCallTracker): void;
247
253
  /** Build an RpcServiceDef from decorator metadata on a contract class. Override in FusionHub for compute support. */
248
254
  protected _buildServiceDef(cls: abstract new (...args: any[]) => any): RpcServiceDef;
249
255
  /** Resolve a service def from either a plain RpcServiceDef or a contract class. */
@@ -254,6 +260,42 @@ declare class RpcHub {
254
260
  protected _createClientMethod(peer: RpcPeer, methodDef: RpcMethodDef): (...args: unknown[]) => unknown;
255
261
  }
256
262
 
263
+ interface RpcObjectId {
264
+ readonly hostId: string;
265
+ readonly localId: number;
266
+ }
267
+ declare const RpcObjectKind: {
268
+ readonly Local: 0;
269
+ readonly Remote: 1;
270
+ };
271
+ type RpcObjectKind = (typeof RpcObjectKind)[keyof typeof RpcObjectKind];
272
+ interface IRpcObject {
273
+ readonly id: RpcObjectId;
274
+ readonly kind: RpcObjectKind;
275
+ readonly allowReconnect: boolean;
276
+ reconnect(): void;
277
+ disconnect(): void;
278
+ }
279
+
280
+ declare class RpcRemoteObjectTracker {
281
+ private _objects;
282
+ register(obj: IRpcObject): void;
283
+ get(localId: number): IRpcObject | undefined;
284
+ unregister(obj: IRpcObject): void;
285
+ disconnectAll(): void;
286
+ reconnectAll(): void;
287
+ }
288
+
289
+ declare class RpcSharedObjectTracker {
290
+ private _nextId;
291
+ private _objects;
292
+ nextId(): number;
293
+ register(obj: IRpcObject): void;
294
+ get(localId: number): IRpcObject | undefined;
295
+ unregister(obj: IRpcObject): void;
296
+ disconnectAll(): void;
297
+ }
298
+
257
299
  /**
258
300
  * Default serialization format for RpcClientPeer connections.
259
301
  * TS uses plain JSON.stringify without polymorphic type wrapping,
@@ -290,6 +332,8 @@ declare abstract class RpcPeer {
290
332
  protected _connection: RpcConnection | undefined;
291
333
  readonly outbound: RpcOutboundCallTracker;
292
334
  readonly inbound: RpcInboundCallTracker;
335
+ readonly remoteObjects: RpcRemoteObjectTracker;
336
+ readonly sharedObjects: RpcSharedObjectTracker;
293
337
  readonly connected: EventHandlerSet<void>;
294
338
  readonly disconnected: EventHandlerSet<{
295
339
  code: number;
@@ -298,6 +342,7 @@ declare abstract class RpcPeer {
298
342
  protected _pendingSends: RpcOutboundCall[];
299
343
  private _keepAliveTimer;
300
344
  constructor(ref: string, hub: RpcHub);
345
+ get hub(): RpcHub;
301
346
  get connection(): RpcConnection | undefined;
302
347
  get isConnected(): boolean;
303
348
  protected setupConnection(conn: RpcConnection): void;
@@ -368,6 +413,119 @@ declare class RpcServerPeer extends RpcPeer {
368
413
  protected _onHandshakeReceived(_handshake: RemoteHandshake): void;
369
414
  }
370
415
 
416
+ /** Handles incoming system call messages — class-based equivalent of the former standalone function. */
417
+ declare class RpcSystemCallHandler {
418
+ handle(message: RpcMessage, args: unknown[], peer: RpcPeer): void;
419
+ }
420
+
421
+ /** Parsed stream reference from the server's result payload. */
422
+ interface RpcStreamRef {
423
+ readonly hostId: string;
424
+ readonly localId: number;
425
+ readonly ackPeriod: number;
426
+ readonly ackAdvance: number;
427
+ readonly allowReconnect: boolean;
428
+ }
429
+ /**
430
+ * Parses a stream reference string of the form "{hostId},{localId},{ackPeriod},{ackAdvance}".
431
+ * Returns null if the value is not a valid stream reference.
432
+ */
433
+ declare function parseStreamRef(value: unknown): RpcStreamRef | null;
434
+ /**
435
+ * Client-side RPC stream — consumes items sent by the server via system calls
436
+ * ($sys.I, $sys.B, $sys.End) and implements AsyncIterable<T> for for-await-of consumption.
437
+ *
438
+ * Wire protocol:
439
+ * - Client sends Ack(0, hostId) to start the stream
440
+ * - Server sends I (single item) / B (batch) messages
441
+ * - Client acks every ackPeriod items for flow control
442
+ * - Server sends End to signal completion (with optional error)
443
+ * - Client sends AckEnd to acknowledge completion
444
+ */
445
+ declare class RpcStream<T> implements AsyncIterable<T>, IRpcObject {
446
+ readonly id: RpcObjectId;
447
+ readonly kind: 1;
448
+ readonly allowReconnect: boolean;
449
+ readonly peer: RpcPeer;
450
+ readonly ackPeriod: number;
451
+ readonly ackAdvance: number;
452
+ private _buffer;
453
+ private _nextExpectedIndex;
454
+ private _consumerWaiting;
455
+ private _completed;
456
+ private _completionError;
457
+ private _disposed;
458
+ private _started;
459
+ private _iterating;
460
+ private _ackSentUpTo;
461
+ constructor(ref: RpcStreamRef, peer: RpcPeer);
462
+ /** Called by system call handler when a single item arrives ($sys.I). */
463
+ onItem(index: number, item: T): void;
464
+ /** Called by system call handler when a batch arrives ($sys.B). */
465
+ onBatch(index: number, items: T[]): void;
466
+ /** Called by system call handler when the stream ends ($sys.End). */
467
+ onEnd(index: number, error: Error | null): void;
468
+ reconnect(): void;
469
+ disconnect(): void;
470
+ [Symbol.asyncIterator](): AsyncIterator<T>;
471
+ dispose(): void;
472
+ private _notifyConsumer;
473
+ private _maybeSendAck;
474
+ private _sendAck;
475
+ private _sendAckEnd;
476
+ }
477
+ /**
478
+ * Recursively walks a deserialized value and replaces any stream ref strings
479
+ * with live RpcStream<unknown> instances registered on the given peer.
480
+ * This handles nested stream refs inside complex return types (e.g. Table<T>
481
+ * containing RpcStream<Row<T>> fields serialized as "{hostId},{localId},{ackPeriod},{ackAdvance}").
482
+ */
483
+ declare function resolveStreamRefs(value: unknown, peer: RpcPeer): unknown;
484
+
485
+ /**
486
+ * Server-side RPC stream producer — sends items to a remote consumer via
487
+ * $sys.I / $sys.B / $sys.End system calls.
488
+ *
489
+ * Wire protocol (server perspective):
490
+ * - Server returns the stream reference string as $sys.Ok
491
+ * - Client sends Ack(0, hostId) to start the stream
492
+ * - Server sends I (single item) / B (batch) messages
493
+ * - Client acks every ackPeriod items for flow control
494
+ * - Server sends End to signal completion (with optional error)
495
+ * - Client sends AckEnd to acknowledge completion
496
+ */
497
+ declare class RpcStreamSender<T> implements IRpcObject {
498
+ readonly id: RpcObjectId;
499
+ readonly kind: 0;
500
+ readonly allowReconnect: boolean;
501
+ readonly peer: RpcPeer;
502
+ readonly ackPeriod: number;
503
+ readonly ackAdvance: number;
504
+ private _nextIndex;
505
+ private _ended;
506
+ private _started;
507
+ constructor(peer: RpcPeer, ackPeriod?: number, ackAdvance?: number, allowReconnect?: boolean);
508
+ /** Returns the stream reference string for the $sys.Ok response. */
509
+ toRef(): string;
510
+ /** Called by system call handler when $sys.Ack is received from the client. */
511
+ onAck(_nextIndex: number, _hostId: string): void;
512
+ /** Called by system call handler when $sys.AckEnd is received from the client. */
513
+ onAckEnd(_hostId: string): void;
514
+ /** Send a single item to the client. */
515
+ sendItem(item: T): void;
516
+ /** Send a batch of items to the client. */
517
+ sendBatch(items: T[]): void;
518
+ /** Signal stream completion to the client. */
519
+ sendEnd(error?: Error | null): void;
520
+ /**
521
+ * Consume an AsyncIterable and send all items to the client.
522
+ * Waits for the client's initial Ack before starting to pump items.
523
+ */
524
+ writeFrom(source: AsyncIterable<T>): Promise<void>;
525
+ reconnect(): void;
526
+ disconnect(): void;
527
+ }
528
+
371
529
  /** Creates a typed RPC client proxy — intercepts method calls and sends them over RPC. */
372
530
  declare function createRpcClient<T extends object>(peer: RpcPeer, serviceDef: RpcServiceDef): T;
373
531
 
@@ -379,26 +537,21 @@ interface WebSocketServer {
379
537
 
380
538
  interface MethodMeta {
381
539
  argCount: number;
382
- stream?: boolean;
383
- noWait?: boolean;
540
+ returns?: symbol;
384
541
  [key: symbol]: unknown;
385
542
  }
386
543
  interface ServiceMeta {
387
544
  name: string;
388
- ctOffset?: number;
389
545
  }
390
546
  /** Read method metadata from a decorated class. */
391
547
  declare function getMethodsMeta(cls: abstract new (...args: any[]) => any): Record<string, MethodMeta> | undefined;
392
548
  /** Read service metadata from a decorated class. */
393
549
  declare function getServiceMeta(cls: abstract new (...args: any[]) => any): ServiceMeta | undefined;
394
- /** Class decorator — stores the RPC service wire name and optional ctOffset. */
395
- declare function rpcService(serviceName: string, options?: {
396
- ctOffset?: number;
397
- }): <T extends abstract new (...args: any[]) => any>(_target: T, context: ClassDecoratorContext<T>) => void;
398
- /** Method decorator — stores RPC method metadata (argCount, stream, noWait). Does NOT wrap the method. */
550
+ /** Class decorator — stores the RPC service wire name. */
551
+ declare function rpcService(serviceName: string): <T extends abstract new (...args: any[]) => any>(_target: T, context: ClassDecoratorContext<T>) => void;
552
+ /** Method decorator — stores RPC method metadata (argCount, returns). Does NOT wrap the method. */
399
553
  declare function rpcMethod(options?: {
400
- stream?: boolean;
401
- noWait?: boolean;
554
+ returns?: symbol;
402
555
  }): <This, Args extends unknown[], Return>(target: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>) => (this: This, ...args: Args) => Return;
403
556
 
404
557
  declare const enum RpcPeerStateKind {
@@ -437,4 +590,4 @@ declare class RpcPeerStateMonitor {
437
590
  private _scheduleRecompute;
438
591
  }
439
592
 
440
- export { ARG_DELIMITER, DEFAULT_SERIALIZATION_FORMAT, ENVELOPE_DELIMITER, FRAME_DELIMITER, 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, RpcOutboundCall, RpcOutboundCallTracker, RpcPeer, RpcPeerConnectionKind, type RpcPeerState, RpcPeerStateKind, RpcPeerStateMonitor, RpcServerPeer, type RpcServiceDef, type RpcServiceDefOptions, RpcServiceHost, type RpcServiceImpl, RpcSystemCallSender, RpcSystemCalls, RpcType, RpcWebSocketConnection, type ServiceMeta, type WebSocketLike, type WebSocketServer, WebSocketState, createMessageChannelPair, createRpcClient, defaultConnectionUrlResolver, defineRpcService, deserializeMessage, getMethodsMeta, getServiceMeta, getStateDescription, handleSystemCall, isConnected, likelyConnected, rpcMethod, rpcService, serializeFrame, serializeMessage, splitFrame, wireMethodName };
593
+ 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 };