react-websocket 3.3.0 → 3.6.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.
- package/README.md +15 -6
- package/dist/chaos.cjs +284 -0
- package/dist/chaos.cjs.map +1 -0
- package/dist/chaos.d.cts +131 -0
- package/dist/chaos.d.ts +131 -0
- package/dist/chaos.js +283 -0
- package/dist/chaos.js.map +1 -0
- package/dist/core.cjs +271 -72
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +166 -11
- package/dist/core.d.ts +166 -11
- package/dist/core.js +271 -73
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +64 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +221 -11
- package/dist/index.d.ts +140 -5
- package/dist/index.js +65 -2
- package/dist/index.js.map +1 -1
- package/dist/timeline.cjs +162 -0
- package/dist/timeline.cjs.map +1 -0
- package/dist/timeline.d.cts +379 -0
- package/dist/timeline.d.ts +140 -0
- package/dist/timeline.js +161 -0
- package/dist/timeline.js.map +1 -0
- package/package.json +67 -16
package/dist/core.d.cts
CHANGED
|
@@ -111,14 +111,42 @@ interface SendOptions {
|
|
|
111
111
|
volatile?: boolean;
|
|
112
112
|
/**
|
|
113
113
|
* Keep only the newest queued message with this key. Sending again with the same key
|
|
114
|
-
* while disconnected replaces the earlier one, which moves to the back of the queue
|
|
114
|
+
* while disconnected replaces the earlier one, which moves to the back of the queue
|
|
115
|
+
* (or of the `priority` messages, for a priority one).
|
|
115
116
|
* For state where only the latest value matters, such as "my position is now (x, y)".
|
|
116
117
|
*/
|
|
117
118
|
key?: string;
|
|
119
|
+
/**
|
|
120
|
+
* Queue this message ahead of every message queued without `priority`, after earlier
|
|
121
|
+
* priority messages. For control messages that must not wait behind a backlog, such as
|
|
122
|
+
* cancel, interrupt or a token refresh. Messages sent from `open` listeners still go first.
|
|
123
|
+
*
|
|
124
|
+
* It only matters while the socket isn't open: once a message is handed to the browser,
|
|
125
|
+
* nothing can overtake it. To keep that buffer short, send bulky streams with `maxBuffered`.
|
|
126
|
+
* @default false
|
|
127
|
+
*/
|
|
128
|
+
priority?: boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Drop the message instead of sending it while more than this many bytes are already
|
|
131
|
+
* waiting in the browser's send buffer (`socket.bufferedAmount`). For high-rate streams on
|
|
132
|
+
* a slow link, such as audio frames or per-tick input, where a late message is worse than
|
|
133
|
+
* none. `send()` returns `false`, and `onDrop` isn't called.
|
|
134
|
+
*
|
|
135
|
+
* Only checked while the socket is open: a message queued while disconnected is sent on
|
|
136
|
+
* open regardless. `bufferedAmount` includes what you sent earlier in the same task, so set
|
|
137
|
+
* it well above one burst of messages.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```ts
|
|
141
|
+
* voice.send(frame, { volatile: true, maxBuffered: 64 * 1024 });
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
maxBuffered?: number;
|
|
118
145
|
/**
|
|
119
146
|
* Called if the message is dropped from the queue without being sent: replaced by a
|
|
120
147
|
* newer message with the same `key`, or evicted by `queue.limit`. Not called when the
|
|
121
|
-
* queue is cleared because the client closed or gave up
|
|
148
|
+
* queue is cleared because the client closed or gave up, or when `send()` drops the
|
|
149
|
+
* message right away (`volatile` while not open, or `maxBuffered`) and returns `false`.
|
|
122
150
|
*/
|
|
123
151
|
onDrop?: () => void;
|
|
124
152
|
}
|
|
@@ -126,7 +154,7 @@ interface SendOptions {
|
|
|
126
154
|
interface QueueOptions {
|
|
127
155
|
/**
|
|
128
156
|
* Maximum number of messages held while not connected. When full, the oldest
|
|
129
|
-
* message is dropped.
|
|
157
|
+
* message is dropped, skipping `priority` messages unless nothing else is queued.
|
|
130
158
|
* @default Infinity
|
|
131
159
|
*/
|
|
132
160
|
limit?: number;
|
|
@@ -309,12 +337,14 @@ interface WebSocketClient<In = unknown, Out = unknown> {
|
|
|
309
337
|
* Send a message (encoded with `serialize`/`json` if configured). If the socket isn't
|
|
310
338
|
* open, the message is queued and sent on open (see the `queue` option), unless
|
|
311
339
|
* `options.volatile` is set.
|
|
312
|
-
* @returns `true` if it was sent immediately, `false` if it was queued or dropped
|
|
340
|
+
* @returns `true` if it was sent immediately, `false` if it was queued or dropped
|
|
341
|
+
* (`volatile` while not open, or `maxBuffered` while open).
|
|
313
342
|
*
|
|
314
343
|
* @example
|
|
315
344
|
* ```ts
|
|
316
345
|
* game.send({ type: 'input', dx, dy }, { volatile: true }); // never replayed after a reconnect
|
|
317
346
|
* game.send({ type: 'position', x, y }, { key: 'position' }); // only the newest is queued
|
|
347
|
+
* game.send({ type: 'leave' }, { priority: true }); // ahead of everything already queued
|
|
318
348
|
* ```
|
|
319
349
|
*/
|
|
320
350
|
send(message: Out, options?: SendOptions): boolean;
|
|
@@ -457,20 +487,36 @@ interface WebSocketRequestsOptions<Req, In, Out> {
|
|
|
457
487
|
reply: (message: In) => number | string | null | undefined;
|
|
458
488
|
/**
|
|
459
489
|
* Called on a reply. Return something other than `undefined` to reject the request with
|
|
460
|
-
* it instead of resolving, e.g. for a server-side error reply.
|
|
490
|
+
* it instead of resolving, e.g. for a server-side error reply. A stream throws it.
|
|
461
491
|
*/
|
|
462
492
|
error?: (message: In) => unknown;
|
|
463
493
|
/**
|
|
464
|
-
*
|
|
494
|
+
* Whether a reply is the last one of a stream. `stream()` needs it. That reply is yielded
|
|
495
|
+
* too, then the stream ends.
|
|
496
|
+
*/
|
|
497
|
+
done?: (message: In) => boolean;
|
|
498
|
+
/**
|
|
499
|
+
* Build the message that tells the server to stop working on request `id`. Sent when this
|
|
500
|
+
* side gives up: the request's `signal` aborts, it times out, a loop over a stream exits
|
|
501
|
+
* early, or the manager is disposed. Not sent after the last reply, an error reply, a lost
|
|
502
|
+
* connection or `close()`.
|
|
503
|
+
*/
|
|
504
|
+
cancel?: (id: number) => Out;
|
|
505
|
+
/**
|
|
506
|
+
* Default time to wait for a reply, in ms. For a stream, the time to wait for each reply,
|
|
507
|
+
* including the first. `Infinity` waits forever.
|
|
465
508
|
* @default 10000
|
|
466
509
|
*/
|
|
467
510
|
timeout?: number;
|
|
468
511
|
}
|
|
469
|
-
/** Per-call options for {@link WebSocketRequests.request}. */
|
|
512
|
+
/** Per-call options for {@link WebSocketRequests.request} and {@link WebSocketRequests.stream}. */
|
|
470
513
|
interface RequestOptions extends SendOptions {
|
|
471
|
-
/**
|
|
514
|
+
/**
|
|
515
|
+
* Time to wait for a reply (for a stream, for each reply), in ms. Overrides the manager's
|
|
516
|
+
* `timeout`.
|
|
517
|
+
*/
|
|
472
518
|
timeout?: number;
|
|
473
|
-
/** Abort the request. It rejects with `signal.reason`. A late reply is ignored. */
|
|
519
|
+
/** Abort the request. It rejects (a stream throws) with `signal.reason`. A late reply is ignored. */
|
|
474
520
|
signal?: AbortSignal;
|
|
475
521
|
}
|
|
476
522
|
/** Request/response over one client. Create with {@link createWebSocketRequests}. */
|
|
@@ -487,7 +533,26 @@ interface WebSocketRequests<Req, In> {
|
|
|
487
533
|
* queue (replaced by a newer request with the same `key`, or evicted by `queue.limit`).
|
|
488
534
|
*/
|
|
489
535
|
request(message: Req, options?: RequestOptions): Promise<In>;
|
|
490
|
-
/**
|
|
536
|
+
/**
|
|
537
|
+
* Send a request and iterate over its replies, up to and including the one `done` matches.
|
|
538
|
+
* Holds the connection until the stream ends. Needs the `done` option.
|
|
539
|
+
*
|
|
540
|
+
* `timeout` is the time to wait for each reply. Replies that arrive before the loop reads
|
|
541
|
+
* them are buffered. The stream is one-shot: iterate it once.
|
|
542
|
+
*
|
|
543
|
+
* Fails where `request()` rejects, with the same errors, after yielding the replies already
|
|
544
|
+
* received. Aborting `signal` throws `signal.reason` right away and discards them. Leaving
|
|
545
|
+
* the loop early, aborting and timing out send `cancel`.
|
|
546
|
+
*
|
|
547
|
+
* @example
|
|
548
|
+
* ```ts
|
|
549
|
+
* for await (const reply of rpc.stream({ type: 'ask', prompt }, { signal })) {
|
|
550
|
+
* text += reply.delta;
|
|
551
|
+
* }
|
|
552
|
+
* ```
|
|
553
|
+
*/
|
|
554
|
+
stream(message: Req, options?: RequestOptions): AsyncIterableIterator<In>;
|
|
555
|
+
/** Number of requests and streams waiting for a reply. */
|
|
491
556
|
pending(): number;
|
|
492
557
|
/** Reject every pending request and stop listening. Only needed for managers created dynamically. */
|
|
493
558
|
dispose(): void;
|
|
@@ -649,6 +714,85 @@ interface WebSocketResponder<P = unknown, R = unknown> {
|
|
|
649
714
|
*/
|
|
650
715
|
export declare function createWebSocketResponder<Q extends RequestFields, R, In, const Out>(client: WebSocketClient<In, Out>, options: WebSocketResponderOptions<Q, R, NoInfer<In>, NoInfer<Out>>): WebSocketResponder<ParamsOf<Q>, R>;
|
|
651
716
|
//#endregion
|
|
717
|
+
//#region src/sendrate.d.ts
|
|
718
|
+
/** Options for {@link createWebSocketSendRate}. */
|
|
719
|
+
interface WebSocketSendRateOptions {
|
|
720
|
+
/**
|
|
721
|
+
* Ticks per second while the connection keeps up.
|
|
722
|
+
* @default 30
|
|
723
|
+
*/
|
|
724
|
+
maxRate?: number;
|
|
725
|
+
/**
|
|
726
|
+
* The rate never drops below this, in ticks per second.
|
|
727
|
+
* @default 5
|
|
728
|
+
*/
|
|
729
|
+
minRate?: number;
|
|
730
|
+
/**
|
|
731
|
+
* Bytes waiting in the browser's send buffer (`socket.bufferedAmount`) above which a tick
|
|
732
|
+
* sends nothing and the rate halves.
|
|
733
|
+
* @default 1024
|
|
734
|
+
*/
|
|
735
|
+
maxBuffered?: number;
|
|
736
|
+
/**
|
|
737
|
+
* Measurements from `createWebSocketLatency` on the same client. With them, a round-trip time
|
|
738
|
+
* that rises also lowers the rate. Without them, only the send buffer is watched.
|
|
739
|
+
*/
|
|
740
|
+
latency?: Pick<WebSocketLatency, 'getSnapshot'>;
|
|
741
|
+
/**
|
|
742
|
+
* How far `rtt` may rise above the lowest one measured on this connection before the rate
|
|
743
|
+
* halves, in ms. A steady high ping keeps the full rate; only a rising one counts.
|
|
744
|
+
* @default 100
|
|
745
|
+
*/
|
|
746
|
+
maxRttIncrease?: number;
|
|
747
|
+
}
|
|
748
|
+
/** The current send rate. A new object is created on every change. */
|
|
749
|
+
interface SendRate {
|
|
750
|
+
/** Ticks per second, rounded. */
|
|
751
|
+
readonly rate: number;
|
|
752
|
+
/**
|
|
753
|
+
* Whether the last tick found the link congested: the send buffer above `maxBuffered`, or
|
|
754
|
+
* `rtt` risen more than `maxRttIncrease`.
|
|
755
|
+
*/
|
|
756
|
+
readonly congested: boolean;
|
|
757
|
+
}
|
|
758
|
+
/** Keyed sends coalesced at a rate that adapts to the link. Create with {@link createWebSocketSendRate}. */
|
|
759
|
+
interface WebSocketSendRate<Out> {
|
|
760
|
+
/** The client the messages are sent on. */
|
|
761
|
+
readonly client: WebSocketClient<any, Out>;
|
|
762
|
+
/**
|
|
763
|
+
* Send `message` at the next tick. A message with the same `key` still waiting for it is
|
|
764
|
+
* replaced, so only the newest one goes out. Sent with `volatile`.
|
|
765
|
+
*/
|
|
766
|
+
send(message: Out, key: string): void;
|
|
767
|
+
/** Send everything waiting now, e.g. right before a one-shot action that must carry the latest aim. */
|
|
768
|
+
flush(): void;
|
|
769
|
+
/** The current {@link SendRate}. Returns the same object until it changes. */
|
|
770
|
+
getSnapshot(): SendRate;
|
|
771
|
+
/** Called whenever the rate or `congested` changes. Compatible with `useSyncExternalStore`. */
|
|
772
|
+
subscribe(listener: () => void): () => void;
|
|
773
|
+
/** Stop sending and listening. Only needed for instances created dynamically. */
|
|
774
|
+
dispose(): void;
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
777
|
+
* Send high-rate state, such as aim, cursor or position, at a rate that adapts to the
|
|
778
|
+
* connection. Messages are coalesced per key between ticks. The rate drops by half when the
|
|
779
|
+
* send buffer fills up or the round trip grows, and climbs back one tick per second at a time
|
|
780
|
+
* when the link keeps up, so players on a poor connection degrade smoothly instead of building
|
|
781
|
+
* up lag.
|
|
782
|
+
*
|
|
783
|
+
* Ticks run only while the socket is open and something is waiting. Messages waiting during a
|
|
784
|
+
* reconnect go out after it; `close()` drops them. It doesn't open the connection by itself.
|
|
785
|
+
*
|
|
786
|
+
* @example
|
|
787
|
+
* ```ts
|
|
788
|
+
* export const stream = createWebSocketSendRate(game, { latency, maxRate: 30 });
|
|
789
|
+
*
|
|
790
|
+
* // On every pointer move: at most 30 a second, fewer on a congested link.
|
|
791
|
+
* stream.send({ type: 'aim', angle }, 'aim');
|
|
792
|
+
* ```
|
|
793
|
+
*/
|
|
794
|
+
export declare function createWebSocketSendRate<Out>(client: WebSocketClient<any, Out>, options?: WebSocketSendRateOptions): WebSocketSendRate<Out>;
|
|
795
|
+
//#endregion
|
|
652
796
|
//#region src/state.d.ts
|
|
653
797
|
/** Options for {@link createWebSocketState}. */
|
|
654
798
|
interface WebSocketStateOptions<S, In> {
|
|
@@ -659,6 +803,17 @@ interface WebSocketStateOptions<S, In> {
|
|
|
659
803
|
* change, or the same `state` to ignore the message (subscribers aren't notified).
|
|
660
804
|
*/
|
|
661
805
|
reduce: (state: S, message: In) => S;
|
|
806
|
+
/**
|
|
807
|
+
* `'frame'`: notify subscribers at most once per animation frame instead of once per
|
|
808
|
+
* message, so a fast stream (tokens, tickers, game state) renders once per frame.
|
|
809
|
+
* `getState()` is always current; only notifications wait. `setState` and `reset` still
|
|
810
|
+
* notify right away.
|
|
811
|
+
*
|
|
812
|
+
* Browsers pause animation frames in background tabs: the state keeps up, and subscribers
|
|
813
|
+
* hear about it when the tab is visible again. Without `requestAnimationFrame` (Node, some
|
|
814
|
+
* workers), it waits about 16 ms instead.
|
|
815
|
+
*/
|
|
816
|
+
batch?: 'frame';
|
|
662
817
|
}
|
|
663
818
|
/**
|
|
664
819
|
* State derived from a client's messages. Read it with `useWebSocketState(store, selector)`,
|
|
@@ -748,5 +903,5 @@ interface WebSocketTopics {
|
|
|
748
903
|
*/
|
|
749
904
|
export declare function createWebSocketTopics<const Out>(client: WebSocketClient<any, Out>, options: WebSocketTopicsOptions<NoInfer<Out>>): WebSocketTopics;
|
|
750
905
|
//#endregion
|
|
751
|
-
export type { CloseInfo, EventMap, HeartbeatOptions, IncomingRequest, Latency, QueueOptions, ReconnectOptions, RequestHandler, RequestOptions, SendData, SendOptions, Snapshot, StandardSchemaV1, Status, UrlSource, WebSocketClient, WebSocketLatency, WebSocketLatencyOptions, WebSocketOptions, WebSocketRequests, WebSocketRequestsOptions, WebSocketResponder, WebSocketResponderOptions, WebSocketState, WebSocketStateOptions, WebSocketTopics, WebSocketTopicsOptions };
|
|
906
|
+
export type { CloseInfo, EventMap, HeartbeatOptions, IncomingRequest, Latency, QueueOptions, ReconnectOptions, RequestHandler, RequestOptions, SendData, SendOptions, SendRate, Snapshot, StandardSchemaV1, Status, UrlSource, WebSocketClient, WebSocketLatency, WebSocketLatencyOptions, WebSocketOptions, WebSocketRequests, WebSocketRequestsOptions, WebSocketResponder, WebSocketResponderOptions, WebSocketSendRate, WebSocketSendRateOptions, WebSocketState, WebSocketStateOptions, WebSocketTopics, WebSocketTopicsOptions };
|
|
752
907
|
//# sourceMappingURL=core.d.cts.map
|
package/dist/core.d.ts
CHANGED
|
@@ -111,14 +111,42 @@ interface SendOptions {
|
|
|
111
111
|
volatile?: boolean;
|
|
112
112
|
/**
|
|
113
113
|
* Keep only the newest queued message with this key. Sending again with the same key
|
|
114
|
-
* while disconnected replaces the earlier one, which moves to the back of the queue
|
|
114
|
+
* while disconnected replaces the earlier one, which moves to the back of the queue
|
|
115
|
+
* (or of the `priority` messages, for a priority one).
|
|
115
116
|
* For state where only the latest value matters, such as "my position is now (x, y)".
|
|
116
117
|
*/
|
|
117
118
|
key?: string;
|
|
119
|
+
/**
|
|
120
|
+
* Queue this message ahead of every message queued without `priority`, after earlier
|
|
121
|
+
* priority messages. For control messages that must not wait behind a backlog, such as
|
|
122
|
+
* cancel, interrupt or a token refresh. Messages sent from `open` listeners still go first.
|
|
123
|
+
*
|
|
124
|
+
* It only matters while the socket isn't open: once a message is handed to the browser,
|
|
125
|
+
* nothing can overtake it. To keep that buffer short, send bulky streams with `maxBuffered`.
|
|
126
|
+
* @default false
|
|
127
|
+
*/
|
|
128
|
+
priority?: boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Drop the message instead of sending it while more than this many bytes are already
|
|
131
|
+
* waiting in the browser's send buffer (`socket.bufferedAmount`). For high-rate streams on
|
|
132
|
+
* a slow link, such as audio frames or per-tick input, where a late message is worse than
|
|
133
|
+
* none. `send()` returns `false`, and `onDrop` isn't called.
|
|
134
|
+
*
|
|
135
|
+
* Only checked while the socket is open: a message queued while disconnected is sent on
|
|
136
|
+
* open regardless. `bufferedAmount` includes what you sent earlier in the same task, so set
|
|
137
|
+
* it well above one burst of messages.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```ts
|
|
141
|
+
* voice.send(frame, { volatile: true, maxBuffered: 64 * 1024 });
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
maxBuffered?: number;
|
|
118
145
|
/**
|
|
119
146
|
* Called if the message is dropped from the queue without being sent: replaced by a
|
|
120
147
|
* newer message with the same `key`, or evicted by `queue.limit`. Not called when the
|
|
121
|
-
* queue is cleared because the client closed or gave up
|
|
148
|
+
* queue is cleared because the client closed or gave up, or when `send()` drops the
|
|
149
|
+
* message right away (`volatile` while not open, or `maxBuffered`) and returns `false`.
|
|
122
150
|
*/
|
|
123
151
|
onDrop?: () => void;
|
|
124
152
|
}
|
|
@@ -126,7 +154,7 @@ interface SendOptions {
|
|
|
126
154
|
interface QueueOptions {
|
|
127
155
|
/**
|
|
128
156
|
* Maximum number of messages held while not connected. When full, the oldest
|
|
129
|
-
* message is dropped.
|
|
157
|
+
* message is dropped, skipping `priority` messages unless nothing else is queued.
|
|
130
158
|
* @default Infinity
|
|
131
159
|
*/
|
|
132
160
|
limit?: number;
|
|
@@ -309,12 +337,14 @@ interface WebSocketClient<In = unknown, Out = unknown> {
|
|
|
309
337
|
* Send a message (encoded with `serialize`/`json` if configured). If the socket isn't
|
|
310
338
|
* open, the message is queued and sent on open (see the `queue` option), unless
|
|
311
339
|
* `options.volatile` is set.
|
|
312
|
-
* @returns `true` if it was sent immediately, `false` if it was queued or dropped
|
|
340
|
+
* @returns `true` if it was sent immediately, `false` if it was queued or dropped
|
|
341
|
+
* (`volatile` while not open, or `maxBuffered` while open).
|
|
313
342
|
*
|
|
314
343
|
* @example
|
|
315
344
|
* ```ts
|
|
316
345
|
* game.send({ type: 'input', dx, dy }, { volatile: true }); // never replayed after a reconnect
|
|
317
346
|
* game.send({ type: 'position', x, y }, { key: 'position' }); // only the newest is queued
|
|
347
|
+
* game.send({ type: 'leave' }, { priority: true }); // ahead of everything already queued
|
|
318
348
|
* ```
|
|
319
349
|
*/
|
|
320
350
|
send(message: Out, options?: SendOptions): boolean;
|
|
@@ -457,20 +487,36 @@ interface WebSocketRequestsOptions<Req, In, Out> {
|
|
|
457
487
|
reply: (message: In) => number | string | null | undefined;
|
|
458
488
|
/**
|
|
459
489
|
* Called on a reply. Return something other than `undefined` to reject the request with
|
|
460
|
-
* it instead of resolving, e.g. for a server-side error reply.
|
|
490
|
+
* it instead of resolving, e.g. for a server-side error reply. A stream throws it.
|
|
461
491
|
*/
|
|
462
492
|
error?: (message: In) => unknown;
|
|
463
493
|
/**
|
|
464
|
-
*
|
|
494
|
+
* Whether a reply is the last one of a stream. `stream()` needs it. That reply is yielded
|
|
495
|
+
* too, then the stream ends.
|
|
496
|
+
*/
|
|
497
|
+
done?: (message: In) => boolean;
|
|
498
|
+
/**
|
|
499
|
+
* Build the message that tells the server to stop working on request `id`. Sent when this
|
|
500
|
+
* side gives up: the request's `signal` aborts, it times out, a loop over a stream exits
|
|
501
|
+
* early, or the manager is disposed. Not sent after the last reply, an error reply, a lost
|
|
502
|
+
* connection or `close()`.
|
|
503
|
+
*/
|
|
504
|
+
cancel?: (id: number) => Out;
|
|
505
|
+
/**
|
|
506
|
+
* Default time to wait for a reply, in ms. For a stream, the time to wait for each reply,
|
|
507
|
+
* including the first. `Infinity` waits forever.
|
|
465
508
|
* @default 10000
|
|
466
509
|
*/
|
|
467
510
|
timeout?: number;
|
|
468
511
|
}
|
|
469
|
-
/** Per-call options for {@link WebSocketRequests.request}. */
|
|
512
|
+
/** Per-call options for {@link WebSocketRequests.request} and {@link WebSocketRequests.stream}. */
|
|
470
513
|
interface RequestOptions extends SendOptions {
|
|
471
|
-
/**
|
|
514
|
+
/**
|
|
515
|
+
* Time to wait for a reply (for a stream, for each reply), in ms. Overrides the manager's
|
|
516
|
+
* `timeout`.
|
|
517
|
+
*/
|
|
472
518
|
timeout?: number;
|
|
473
|
-
/** Abort the request. It rejects with `signal.reason`. A late reply is ignored. */
|
|
519
|
+
/** Abort the request. It rejects (a stream throws) with `signal.reason`. A late reply is ignored. */
|
|
474
520
|
signal?: AbortSignal;
|
|
475
521
|
}
|
|
476
522
|
/** Request/response over one client. Create with {@link createWebSocketRequests}. */
|
|
@@ -487,7 +533,26 @@ interface WebSocketRequests<Req, In> {
|
|
|
487
533
|
* queue (replaced by a newer request with the same `key`, or evicted by `queue.limit`).
|
|
488
534
|
*/
|
|
489
535
|
request(message: Req, options?: RequestOptions): Promise<In>;
|
|
490
|
-
/**
|
|
536
|
+
/**
|
|
537
|
+
* Send a request and iterate over its replies, up to and including the one `done` matches.
|
|
538
|
+
* Holds the connection until the stream ends. Needs the `done` option.
|
|
539
|
+
*
|
|
540
|
+
* `timeout` is the time to wait for each reply. Replies that arrive before the loop reads
|
|
541
|
+
* them are buffered. The stream is one-shot: iterate it once.
|
|
542
|
+
*
|
|
543
|
+
* Fails where `request()` rejects, with the same errors, after yielding the replies already
|
|
544
|
+
* received. Aborting `signal` throws `signal.reason` right away and discards them. Leaving
|
|
545
|
+
* the loop early, aborting and timing out send `cancel`.
|
|
546
|
+
*
|
|
547
|
+
* @example
|
|
548
|
+
* ```ts
|
|
549
|
+
* for await (const reply of rpc.stream({ type: 'ask', prompt }, { signal })) {
|
|
550
|
+
* text += reply.delta;
|
|
551
|
+
* }
|
|
552
|
+
* ```
|
|
553
|
+
*/
|
|
554
|
+
stream(message: Req, options?: RequestOptions): AsyncIterableIterator<In>;
|
|
555
|
+
/** Number of requests and streams waiting for a reply. */
|
|
491
556
|
pending(): number;
|
|
492
557
|
/** Reject every pending request and stop listening. Only needed for managers created dynamically. */
|
|
493
558
|
dispose(): void;
|
|
@@ -649,6 +714,85 @@ interface WebSocketResponder<P = unknown, R = unknown> {
|
|
|
649
714
|
*/
|
|
650
715
|
export declare function createWebSocketResponder<Q extends RequestFields, R, In, const Out>(client: WebSocketClient<In, Out>, options: WebSocketResponderOptions<Q, R, NoInfer<In>, NoInfer<Out>>): WebSocketResponder<ParamsOf<Q>, R>;
|
|
651
716
|
//#endregion
|
|
717
|
+
//#region src/sendrate.d.ts
|
|
718
|
+
/** Options for {@link createWebSocketSendRate}. */
|
|
719
|
+
interface WebSocketSendRateOptions {
|
|
720
|
+
/**
|
|
721
|
+
* Ticks per second while the connection keeps up.
|
|
722
|
+
* @default 30
|
|
723
|
+
*/
|
|
724
|
+
maxRate?: number;
|
|
725
|
+
/**
|
|
726
|
+
* The rate never drops below this, in ticks per second.
|
|
727
|
+
* @default 5
|
|
728
|
+
*/
|
|
729
|
+
minRate?: number;
|
|
730
|
+
/**
|
|
731
|
+
* Bytes waiting in the browser's send buffer (`socket.bufferedAmount`) above which a tick
|
|
732
|
+
* sends nothing and the rate halves.
|
|
733
|
+
* @default 1024
|
|
734
|
+
*/
|
|
735
|
+
maxBuffered?: number;
|
|
736
|
+
/**
|
|
737
|
+
* Measurements from `createWebSocketLatency` on the same client. With them, a round-trip time
|
|
738
|
+
* that rises also lowers the rate. Without them, only the send buffer is watched.
|
|
739
|
+
*/
|
|
740
|
+
latency?: Pick<WebSocketLatency, 'getSnapshot'>;
|
|
741
|
+
/**
|
|
742
|
+
* How far `rtt` may rise above the lowest one measured on this connection before the rate
|
|
743
|
+
* halves, in ms. A steady high ping keeps the full rate; only a rising one counts.
|
|
744
|
+
* @default 100
|
|
745
|
+
*/
|
|
746
|
+
maxRttIncrease?: number;
|
|
747
|
+
}
|
|
748
|
+
/** The current send rate. A new object is created on every change. */
|
|
749
|
+
interface SendRate {
|
|
750
|
+
/** Ticks per second, rounded. */
|
|
751
|
+
readonly rate: number;
|
|
752
|
+
/**
|
|
753
|
+
* Whether the last tick found the link congested: the send buffer above `maxBuffered`, or
|
|
754
|
+
* `rtt` risen more than `maxRttIncrease`.
|
|
755
|
+
*/
|
|
756
|
+
readonly congested: boolean;
|
|
757
|
+
}
|
|
758
|
+
/** Keyed sends coalesced at a rate that adapts to the link. Create with {@link createWebSocketSendRate}. */
|
|
759
|
+
interface WebSocketSendRate<Out> {
|
|
760
|
+
/** The client the messages are sent on. */
|
|
761
|
+
readonly client: WebSocketClient<any, Out>;
|
|
762
|
+
/**
|
|
763
|
+
* Send `message` at the next tick. A message with the same `key` still waiting for it is
|
|
764
|
+
* replaced, so only the newest one goes out. Sent with `volatile`.
|
|
765
|
+
*/
|
|
766
|
+
send(message: Out, key: string): void;
|
|
767
|
+
/** Send everything waiting now, e.g. right before a one-shot action that must carry the latest aim. */
|
|
768
|
+
flush(): void;
|
|
769
|
+
/** The current {@link SendRate}. Returns the same object until it changes. */
|
|
770
|
+
getSnapshot(): SendRate;
|
|
771
|
+
/** Called whenever the rate or `congested` changes. Compatible with `useSyncExternalStore`. */
|
|
772
|
+
subscribe(listener: () => void): () => void;
|
|
773
|
+
/** Stop sending and listening. Only needed for instances created dynamically. */
|
|
774
|
+
dispose(): void;
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
777
|
+
* Send high-rate state, such as aim, cursor or position, at a rate that adapts to the
|
|
778
|
+
* connection. Messages are coalesced per key between ticks. The rate drops by half when the
|
|
779
|
+
* send buffer fills up or the round trip grows, and climbs back one tick per second at a time
|
|
780
|
+
* when the link keeps up, so players on a poor connection degrade smoothly instead of building
|
|
781
|
+
* up lag.
|
|
782
|
+
*
|
|
783
|
+
* Ticks run only while the socket is open and something is waiting. Messages waiting during a
|
|
784
|
+
* reconnect go out after it; `close()` drops them. It doesn't open the connection by itself.
|
|
785
|
+
*
|
|
786
|
+
* @example
|
|
787
|
+
* ```ts
|
|
788
|
+
* export const stream = createWebSocketSendRate(game, { latency, maxRate: 30 });
|
|
789
|
+
*
|
|
790
|
+
* // On every pointer move: at most 30 a second, fewer on a congested link.
|
|
791
|
+
* stream.send({ type: 'aim', angle }, 'aim');
|
|
792
|
+
* ```
|
|
793
|
+
*/
|
|
794
|
+
export declare function createWebSocketSendRate<Out>(client: WebSocketClient<any, Out>, options?: WebSocketSendRateOptions): WebSocketSendRate<Out>;
|
|
795
|
+
//#endregion
|
|
652
796
|
//#region src/state.d.ts
|
|
653
797
|
/** Options for {@link createWebSocketState}. */
|
|
654
798
|
interface WebSocketStateOptions<S, In> {
|
|
@@ -659,6 +803,17 @@ interface WebSocketStateOptions<S, In> {
|
|
|
659
803
|
* change, or the same `state` to ignore the message (subscribers aren't notified).
|
|
660
804
|
*/
|
|
661
805
|
reduce: (state: S, message: In) => S;
|
|
806
|
+
/**
|
|
807
|
+
* `'frame'`: notify subscribers at most once per animation frame instead of once per
|
|
808
|
+
* message, so a fast stream (tokens, tickers, game state) renders once per frame.
|
|
809
|
+
* `getState()` is always current; only notifications wait. `setState` and `reset` still
|
|
810
|
+
* notify right away.
|
|
811
|
+
*
|
|
812
|
+
* Browsers pause animation frames in background tabs: the state keeps up, and subscribers
|
|
813
|
+
* hear about it when the tab is visible again. Without `requestAnimationFrame` (Node, some
|
|
814
|
+
* workers), it waits about 16 ms instead.
|
|
815
|
+
*/
|
|
816
|
+
batch?: 'frame';
|
|
662
817
|
}
|
|
663
818
|
/**
|
|
664
819
|
* State derived from a client's messages. Read it with `useWebSocketState(store, selector)`,
|
|
@@ -748,5 +903,5 @@ interface WebSocketTopics {
|
|
|
748
903
|
*/
|
|
749
904
|
export declare function createWebSocketTopics<const Out>(client: WebSocketClient<any, Out>, options: WebSocketTopicsOptions<NoInfer<Out>>): WebSocketTopics;
|
|
750
905
|
//#endregion
|
|
751
|
-
export type { CloseInfo, EventMap, HeartbeatOptions, IncomingRequest, Latency, QueueOptions, ReconnectOptions, RequestHandler, RequestOptions, SendData, SendOptions, Snapshot, StandardSchemaV1, Status, UrlSource, WebSocketClient, WebSocketLatency, WebSocketLatencyOptions, WebSocketOptions, WebSocketRequests, WebSocketRequestsOptions, WebSocketResponder, WebSocketResponderOptions, WebSocketState, WebSocketStateOptions, WebSocketTopics, WebSocketTopicsOptions };
|
|
906
|
+
export type { CloseInfo, EventMap, HeartbeatOptions, IncomingRequest, Latency, QueueOptions, ReconnectOptions, RequestHandler, RequestOptions, SendData, SendOptions, SendRate, Snapshot, StandardSchemaV1, Status, UrlSource, WebSocketClient, WebSocketLatency, WebSocketLatencyOptions, WebSocketOptions, WebSocketRequests, WebSocketRequestsOptions, WebSocketResponder, WebSocketResponderOptions, WebSocketSendRate, WebSocketSendRateOptions, WebSocketState, WebSocketStateOptions, WebSocketTopics, WebSocketTopicsOptions };
|
|
752
907
|
//# sourceMappingURL=core.d.ts.map
|