@replit/river 0.207.3 → 0.208.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/dist/{adapter-f2b6e211.d.ts → adapter-ChksXKVN.d.ts} +2 -2
- package/dist/adapter-Cuc4JtfV.d.cts +46 -0
- package/dist/{chunk-BO7MFCO6.js → chunk-2JNVDUMN.js} +55 -97
- package/dist/chunk-2JNVDUMN.js.map +1 -0
- package/dist/{chunk-B7REV3ZV.js → chunk-DKW3GC3M.js} +2 -2
- package/dist/{chunk-QGPYCXV4.js → chunk-ETZAHFGQ.js} +80 -61
- package/dist/chunk-ETZAHFGQ.js.map +1 -0
- package/dist/codec/index.d.cts +3 -3
- package/dist/codec/index.d.ts +3 -3
- package/dist/codec/index.js +2 -2
- package/dist/connection-BF4zg6Qv.d.cts +35 -0
- package/dist/{connection-06d72f2e.d.ts → connection-Donr3JRB.d.ts} +4 -4
- package/dist/index-C9tpZjBN.d.cts +37 -0
- package/dist/{index-02554794.d.ts → index-D8IOd3LG.d.ts} +2 -2
- package/dist/logging/index.d.cts +2 -2
- package/dist/logging/index.d.ts +2 -2
- package/dist/{message-01c3e85a.d.ts → message-Di94OL80.d.cts} +1 -1
- package/dist/message-Di94OL80.d.ts +108 -0
- package/dist/router/index.cjs +62 -43
- package/dist/router/index.cjs.map +1 -1
- package/dist/router/index.d.cts +27 -8
- package/dist/router/index.d.ts +27 -8
- package/dist/router/index.js +1 -1
- package/dist/testUtil/index.cjs +56 -105
- package/dist/testUtil/index.cjs.map +1 -1
- package/dist/testUtil/index.d.cts +5 -5
- package/dist/testUtil/index.d.ts +5 -5
- package/dist/testUtil/index.js +7 -14
- package/dist/testUtil/index.js.map +1 -1
- package/dist/transport/impls/ws/client.cjs +51 -80
- package/dist/transport/impls/ws/client.cjs.map +1 -1
- package/dist/transport/impls/ws/client.d.cts +6 -6
- package/dist/transport/impls/ws/client.d.ts +6 -6
- package/dist/transport/impls/ws/client.js +3 -3
- package/dist/transport/impls/ws/server.cjs +52 -85
- package/dist/transport/impls/ws/server.cjs.map +1 -1
- package/dist/transport/impls/ws/server.d.cts +6 -6
- package/dist/transport/impls/ws/server.d.ts +6 -6
- package/dist/transport/impls/ws/server.js +3 -3
- package/dist/transport/index.cjs +52 -94
- package/dist/transport/index.cjs.map +1 -1
- package/dist/transport/index.d.cts +6 -6
- package/dist/transport/index.d.ts +6 -6
- package/dist/transport/index.js +3 -3
- package/dist/transport-CCaWx1Rb.d.cts +1566 -0
- package/dist/{services-87887bc5.d.ts → transport-CZb3vdB4.d.ts} +344 -347
- package/dist/{wslike-e0b32dd5.d.ts → wslike-Dng9H1C7.d.cts} +1 -1
- package/dist/wslike-Dng9H1C7.d.ts +40 -0
- package/package.json +3 -3
- package/dist/chunk-BO7MFCO6.js.map +0 -1
- package/dist/chunk-QGPYCXV4.js.map +0 -1
- /package/dist/{chunk-B7REV3ZV.js.map → chunk-DKW3GC3M.js.map} +0 -0
|
@@ -0,0 +1,1566 @@
|
|
|
1
|
+
import * as _sinclair_typebox from '@sinclair/typebox';
|
|
2
|
+
import { TSchema, Static, TNever, TObject, TLiteral, TString, TUnion } from '@sinclair/typebox';
|
|
3
|
+
import { Tracer, Span } from '@opentelemetry/api';
|
|
4
|
+
import { b as TelemetryInfo, T as TransportClientId, P as ProtocolVersion, O as OpaqueTransportMessage, a as PartialTransportMessage, c as TransportMessage, H as HandshakeErrorCustomHandlerFatalResponseCodes, d as HandshakeErrorResponseCodes } from './message-Di94OL80.cjs';
|
|
5
|
+
import { M as MessageMetadata, L as Logger, T as Tags, a as LogFn, b as LoggingLevel } from './index-C9tpZjBN.cjs';
|
|
6
|
+
import { C as Codec, a as CodecMessageAdapter, S as SendResult, b as SendBufferResult } from './adapter-Cuc4JtfV.cjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A connection is the actual raw underlying transport connection.
|
|
10
|
+
* It's responsible for dispatching to/from the actual connection itself
|
|
11
|
+
* This should be instantiated as soon as the client/server has a connection
|
|
12
|
+
* It's tied to the lifecycle of the underlying transport connection (i.e. if the WS drops, this connection should be deleted)
|
|
13
|
+
*/
|
|
14
|
+
declare abstract class Connection {
|
|
15
|
+
id: string;
|
|
16
|
+
telemetry?: TelemetryInfo;
|
|
17
|
+
constructor();
|
|
18
|
+
get loggingMetadata(): MessageMetadata;
|
|
19
|
+
dataListener?: (msg: Uint8Array) => void;
|
|
20
|
+
closeListener?: () => void;
|
|
21
|
+
errorListener?: (err: Error) => void;
|
|
22
|
+
onData(msg: Uint8Array): void;
|
|
23
|
+
onError(err: Error): void;
|
|
24
|
+
onClose(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Set the callback for when a message is received.
|
|
27
|
+
* @param cb The message handler callback.
|
|
28
|
+
*/
|
|
29
|
+
setDataListener(cb: (msg: Uint8Array) => void): void;
|
|
30
|
+
removeDataListener(): void;
|
|
31
|
+
/**
|
|
32
|
+
* Set the callback for when the connection is closed.
|
|
33
|
+
* This should also be called if an error happens and after notifying the error listener.
|
|
34
|
+
* @param cb The callback to call when the connection is closed.
|
|
35
|
+
*/
|
|
36
|
+
setCloseListener(cb: () => void): void;
|
|
37
|
+
removeCloseListener(): void;
|
|
38
|
+
/**
|
|
39
|
+
* Set the callback for when an error is received.
|
|
40
|
+
* This should only be used for logging errors, all cleanup
|
|
41
|
+
* should be delegated to setCloseListener.
|
|
42
|
+
*
|
|
43
|
+
* The implementer should take care such that the implemented
|
|
44
|
+
* connection will call both the close and error callbacks
|
|
45
|
+
* on an error.
|
|
46
|
+
*
|
|
47
|
+
* @param cb The callback to call when an error is received.
|
|
48
|
+
*/
|
|
49
|
+
setErrorListener(cb: (err: Error) => void): void;
|
|
50
|
+
removeErrorListener(): void;
|
|
51
|
+
/**
|
|
52
|
+
* Sends a message over the connection.
|
|
53
|
+
* @param msg The message to send.
|
|
54
|
+
* @returns true if the message was sent, false otherwise.
|
|
55
|
+
*/
|
|
56
|
+
abstract send(msg: Uint8Array): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Closes the connection.
|
|
59
|
+
*/
|
|
60
|
+
abstract close(): void;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
declare const enum SessionState {
|
|
64
|
+
NoConnection = "NoConnection",
|
|
65
|
+
BackingOff = "BackingOff",
|
|
66
|
+
Connecting = "Connecting",
|
|
67
|
+
Handshaking = "Handshaking",
|
|
68
|
+
Connected = "Connected",
|
|
69
|
+
WaitingForHandshake = "WaitingForHandshake"
|
|
70
|
+
}
|
|
71
|
+
declare abstract class StateMachineState {
|
|
72
|
+
abstract readonly state: SessionState;
|
|
73
|
+
_isConsumed: boolean;
|
|
74
|
+
abstract _handleStateExit(): void;
|
|
75
|
+
abstract _handleClose(): void;
|
|
76
|
+
/**
|
|
77
|
+
* Cleanup this state machine state and mark it as consumed.
|
|
78
|
+
* After calling close, it is an error to access any properties on the state.
|
|
79
|
+
* You should never need to call this as a consumer.
|
|
80
|
+
*
|
|
81
|
+
* If you're looking to close the session from the client,
|
|
82
|
+
* use `.hardDisconnect` on the client transport.
|
|
83
|
+
*/
|
|
84
|
+
close(): void;
|
|
85
|
+
constructor();
|
|
86
|
+
}
|
|
87
|
+
interface SessionOptions {
|
|
88
|
+
/**
|
|
89
|
+
* Frequency at which to send heartbeat acknowledgements
|
|
90
|
+
*/
|
|
91
|
+
heartbeatIntervalMs: number;
|
|
92
|
+
/**
|
|
93
|
+
* Number of elapsed heartbeats without a response message before we consider
|
|
94
|
+
* the connection dead.
|
|
95
|
+
*/
|
|
96
|
+
heartbeatsUntilDead: number;
|
|
97
|
+
/**
|
|
98
|
+
* Max duration that a session can be without a connection before we consider
|
|
99
|
+
* it dead. This deadline is carried between states and is used to determine
|
|
100
|
+
* when to consider the session a lost cause and delete it entirely.
|
|
101
|
+
* Generally, this should be strictly greater than the sum of
|
|
102
|
+
* {@link connectionTimeoutMs} and {@link handshakeTimeoutMs}.
|
|
103
|
+
*/
|
|
104
|
+
sessionDisconnectGraceMs: number;
|
|
105
|
+
/**
|
|
106
|
+
* Connection timeout in milliseconds
|
|
107
|
+
*/
|
|
108
|
+
connectionTimeoutMs: number;
|
|
109
|
+
/**
|
|
110
|
+
* Handshake timeout in milliseconds
|
|
111
|
+
*/
|
|
112
|
+
handshakeTimeoutMs: number;
|
|
113
|
+
/**
|
|
114
|
+
* Whether to enable transparent session reconnects
|
|
115
|
+
*/
|
|
116
|
+
enableTransparentSessionReconnects: boolean;
|
|
117
|
+
/**
|
|
118
|
+
* The codec to use for encoding/decoding messages over the wire
|
|
119
|
+
*/
|
|
120
|
+
codec: Codec;
|
|
121
|
+
}
|
|
122
|
+
interface CommonSessionProps {
|
|
123
|
+
from: TransportClientId;
|
|
124
|
+
options: SessionOptions;
|
|
125
|
+
codec: CodecMessageAdapter;
|
|
126
|
+
tracer: Tracer;
|
|
127
|
+
log: Logger | undefined;
|
|
128
|
+
}
|
|
129
|
+
declare abstract class CommonSession extends StateMachineState {
|
|
130
|
+
readonly from: TransportClientId;
|
|
131
|
+
readonly options: SessionOptions;
|
|
132
|
+
readonly codec: CodecMessageAdapter;
|
|
133
|
+
tracer: Tracer;
|
|
134
|
+
log?: Logger;
|
|
135
|
+
abstract get loggingMetadata(): MessageMetadata;
|
|
136
|
+
constructor({ from, options, log, tracer, codec }: CommonSessionProps);
|
|
137
|
+
}
|
|
138
|
+
type SessionId = string;
|
|
139
|
+
interface IdentifiedSessionProps extends CommonSessionProps {
|
|
140
|
+
id: SessionId;
|
|
141
|
+
to: TransportClientId;
|
|
142
|
+
seq: number;
|
|
143
|
+
ack: number;
|
|
144
|
+
seqSent: number;
|
|
145
|
+
sendBuffer: Array<OpaqueTransportMessage>;
|
|
146
|
+
telemetry: TelemetryInfo;
|
|
147
|
+
protocolVersion: ProtocolVersion;
|
|
148
|
+
}
|
|
149
|
+
declare abstract class IdentifiedSession extends CommonSession {
|
|
150
|
+
readonly id: SessionId;
|
|
151
|
+
readonly telemetry: TelemetryInfo;
|
|
152
|
+
readonly to: TransportClientId;
|
|
153
|
+
readonly protocolVersion: ProtocolVersion;
|
|
154
|
+
/**
|
|
155
|
+
* Index of the message we will send next (excluding handshake)
|
|
156
|
+
*/
|
|
157
|
+
seq: number;
|
|
158
|
+
/**
|
|
159
|
+
* Last seq we sent over the wire this session (excluding handshake) and retransmissions
|
|
160
|
+
*/
|
|
161
|
+
seqSent: number;
|
|
162
|
+
/**
|
|
163
|
+
* Number of unique messages we've received this session (excluding handshake)
|
|
164
|
+
*/
|
|
165
|
+
ack: number;
|
|
166
|
+
sendBuffer: Array<OpaqueTransportMessage>;
|
|
167
|
+
constructor(props: IdentifiedSessionProps);
|
|
168
|
+
get loggingMetadata(): MessageMetadata;
|
|
169
|
+
constructMsg<Payload>(partialMsg: PartialTransportMessage<Payload>): TransportMessage<Payload>;
|
|
170
|
+
nextSeq(): number;
|
|
171
|
+
send(msg: PartialTransportMessage): SendResult;
|
|
172
|
+
_handleStateExit(): void;
|
|
173
|
+
_handleClose(): void;
|
|
174
|
+
}
|
|
175
|
+
interface IdentifiedSessionWithGracePeriodListeners {
|
|
176
|
+
onSessionGracePeriodElapsed: () => void;
|
|
177
|
+
}
|
|
178
|
+
interface IdentifiedSessionWithGracePeriodProps extends IdentifiedSessionProps {
|
|
179
|
+
graceExpiryTime: number;
|
|
180
|
+
listeners: IdentifiedSessionWithGracePeriodListeners;
|
|
181
|
+
}
|
|
182
|
+
declare abstract class IdentifiedSessionWithGracePeriod extends IdentifiedSession {
|
|
183
|
+
graceExpiryTime: number;
|
|
184
|
+
protected gracePeriodTimeout?: ReturnType<typeof setTimeout>;
|
|
185
|
+
listeners: IdentifiedSessionWithGracePeriodListeners;
|
|
186
|
+
constructor(props: IdentifiedSessionWithGracePeriodProps);
|
|
187
|
+
_handleStateExit(): void;
|
|
188
|
+
_handleClose(): void;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
type ConstructHandshake<T extends TSchema> = () => Static<T> | Promise<Static<T>>;
|
|
192
|
+
type ValidateHandshake<T extends TSchema> = (metadata: Static<T>, previousParsedMetadata?: ParsedMetadata) => Static<typeof HandshakeErrorCustomHandlerFatalResponseCodes> | ParsedMetadata | Promise<Static<typeof HandshakeErrorCustomHandlerFatalResponseCodes> | ParsedMetadata>;
|
|
193
|
+
interface ClientHandshakeOptions<MetadataSchema extends TSchema = TSchema> {
|
|
194
|
+
/**
|
|
195
|
+
* Schema for the metadata that the client sends to the server
|
|
196
|
+
* during the handshake.
|
|
197
|
+
*/
|
|
198
|
+
schema: MetadataSchema;
|
|
199
|
+
/**
|
|
200
|
+
* Gets the {@link HandshakeRequestMetadata} to send to the server.
|
|
201
|
+
*/
|
|
202
|
+
construct: ConstructHandshake<MetadataSchema>;
|
|
203
|
+
}
|
|
204
|
+
interface ServerHandshakeOptions<MetadataSchema extends TSchema = TSchema> {
|
|
205
|
+
/**
|
|
206
|
+
* Schema for the metadata that the server receives from the client
|
|
207
|
+
* during the handshake.
|
|
208
|
+
*/
|
|
209
|
+
schema: MetadataSchema;
|
|
210
|
+
/**
|
|
211
|
+
* Parses the {@link HandshakeRequestMetadata} sent by the client, transforming
|
|
212
|
+
* it into {@link ParsedHandshakeMetadata}.
|
|
213
|
+
*
|
|
214
|
+
* May return `false` if the client should be rejected.
|
|
215
|
+
*
|
|
216
|
+
* @param metadata - The metadata sent by the client.
|
|
217
|
+
* @param session - The session that the client would be associated with.
|
|
218
|
+
* @param isReconnect - Whether the client is reconnecting to the session,
|
|
219
|
+
* or if this is a new session.
|
|
220
|
+
*/
|
|
221
|
+
validate: ValidateHandshake<MetadataSchema>;
|
|
222
|
+
}
|
|
223
|
+
declare function createClientHandshakeOptions<MetadataSchema extends TSchema = TSchema>(schema: MetadataSchema, construct: ConstructHandshake<MetadataSchema>): ClientHandshakeOptions;
|
|
224
|
+
declare function createServerHandshakeOptions<MetadataSchema extends TSchema = TSchema>(schema: MetadataSchema, validate: ValidateHandshake<MetadataSchema>): ServerHandshakeOptions;
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Options to control the backoff and retry behavior of the client transport's connection behaviour.
|
|
228
|
+
*
|
|
229
|
+
* River implements exponential backoff with jitter to prevent flooding the server
|
|
230
|
+
* when there's an issue with connection establishment.
|
|
231
|
+
*
|
|
232
|
+
* The backoff is calculated via the following:
|
|
233
|
+
* backOff = min(jitter + {@link baseIntervalMs} * 2 ^ budget_consumed, {@link maxBackoffMs})
|
|
234
|
+
*
|
|
235
|
+
* We use a leaky bucket rate limit with a budget of {@link attemptBudgetCapacity} reconnection attempts.
|
|
236
|
+
* Budget only starts to restore after a successful handshake at a rate of one budget per {@link budgetRestoreIntervalMs}.
|
|
237
|
+
*/
|
|
238
|
+
interface ConnectionRetryOptions {
|
|
239
|
+
/**
|
|
240
|
+
* The base interval to wait before retrying a connection.
|
|
241
|
+
*/
|
|
242
|
+
baseIntervalMs: number;
|
|
243
|
+
/**
|
|
244
|
+
* The maximum random jitter to add to the total backoff time.
|
|
245
|
+
*/
|
|
246
|
+
maxJitterMs: number;
|
|
247
|
+
/**
|
|
248
|
+
* The maximum amount of time to wait before retrying a connection.
|
|
249
|
+
* This does not include the jitter.
|
|
250
|
+
*/
|
|
251
|
+
maxBackoffMs: number;
|
|
252
|
+
/**
|
|
253
|
+
* The max number of times to attempt a connection before a successful handshake.
|
|
254
|
+
* This persists across connections but starts restoring budget after a successful handshake.
|
|
255
|
+
* The restoration interval depends on {@link budgetRestoreIntervalMs}
|
|
256
|
+
*/
|
|
257
|
+
attemptBudgetCapacity: number;
|
|
258
|
+
/**
|
|
259
|
+
* After a successful connection attempt, how long to wait before we restore a single budget.
|
|
260
|
+
*/
|
|
261
|
+
budgetRestoreIntervalMs: number;
|
|
262
|
+
}
|
|
263
|
+
declare class LeakyBucketRateLimit {
|
|
264
|
+
private budgetConsumed;
|
|
265
|
+
private intervalHandle?;
|
|
266
|
+
private readonly options;
|
|
267
|
+
constructor(options: ConnectionRetryOptions);
|
|
268
|
+
getBackoffMs(): number;
|
|
269
|
+
get totalBudgetRestoreTime(): number;
|
|
270
|
+
consumeBudget(): void;
|
|
271
|
+
getBudgetConsumed(): number;
|
|
272
|
+
hasBudget(): boolean;
|
|
273
|
+
startRestoringBudget(): void;
|
|
274
|
+
private stopLeak;
|
|
275
|
+
close(): void;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
type TransportOptions = SessionOptions;
|
|
279
|
+
type ProvidedTransportOptions = Partial<TransportOptions>;
|
|
280
|
+
type ClientTransportOptions = TransportOptions & ConnectionRetryOptions;
|
|
281
|
+
type ProvidedClientTransportOptions = Partial<ClientTransportOptions>;
|
|
282
|
+
type ServerTransportOptions = TransportOptions;
|
|
283
|
+
type ProvidedServerTransportOptions = Partial<ServerTransportOptions>;
|
|
284
|
+
|
|
285
|
+
interface SessionConnectingListeners extends IdentifiedSessionWithGracePeriodListeners {
|
|
286
|
+
onConnectionEstablished: (conn: Connection) => void;
|
|
287
|
+
onConnectionFailed: (err: unknown) => void;
|
|
288
|
+
onConnectionTimeout: () => void;
|
|
289
|
+
}
|
|
290
|
+
interface SessionConnectingProps<ConnType extends Connection> extends IdentifiedSessionWithGracePeriodProps {
|
|
291
|
+
connPromise: Promise<ConnType>;
|
|
292
|
+
listeners: SessionConnectingListeners;
|
|
293
|
+
}
|
|
294
|
+
declare class SessionConnecting<ConnType extends Connection> extends IdentifiedSessionWithGracePeriod {
|
|
295
|
+
readonly state: SessionState.Connecting;
|
|
296
|
+
connPromise: Promise<ConnType>;
|
|
297
|
+
listeners: SessionConnectingListeners;
|
|
298
|
+
connectionTimeout?: ReturnType<typeof setTimeout>;
|
|
299
|
+
constructor(props: SessionConnectingProps<ConnType>);
|
|
300
|
+
bestEffortClose(): void;
|
|
301
|
+
_handleStateExit(): void;
|
|
302
|
+
_handleClose(): void;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
interface SessionHandshakingListeners extends IdentifiedSessionWithGracePeriodListeners {
|
|
306
|
+
onConnectionErrored: (err: unknown) => void;
|
|
307
|
+
onConnectionClosed: () => void;
|
|
308
|
+
onHandshake: (msg: OpaqueTransportMessage) => void;
|
|
309
|
+
onInvalidHandshake: (reason: string, code: Static<typeof HandshakeErrorResponseCodes>) => void;
|
|
310
|
+
onHandshakeTimeout: () => void;
|
|
311
|
+
}
|
|
312
|
+
interface SessionHandshakingProps<ConnType extends Connection> extends IdentifiedSessionWithGracePeriodProps {
|
|
313
|
+
conn: ConnType;
|
|
314
|
+
listeners: SessionHandshakingListeners;
|
|
315
|
+
}
|
|
316
|
+
declare class SessionHandshaking<ConnType extends Connection> extends IdentifiedSessionWithGracePeriod {
|
|
317
|
+
readonly state: SessionState.Handshaking;
|
|
318
|
+
conn: ConnType;
|
|
319
|
+
listeners: SessionHandshakingListeners;
|
|
320
|
+
handshakeTimeout?: ReturnType<typeof setTimeout>;
|
|
321
|
+
constructor(props: SessionHandshakingProps<ConnType>);
|
|
322
|
+
get loggingMetadata(): {
|
|
323
|
+
protocolVersion?: ProtocolVersion | undefined;
|
|
324
|
+
clientId?: string | undefined;
|
|
325
|
+
connectedTo?: string | undefined;
|
|
326
|
+
sessionId?: string | undefined;
|
|
327
|
+
connId?: string | undefined;
|
|
328
|
+
transportMessage?: Partial<OpaqueTransportMessage> | undefined;
|
|
329
|
+
validationErrors?: {
|
|
330
|
+
path: string;
|
|
331
|
+
message: string;
|
|
332
|
+
}[] | undefined;
|
|
333
|
+
tags?: Tags[] | undefined;
|
|
334
|
+
telemetry?: {
|
|
335
|
+
traceId: string;
|
|
336
|
+
spanId: string;
|
|
337
|
+
} | undefined;
|
|
338
|
+
extras?: Record<string, unknown> | undefined;
|
|
339
|
+
};
|
|
340
|
+
onHandshakeData: (msg: Uint8Array) => void;
|
|
341
|
+
sendHandshake(msg: TransportMessage): SendResult;
|
|
342
|
+
_handleStateExit(): void;
|
|
343
|
+
_handleClose(): void;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
interface SessionConnectedListeners {
|
|
347
|
+
onConnectionErrored: (err: unknown) => void;
|
|
348
|
+
onConnectionClosed: () => void;
|
|
349
|
+
onMessage: (msg: OpaqueTransportMessage) => void;
|
|
350
|
+
onMessageSendFailure: (msg: PartialTransportMessage, reason: string) => void;
|
|
351
|
+
onInvalidMessage: (reason: string) => void;
|
|
352
|
+
}
|
|
353
|
+
interface SessionConnectedProps<ConnType extends Connection> extends IdentifiedSessionProps {
|
|
354
|
+
conn: ConnType;
|
|
355
|
+
listeners: SessionConnectedListeners;
|
|
356
|
+
}
|
|
357
|
+
declare class SessionConnected<ConnType extends Connection> extends IdentifiedSession {
|
|
358
|
+
readonly state: SessionState.Connected;
|
|
359
|
+
conn: ConnType;
|
|
360
|
+
listeners: SessionConnectedListeners;
|
|
361
|
+
private heartbeatHandle?;
|
|
362
|
+
private heartbeatMissTimeout?;
|
|
363
|
+
private isActivelyHeartbeating;
|
|
364
|
+
updateBookkeeping(ack: number, seq: number): void;
|
|
365
|
+
private assertSendOrdering;
|
|
366
|
+
send(msg: PartialTransportMessage): SendResult;
|
|
367
|
+
constructor(props: SessionConnectedProps<ConnType>);
|
|
368
|
+
sendBufferedMessages(): SendBufferResult;
|
|
369
|
+
get loggingMetadata(): {
|
|
370
|
+
protocolVersion?: ProtocolVersion | undefined;
|
|
371
|
+
clientId?: string | undefined;
|
|
372
|
+
connectedTo?: string | undefined;
|
|
373
|
+
sessionId?: string | undefined;
|
|
374
|
+
connId?: string | undefined;
|
|
375
|
+
transportMessage?: Partial<OpaqueTransportMessage> | undefined;
|
|
376
|
+
validationErrors?: {
|
|
377
|
+
path: string;
|
|
378
|
+
message: string;
|
|
379
|
+
}[] | undefined;
|
|
380
|
+
tags?: Tags[] | undefined;
|
|
381
|
+
telemetry?: {
|
|
382
|
+
traceId: string;
|
|
383
|
+
spanId: string;
|
|
384
|
+
} | undefined;
|
|
385
|
+
extras?: Record<string, unknown> | undefined;
|
|
386
|
+
};
|
|
387
|
+
startMissingHeartbeatTimeout(): void;
|
|
388
|
+
startActiveHeartbeat(): void;
|
|
389
|
+
private sendHeartbeat;
|
|
390
|
+
onMessageData: (msg: Uint8Array) => void;
|
|
391
|
+
_handleStateExit(): void;
|
|
392
|
+
_handleClose(): void;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
declare class SessionNoConnection extends IdentifiedSessionWithGracePeriod {
|
|
396
|
+
readonly state: SessionState.NoConnection;
|
|
397
|
+
_handleClose(): void;
|
|
398
|
+
_handleStateExit(): void;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
interface SessionBackingOffListeners extends IdentifiedSessionWithGracePeriodListeners {
|
|
402
|
+
onBackoffFinished: () => void;
|
|
403
|
+
}
|
|
404
|
+
interface SessionBackingOffProps extends IdentifiedSessionWithGracePeriodProps {
|
|
405
|
+
backoffMs: number;
|
|
406
|
+
listeners: SessionBackingOffListeners;
|
|
407
|
+
}
|
|
408
|
+
declare class SessionBackingOff extends IdentifiedSessionWithGracePeriod {
|
|
409
|
+
readonly state: SessionState.BackingOff;
|
|
410
|
+
listeners: SessionBackingOffListeners;
|
|
411
|
+
backoffTimeout?: ReturnType<typeof setTimeout>;
|
|
412
|
+
constructor(props: SessionBackingOffProps);
|
|
413
|
+
_handleClose(): void;
|
|
414
|
+
_handleStateExit(): void;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
type ClientSession<ConnType extends Connection> = SessionNoConnection | SessionBackingOff | SessionConnecting<ConnType> | SessionHandshaking<ConnType> | SessionConnected<ConnType>;
|
|
418
|
+
type ServerSession<ConnType extends Connection> = SessionConnected<ConnType> | SessionNoConnection;
|
|
419
|
+
type Session<ConnType extends Connection> = ClientSession<ConnType> | ServerSession<ConnType>;
|
|
420
|
+
|
|
421
|
+
declare abstract class ClientTransport<ConnType extends Connection> extends Transport<ConnType> {
|
|
422
|
+
/**
|
|
423
|
+
* The options for this transport.
|
|
424
|
+
*/
|
|
425
|
+
protected options: ClientTransportOptions;
|
|
426
|
+
retryBudget: LeakyBucketRateLimit;
|
|
427
|
+
/**
|
|
428
|
+
* A flag indicating whether the transport should automatically reconnect
|
|
429
|
+
* when a connection is dropped.
|
|
430
|
+
* Realistically, this should always be true for clients unless you are writing
|
|
431
|
+
* tests or a special case where you don't want to reconnect.
|
|
432
|
+
*/
|
|
433
|
+
reconnectOnConnectionDrop: boolean;
|
|
434
|
+
/**
|
|
435
|
+
* Optional handshake options for this client.
|
|
436
|
+
*/
|
|
437
|
+
handshakeExtensions?: ClientHandshakeOptions;
|
|
438
|
+
sessions: Map<TransportClientId, ClientSession<ConnType>>;
|
|
439
|
+
constructor(clientId: TransportClientId, providedOptions?: ProvidedClientTransportOptions);
|
|
440
|
+
extendHandshake(options: ClientHandshakeOptions): void;
|
|
441
|
+
/**
|
|
442
|
+
* Abstract method that creates a new {@link Connection} object.
|
|
443
|
+
*
|
|
444
|
+
* @param to The client ID of the node to connect to.
|
|
445
|
+
* @returns The new connection object.
|
|
446
|
+
*/
|
|
447
|
+
protected abstract createNewOutgoingConnection(to: TransportClientId): Promise<ConnType>;
|
|
448
|
+
private tryReconnecting;
|
|
449
|
+
createUnconnectedSession(to: string): SessionNoConnection;
|
|
450
|
+
protected onConnectingFailed(session: SessionConnecting<ConnType>): SessionNoConnection;
|
|
451
|
+
protected onConnClosed(session: SessionHandshaking<ConnType> | SessionConnected<ConnType>): SessionNoConnection;
|
|
452
|
+
protected onConnectionEstablished(session: SessionConnecting<ConnType>, conn: ConnType): SessionHandshaking<ConnType>;
|
|
453
|
+
private rejectHandshakeResponse;
|
|
454
|
+
protected onHandshakeResponse(session: SessionHandshaking<ConnType>, msg: OpaqueTransportMessage): void;
|
|
455
|
+
/**
|
|
456
|
+
* Manually attempts to connect to a client.
|
|
457
|
+
* @param to The client ID of the node to connect to.
|
|
458
|
+
*/
|
|
459
|
+
connect(to: TransportClientId): void;
|
|
460
|
+
/**
|
|
461
|
+
* Manually kills all sessions to the server (including all pending state).
|
|
462
|
+
* This is useful for when you want to close all connections to a server
|
|
463
|
+
* and don't want to wait for the grace period to elapse.
|
|
464
|
+
*/
|
|
465
|
+
hardDisconnect(): void;
|
|
466
|
+
protected onBackoffFinished(session: SessionBackingOff): void;
|
|
467
|
+
private sendHandshake;
|
|
468
|
+
close(): void;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* {@link UNCAUGHT_ERROR_CODE} is the code that is used when an error is thrown
|
|
473
|
+
* inside a procedure handler that's not required.
|
|
474
|
+
*/
|
|
475
|
+
declare const UNCAUGHT_ERROR_CODE = "UNCAUGHT_ERROR";
|
|
476
|
+
/**
|
|
477
|
+
* {@link UNEXPECTED_DISCONNECT_CODE} is the code used the stream's session
|
|
478
|
+
* disconnect unexpetedly.
|
|
479
|
+
*/
|
|
480
|
+
declare const UNEXPECTED_DISCONNECT_CODE = "UNEXPECTED_DISCONNECT";
|
|
481
|
+
/**
|
|
482
|
+
* {@link INVALID_REQUEST_CODE} is the code used when a client's request is invalid.
|
|
483
|
+
*/
|
|
484
|
+
declare const INVALID_REQUEST_CODE = "INVALID_REQUEST";
|
|
485
|
+
/**
|
|
486
|
+
* {@link CANCEL_CODE} is the code used when either server or client cancels the stream.
|
|
487
|
+
*/
|
|
488
|
+
declare const CANCEL_CODE = "CANCEL";
|
|
489
|
+
type TLiteralString = TLiteral<string>;
|
|
490
|
+
type BaseErrorSchemaType = TObject<{
|
|
491
|
+
code: TLiteralString;
|
|
492
|
+
message: TLiteralString | TString;
|
|
493
|
+
}> | TObject<{
|
|
494
|
+
code: TLiteralString;
|
|
495
|
+
message: TLiteralString | TString;
|
|
496
|
+
extras: TSchema;
|
|
497
|
+
}>;
|
|
498
|
+
/**
|
|
499
|
+
* A schema for cancel payloads sent from the client
|
|
500
|
+
*/
|
|
501
|
+
declare const CancelErrorSchema: TObject<{
|
|
502
|
+
code: TLiteral<"CANCEL">;
|
|
503
|
+
message: TString;
|
|
504
|
+
}>;
|
|
505
|
+
/**
|
|
506
|
+
* {@link ReaderErrorSchema} is the schema for all the built-in river errors that
|
|
507
|
+
* can be emitted to a reader (request reader on the server, and response reader
|
|
508
|
+
* on the client).
|
|
509
|
+
*/
|
|
510
|
+
declare const ReaderErrorSchema: TUnion<[TObject<{
|
|
511
|
+
code: TLiteral<"UNCAUGHT_ERROR">;
|
|
512
|
+
message: TString;
|
|
513
|
+
}>, TObject<{
|
|
514
|
+
code: TLiteral<"UNEXPECTED_DISCONNECT">;
|
|
515
|
+
message: TString;
|
|
516
|
+
}>, TObject<{
|
|
517
|
+
code: TLiteral<"INVALID_REQUEST">;
|
|
518
|
+
message: TString;
|
|
519
|
+
extras: _sinclair_typebox.TOptional<TObject<{
|
|
520
|
+
firstValidationErrors: _sinclair_typebox.TArray<TObject<{
|
|
521
|
+
path: TString;
|
|
522
|
+
message: TString;
|
|
523
|
+
}>>;
|
|
524
|
+
totalErrors: _sinclair_typebox.TNumber;
|
|
525
|
+
}>>;
|
|
526
|
+
}>, TObject<{
|
|
527
|
+
code: TLiteral<"CANCEL">;
|
|
528
|
+
message: TString;
|
|
529
|
+
}>]>;
|
|
530
|
+
/**
|
|
531
|
+
* Represents an acceptable schema to pass to a procedure.
|
|
532
|
+
* Just a type of a schema, not an actual schema.
|
|
533
|
+
*
|
|
534
|
+
*/
|
|
535
|
+
type ProcedureErrorSchemaType = TNever | BaseErrorSchemaType | TUnion<Array<BaseErrorSchemaType>>;
|
|
536
|
+
type NestableProcedureErrorSchemaType = BaseErrorSchemaType | TUnion<NestableProcedureErrorSchemaTypeArray>;
|
|
537
|
+
interface NestableProcedureErrorSchemaTypeArray extends Array<NestableProcedureErrorSchemaType> {
|
|
538
|
+
}
|
|
539
|
+
type Flatten<T> = T extends BaseErrorSchemaType ? T : T extends TUnion<Array<infer U extends TSchema>> ? Flatten<U> : unknown;
|
|
540
|
+
/**
|
|
541
|
+
* In the case where API consumers for some god-forsaken reason want to use
|
|
542
|
+
* arbitrarily nested unions, this helper flattens them to a single level.
|
|
543
|
+
*
|
|
544
|
+
* Note that loses some metadata information on the nested unions like
|
|
545
|
+
* nested description fields, etc.
|
|
546
|
+
*
|
|
547
|
+
* @param errType - An arbitrarily union-nested error schema.
|
|
548
|
+
* @returns The flattened error schema.
|
|
549
|
+
*/
|
|
550
|
+
declare function flattenErrorType<T extends NestableProcedureErrorSchemaType>(errType: T): Flatten<T>;
|
|
551
|
+
|
|
552
|
+
declare const ReadableBrokenError: {
|
|
553
|
+
readonly code: "READABLE_BROKEN";
|
|
554
|
+
readonly message: "Readable was broken before it is fully consumed";
|
|
555
|
+
};
|
|
556
|
+
/**
|
|
557
|
+
* Similar to {@link Result} but with an extra error to handle cases where {@link Readable.break} is called
|
|
558
|
+
*/
|
|
559
|
+
type ReadableResult<T, E extends Static<BaseErrorSchemaType>> = Result<T, E | typeof ReadableBrokenError>;
|
|
560
|
+
/**
|
|
561
|
+
* A simple {@link AsyncIterator} used in {@link Readable}
|
|
562
|
+
* that doesn't have a the extra "return" and "throw" methods, and
|
|
563
|
+
* the doesn't have a "done value" (TReturn).
|
|
564
|
+
*/
|
|
565
|
+
interface ReadableIterator<T, E extends Static<BaseErrorSchemaType>> {
|
|
566
|
+
next(): Promise<{
|
|
567
|
+
done: false;
|
|
568
|
+
value: ReadableResult<T, E>;
|
|
569
|
+
} | {
|
|
570
|
+
done: true;
|
|
571
|
+
value: undefined;
|
|
572
|
+
}>;
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* A {@link Readable} is an abstraction from which data is consumed from {@link Writable} source.
|
|
576
|
+
*
|
|
577
|
+
* - On the server the argument passed the procedure handler for `upload` and `stream` implements a {@link Readable} interface
|
|
578
|
+
* so you can read client's request data.
|
|
579
|
+
* - On the client the returned value of `subscription` or `stream` invocation implements a {@link Readable} interface
|
|
580
|
+
* so you can read server's response data.
|
|
581
|
+
*
|
|
582
|
+
* A {@link Readable} can only have one consumer (iterator or {@link collect}) for the {@link Readable}'s
|
|
583
|
+
* lifetime, in essense, reading from a {@link Readable} locks it forever.
|
|
584
|
+
*/
|
|
585
|
+
interface Readable<T, E extends Static<BaseErrorSchemaType>> {
|
|
586
|
+
/**
|
|
587
|
+
* {@link Readable} implements AsyncIterator API and can be consumed via
|
|
588
|
+
* for-await-of loops. Iteration locks the Readable. Exiting the loop
|
|
589
|
+
* will **not** release the lock and it'll be equivalent of calling
|
|
590
|
+
* {@link break}.
|
|
591
|
+
*/
|
|
592
|
+
[Symbol.asyncIterator](): ReadableIterator<T, E>;
|
|
593
|
+
/**
|
|
594
|
+
* {@link collect} locks the {@link Readable} and returns a promise that resolves
|
|
595
|
+
* with an array of the content when the {@link Readable} is fully done. This could
|
|
596
|
+
* be due to the {@link Writable} end of the pipe closing cleanly, the procedure invocation
|
|
597
|
+
* is cancelled, or {@link break} is called.
|
|
598
|
+
*/
|
|
599
|
+
collect(): Promise<Array<ReadableResult<T, E>>>;
|
|
600
|
+
/**
|
|
601
|
+
* {@link break} locks the {@link Readable} and discards any existing or future incoming data.
|
|
602
|
+
*
|
|
603
|
+
* If there is an existing reader waiting for the next value, {@link break} causes it to
|
|
604
|
+
* resolve with a {@link ReadableBrokenError} error.
|
|
605
|
+
*/
|
|
606
|
+
break(): undefined;
|
|
607
|
+
/**
|
|
608
|
+
* {@link isReadable} returns true if it's safe to read from the {@link Readable}, either
|
|
609
|
+
* via iteration or {@link collect}. It returns false if the {@link Readable} is locked
|
|
610
|
+
* by a consumer (iterator or {@link collect}) or readable was broken via {@link break}.
|
|
611
|
+
*/
|
|
612
|
+
isReadable(): boolean;
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* A {@link Writeable} is a an abstraction for a {@link Readable} destination to which data is written to.
|
|
616
|
+
*
|
|
617
|
+
* - On the server the argument passed the procedure handler for `subscription` and `stream` implements a {@link Writeable}
|
|
618
|
+
* so you can write server's response data.
|
|
619
|
+
* - On the client the returned value of `upload` or `stream` invocation implements a {@link Writeable}
|
|
620
|
+
* so you can write client's request data.
|
|
621
|
+
*
|
|
622
|
+
* Once closed, a {@link Writeable} can't be re-opened.` `
|
|
623
|
+
*/
|
|
624
|
+
interface Writable<T> {
|
|
625
|
+
/**
|
|
626
|
+
* {@link write} writes a value to the pipe. An error is thrown if writing to a closed {@link Writable}.
|
|
627
|
+
*/
|
|
628
|
+
write(value: T): undefined;
|
|
629
|
+
/**
|
|
630
|
+
* {@link close} signals the closure of the {@link Writeable}, informing the {@link Readable} end that
|
|
631
|
+
* all data has been transmitted and we've cleanly closed.
|
|
632
|
+
*
|
|
633
|
+
* Calling {@link close} multiple times is a no-op.
|
|
634
|
+
*/
|
|
635
|
+
close(): undefined;
|
|
636
|
+
/**
|
|
637
|
+
* {@link isWritable} returns true if it's safe to call {@link write}, which
|
|
638
|
+
* means that the {@link Writable} hasn't been closed due to {@link close} being called
|
|
639
|
+
* on this {@link Writable} or the procedure invocation ending for any reason.
|
|
640
|
+
*/
|
|
641
|
+
isWritable(): boolean;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
interface CallOptions {
|
|
645
|
+
signal?: AbortSignal;
|
|
646
|
+
}
|
|
647
|
+
type RpcFn<Service extends AnyService, ProcName extends keyof Service['procedures']> = (reqInit: ProcInit<Service, ProcName>, options?: CallOptions) => Promise<Result<ProcResponse<Service, ProcName>, ProcErrors<Service, ProcName>>>;
|
|
648
|
+
type UploadFn<Service extends AnyService, ProcName extends keyof Service['procedures']> = (reqInit: ProcInit<Service, ProcName>, options?: CallOptions) => {
|
|
649
|
+
reqWritable: Writable<ProcRequest<Service, ProcName>>;
|
|
650
|
+
finalize: () => Promise<Result<ProcResponse<Service, ProcName>, ProcErrors<Service, ProcName>>>;
|
|
651
|
+
};
|
|
652
|
+
type StreamFn<Service extends AnyService, ProcName extends keyof Service['procedures']> = (reqInit: ProcInit<Service, ProcName>, options?: CallOptions) => {
|
|
653
|
+
reqWritable: Writable<ProcRequest<Service, ProcName>>;
|
|
654
|
+
resReadable: Readable<ProcResponse<Service, ProcName>, ProcErrors<Service, ProcName>>;
|
|
655
|
+
};
|
|
656
|
+
type SubscriptionFn<Service extends AnyService, ProcName extends keyof Service['procedures']> = (reqInit: ProcInit<Service, ProcName>, options?: CallOptions) => {
|
|
657
|
+
resReadable: Readable<ProcResponse<Service, ProcName>, ProcErrors<Service, ProcName>>;
|
|
658
|
+
};
|
|
659
|
+
/**
|
|
660
|
+
* A helper type to transform an actual service type into a type
|
|
661
|
+
* we can case to in the proxy.
|
|
662
|
+
* @template Service - The type of the Service.
|
|
663
|
+
*/
|
|
664
|
+
type ServiceClient<Service extends AnyService> = {
|
|
665
|
+
[ProcName in keyof Service['procedures']]: ProcType<Service, ProcName> extends 'rpc' ? {
|
|
666
|
+
rpc: RpcFn<Service, ProcName>;
|
|
667
|
+
} : ProcType<Service, ProcName> extends 'upload' ? {
|
|
668
|
+
upload: UploadFn<Service, ProcName>;
|
|
669
|
+
} : ProcType<Service, ProcName> extends 'stream' ? {
|
|
670
|
+
stream: StreamFn<Service, ProcName>;
|
|
671
|
+
} : ProcType<Service, ProcName> extends 'subscription' ? {
|
|
672
|
+
subscribe: SubscriptionFn<Service, ProcName>;
|
|
673
|
+
} : never;
|
|
674
|
+
};
|
|
675
|
+
/**
|
|
676
|
+
* Defines a type that represents a client for a server with a set of services.
|
|
677
|
+
* @template Srv - The type of the server.
|
|
678
|
+
*/
|
|
679
|
+
type Client<Services extends AnyServiceSchemaMap, IS extends InstantiatedServiceSchemaMap<Services> = InstantiatedServiceSchemaMap<Services>> = {
|
|
680
|
+
[SvcName in keyof IS]: ServiceClient<IS[SvcName]>;
|
|
681
|
+
};
|
|
682
|
+
interface ClientOptions {
|
|
683
|
+
connectOnInvoke: boolean;
|
|
684
|
+
eagerlyConnect: boolean;
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Creates a client for a given server using the provided transport.
|
|
688
|
+
* Note that the client only needs the type of the server, not the actual
|
|
689
|
+
* server definition itself.
|
|
690
|
+
*
|
|
691
|
+
* This relies on a proxy to dynamically create the client, so the client
|
|
692
|
+
* will be typed as if it were the actual server with the appropriate services
|
|
693
|
+
* and procedures.
|
|
694
|
+
*
|
|
695
|
+
* @template Srv - The type of the server.
|
|
696
|
+
* @param {Transport} transport - The transport to use for communication.
|
|
697
|
+
* @param {TransportClientId} serverId - The ID of the server to connect to.
|
|
698
|
+
* @param {Partial<ClientOptions>} providedClientOptions - The options for the client.
|
|
699
|
+
* @returns The client for the server.
|
|
700
|
+
*/
|
|
701
|
+
declare function createClient<ServiceSchemaMap extends AnyServiceSchemaMap>(transport: ClientTransport<Connection>, serverId: TransportClientId, providedClientOptions?: Partial<ClientOptions & {
|
|
702
|
+
handshakeOptions: ClientHandshakeOptions;
|
|
703
|
+
}>): Client<ServiceSchemaMap>;
|
|
704
|
+
|
|
705
|
+
interface OkResult<T> {
|
|
706
|
+
ok: true;
|
|
707
|
+
payload: T;
|
|
708
|
+
}
|
|
709
|
+
interface ErrResult<Err extends Static<BaseErrorSchemaType>> {
|
|
710
|
+
ok: false;
|
|
711
|
+
payload: Err;
|
|
712
|
+
}
|
|
713
|
+
type Result<T, Err extends Static<BaseErrorSchemaType>> = OkResult<T> | ErrResult<Err>;
|
|
714
|
+
declare function Ok<const T extends Array<unknown>>(p: T): OkResult<T>;
|
|
715
|
+
declare function Ok<const T extends ReadonlyArray<unknown>>(p: T): OkResult<T>;
|
|
716
|
+
declare function Ok<const T>(payload: T): OkResult<T>;
|
|
717
|
+
declare function Err<const Err extends Static<BaseErrorSchemaType>>(error: Err): ErrResult<Err>;
|
|
718
|
+
/**
|
|
719
|
+
* Refine a {@link Result} type to its returned payload.
|
|
720
|
+
*/
|
|
721
|
+
type ResultUnwrapOk<R> = R extends Result<infer T, infer __E> ? T : never;
|
|
722
|
+
/**
|
|
723
|
+
* Refine a {@link Result} type to its error payload.
|
|
724
|
+
*/
|
|
725
|
+
type ResultUnwrapErr<R> = R extends Result<infer __T, infer Err> ? Err : never;
|
|
726
|
+
/**
|
|
727
|
+
* Retrieve the response type for a procedure, represented as a {@link Result}
|
|
728
|
+
* type.
|
|
729
|
+
* Example:
|
|
730
|
+
* ```
|
|
731
|
+
* type Message = ResponseData<typeof client, 'serviceName', 'procedureName'>
|
|
732
|
+
* ```
|
|
733
|
+
*/
|
|
734
|
+
type ResponseData<RiverClient, ServiceName extends keyof RiverClient, ProcedureName extends keyof RiverClient[ServiceName], Procedure = RiverClient[ServiceName][ProcedureName], Fn extends (...args: never) => unknown = (...args: never) => unknown> = RiverClient extends Client<infer __ServiceSchemaMap> ? Procedure extends object ? Procedure extends object & {
|
|
735
|
+
rpc: infer RpcFn extends Fn;
|
|
736
|
+
} ? Awaited<ReturnType<RpcFn>> : Procedure extends object & {
|
|
737
|
+
upload: infer UploadFn extends Fn;
|
|
738
|
+
} ? ReturnType<UploadFn> extends {
|
|
739
|
+
finalize: (...args: never) => Promise<infer UploadOutputMessage>;
|
|
740
|
+
} ? UploadOutputMessage : never : Procedure extends object & {
|
|
741
|
+
stream: infer StreamFn extends Fn;
|
|
742
|
+
} ? ReturnType<StreamFn> extends {
|
|
743
|
+
resReadable: Readable<infer StreamOutputMessage, Static<BaseErrorSchemaType>>;
|
|
744
|
+
} ? StreamOutputMessage : never : Procedure extends object & {
|
|
745
|
+
subscribe: infer SubscriptionFn extends Fn;
|
|
746
|
+
} ? Awaited<ReturnType<SubscriptionFn>> extends {
|
|
747
|
+
resReadable: Readable<infer SubscriptionOutputMessage, Static<BaseErrorSchemaType>>;
|
|
748
|
+
} ? SubscriptionOutputMessage : never : never : never : never;
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* ServiceContext exist for the purpose of declaration merging
|
|
752
|
+
* to extend the context with additional properties.
|
|
753
|
+
*
|
|
754
|
+
* For example:
|
|
755
|
+
*
|
|
756
|
+
* ```ts
|
|
757
|
+
* declare module '@replit/river' {
|
|
758
|
+
* interface ServiceContext {
|
|
759
|
+
* db: Database;
|
|
760
|
+
* }
|
|
761
|
+
* }
|
|
762
|
+
*
|
|
763
|
+
* createServer(someTransport, myServices, { extendedContext: { db: myDb } });
|
|
764
|
+
* ```
|
|
765
|
+
*
|
|
766
|
+
* Once you do this, your {@link ProcedureHandlerContext} will have `db` property on it.
|
|
767
|
+
*/
|
|
768
|
+
interface ServiceContext {
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* The parsed metadata schema for a service. This is the
|
|
772
|
+
* return value of the {@link ServerHandshakeOptions.validate}
|
|
773
|
+
* if the handshake extension is used.
|
|
774
|
+
*
|
|
775
|
+
* You should use declaration merging to extend this interface
|
|
776
|
+
* with the sanitized metadata.
|
|
777
|
+
*
|
|
778
|
+
* ```ts
|
|
779
|
+
* declare module '@replit/river' {
|
|
780
|
+
* interface ParsedMetadata {
|
|
781
|
+
* userId: number;
|
|
782
|
+
* }
|
|
783
|
+
* }
|
|
784
|
+
* ```
|
|
785
|
+
*/
|
|
786
|
+
interface ParsedMetadata extends Record<string, unknown> {
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
789
|
+
* This is passed to every procedure handler and contains various context-level
|
|
790
|
+
* information and utilities. This may be extended, see {@link ServiceContext}
|
|
791
|
+
*/
|
|
792
|
+
type ProcedureHandlerContext<State> = ServiceContext & {
|
|
793
|
+
/**
|
|
794
|
+
* State for this service as defined by the service definition.
|
|
795
|
+
*/
|
|
796
|
+
state: State;
|
|
797
|
+
/**
|
|
798
|
+
* The span for this procedure call. You can use this to add attributes, events, and
|
|
799
|
+
* links to the span.
|
|
800
|
+
*/
|
|
801
|
+
span: Span;
|
|
802
|
+
/**
|
|
803
|
+
* Metadata parsed on the server. See {@link ParsedMetadata}
|
|
804
|
+
*/
|
|
805
|
+
metadata: ParsedMetadata;
|
|
806
|
+
/**
|
|
807
|
+
* The ID of the session that sent this request.
|
|
808
|
+
*/
|
|
809
|
+
sessionId: SessionId;
|
|
810
|
+
/**
|
|
811
|
+
* The ID of the client that sent this request. There may be multiple sessions per client.
|
|
812
|
+
*/
|
|
813
|
+
from: TransportClientId;
|
|
814
|
+
/**
|
|
815
|
+
* This is used to cancel the procedure call from the handler and notify the client that the
|
|
816
|
+
* call was cancelled.
|
|
817
|
+
*
|
|
818
|
+
* Cancelling is not the same as closing procedure calls gracefully, please refer to
|
|
819
|
+
* the river documentation to understand the difference between the two concepts.
|
|
820
|
+
*/
|
|
821
|
+
cancel: (message?: string) => ErrResult<Static<typeof CancelErrorSchema>>;
|
|
822
|
+
/**
|
|
823
|
+
* This signal is a standard [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)
|
|
824
|
+
* triggered when the procedure invocation is done. This signal tracks the invocation/request finishing
|
|
825
|
+
* for _any_ reason, for example:
|
|
826
|
+
* - client explicit cancellation
|
|
827
|
+
* - procedure handler explicit cancellation via {@link cancel}
|
|
828
|
+
* - client session disconnect
|
|
829
|
+
* - server cancellation due to client invalid payload
|
|
830
|
+
* - invocation finishes cleanly, this depends on the type of the procedure (i.e. rpc handler return, or in a stream after the client-side has closed the request writable and the server-side has closed the response writable)
|
|
831
|
+
*
|
|
832
|
+
* You can use this to pass it on to asynchronous operations (such as fetch).
|
|
833
|
+
*
|
|
834
|
+
* You may also want to explicitly register callbacks on the
|
|
835
|
+
* ['abort' event](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/abort_event)
|
|
836
|
+
* as a way to cleanup after the request is finished.
|
|
837
|
+
*
|
|
838
|
+
* Note that (per standard AbortSignals) callbacks registered _after_ the procedure invocation
|
|
839
|
+
* is done are not triggered. In such cases, you can check the "aborted" property and cleanup
|
|
840
|
+
* immediately if needed.
|
|
841
|
+
*/
|
|
842
|
+
signal: AbortSignal;
|
|
843
|
+
};
|
|
844
|
+
|
|
845
|
+
/**
|
|
846
|
+
* Brands a type to prevent it from being directly constructed.
|
|
847
|
+
*/
|
|
848
|
+
type Branded<T> = T & {
|
|
849
|
+
readonly __BRAND_DO_NOT_USE: unique symbol;
|
|
850
|
+
};
|
|
851
|
+
/**
|
|
852
|
+
* Unbrands a {@link Branded} type.
|
|
853
|
+
*/
|
|
854
|
+
type Unbranded<T> = T extends Branded<infer U> ? U : never;
|
|
855
|
+
/**
|
|
856
|
+
* The valid {@link Procedure} types. The `stream` and `upload` types can optionally have a
|
|
857
|
+
* different type for the very first initialization message. The suffixless types correspond to
|
|
858
|
+
* gRPC's four combinations of stream / non-stream in each direction.
|
|
859
|
+
*/
|
|
860
|
+
type ValidProcType = 'rpc' | 'upload' | 'subscription' | 'stream';
|
|
861
|
+
/**
|
|
862
|
+
* Represents the payload type for {@link Procedure}s.
|
|
863
|
+
*/
|
|
864
|
+
type PayloadType = TSchema;
|
|
865
|
+
type Cancellable<T> = T | Static<typeof CancelErrorSchema>;
|
|
866
|
+
/**
|
|
867
|
+
* Procedure for a single message in both directions (1:1).
|
|
868
|
+
*
|
|
869
|
+
* @template State - The context state object.
|
|
870
|
+
* @template RequestInit - The TypeBox schema of the initialization object.
|
|
871
|
+
* @template ResponseData - The TypeBox schema of the response object.
|
|
872
|
+
* @template ResponseErr - The TypeBox schema of the error object.
|
|
873
|
+
*/
|
|
874
|
+
interface RpcProcedure<State, RequestInit extends PayloadType, ResponseData extends PayloadType, ResponseErr extends ProcedureErrorSchemaType> {
|
|
875
|
+
type: 'rpc';
|
|
876
|
+
requestInit: RequestInit;
|
|
877
|
+
responseData: ResponseData;
|
|
878
|
+
responseError: ResponseErr;
|
|
879
|
+
description?: string;
|
|
880
|
+
handler(param: {
|
|
881
|
+
ctx: ProcedureHandlerContext<State>;
|
|
882
|
+
reqInit: Static<RequestInit>;
|
|
883
|
+
}): Promise<Result<Static<ResponseData>, Cancellable<Static<ResponseErr>>>>;
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* Procedure for a client-stream (potentially preceded by an initialization message),
|
|
887
|
+
* single message from server (n:1).
|
|
888
|
+
*
|
|
889
|
+
* @template State - The context state object.
|
|
890
|
+
* @template RequestInit - The TypeBox schema of the initialization object.
|
|
891
|
+
* @template RequestData - The TypeBox schema of the request object.
|
|
892
|
+
* @template ResponseData - The TypeBox schema of the response object.
|
|
893
|
+
* @template ResponseErr - The TypeBox schema of the error object.
|
|
894
|
+
*/
|
|
895
|
+
interface UploadProcedure<State, RequestInit extends PayloadType, RequestData extends PayloadType, ResponseData extends PayloadType, ResponseErr extends ProcedureErrorSchemaType> {
|
|
896
|
+
type: 'upload';
|
|
897
|
+
requestInit: RequestInit;
|
|
898
|
+
requestData: RequestData;
|
|
899
|
+
responseData: ResponseData;
|
|
900
|
+
responseError: ResponseErr;
|
|
901
|
+
description?: string;
|
|
902
|
+
handler(param: {
|
|
903
|
+
ctx: ProcedureHandlerContext<State>;
|
|
904
|
+
reqInit: Static<RequestInit>;
|
|
905
|
+
reqReadable: Readable<Static<RequestData>, Static<typeof ReaderErrorSchema>>;
|
|
906
|
+
}): Promise<Result<Static<ResponseData>, Cancellable<Static<ResponseErr>>>>;
|
|
907
|
+
}
|
|
908
|
+
/**
|
|
909
|
+
* Procedure for a single message from client, stream from server (1:n).
|
|
910
|
+
*
|
|
911
|
+
* @template State - The context state object.
|
|
912
|
+
* @template RequestInit - The TypeBox schema of the initialization object.
|
|
913
|
+
* @template ResponseData - The TypeBox schema of the response object.
|
|
914
|
+
* @template ResponseErr - The TypeBox schema of the error object.
|
|
915
|
+
*/
|
|
916
|
+
interface SubscriptionProcedure<State, RequestInit extends PayloadType, ResponseData extends PayloadType, ResponseErr extends ProcedureErrorSchemaType> {
|
|
917
|
+
type: 'subscription';
|
|
918
|
+
requestInit: RequestInit;
|
|
919
|
+
responseData: ResponseData;
|
|
920
|
+
responseError: ResponseErr;
|
|
921
|
+
description?: string;
|
|
922
|
+
handler(param: {
|
|
923
|
+
ctx: ProcedureHandlerContext<State>;
|
|
924
|
+
reqInit: Static<RequestInit>;
|
|
925
|
+
resWritable: Writable<Result<Static<ResponseData>, Cancellable<Static<ResponseErr>>>>;
|
|
926
|
+
}): Promise<void | undefined>;
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* Procedure for a bidirectional stream (potentially preceded by an initialization message),
|
|
930
|
+
* (n:n).
|
|
931
|
+
*
|
|
932
|
+
* @template State - The context state object.
|
|
933
|
+
* @template RequestInit - The TypeBox schema of the initialization object.
|
|
934
|
+
* @template RequestData - The TypeBox schema of the request object.
|
|
935
|
+
* @template ResponseData - The TypeBox schema of the response object.
|
|
936
|
+
* @template ResponseErr - The TypeBox schema of the error object.
|
|
937
|
+
*/
|
|
938
|
+
interface StreamProcedure<State, RequestInit extends PayloadType, RequestData extends PayloadType, ResponseData extends PayloadType, ResponseErr extends ProcedureErrorSchemaType> {
|
|
939
|
+
type: 'stream';
|
|
940
|
+
requestInit: RequestInit;
|
|
941
|
+
requestData: RequestData;
|
|
942
|
+
responseData: ResponseData;
|
|
943
|
+
responseError: ResponseErr;
|
|
944
|
+
description?: string;
|
|
945
|
+
handler(param: {
|
|
946
|
+
ctx: ProcedureHandlerContext<State>;
|
|
947
|
+
reqInit: Static<RequestInit>;
|
|
948
|
+
reqReadable: Readable<Static<RequestData>, Static<typeof ReaderErrorSchema>>;
|
|
949
|
+
resWritable: Writable<Result<Static<ResponseData>, Cancellable<Static<ResponseErr>>>>;
|
|
950
|
+
}): Promise<void | undefined>;
|
|
951
|
+
}
|
|
952
|
+
/**
|
|
953
|
+
* Represents any {@link Procedure} type.
|
|
954
|
+
*
|
|
955
|
+
* @template State - The context state object. You can provide this to constrain
|
|
956
|
+
* the type of procedures.
|
|
957
|
+
*/
|
|
958
|
+
type AnyProcedure<State = object> = Procedure<State, ValidProcType, PayloadType, PayloadType | null, PayloadType, ProcedureErrorSchemaType>;
|
|
959
|
+
/**
|
|
960
|
+
* Represents a map of {@link Procedure}s.
|
|
961
|
+
*
|
|
962
|
+
* @template State - The context state object. You can provide this to constrain
|
|
963
|
+
* the type of procedures.
|
|
964
|
+
*/
|
|
965
|
+
type ProcedureMap<State = object> = Record<string, AnyProcedure<State>>;
|
|
966
|
+
/**
|
|
967
|
+
* Creates an {@link RpcProcedure}.
|
|
968
|
+
*/
|
|
969
|
+
declare function rpc<State, RequestInit extends PayloadType, ResponseData extends PayloadType>(def: {
|
|
970
|
+
requestInit: RequestInit;
|
|
971
|
+
responseData: ResponseData;
|
|
972
|
+
responseError?: never;
|
|
973
|
+
description?: string;
|
|
974
|
+
handler: RpcProcedure<State, RequestInit, ResponseData, TNever>['handler'];
|
|
975
|
+
}): Branded<RpcProcedure<State, RequestInit, ResponseData, TNever>>;
|
|
976
|
+
declare function rpc<State, RequestInit extends PayloadType, ResponseData extends PayloadType, ResponseErr extends ProcedureErrorSchemaType>(def: {
|
|
977
|
+
requestInit: RequestInit;
|
|
978
|
+
responseData: ResponseData;
|
|
979
|
+
responseError: ResponseErr;
|
|
980
|
+
description?: string;
|
|
981
|
+
handler: RpcProcedure<State, RequestInit, ResponseData, ResponseErr>['handler'];
|
|
982
|
+
}): Branded<RpcProcedure<State, RequestInit, ResponseData, ResponseErr>>;
|
|
983
|
+
/**
|
|
984
|
+
* Creates an {@link UploadProcedure}, optionally with an initialization message.
|
|
985
|
+
*/
|
|
986
|
+
declare function upload<State, RequestInit extends PayloadType, RequestData extends PayloadType, ResponseData extends PayloadType>(def: {
|
|
987
|
+
requestInit: RequestInit;
|
|
988
|
+
requestData: RequestData;
|
|
989
|
+
responseData: ResponseData;
|
|
990
|
+
responseError?: never;
|
|
991
|
+
description?: string;
|
|
992
|
+
handler: UploadProcedure<State, RequestInit, RequestData, ResponseData, TNever>['handler'];
|
|
993
|
+
}): Branded<UploadProcedure<State, RequestInit, RequestData, ResponseData, TNever>>;
|
|
994
|
+
declare function upload<State, RequestInit extends PayloadType, RequestData extends PayloadType, ResponseData extends PayloadType, ResponseErr extends ProcedureErrorSchemaType>(def: {
|
|
995
|
+
requestInit: RequestInit;
|
|
996
|
+
requestData: RequestData;
|
|
997
|
+
responseData: ResponseData;
|
|
998
|
+
responseError: ResponseErr;
|
|
999
|
+
description?: string;
|
|
1000
|
+
handler: UploadProcedure<State, RequestInit, RequestData, ResponseData, ResponseErr>['handler'];
|
|
1001
|
+
}): Branded<UploadProcedure<State, RequestInit, RequestData, ResponseData, ResponseErr>>;
|
|
1002
|
+
/**
|
|
1003
|
+
* Creates a {@link SubscriptionProcedure}.
|
|
1004
|
+
*/
|
|
1005
|
+
declare function subscription<State, RequestInit extends PayloadType, ResponseData extends PayloadType>(def: {
|
|
1006
|
+
requestInit: RequestInit;
|
|
1007
|
+
responseData: ResponseData;
|
|
1008
|
+
responseError?: never;
|
|
1009
|
+
description?: string;
|
|
1010
|
+
handler: SubscriptionProcedure<State, RequestInit, ResponseData, TNever>['handler'];
|
|
1011
|
+
}): Branded<SubscriptionProcedure<State, RequestInit, ResponseData, TNever>>;
|
|
1012
|
+
declare function subscription<State, RequestInit extends PayloadType, ResponseData extends PayloadType, ResponseErr extends ProcedureErrorSchemaType>(def: {
|
|
1013
|
+
requestInit: RequestInit;
|
|
1014
|
+
responseData: ResponseData;
|
|
1015
|
+
responseError: ResponseErr;
|
|
1016
|
+
description?: string;
|
|
1017
|
+
handler: SubscriptionProcedure<State, RequestInit, ResponseData, ResponseErr>['handler'];
|
|
1018
|
+
}): Branded<SubscriptionProcedure<State, RequestInit, ResponseData, ResponseErr>>;
|
|
1019
|
+
/**
|
|
1020
|
+
* Creates a {@link StreamProcedure}, optionally with an initialization message.
|
|
1021
|
+
*/
|
|
1022
|
+
declare function stream<State, RequestInit extends PayloadType, RequestData extends PayloadType, ResponseData extends PayloadType>(def: {
|
|
1023
|
+
requestInit: RequestInit;
|
|
1024
|
+
requestData: RequestData;
|
|
1025
|
+
responseData: ResponseData;
|
|
1026
|
+
responseError?: never;
|
|
1027
|
+
description?: string;
|
|
1028
|
+
handler: StreamProcedure<State, RequestInit, RequestData, ResponseData, TNever>['handler'];
|
|
1029
|
+
}): Branded<StreamProcedure<State, RequestInit, RequestData, ResponseData, TNever>>;
|
|
1030
|
+
declare function stream<State, RequestInit extends PayloadType, RequestData extends PayloadType, ResponseData extends PayloadType, ResponseErr extends ProcedureErrorSchemaType>(def: {
|
|
1031
|
+
requestInit: RequestInit;
|
|
1032
|
+
requestData: RequestData;
|
|
1033
|
+
responseData: ResponseData;
|
|
1034
|
+
responseError: ResponseErr;
|
|
1035
|
+
description?: string;
|
|
1036
|
+
handler: StreamProcedure<State, RequestInit, RequestData, ResponseData, ResponseErr>['handler'];
|
|
1037
|
+
}): Branded<StreamProcedure<State, RequestInit, RequestData, ResponseData, ResponseErr>>;
|
|
1038
|
+
/**
|
|
1039
|
+
* Defines a Procedure type that can be a:
|
|
1040
|
+
* - {@link RpcProcedure} for a single message in both directions (1:1)
|
|
1041
|
+
* - {@link UploadProcedure} for a client-stream (potentially preceded by an
|
|
1042
|
+
* initialization message)
|
|
1043
|
+
* - {@link SubscriptionProcedure} for a single message from client, stream from server (1:n)
|
|
1044
|
+
* - {@link StreamProcedure} for a bidirectional stream (potentially preceded by an
|
|
1045
|
+
* initialization message)
|
|
1046
|
+
*
|
|
1047
|
+
* @template State - The TypeBox schema of the state object.
|
|
1048
|
+
* @template Ty - The type of the procedure.
|
|
1049
|
+
* @template RequestData - The TypeBox schema of the request object.
|
|
1050
|
+
* @template RequestInit - The TypeBox schema of the request initialization object, if any.
|
|
1051
|
+
* @template ResponseData - The TypeBox schema of the response object.
|
|
1052
|
+
*/
|
|
1053
|
+
type Procedure<State, Ty extends ValidProcType, RequestInit extends PayloadType, RequestData extends PayloadType | null, ResponseData extends PayloadType, ResponseErr extends ProcedureErrorSchemaType> = {
|
|
1054
|
+
type: Ty;
|
|
1055
|
+
} & (RequestData extends PayloadType ? Ty extends 'upload' ? UploadProcedure<State, RequestInit, RequestData, ResponseData, ResponseErr> : Ty extends 'stream' ? StreamProcedure<State, RequestInit, RequestData, ResponseData, ResponseErr> : never : Ty extends 'rpc' ? RpcProcedure<State, RequestInit, ResponseData, ResponseErr> : Ty extends 'subscription' ? SubscriptionProcedure<State, RequestInit, ResponseData, ResponseErr> : never);
|
|
1056
|
+
/**
|
|
1057
|
+
* Holds the {@link Procedure} creation functions. Use these to create
|
|
1058
|
+
* procedures for services. You aren't allowed to create procedures directly.
|
|
1059
|
+
*/
|
|
1060
|
+
declare const Procedure: {
|
|
1061
|
+
rpc: typeof rpc;
|
|
1062
|
+
upload: typeof upload;
|
|
1063
|
+
subscription: typeof subscription;
|
|
1064
|
+
stream: typeof stream;
|
|
1065
|
+
};
|
|
1066
|
+
|
|
1067
|
+
/**
|
|
1068
|
+
* An instantiated service, probably from a {@link ServiceSchema}.
|
|
1069
|
+
*
|
|
1070
|
+
* You shouldn't construct these directly, use {@link ServiceSchema} instead.
|
|
1071
|
+
*/
|
|
1072
|
+
interface Service<State extends object, Procs extends ProcedureMap<State>> {
|
|
1073
|
+
readonly state: State;
|
|
1074
|
+
readonly procedures: Procs;
|
|
1075
|
+
[Symbol.asyncDispose]: () => Promise<void>;
|
|
1076
|
+
}
|
|
1077
|
+
/**
|
|
1078
|
+
* Represents any {@link Service} object.
|
|
1079
|
+
*/
|
|
1080
|
+
type AnyService = Service<object, ProcedureMap>;
|
|
1081
|
+
/**
|
|
1082
|
+
* Represents any {@link ServiceSchema} object.
|
|
1083
|
+
*/
|
|
1084
|
+
type AnyServiceSchema = ServiceSchema<object, ProcedureMap>;
|
|
1085
|
+
/**
|
|
1086
|
+
* A dictionary of {@link ServiceSchema}s, where the key is the service name.
|
|
1087
|
+
*/
|
|
1088
|
+
type AnyServiceSchemaMap = Record<string, AnyServiceSchema>;
|
|
1089
|
+
/**
|
|
1090
|
+
* Takes a {@link AnyServiceSchemaMap} and returns a dictionary of instantiated
|
|
1091
|
+
* services.
|
|
1092
|
+
*/
|
|
1093
|
+
type InstantiatedServiceSchemaMap<T extends AnyServiceSchemaMap> = {
|
|
1094
|
+
[K in keyof T]: T[K] extends ServiceSchema<infer S, infer P> ? Service<S, P> : never;
|
|
1095
|
+
};
|
|
1096
|
+
/**
|
|
1097
|
+
* Helper to get the type definition for a specific handler of a procedure in a service.
|
|
1098
|
+
* @template S - The service.
|
|
1099
|
+
* @template ProcName - The name of the procedure.
|
|
1100
|
+
*/
|
|
1101
|
+
type ProcHandler<S extends AnyService, ProcName extends keyof S['procedures']> = S['procedures'][ProcName]['handler'];
|
|
1102
|
+
/**
|
|
1103
|
+
* Helper to get the type definition for the procedure init type of a service.
|
|
1104
|
+
* @template S - The service.
|
|
1105
|
+
* @template ProcName - The name of the procedure.
|
|
1106
|
+
*/
|
|
1107
|
+
type ProcInit<S extends AnyService, ProcName extends keyof S['procedures']> = Static<S['procedures'][ProcName]['requestInit']>;
|
|
1108
|
+
/**
|
|
1109
|
+
* Helper to get the type definition for the procedure request of a service.
|
|
1110
|
+
* @template S - The service.
|
|
1111
|
+
* @template ProcName - The name of the procedure.
|
|
1112
|
+
*/
|
|
1113
|
+
type ProcRequest<S extends AnyService, ProcName extends keyof S['procedures']> = S['procedures'][ProcName] extends {
|
|
1114
|
+
requestData: PayloadType;
|
|
1115
|
+
} ? Static<S['procedures'][ProcName]['requestData']> : never;
|
|
1116
|
+
/**
|
|
1117
|
+
* Helper to get the type definition for the procedure response of a service.
|
|
1118
|
+
* @template S - The service.
|
|
1119
|
+
* @template ProcName - The name of the procedure.
|
|
1120
|
+
*/
|
|
1121
|
+
type ProcResponse<S extends AnyService, ProcName extends keyof S['procedures']> = Static<S['procedures'][ProcName]['responseData']>;
|
|
1122
|
+
/**
|
|
1123
|
+
* Helper to get the type definition for the procedure errors of a service.
|
|
1124
|
+
* @template S - The service.
|
|
1125
|
+
* @template ProcName - The name of the procedure.
|
|
1126
|
+
*/
|
|
1127
|
+
type ProcErrors<S extends AnyService, ProcName extends keyof S['procedures']> = Static<S['procedures'][ProcName]['responseError']> | Static<typeof ReaderErrorSchema>;
|
|
1128
|
+
/**
|
|
1129
|
+
* Helper to get the type of procedure in a service.
|
|
1130
|
+
* @template S - The service.
|
|
1131
|
+
* @template ProcName - The name of the procedure.
|
|
1132
|
+
*/
|
|
1133
|
+
type ProcType<S extends AnyService, ProcName extends keyof S['procedures']> = S['procedures'][ProcName]['type'];
|
|
1134
|
+
/**
|
|
1135
|
+
* A list of procedures where every procedure is "branded", as-in the procedure
|
|
1136
|
+
* was created via the {@link Procedure} constructors.
|
|
1137
|
+
*/
|
|
1138
|
+
type BrandedProcedureMap<State> = Record<string, Branded<AnyProcedure<State>>>;
|
|
1139
|
+
type MaybeDisposable<State extends object> = State & {
|
|
1140
|
+
[Symbol.asyncDispose]?: () => Promise<void>;
|
|
1141
|
+
[Symbol.dispose]?: () => void;
|
|
1142
|
+
};
|
|
1143
|
+
/**
|
|
1144
|
+
* The configuration for a service.
|
|
1145
|
+
*/
|
|
1146
|
+
interface ServiceConfiguration<State extends object> {
|
|
1147
|
+
/**
|
|
1148
|
+
* A factory function for creating a fresh state.
|
|
1149
|
+
*/
|
|
1150
|
+
initializeState: (extendedContext: ServiceContext) => MaybeDisposable<State>;
|
|
1151
|
+
}
|
|
1152
|
+
interface SerializedProcedureSchemaProtocolv1 {
|
|
1153
|
+
init?: PayloadType;
|
|
1154
|
+
input: PayloadType;
|
|
1155
|
+
output: PayloadType;
|
|
1156
|
+
errors?: ProcedureErrorSchemaType;
|
|
1157
|
+
type: 'rpc' | 'subscription' | 'upload' | 'stream';
|
|
1158
|
+
}
|
|
1159
|
+
interface SerializedServiceSchemaProtocolv1 {
|
|
1160
|
+
procedures: Record<string, SerializedProcedureSchemaProtocolv1>;
|
|
1161
|
+
}
|
|
1162
|
+
interface SerializedServerSchemaProtocolv1 {
|
|
1163
|
+
handshakeSchema?: TSchema;
|
|
1164
|
+
services: Record<string, SerializedServiceSchemaProtocolv1>;
|
|
1165
|
+
}
|
|
1166
|
+
/**
|
|
1167
|
+
* Same as {@link serializeSchema} but with a format that is compatible with
|
|
1168
|
+
* protocolv1. This is useful to be able to continue to generate schemas for older
|
|
1169
|
+
* clients as they are still supported.
|
|
1170
|
+
*/
|
|
1171
|
+
declare function serializeSchemaV1Compat(services: AnyServiceSchemaMap, handshakeSchema?: TSchema): SerializedServerSchemaProtocolv1;
|
|
1172
|
+
interface SerializedProcedureSchema {
|
|
1173
|
+
init: PayloadType;
|
|
1174
|
+
input?: PayloadType;
|
|
1175
|
+
output: PayloadType;
|
|
1176
|
+
errors?: ProcedureErrorSchemaType;
|
|
1177
|
+
type: 'rpc' | 'subscription' | 'upload' | 'stream';
|
|
1178
|
+
}
|
|
1179
|
+
interface SerializedServiceSchema {
|
|
1180
|
+
procedures: Record<string, SerializedProcedureSchema>;
|
|
1181
|
+
}
|
|
1182
|
+
interface SerializedServerSchema {
|
|
1183
|
+
handshakeSchema?: TSchema;
|
|
1184
|
+
services: Record<string, SerializedServiceSchema>;
|
|
1185
|
+
}
|
|
1186
|
+
/**
|
|
1187
|
+
* Serializes a server schema into a plain object that is JSON compatible.
|
|
1188
|
+
*/
|
|
1189
|
+
declare function serializeSchema(services: AnyServiceSchemaMap, handshakeSchema?: TSchema): SerializedServerSchema;
|
|
1190
|
+
/**
|
|
1191
|
+
* The schema for a {@link Service}. This is used to define a service, specifically
|
|
1192
|
+
* its initial state and procedures.
|
|
1193
|
+
*
|
|
1194
|
+
* There are two ways to define a service:
|
|
1195
|
+
* 1. the {@link ServiceSchema.define} static method, which takes a configuration and
|
|
1196
|
+
* a list of procedures directly. Use this to ergonomically define a service schema
|
|
1197
|
+
* in one go. Good for smaller services, especially if they're stateless.
|
|
1198
|
+
* 2. the {@link ServiceSchema.scaffold} static method, which creates a scaffold that
|
|
1199
|
+
* can be used to define procedures separately from the configuration. Use this to
|
|
1200
|
+
* better organize your service's definition, especially if it's a large service.
|
|
1201
|
+
* You can also use it in a builder pattern to define the service in a more
|
|
1202
|
+
* fluent way.
|
|
1203
|
+
*
|
|
1204
|
+
* See the static methods for more information and examples.
|
|
1205
|
+
*
|
|
1206
|
+
* When defining procedures, use the {@link Procedure} constructors to create them.
|
|
1207
|
+
*/
|
|
1208
|
+
declare class ServiceSchema<State extends object, Procedures extends ProcedureMap<State>> {
|
|
1209
|
+
/**
|
|
1210
|
+
* Factory function for creating a fresh state.
|
|
1211
|
+
*/
|
|
1212
|
+
protected readonly initializeState: (extendedContext: ServiceContext) => MaybeDisposable<State>;
|
|
1213
|
+
/**
|
|
1214
|
+
* The procedures for this service.
|
|
1215
|
+
*/
|
|
1216
|
+
readonly procedures: Procedures;
|
|
1217
|
+
/**
|
|
1218
|
+
* @param config - The configuration for this service.
|
|
1219
|
+
* @param procedures - The procedures for this service.
|
|
1220
|
+
*/
|
|
1221
|
+
protected constructor(config: ServiceConfiguration<State>, procedures: Procedures);
|
|
1222
|
+
/**
|
|
1223
|
+
* Creates a {@link ServiceScaffold}, which can be used to define procedures
|
|
1224
|
+
* that can then be merged into a {@link ServiceSchema}, via the scaffold's
|
|
1225
|
+
* `finalize` method.
|
|
1226
|
+
*
|
|
1227
|
+
* There are two patterns that work well with this method. The first is using
|
|
1228
|
+
* it to separate the definition of procedures from the definition of the
|
|
1229
|
+
* service's configuration:
|
|
1230
|
+
* ```ts
|
|
1231
|
+
* const MyServiceScaffold = ServiceSchema.scaffold({
|
|
1232
|
+
* initializeState: () => ({ count: 0 }),
|
|
1233
|
+
* });
|
|
1234
|
+
*
|
|
1235
|
+
* const incrementProcedures = MyServiceScaffold.procedures({
|
|
1236
|
+
* increment: Procedure.rpc({
|
|
1237
|
+
* requestInit: Type.Object({ amount: Type.Number() }),
|
|
1238
|
+
* responseData: Type.Object({ current: Type.Number() }),
|
|
1239
|
+
* async handler(ctx, init) {
|
|
1240
|
+
* ctx.state.count += init.amount;
|
|
1241
|
+
* return Ok({ current: ctx.state.count });
|
|
1242
|
+
* }
|
|
1243
|
+
* }),
|
|
1244
|
+
* })
|
|
1245
|
+
*
|
|
1246
|
+
* const MyService = MyServiceScaffold.finalize({
|
|
1247
|
+
* ...incrementProcedures,
|
|
1248
|
+
* // you can also directly define procedures here
|
|
1249
|
+
* });
|
|
1250
|
+
* ```
|
|
1251
|
+
* This might be really handy if you have a very large service and you're
|
|
1252
|
+
* wanting to split it over multiple files. You can define the scaffold
|
|
1253
|
+
* in one file, and then import that scaffold in other files where you
|
|
1254
|
+
* define procedures - and then finally import the scaffolds and your
|
|
1255
|
+
* procedure objects in a final file where you finalize the scaffold into
|
|
1256
|
+
* a service schema.
|
|
1257
|
+
*
|
|
1258
|
+
* The other way is to use it like in a builder pattern:
|
|
1259
|
+
* ```ts
|
|
1260
|
+
* const MyService = ServiceSchema
|
|
1261
|
+
* .scaffold({ initializeState: () => ({ count: 0 }) })
|
|
1262
|
+
* .finalize({
|
|
1263
|
+
* increment: Procedure.rpc({
|
|
1264
|
+
* requestInit: Type.Object({ amount: Type.Number() }),
|
|
1265
|
+
* responseData: Type.Object({ current: Type.Number() }),
|
|
1266
|
+
* async handler(ctx, init) {
|
|
1267
|
+
* ctx.state.count += init.amount;
|
|
1268
|
+
* return Ok({ current: ctx.state.count });
|
|
1269
|
+
* }
|
|
1270
|
+
* }),
|
|
1271
|
+
* })
|
|
1272
|
+
* ```
|
|
1273
|
+
* Depending on your preferences, this may be a more appealing way to define
|
|
1274
|
+
* a schema versus using the {@link ServiceSchema.define} method.
|
|
1275
|
+
*/
|
|
1276
|
+
static scaffold<State extends object>(config: ServiceConfiguration<State>): ServiceScaffold<State>;
|
|
1277
|
+
/**
|
|
1278
|
+
* Creates a new {@link ServiceSchema} with the given configuration and procedures.
|
|
1279
|
+
*
|
|
1280
|
+
* All procedures must be created with the {@link Procedure} constructors.
|
|
1281
|
+
*
|
|
1282
|
+
* NOTE: There is an overload that lets you just provide the procedures alone if your
|
|
1283
|
+
* service has no state.
|
|
1284
|
+
*
|
|
1285
|
+
* @param config - The configuration for this service.
|
|
1286
|
+
* @param procedures - The procedures for this service.
|
|
1287
|
+
*
|
|
1288
|
+
* @example
|
|
1289
|
+
* ```
|
|
1290
|
+
* const service = ServiceSchema.define(
|
|
1291
|
+
* { initializeState: () => ({ count: 0 }) },
|
|
1292
|
+
* {
|
|
1293
|
+
* increment: Procedure.rpc({
|
|
1294
|
+
* requestInit: Type.Object({ amount: Type.Number() }),
|
|
1295
|
+
* responseData: Type.Object({ current: Type.Number() }),
|
|
1296
|
+
* async handler(ctx, init) {
|
|
1297
|
+
* ctx.state.count += init.amount;
|
|
1298
|
+
* return Ok({ current: ctx.state.count });
|
|
1299
|
+
* }
|
|
1300
|
+
* }),
|
|
1301
|
+
* },
|
|
1302
|
+
* );
|
|
1303
|
+
* ```
|
|
1304
|
+
*/
|
|
1305
|
+
static define<State extends object, Procedures extends BrandedProcedureMap<State>>(config: ServiceConfiguration<State>, procedures: Procedures): ServiceSchema<State, {
|
|
1306
|
+
[K in keyof Procedures]: Unbranded<Procedures[K]>;
|
|
1307
|
+
}>;
|
|
1308
|
+
/**
|
|
1309
|
+
* Creates a new {@link ServiceSchema} with the given procedures.
|
|
1310
|
+
*
|
|
1311
|
+
* All procedures must be created with the {@link Procedure} constructors.
|
|
1312
|
+
*
|
|
1313
|
+
* NOTE: There is an overload that lets you provide configuration as well,
|
|
1314
|
+
* if your service has extra configuration like a state.
|
|
1315
|
+
*
|
|
1316
|
+
* @param procedures - The procedures for this service.
|
|
1317
|
+
*
|
|
1318
|
+
* @example
|
|
1319
|
+
* ```
|
|
1320
|
+
* const service = ServiceSchema.define({
|
|
1321
|
+
* add: Procedure.rpc({
|
|
1322
|
+
* requestInit: Type.Object({ a: Type.Number(), b: Type.Number() }),
|
|
1323
|
+
* responseData: Type.Object({ result: Type.Number() }),
|
|
1324
|
+
* async handler(ctx, init) {
|
|
1325
|
+
* return Ok({ result: init.a + init.b });
|
|
1326
|
+
* }
|
|
1327
|
+
* }),
|
|
1328
|
+
* });
|
|
1329
|
+
*/
|
|
1330
|
+
static define<Procedures extends BrandedProcedureMap<Record<string, never>>>(procedures: Procedures): ServiceSchema<Record<string, never>, {
|
|
1331
|
+
[K in keyof Procedures]: Unbranded<Procedures[K]>;
|
|
1332
|
+
}>;
|
|
1333
|
+
/**
|
|
1334
|
+
* Serializes this schema's procedures into a plain object that is JSON compatible.
|
|
1335
|
+
*/
|
|
1336
|
+
serialize(): SerializedServiceSchema;
|
|
1337
|
+
/**
|
|
1338
|
+
* Same as {@link ServiceSchema.serialize}, but with a format that is compatible with
|
|
1339
|
+
* protocol v1. This is useful to be able to continue to generate schemas for older
|
|
1340
|
+
* clients as they are still supported.
|
|
1341
|
+
*/
|
|
1342
|
+
serializeV1Compat(): SerializedServiceSchemaProtocolv1;
|
|
1343
|
+
/**
|
|
1344
|
+
* Instantiates this schema into a {@link Service} object.
|
|
1345
|
+
*
|
|
1346
|
+
* You probably don't need this, usually the River server will handle this
|
|
1347
|
+
* for you.
|
|
1348
|
+
*/
|
|
1349
|
+
instantiate(extendedContext: ServiceContext): Service<State, Procedures>;
|
|
1350
|
+
}
|
|
1351
|
+
/**
|
|
1352
|
+
* A scaffold for defining a service's procedures.
|
|
1353
|
+
*
|
|
1354
|
+
* @see {@link ServiceSchema.scaffold}
|
|
1355
|
+
*/
|
|
1356
|
+
declare class ServiceScaffold<State extends object> {
|
|
1357
|
+
/**
|
|
1358
|
+
* The configuration for this service.
|
|
1359
|
+
*/
|
|
1360
|
+
protected readonly config: ServiceConfiguration<State>;
|
|
1361
|
+
/**
|
|
1362
|
+
* @param config - The configuration for this service.
|
|
1363
|
+
*/
|
|
1364
|
+
constructor(config: ServiceConfiguration<State>);
|
|
1365
|
+
/**
|
|
1366
|
+
* Define procedures for this service. Use the {@link Procedure} constructors
|
|
1367
|
+
* to create them. This returns the procedures object, which can then be
|
|
1368
|
+
* passed to {@link ServiceSchema.finalize} to create a {@link ServiceSchema}.
|
|
1369
|
+
*
|
|
1370
|
+
* @example
|
|
1371
|
+
* ```
|
|
1372
|
+
* const myProcedures = MyServiceScaffold.procedures({
|
|
1373
|
+
* myRPC: Procedure.rpc({
|
|
1374
|
+
* // ...
|
|
1375
|
+
* }),
|
|
1376
|
+
* });
|
|
1377
|
+
*
|
|
1378
|
+
* const MyService = MyServiceScaffold.finalize({
|
|
1379
|
+
* ...myProcedures,
|
|
1380
|
+
* });
|
|
1381
|
+
* ```
|
|
1382
|
+
*
|
|
1383
|
+
* @param procedures - The procedures for this service.
|
|
1384
|
+
*/
|
|
1385
|
+
procedures<T extends BrandedProcedureMap<State>>(procedures: T): T;
|
|
1386
|
+
/**
|
|
1387
|
+
* Finalizes the scaffold into a {@link ServiceSchema}. This is where you
|
|
1388
|
+
* provide the service's procedures and get a {@link ServiceSchema} in return.
|
|
1389
|
+
*
|
|
1390
|
+
* You can directly define procedures here, or you can define them separately
|
|
1391
|
+
* with the {@link ServiceScaffold.procedures} method, and then pass them here.
|
|
1392
|
+
*
|
|
1393
|
+
* @example
|
|
1394
|
+
* ```
|
|
1395
|
+
* const MyService = MyServiceScaffold.finalize({
|
|
1396
|
+
* myRPC: Procedure.rpc({
|
|
1397
|
+
* // ...
|
|
1398
|
+
* }),
|
|
1399
|
+
* // e.g. from the procedures method
|
|
1400
|
+
* ...myOtherProcedures,
|
|
1401
|
+
* });
|
|
1402
|
+
* ```
|
|
1403
|
+
*/
|
|
1404
|
+
finalize<T extends BrandedProcedureMap<State>>(procedures: T): ServiceSchema<State, {
|
|
1405
|
+
[K in keyof T]: Unbranded<T[K]>;
|
|
1406
|
+
}>;
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
declare const ProtocolError: {
|
|
1410
|
+
readonly RetriesExceeded: "conn_retry_exceeded";
|
|
1411
|
+
readonly HandshakeFailed: "handshake_failed";
|
|
1412
|
+
readonly MessageOrderingViolated: "message_ordering_violated";
|
|
1413
|
+
readonly InvalidMessage: "invalid_message";
|
|
1414
|
+
readonly MessageSendFailure: "message_send_failure";
|
|
1415
|
+
};
|
|
1416
|
+
type ProtocolErrorType = (typeof ProtocolError)[keyof typeof ProtocolError];
|
|
1417
|
+
interface EventMap {
|
|
1418
|
+
message: OpaqueTransportMessage;
|
|
1419
|
+
sessionStatus: {
|
|
1420
|
+
status: 'created' | 'closing';
|
|
1421
|
+
session: Session<Connection>;
|
|
1422
|
+
} | {
|
|
1423
|
+
status: 'closed';
|
|
1424
|
+
session: Pick<Session<Connection>, 'id' | 'to'>;
|
|
1425
|
+
};
|
|
1426
|
+
sessionTransition: {
|
|
1427
|
+
state: SessionState.Connected;
|
|
1428
|
+
id: SessionId;
|
|
1429
|
+
} | {
|
|
1430
|
+
state: SessionState.Handshaking;
|
|
1431
|
+
id: SessionId;
|
|
1432
|
+
} | {
|
|
1433
|
+
state: SessionState.Connecting;
|
|
1434
|
+
id: SessionId;
|
|
1435
|
+
} | {
|
|
1436
|
+
state: SessionState.BackingOff;
|
|
1437
|
+
id: SessionId;
|
|
1438
|
+
} | {
|
|
1439
|
+
state: SessionState.NoConnection;
|
|
1440
|
+
id: SessionId;
|
|
1441
|
+
};
|
|
1442
|
+
protocolError: {
|
|
1443
|
+
type: (typeof ProtocolError)['HandshakeFailed'];
|
|
1444
|
+
code: Static<typeof HandshakeErrorResponseCodes>;
|
|
1445
|
+
message: string;
|
|
1446
|
+
} | {
|
|
1447
|
+
type: Omit<ProtocolErrorType, (typeof ProtocolError)['HandshakeFailed']>;
|
|
1448
|
+
message: string;
|
|
1449
|
+
};
|
|
1450
|
+
transportStatus: {
|
|
1451
|
+
status: TransportStatus;
|
|
1452
|
+
};
|
|
1453
|
+
}
|
|
1454
|
+
type EventTypes = keyof EventMap;
|
|
1455
|
+
type EventHandler<K extends EventTypes> = (event: EventMap[K]) => unknown;
|
|
1456
|
+
declare class EventDispatcher<T extends EventTypes> {
|
|
1457
|
+
private eventListeners;
|
|
1458
|
+
removeAllListeners(): void;
|
|
1459
|
+
numberOfListeners<K extends T>(eventType: K): number;
|
|
1460
|
+
addEventListener<K extends T>(eventType: K, handler: EventHandler<K>): void;
|
|
1461
|
+
removeEventListener<K extends T>(eventType: K, handler: EventHandler<K>): void;
|
|
1462
|
+
dispatchEvent<K extends T>(eventType: K, event: EventMap[K]): void;
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
/**
|
|
1466
|
+
* Represents the possible states of a transport.
|
|
1467
|
+
* @property {'open'} open - The transport is open and operational (note that this doesn't mean it is actively connected)
|
|
1468
|
+
* @property {'closed'} closed - The transport is permanently closed and cannot be reopened.
|
|
1469
|
+
*/
|
|
1470
|
+
type TransportStatus = 'open' | 'closed';
|
|
1471
|
+
interface DeleteSessionOptions {
|
|
1472
|
+
unhealthy: boolean;
|
|
1473
|
+
}
|
|
1474
|
+
type SessionBoundSendFn = (msg: PartialTransportMessage) => string;
|
|
1475
|
+
/**
|
|
1476
|
+
* Transports manage the lifecycle (creation/deletion) of sessions
|
|
1477
|
+
*
|
|
1478
|
+
* ```plaintext
|
|
1479
|
+
* ▲
|
|
1480
|
+
* incoming │
|
|
1481
|
+
* messages │
|
|
1482
|
+
* ▼
|
|
1483
|
+
* ┌─────────────┐ 1:N ┌───────────┐ 1:1* ┌────────────┐
|
|
1484
|
+
* │ Transport │ ◄─────► │ Session │ ◄─────► │ Connection │
|
|
1485
|
+
* └─────────────┘ └───────────┘ └────────────┘
|
|
1486
|
+
* ▲ * (may or may not be initialized yet)
|
|
1487
|
+
* │
|
|
1488
|
+
* ▼
|
|
1489
|
+
* ┌───────────┐
|
|
1490
|
+
* │ Message │
|
|
1491
|
+
* │ Listeners │
|
|
1492
|
+
* └───────────┘
|
|
1493
|
+
* ```
|
|
1494
|
+
* @abstract
|
|
1495
|
+
*/
|
|
1496
|
+
declare abstract class Transport<ConnType extends Connection> {
|
|
1497
|
+
/**
|
|
1498
|
+
* The status of the transport.
|
|
1499
|
+
*/
|
|
1500
|
+
private status;
|
|
1501
|
+
/**
|
|
1502
|
+
* The client ID of this transport.
|
|
1503
|
+
*/
|
|
1504
|
+
clientId: TransportClientId;
|
|
1505
|
+
/**
|
|
1506
|
+
* The event dispatcher for handling events of type EventTypes.
|
|
1507
|
+
*/
|
|
1508
|
+
eventDispatcher: EventDispatcher<EventTypes>;
|
|
1509
|
+
/**
|
|
1510
|
+
* The options for this transport.
|
|
1511
|
+
*/
|
|
1512
|
+
protected options: TransportOptions;
|
|
1513
|
+
log?: Logger;
|
|
1514
|
+
tracer: Tracer;
|
|
1515
|
+
sessions: Map<TransportClientId, Session<ConnType>>;
|
|
1516
|
+
/**
|
|
1517
|
+
* Creates a new Transport instance.
|
|
1518
|
+
* @param codec The codec used to encode and decode messages.
|
|
1519
|
+
* @param clientId The client ID of this transport.
|
|
1520
|
+
*/
|
|
1521
|
+
constructor(clientId: TransportClientId, providedOptions?: ProvidedTransportOptions);
|
|
1522
|
+
bindLogger(fn: LogFn | Logger, level?: LoggingLevel): void;
|
|
1523
|
+
/**
|
|
1524
|
+
* Called when a message is received by this transport.
|
|
1525
|
+
* You generally shouldn't need to override this in downstream transport implementations.
|
|
1526
|
+
* @param message The received message.
|
|
1527
|
+
*/
|
|
1528
|
+
protected handleMsg(message: OpaqueTransportMessage): void;
|
|
1529
|
+
/**
|
|
1530
|
+
* Adds a listener to this transport.
|
|
1531
|
+
* @param the type of event to listen for
|
|
1532
|
+
* @param handler The message handler to add.
|
|
1533
|
+
*/
|
|
1534
|
+
addEventListener<K extends EventTypes, T extends EventHandler<K>>(type: K, handler: T): void;
|
|
1535
|
+
/**
|
|
1536
|
+
* Removes a listener from this transport.
|
|
1537
|
+
* @param the type of event to un-listen on
|
|
1538
|
+
* @param handler The message handler to remove.
|
|
1539
|
+
*/
|
|
1540
|
+
removeEventListener<K extends EventTypes, T extends EventHandler<K>>(type: K, handler: T): void;
|
|
1541
|
+
protected protocolError(message: EventMap['protocolError']): void;
|
|
1542
|
+
/**
|
|
1543
|
+
* Default close implementation for transports. You should override this in the downstream
|
|
1544
|
+
* implementation if you need to do any additional cleanup and call super.close() at the end.
|
|
1545
|
+
* Closes the transport. Any messages sent while the transport is closed will be silently discarded.
|
|
1546
|
+
*/
|
|
1547
|
+
close(): void;
|
|
1548
|
+
getStatus(): TransportStatus;
|
|
1549
|
+
protected createSession<S extends Session<ConnType>>(session: S): void;
|
|
1550
|
+
protected updateSession<S extends Session<ConnType>>(session: S): void;
|
|
1551
|
+
protected deleteSession(session: Session<ConnType>, options?: DeleteSessionOptions): void;
|
|
1552
|
+
protected onSessionGracePeriodElapsed(session: Session<ConnType>): void;
|
|
1553
|
+
protected onConnectingFailed(session: SessionConnecting<ConnType>): SessionNoConnection;
|
|
1554
|
+
protected onConnClosed(session: SessionHandshaking<ConnType> | SessionConnected<ConnType>): SessionNoConnection;
|
|
1555
|
+
/**
|
|
1556
|
+
* Gets a send closure scoped to a specific session. Sending using the returned
|
|
1557
|
+
* closure after the session has transitioned to a different state will be a noop.
|
|
1558
|
+
*
|
|
1559
|
+
* Session objects themselves can become stale as they transition between
|
|
1560
|
+
* states. As stale sessions cannot be used again (and will throw), holding
|
|
1561
|
+
* onto a session object is not recommended.
|
|
1562
|
+
*/
|
|
1563
|
+
getSessionBoundSendFn(to: TransportClientId, sessionId: SessionId): SessionBoundSendFn;
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
export { type ResultUnwrapOk as $, type AnyServiceSchemaMap as A, type StreamProcedure as B, ClientTransport as C, type Readable as D, Procedure as E, type ProcedureErrorSchemaType as F, flattenErrorType as G, UNCAUGHT_ERROR_CODE as H, type InstantiatedServiceSchemaMap as I, UNEXPECTED_DISCONNECT_CODE as J, INVALID_REQUEST_CODE as K, CANCEL_CODE as L, ReaderErrorSchema as M, type BaseErrorSchemaType as N, createClient as O, type ProvidedClientTransportOptions as P, type Client as Q, type RpcProcedure as R, type ServerHandshakeOptions as S, Ok as T, type UploadProcedure as U, type ValidProcType as V, type Writable as W, Err as X, type Result as Y, type ErrResult as Z, type OkResult as _, type ProvidedServerTransportOptions as a, type ResultUnwrapErr as a0, type ResponseData as a1, createClientHandshakeOptions as a2, createServerHandshakeOptions as a3, type ClientHandshakeOptions as a4, type ReadableIterator as a5, type ReadableResult as a6, Transport as a7, type SessionOptions as a8, type ClientTransportOptions as a9, SessionNoConnection as aa, type SessionBoundSendFn as ab, CommonSession as ac, SessionState as ad, type CommonSessionProps as ae, type ServerTransportOptions as af, type ServerSession as ag, type DeleteSessionOptions as ah, type TransportStatus as ai, type ProvidedTransportOptions as aj, type Session as ak, SessionConnecting as al, SessionHandshaking as am, SessionConnected as an, type EventMap as ao, type EventTypes as ap, type EventHandler as aq, ProtocolError as ar, type ProtocolErrorType as as, Connection as b, type ServiceContext as c, type ProcedureHandlerContext as d, type PayloadType as e, type ParsedMetadata as f, type AnyProcedure as g, type Service as h, type ServiceConfiguration as i, type ProcHandler as j, type ProcInit as k, type ProcRequest as l, type ProcResponse as m, type ProcErrors as n, type ProcType as o, ServiceSchema as p, type SerializedServerSchema as q, type SerializedServiceSchema as r, serializeSchema as s, type SerializedProcedureSchema as t, serializeSchemaV1Compat as u, type SerializedServerSchemaProtocolv1 as v, type SerializedServiceSchemaProtocolv1 as w, type SerializedProcedureSchemaProtocolv1 as x, type ProcedureMap as y, type SubscriptionProcedure as z };
|