@trpc/client 11.3.1 → 11.3.2-canary.2
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/TRPCClientError-CGgRtttT.cjs +67 -0
- package/dist/TRPCClientError-COkhCKf3.mjs +56 -0
- package/dist/TRPCClientError-COkhCKf3.mjs.map +1 -0
- package/dist/chunk-DWy1uDak.cjs +39 -0
- package/dist/httpBatchLink-CIC9PZ_Z.cjs +267 -0
- package/dist/httpBatchLink-DIfnmmcu.mjs +238 -0
- package/dist/httpBatchLink-DIfnmmcu.mjs.map +1 -0
- package/dist/httpBatchLink.d-BN2Iw_cK.d.mts +33 -0
- package/dist/httpBatchLink.d-BN2Iw_cK.d.mts.map +1 -0
- package/dist/httpBatchLink.d-CLAuJKNV.d.cts +33 -0
- package/dist/httpBatchLink.d-CLAuJKNV.d.cts.map +1 -0
- package/dist/httpLink-9bpwQ15c.mjs +90 -0
- package/dist/httpLink-9bpwQ15c.mjs.map +1 -0
- package/dist/httpLink-BbVj_TgM.cjs +113 -0
- package/dist/httpLink.d-CTSOARfE.d.mts +23 -0
- package/dist/httpLink.d-CTSOARfE.d.mts.map +1 -0
- package/dist/httpLink.d-yMKfOlTU.d.cts +23 -0
- package/dist/httpLink.d-yMKfOlTU.d.cts.map +1 -0
- package/dist/httpUtils-3pbQzhUL.mjs +123 -0
- package/dist/httpUtils-3pbQzhUL.mjs.map +1 -0
- package/dist/httpUtils-Buf6jCgh.cjs +163 -0
- package/dist/httpUtils.d-C8wPxU79.d.mts +25 -0
- package/dist/httpUtils.d-C8wPxU79.d.mts.map +1 -0
- package/dist/httpUtils.d-DNRVGNHs.d.cts +25 -0
- package/dist/httpUtils.d-DNRVGNHs.d.cts.map +1 -0
- package/dist/index.cjs +731 -0
- package/dist/index.d.cts +197 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +197 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +733 -16
- package/dist/index.mjs.map +1 -0
- package/dist/links/httpBatchLink.cjs +6 -0
- package/dist/links/httpBatchLink.d.cts +6 -0
- package/dist/links/httpBatchLink.d.mts +6 -0
- package/dist/links/httpBatchLink.mjs +5 -107
- package/dist/links/httpLink.cjs +6 -0
- package/dist/links/httpLink.d.cts +6 -0
- package/dist/links/httpLink.d.mts +6 -0
- package/dist/links/httpLink.mjs +5 -92
- package/dist/links/loggerLink.cjs +3 -0
- package/dist/links/loggerLink.d.cts +4 -0
- package/dist/links/loggerLink.d.mts +4 -0
- package/dist/links/loggerLink.mjs +2 -175
- package/dist/links/splitLink.cjs +3 -0
- package/dist/links/splitLink.d.cts +4 -0
- package/dist/links/splitLink.d.mts +4 -0
- package/dist/links/splitLink.mjs +2 -24
- package/dist/links/wsLink/wsLink.cjs +6 -0
- package/dist/links/wsLink/wsLink.d.cts +5 -0
- package/dist/links/wsLink/wsLink.d.mts +5 -0
- package/dist/links/wsLink/wsLink.mjs +4 -31
- package/dist/loggerLink-CsDfg5Bb.cjs +130 -0
- package/dist/loggerLink-PGBSQFcR.mjs +125 -0
- package/dist/loggerLink-PGBSQFcR.mjs.map +1 -0
- package/dist/loggerLink.d-CZjK1CXm.d.mts +54 -0
- package/dist/loggerLink.d-CZjK1CXm.d.mts.map +1 -0
- package/dist/loggerLink.d-DU855urG.d.cts +54 -0
- package/dist/loggerLink.d-DU855urG.d.cts.map +1 -0
- package/dist/splitLink-BMgxggng.cjs +58 -0
- package/dist/splitLink-BVblHq4n.mjs +47 -0
- package/dist/splitLink-BVblHq4n.mjs.map +1 -0
- package/dist/splitLink.d-BAqgq0NG.d.mts +20 -0
- package/dist/splitLink.d-BAqgq0NG.d.mts.map +1 -0
- package/dist/splitLink.d-GdevSkGW.d.cts +20 -0
- package/dist/splitLink.d-GdevSkGW.d.cts.map +1 -0
- package/dist/subscriptions.d-Ciljg_dH.d.cts +19 -0
- package/dist/subscriptions.d-Ciljg_dH.d.cts.map +1 -0
- package/dist/subscriptions.d-U92STdZl.d.mts +19 -0
- package/dist/subscriptions.d-U92STdZl.d.mts.map +1 -0
- package/dist/types.d-DXbqQLCC.d.mts +182 -0
- package/dist/types.d-DXbqQLCC.d.mts.map +1 -0
- package/dist/types.d-DqGYG6S_.d.cts +182 -0
- package/dist/types.d-DqGYG6S_.d.cts.map +1 -0
- package/dist/unstable-internals-CYBH4jbF.cjs +34 -0
- package/dist/unstable-internals-DU4WecoG.mjs +29 -0
- package/dist/unstable-internals-DU4WecoG.mjs.map +1 -0
- package/dist/unstable-internals.cjs +3 -0
- package/dist/unstable-internals.d-DyLd-B0J.d.mts +46 -0
- package/dist/unstable-internals.d-DyLd-B0J.d.mts.map +1 -0
- package/dist/unstable-internals.d-kWsZTlQq.d.cts +46 -0
- package/dist/unstable-internals.d-kWsZTlQq.d.cts.map +1 -0
- package/dist/unstable-internals.d.cts +3 -0
- package/dist/unstable-internals.d.mts +3 -0
- package/dist/unstable-internals.mjs +3 -1
- package/dist/wsLink-DbSHOzlB.mjs +698 -0
- package/dist/wsLink-DbSHOzlB.mjs.map +1 -0
- package/dist/wsLink-DhJ50EC5.cjs +715 -0
- package/dist/wsLink.d-BqO7ltN_.d.mts +194 -0
- package/dist/wsLink.d-BqO7ltN_.d.mts.map +1 -0
- package/dist/wsLink.d-DtZjg09g.d.cts +194 -0
- package/dist/wsLink.d-DtZjg09g.d.cts.map +1 -0
- package/links/httpBatchLink/package.json +1 -0
- package/links/httpLink/package.json +1 -0
- package/links/loggerLink/package.json +1 -0
- package/links/splitLink/package.json +1 -0
- package/links/wsLink/wsLink/package.json +1 -0
- package/package.json +67 -33
- package/unstable-internals/package.json +1 -0
- package/dist/TRPCClientError.d.ts +0 -30
- package/dist/TRPCClientError.d.ts.map +0 -1
- package/dist/TRPCClientError.js +0 -79
- package/dist/TRPCClientError.mjs +0 -76
- package/dist/createTRPCClient.d.ts +0 -69
- package/dist/createTRPCClient.d.ts.map +0 -1
- package/dist/createTRPCClient.js +0 -48
- package/dist/createTRPCClient.mjs +0 -43
- package/dist/createTRPCUntypedClient.d.ts +0 -7
- package/dist/createTRPCUntypedClient.d.ts.map +0 -1
- package/dist/createTRPCUntypedClient.js +0 -10
- package/dist/createTRPCUntypedClient.mjs +0 -7
- package/dist/getFetch.d.ts +0 -3
- package/dist/getFetch.d.ts.map +0 -1
- package/dist/getFetch.js +0 -17
- package/dist/getFetch.mjs +0 -15
- package/dist/index.d.ts +0 -16
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -46
- package/dist/internals/TRPCUntypedClient.d.ts +0 -39
- package/dist/internals/TRPCUntypedClient.d.ts.map +0 -1
- package/dist/internals/TRPCUntypedClient.js +0 -115
- package/dist/internals/TRPCUntypedClient.mjs +0 -113
- package/dist/internals/dataLoader.d.ts +0 -13
- package/dist/internals/dataLoader.d.ts.map +0 -1
- package/dist/internals/dataLoader.js +0 -117
- package/dist/internals/dataLoader.mjs +0 -115
- package/dist/internals/inputWithTrackedEventId.d.ts +0 -2
- package/dist/internals/inputWithTrackedEventId.d.ts.map +0 -1
- package/dist/internals/inputWithTrackedEventId.js +0 -16
- package/dist/internals/inputWithTrackedEventId.mjs +0 -14
- package/dist/internals/signals.d.ts +0 -16
- package/dist/internals/signals.d.ts.map +0 -1
- package/dist/internals/signals.js +0 -61
- package/dist/internals/signals.mjs +0 -57
- package/dist/internals/transformer.d.ts +0 -42
- package/dist/internals/transformer.d.ts.map +0 -1
- package/dist/internals/transformer.js +0 -30
- package/dist/internals/transformer.mjs +0 -28
- package/dist/internals/types.d.ts +0 -82
- package/dist/internals/types.d.ts.map +0 -1
- package/dist/links/HTTPBatchLinkOptions.d.ts +0 -20
- package/dist/links/HTTPBatchLinkOptions.d.ts.map +0 -1
- package/dist/links/httpBatchLink.d.ts +0 -8
- package/dist/links/httpBatchLink.d.ts.map +0 -1
- package/dist/links/httpBatchLink.js +0 -110
- package/dist/links/httpBatchStreamLink.d.ts +0 -12
- package/dist/links/httpBatchStreamLink.d.ts.map +0 -1
- package/dist/links/httpBatchStreamLink.js +0 -150
- package/dist/links/httpBatchStreamLink.mjs +0 -147
- package/dist/links/httpLink.d.ts +0 -17
- package/dist/links/httpLink.d.ts.map +0 -1
- package/dist/links/httpLink.js +0 -95
- package/dist/links/httpSubscriptionLink.d.ts +0 -26
- package/dist/links/httpSubscriptionLink.d.ts.map +0 -1
- package/dist/links/httpSubscriptionLink.js +0 -177
- package/dist/links/httpSubscriptionLink.mjs +0 -174
- package/dist/links/internals/contentTypes.d.ts +0 -4
- package/dist/links/internals/contentTypes.d.ts.map +0 -1
- package/dist/links/internals/contentTypes.js +0 -16
- package/dist/links/internals/contentTypes.mjs +0 -12
- package/dist/links/internals/createChain.d.ts +0 -8
- package/dist/links/internals/createChain.d.ts.map +0 -1
- package/dist/links/internals/createChain.js +0 -26
- package/dist/links/internals/createChain.mjs +0 -24
- package/dist/links/internals/dedupeLink.d.ts +0 -7
- package/dist/links/internals/dedupeLink.d.ts.map +0 -1
- package/dist/links/internals/httpUtils.d.ts +0 -68
- package/dist/links/internals/httpUtils.d.ts.map +0 -1
- package/dist/links/internals/httpUtils.js +0 -141
- package/dist/links/internals/httpUtils.mjs +0 -133
- package/dist/links/internals/subscriptions.d.ts +0 -17
- package/dist/links/internals/subscriptions.d.ts.map +0 -1
- package/dist/links/internals/urlWithConnectionParams.d.ts +0 -23
- package/dist/links/internals/urlWithConnectionParams.d.ts.map +0 -1
- package/dist/links/internals/urlWithConnectionParams.js +0 -10
- package/dist/links/internals/urlWithConnectionParams.mjs +0 -8
- package/dist/links/localLink.d.ts +0 -15
- package/dist/links/localLink.d.ts.map +0 -1
- package/dist/links/localLink.js +0 -333
- package/dist/links/localLink.mjs +0 -331
- package/dist/links/loggerLink.d.ts +0 -52
- package/dist/links/loggerLink.d.ts.map +0 -1
- package/dist/links/loggerLink.js +0 -178
- package/dist/links/retryLink.d.ts +0 -33
- package/dist/links/retryLink.d.ts.map +0 -1
- package/dist/links/retryLink.js +0 -72
- package/dist/links/retryLink.mjs +0 -70
- package/dist/links/splitLink.d.ts +0 -14
- package/dist/links/splitLink.d.ts.map +0 -1
- package/dist/links/splitLink.js +0 -27
- package/dist/links/types.d.ts +0 -63
- package/dist/links/types.d.ts.map +0 -1
- package/dist/links/wsLink/createWsClient.d.ts +0 -6
- package/dist/links/wsLink/createWsClient.d.ts.map +0 -1
- package/dist/links/wsLink/createWsClient.js +0 -9
- package/dist/links/wsLink/createWsClient.mjs +0 -7
- package/dist/links/wsLink/wsClient/options.d.ts +0 -79
- package/dist/links/wsLink/wsClient/options.d.ts.map +0 -1
- package/dist/links/wsLink/wsClient/options.js +0 -22
- package/dist/links/wsLink/wsClient/options.mjs +0 -18
- package/dist/links/wsLink/wsClient/requestManager.d.ts +0 -106
- package/dist/links/wsLink/wsClient/requestManager.d.ts.map +0 -1
- package/dist/links/wsLink/wsClient/requestManager.js +0 -143
- package/dist/links/wsLink/wsClient/requestManager.mjs +0 -141
- package/dist/links/wsLink/wsClient/utils.d.ts +0 -38
- package/dist/links/wsLink/wsClient/utils.d.ts.map +0 -1
- package/dist/links/wsLink/wsClient/utils.js +0 -94
- package/dist/links/wsLink/wsClient/utils.mjs +0 -88
- package/dist/links/wsLink/wsClient/wsClient.d.ts +0 -84
- package/dist/links/wsLink/wsClient/wsClient.d.ts.map +0 -1
- package/dist/links/wsLink/wsClient/wsClient.js +0 -325
- package/dist/links/wsLink/wsClient/wsClient.mjs +0 -323
- package/dist/links/wsLink/wsClient/wsConnection.d.ts +0 -79
- package/dist/links/wsLink/wsClient/wsConnection.d.ts.map +0 -1
- package/dist/links/wsLink/wsClient/wsConnection.js +0 -188
- package/dist/links/wsLink/wsClient/wsConnection.mjs +0 -185
- package/dist/links/wsLink/wsLink.d.ts +0 -11
- package/dist/links/wsLink/wsLink.d.ts.map +0 -1
- package/dist/links/wsLink/wsLink.js +0 -35
- package/dist/links.d.ts +0 -12
- package/dist/links.d.ts.map +0 -1
- package/dist/unstable-internals.d.ts +0 -3
- package/dist/unstable-internals.d.ts.map +0 -1
- package/dist/unstable-internals.js +0 -7
- package/links/httpBatchLink/index.d.ts +0 -1
- package/links/httpBatchLink/index.js +0 -1
- package/links/httpLink/index.d.ts +0 -1
- package/links/httpLink/index.js +0 -1
- package/links/loggerLink/index.d.ts +0 -1
- package/links/loggerLink/index.js +0 -1
- package/links/splitLink/index.d.ts +0 -1
- package/links/splitLink/index.js +0 -1
- package/links/wsLink/index.d.ts +0 -1
- package/links/wsLink/index.js +0 -1
- package/links/wsLink/wsLink/index.d.ts +0 -1
- package/links/wsLink/wsLink/index.js +0 -1
- package/unstable-internals/index.d.ts +0 -1
- package/unstable-internals/index.js +0 -1
|
@@ -0,0 +1,698 @@
|
|
|
1
|
+
import { TRPCClientError } from "./TRPCClientError-COkhCKf3.mjs";
|
|
2
|
+
import { getTransformer } from "./unstable-internals-DU4WecoG.mjs";
|
|
3
|
+
import { behaviorSubject, observable } from "@trpc/server/observable";
|
|
4
|
+
import { run, sleep, transformResult } from "@trpc/server/unstable-core-do-not-import";
|
|
5
|
+
|
|
6
|
+
//#region src/links/wsLink/wsClient/options.ts
|
|
7
|
+
const lazyDefaults = {
|
|
8
|
+
enabled: false,
|
|
9
|
+
closeMs: 0
|
|
10
|
+
};
|
|
11
|
+
const keepAliveDefaults = {
|
|
12
|
+
enabled: false,
|
|
13
|
+
pongTimeoutMs: 1e3,
|
|
14
|
+
intervalMs: 5e3
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Calculates a delay for exponential backoff based on the retry attempt index.
|
|
18
|
+
* The delay starts at 0 for the first attempt and doubles for each subsequent attempt,
|
|
19
|
+
* capped at 30 seconds.
|
|
20
|
+
*/
|
|
21
|
+
const exponentialBackoff = (attemptIndex) => {
|
|
22
|
+
return attemptIndex === 0 ? 0 : Math.min(1e3 * 2 ** attemptIndex, 3e4);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/links/internals/urlWithConnectionParams.ts
|
|
27
|
+
/**
|
|
28
|
+
* Get the result of a value or function that returns a value
|
|
29
|
+
* It also optionally accepts typesafe arguments for the function
|
|
30
|
+
*/
|
|
31
|
+
const resultOf = (value, ...args) => {
|
|
32
|
+
return typeof value === "function" ? value(...args) : value;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/links/wsLink/wsClient/utils.ts
|
|
37
|
+
var TRPCWebSocketClosedError = class TRPCWebSocketClosedError extends Error {
|
|
38
|
+
constructor(opts) {
|
|
39
|
+
super(opts.message, { cause: opts.cause });
|
|
40
|
+
this.name = "TRPCWebSocketClosedError";
|
|
41
|
+
Object.setPrototypeOf(this, TRPCWebSocketClosedError.prototype);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Utility class for managing a timeout that can be started, stopped, and reset.
|
|
46
|
+
* Useful for scenarios where the timeout duration is reset dynamically based on events.
|
|
47
|
+
*/
|
|
48
|
+
var ResettableTimeout = class {
|
|
49
|
+
timeout;
|
|
50
|
+
constructor(onTimeout, timeoutMs) {
|
|
51
|
+
this.onTimeout = onTimeout;
|
|
52
|
+
this.timeoutMs = timeoutMs;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resets the current timeout, restarting it with the same duration.
|
|
56
|
+
* Does nothing if no timeout is active.
|
|
57
|
+
*/
|
|
58
|
+
reset() {
|
|
59
|
+
if (!this.timeout) return;
|
|
60
|
+
clearTimeout(this.timeout);
|
|
61
|
+
this.timeout = setTimeout(this.onTimeout, this.timeoutMs);
|
|
62
|
+
}
|
|
63
|
+
start() {
|
|
64
|
+
clearTimeout(this.timeout);
|
|
65
|
+
this.timeout = setTimeout(this.onTimeout, this.timeoutMs);
|
|
66
|
+
}
|
|
67
|
+
stop() {
|
|
68
|
+
clearTimeout(this.timeout);
|
|
69
|
+
this.timeout = void 0;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
function withResolvers() {
|
|
73
|
+
let resolve;
|
|
74
|
+
let reject;
|
|
75
|
+
const promise = new Promise((res, rej) => {
|
|
76
|
+
resolve = res;
|
|
77
|
+
reject = rej;
|
|
78
|
+
});
|
|
79
|
+
return {
|
|
80
|
+
promise,
|
|
81
|
+
resolve,
|
|
82
|
+
reject
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Resolves a WebSocket URL and optionally appends connection parameters.
|
|
87
|
+
*
|
|
88
|
+
* If connectionParams are provided, appends 'connectionParams=1' query parameter.
|
|
89
|
+
*/
|
|
90
|
+
async function prepareUrl(urlOptions) {
|
|
91
|
+
const url = await resultOf(urlOptions.url);
|
|
92
|
+
if (!urlOptions.connectionParams) return url;
|
|
93
|
+
const prefix = url.includes("?") ? "&" : "?";
|
|
94
|
+
const connectionParams = `${prefix}connectionParams=1`;
|
|
95
|
+
return url + connectionParams;
|
|
96
|
+
}
|
|
97
|
+
async function buildConnectionMessage(connectionParams) {
|
|
98
|
+
const message = {
|
|
99
|
+
method: "connectionParams",
|
|
100
|
+
data: await resultOf(connectionParams)
|
|
101
|
+
};
|
|
102
|
+
return JSON.stringify(message);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
//#endregion
|
|
106
|
+
//#region src/links/wsLink/wsClient/requestManager.ts
|
|
107
|
+
/**
|
|
108
|
+
* Manages WebSocket requests, tracking their lifecycle and providing utility methods
|
|
109
|
+
* for handling outgoing and pending requests.
|
|
110
|
+
*
|
|
111
|
+
* - **Outgoing requests**: Requests that are queued and waiting to be sent.
|
|
112
|
+
* - **Pending requests**: Requests that have been sent and are in flight awaiting a response.
|
|
113
|
+
* For subscriptions, multiple responses may be received until the subscription is closed.
|
|
114
|
+
*/
|
|
115
|
+
var RequestManager = class {
|
|
116
|
+
/**
|
|
117
|
+
* Stores requests that are outgoing, meaning they are registered but not yet sent over the WebSocket.
|
|
118
|
+
*/
|
|
119
|
+
outgoingRequests = new Array();
|
|
120
|
+
/**
|
|
121
|
+
* Stores requests that are pending (in flight), meaning they have been sent over the WebSocket
|
|
122
|
+
* and are awaiting responses. For subscriptions, this includes requests
|
|
123
|
+
* that may receive multiple responses.
|
|
124
|
+
*/
|
|
125
|
+
pendingRequests = {};
|
|
126
|
+
/**
|
|
127
|
+
* Registers a new request by adding it to the outgoing queue and setting up
|
|
128
|
+
* callbacks for lifecycle events such as completion or error.
|
|
129
|
+
*
|
|
130
|
+
* @param message - The outgoing message to be sent.
|
|
131
|
+
* @param callbacks - Callback functions to observe the request's state.
|
|
132
|
+
* @returns A cleanup function to manually remove the request.
|
|
133
|
+
*/
|
|
134
|
+
register(message, callbacks) {
|
|
135
|
+
const { promise: end, resolve } = withResolvers();
|
|
136
|
+
this.outgoingRequests.push({
|
|
137
|
+
id: String(message.id),
|
|
138
|
+
message,
|
|
139
|
+
end,
|
|
140
|
+
callbacks: {
|
|
141
|
+
next: callbacks.next,
|
|
142
|
+
complete: () => {
|
|
143
|
+
callbacks.complete();
|
|
144
|
+
resolve();
|
|
145
|
+
},
|
|
146
|
+
error: (e) => {
|
|
147
|
+
callbacks.error(e);
|
|
148
|
+
resolve();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
return () => {
|
|
153
|
+
this.delete(message.id);
|
|
154
|
+
callbacks.complete();
|
|
155
|
+
resolve();
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Deletes a request from both the outgoing and pending collections, if it exists.
|
|
160
|
+
*/
|
|
161
|
+
delete(messageId) {
|
|
162
|
+
if (messageId === null) return;
|
|
163
|
+
this.outgoingRequests = this.outgoingRequests.filter(({ id }) => id !== String(messageId));
|
|
164
|
+
delete this.pendingRequests[String(messageId)];
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Moves all outgoing requests to the pending state and clears the outgoing queue.
|
|
168
|
+
*
|
|
169
|
+
* The caller is expected to handle the actual sending of the requests
|
|
170
|
+
* (e.g., sending them over the network) after this method is called.
|
|
171
|
+
*
|
|
172
|
+
* @returns The list of requests that were transitioned to the pending state.
|
|
173
|
+
*/
|
|
174
|
+
flush() {
|
|
175
|
+
const requests = this.outgoingRequests;
|
|
176
|
+
this.outgoingRequests = [];
|
|
177
|
+
for (const request of requests) this.pendingRequests[request.id] = request;
|
|
178
|
+
return requests;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Retrieves all currently pending requests, which are in flight awaiting responses
|
|
182
|
+
* or handling ongoing subscriptions.
|
|
183
|
+
*/
|
|
184
|
+
getPendingRequests() {
|
|
185
|
+
return Object.values(this.pendingRequests);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Retrieves a specific pending request by its message ID.
|
|
189
|
+
*/
|
|
190
|
+
getPendingRequest(messageId) {
|
|
191
|
+
if (messageId === null) return null;
|
|
192
|
+
return this.pendingRequests[String(messageId)];
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Retrieves all outgoing requests, which are waiting to be sent.
|
|
196
|
+
*/
|
|
197
|
+
getOutgoingRequests() {
|
|
198
|
+
return this.outgoingRequests;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Retrieves all requests, both outgoing and pending, with their respective states.
|
|
202
|
+
*
|
|
203
|
+
* @returns An array of all requests with their state ("outgoing" or "pending").
|
|
204
|
+
*/
|
|
205
|
+
getRequests() {
|
|
206
|
+
return [...this.getOutgoingRequests().map((request) => ({
|
|
207
|
+
state: "outgoing",
|
|
208
|
+
message: request.message,
|
|
209
|
+
end: request.end,
|
|
210
|
+
callbacks: request.callbacks
|
|
211
|
+
})), ...this.getPendingRequests().map((request) => ({
|
|
212
|
+
state: "pending",
|
|
213
|
+
message: request.message,
|
|
214
|
+
end: request.end,
|
|
215
|
+
callbacks: request.callbacks
|
|
216
|
+
}))];
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Checks if there are any pending requests, including ongoing subscriptions.
|
|
220
|
+
*/
|
|
221
|
+
hasPendingRequests() {
|
|
222
|
+
return this.getPendingRequests().length > 0;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Checks if there are any pending subscriptions
|
|
226
|
+
*/
|
|
227
|
+
hasPendingSubscriptions() {
|
|
228
|
+
return this.getPendingRequests().some((request) => request.message.method === "subscription");
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Checks if there are any outgoing requests waiting to be sent.
|
|
232
|
+
*/
|
|
233
|
+
hasOutgoingRequests() {
|
|
234
|
+
return this.outgoingRequests.length > 0;
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
//#endregion
|
|
239
|
+
//#region src/links/wsLink/wsClient/wsConnection.ts
|
|
240
|
+
/**
|
|
241
|
+
* Opens a WebSocket connection asynchronously and returns a promise
|
|
242
|
+
* that resolves when the connection is successfully established.
|
|
243
|
+
* The promise rejects if an error occurs during the connection attempt.
|
|
244
|
+
*/
|
|
245
|
+
function asyncWsOpen(ws) {
|
|
246
|
+
const { promise, resolve, reject } = withResolvers();
|
|
247
|
+
ws.addEventListener("open", () => {
|
|
248
|
+
ws.removeEventListener("error", reject);
|
|
249
|
+
resolve();
|
|
250
|
+
});
|
|
251
|
+
ws.addEventListener("error", reject);
|
|
252
|
+
return promise;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Sets up a periodic ping-pong mechanism to keep the WebSocket connection alive.
|
|
256
|
+
*
|
|
257
|
+
* - Sends "PING" messages at regular intervals defined by `intervalMs`.
|
|
258
|
+
* - If a "PONG" response is not received within the `pongTimeoutMs`, the WebSocket is closed.
|
|
259
|
+
* - The ping timer resets upon receiving any message to maintain activity.
|
|
260
|
+
* - Automatically starts the ping process when the WebSocket connection is opened.
|
|
261
|
+
* - Cleans up timers when the WebSocket is closed.
|
|
262
|
+
*
|
|
263
|
+
* @param ws - The WebSocket instance to manage.
|
|
264
|
+
* @param options - Configuration options for ping-pong intervals and timeouts.
|
|
265
|
+
*/
|
|
266
|
+
function setupPingInterval(ws, { intervalMs, pongTimeoutMs }) {
|
|
267
|
+
let pingTimeout;
|
|
268
|
+
let pongTimeout;
|
|
269
|
+
function start() {
|
|
270
|
+
pingTimeout = setTimeout(() => {
|
|
271
|
+
ws.send("PING");
|
|
272
|
+
pongTimeout = setTimeout(() => {
|
|
273
|
+
ws.close();
|
|
274
|
+
}, pongTimeoutMs);
|
|
275
|
+
}, intervalMs);
|
|
276
|
+
}
|
|
277
|
+
function reset() {
|
|
278
|
+
clearTimeout(pingTimeout);
|
|
279
|
+
start();
|
|
280
|
+
}
|
|
281
|
+
function pong() {
|
|
282
|
+
clearTimeout(pongTimeout);
|
|
283
|
+
reset();
|
|
284
|
+
}
|
|
285
|
+
ws.addEventListener("open", start);
|
|
286
|
+
ws.addEventListener("message", ({ data }) => {
|
|
287
|
+
clearTimeout(pingTimeout);
|
|
288
|
+
start();
|
|
289
|
+
if (data === "PONG") pong();
|
|
290
|
+
});
|
|
291
|
+
ws.addEventListener("close", () => {
|
|
292
|
+
clearTimeout(pingTimeout);
|
|
293
|
+
clearTimeout(pongTimeout);
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Manages a WebSocket connection with support for reconnection, keep-alive mechanisms,
|
|
298
|
+
* and observable state tracking.
|
|
299
|
+
*/
|
|
300
|
+
var WsConnection = class WsConnection {
|
|
301
|
+
static connectCount = 0;
|
|
302
|
+
id = ++WsConnection.connectCount;
|
|
303
|
+
WebSocketPonyfill;
|
|
304
|
+
urlOptions;
|
|
305
|
+
keepAliveOpts;
|
|
306
|
+
wsObservable = behaviorSubject(null);
|
|
307
|
+
constructor(opts) {
|
|
308
|
+
this.WebSocketPonyfill = opts.WebSocketPonyfill ?? WebSocket;
|
|
309
|
+
if (!this.WebSocketPonyfill) throw new Error("No WebSocket implementation found - you probably don't want to use this on the server, but if you do you need to pass a `WebSocket`-ponyfill");
|
|
310
|
+
this.urlOptions = opts.urlOptions;
|
|
311
|
+
this.keepAliveOpts = opts.keepAlive;
|
|
312
|
+
}
|
|
313
|
+
get ws() {
|
|
314
|
+
return this.wsObservable.get();
|
|
315
|
+
}
|
|
316
|
+
set ws(ws) {
|
|
317
|
+
this.wsObservable.next(ws);
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Checks if the WebSocket connection is open and ready to communicate.
|
|
321
|
+
*/
|
|
322
|
+
isOpen() {
|
|
323
|
+
return !!this.ws && this.ws.readyState === this.WebSocketPonyfill.OPEN && !this.openPromise;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Checks if the WebSocket connection is closed or in the process of closing.
|
|
327
|
+
*/
|
|
328
|
+
isClosed() {
|
|
329
|
+
return !!this.ws && (this.ws.readyState === this.WebSocketPonyfill.CLOSING || this.ws.readyState === this.WebSocketPonyfill.CLOSED);
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Manages the WebSocket opening process, ensuring that only one open operation
|
|
333
|
+
* occurs at a time. Tracks the ongoing operation with `openPromise` to avoid
|
|
334
|
+
* redundant calls and ensure proper synchronization.
|
|
335
|
+
*
|
|
336
|
+
* Sets up the keep-alive mechanism and necessary event listeners for the connection.
|
|
337
|
+
*
|
|
338
|
+
* @returns A promise that resolves once the WebSocket connection is successfully opened.
|
|
339
|
+
*/
|
|
340
|
+
openPromise = null;
|
|
341
|
+
async open() {
|
|
342
|
+
if (this.openPromise) return this.openPromise;
|
|
343
|
+
this.id = ++WsConnection.connectCount;
|
|
344
|
+
const wsPromise = prepareUrl(this.urlOptions).then((url) => new this.WebSocketPonyfill(url));
|
|
345
|
+
this.openPromise = wsPromise.then(async (ws) => {
|
|
346
|
+
this.ws = ws;
|
|
347
|
+
ws.addEventListener("message", function({ data }) {
|
|
348
|
+
if (data === "PING") this.send("PONG");
|
|
349
|
+
});
|
|
350
|
+
if (this.keepAliveOpts.enabled) setupPingInterval(ws, this.keepAliveOpts);
|
|
351
|
+
ws.addEventListener("close", () => {
|
|
352
|
+
if (this.ws === ws) this.ws = null;
|
|
353
|
+
});
|
|
354
|
+
await asyncWsOpen(ws);
|
|
355
|
+
if (this.urlOptions.connectionParams) ws.send(await buildConnectionMessage(this.urlOptions.connectionParams));
|
|
356
|
+
});
|
|
357
|
+
try {
|
|
358
|
+
await this.openPromise;
|
|
359
|
+
} finally {
|
|
360
|
+
this.openPromise = null;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Closes the WebSocket connection gracefully.
|
|
365
|
+
* Waits for any ongoing open operation to complete before closing.
|
|
366
|
+
*/
|
|
367
|
+
async close() {
|
|
368
|
+
try {
|
|
369
|
+
await this.openPromise;
|
|
370
|
+
} finally {
|
|
371
|
+
this.ws?.close();
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
/**
|
|
376
|
+
* Provides a backward-compatible representation of the connection state.
|
|
377
|
+
*/
|
|
378
|
+
function backwardCompatibility(connection) {
|
|
379
|
+
if (connection.isOpen()) return {
|
|
380
|
+
id: connection.id,
|
|
381
|
+
state: "open",
|
|
382
|
+
ws: connection.ws
|
|
383
|
+
};
|
|
384
|
+
if (connection.isClosed()) return {
|
|
385
|
+
id: connection.id,
|
|
386
|
+
state: "closed",
|
|
387
|
+
ws: connection.ws
|
|
388
|
+
};
|
|
389
|
+
if (!connection.ws) return null;
|
|
390
|
+
return {
|
|
391
|
+
id: connection.id,
|
|
392
|
+
state: "connecting",
|
|
393
|
+
ws: connection.ws
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
//#endregion
|
|
398
|
+
//#region src/links/wsLink/wsClient/wsClient.ts
|
|
399
|
+
/**
|
|
400
|
+
* A WebSocket client for managing TRPC operations, supporting lazy initialization,
|
|
401
|
+
* reconnection, keep-alive, and request management.
|
|
402
|
+
*/
|
|
403
|
+
var WsClient = class {
|
|
404
|
+
/**
|
|
405
|
+
* Observable tracking the current connection state, including errors.
|
|
406
|
+
*/
|
|
407
|
+
connectionState;
|
|
408
|
+
allowReconnect = false;
|
|
409
|
+
requestManager = new RequestManager();
|
|
410
|
+
activeConnection;
|
|
411
|
+
reconnectRetryDelay;
|
|
412
|
+
inactivityTimeout;
|
|
413
|
+
callbacks;
|
|
414
|
+
lazyMode;
|
|
415
|
+
constructor(opts) {
|
|
416
|
+
this.callbacks = {
|
|
417
|
+
onOpen: opts.onOpen,
|
|
418
|
+
onClose: opts.onClose,
|
|
419
|
+
onError: opts.onError
|
|
420
|
+
};
|
|
421
|
+
const lazyOptions = {
|
|
422
|
+
...lazyDefaults,
|
|
423
|
+
...opts.lazy
|
|
424
|
+
};
|
|
425
|
+
this.inactivityTimeout = new ResettableTimeout(() => {
|
|
426
|
+
if (this.requestManager.hasOutgoingRequests() || this.requestManager.hasPendingRequests()) {
|
|
427
|
+
this.inactivityTimeout.reset();
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
this.close().catch(() => null);
|
|
431
|
+
}, lazyOptions.closeMs);
|
|
432
|
+
this.activeConnection = new WsConnection({
|
|
433
|
+
WebSocketPonyfill: opts.WebSocket,
|
|
434
|
+
urlOptions: opts,
|
|
435
|
+
keepAlive: {
|
|
436
|
+
...keepAliveDefaults,
|
|
437
|
+
...opts.keepAlive
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
this.activeConnection.wsObservable.subscribe({ next: (ws) => {
|
|
441
|
+
if (!ws) return;
|
|
442
|
+
this.setupWebSocketListeners(ws);
|
|
443
|
+
} });
|
|
444
|
+
this.reconnectRetryDelay = opts.retryDelayMs ?? exponentialBackoff;
|
|
445
|
+
this.lazyMode = lazyOptions.enabled;
|
|
446
|
+
this.connectionState = behaviorSubject({
|
|
447
|
+
type: "state",
|
|
448
|
+
state: lazyOptions.enabled ? "idle" : "connecting",
|
|
449
|
+
error: null
|
|
450
|
+
});
|
|
451
|
+
if (!this.lazyMode) this.open().catch(() => null);
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Opens the WebSocket connection. Handles reconnection attempts and updates
|
|
455
|
+
* the connection state accordingly.
|
|
456
|
+
*/
|
|
457
|
+
async open() {
|
|
458
|
+
this.allowReconnect = true;
|
|
459
|
+
if (this.connectionState.get().state !== "connecting") this.connectionState.next({
|
|
460
|
+
type: "state",
|
|
461
|
+
state: "connecting",
|
|
462
|
+
error: null
|
|
463
|
+
});
|
|
464
|
+
try {
|
|
465
|
+
await this.activeConnection.open();
|
|
466
|
+
} catch (error) {
|
|
467
|
+
this.reconnect(new TRPCWebSocketClosedError({
|
|
468
|
+
message: "Initialization error",
|
|
469
|
+
cause: error
|
|
470
|
+
}));
|
|
471
|
+
return this.reconnecting;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Closes the WebSocket connection and stops managing requests.
|
|
476
|
+
* Ensures all outgoing and pending requests are properly finalized.
|
|
477
|
+
*/
|
|
478
|
+
async close() {
|
|
479
|
+
this.allowReconnect = false;
|
|
480
|
+
this.inactivityTimeout.stop();
|
|
481
|
+
const requestsToAwait = [];
|
|
482
|
+
for (const request of this.requestManager.getRequests()) if (request.message.method === "subscription") request.callbacks.complete();
|
|
483
|
+
else if (request.state === "outgoing") request.callbacks.error(TRPCClientError.from(new TRPCWebSocketClosedError({ message: "Closed before connection was established" })));
|
|
484
|
+
else requestsToAwait.push(request.end);
|
|
485
|
+
await Promise.all(requestsToAwait).catch(() => null);
|
|
486
|
+
await this.activeConnection.close().catch(() => null);
|
|
487
|
+
this.connectionState.next({
|
|
488
|
+
type: "state",
|
|
489
|
+
state: "idle",
|
|
490
|
+
error: null
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Method to request the server.
|
|
495
|
+
* Handles data transformation, batching of requests, and subscription lifecycle.
|
|
496
|
+
*
|
|
497
|
+
* @param op - The operation details including id, type, path, input and signal
|
|
498
|
+
* @param transformer - Data transformer for serializing requests and deserializing responses
|
|
499
|
+
* @param lastEventId - Optional ID of the last received event for subscriptions
|
|
500
|
+
*
|
|
501
|
+
* @returns An observable that emits operation results and handles cleanup
|
|
502
|
+
*/
|
|
503
|
+
request({ op: { id, type, path, input, signal }, transformer, lastEventId }) {
|
|
504
|
+
return observable((observer) => {
|
|
505
|
+
const abort = this.batchSend({
|
|
506
|
+
id,
|
|
507
|
+
method: type,
|
|
508
|
+
params: {
|
|
509
|
+
input: transformer.input.serialize(input),
|
|
510
|
+
path,
|
|
511
|
+
lastEventId
|
|
512
|
+
}
|
|
513
|
+
}, {
|
|
514
|
+
...observer,
|
|
515
|
+
next(event) {
|
|
516
|
+
const transformed = transformResult(event, transformer.output);
|
|
517
|
+
if (!transformed.ok) {
|
|
518
|
+
observer.error(TRPCClientError.from(transformed.error));
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
observer.next({ result: transformed.result });
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
return () => {
|
|
525
|
+
abort();
|
|
526
|
+
if (type === "subscription" && this.activeConnection.isOpen()) this.send({
|
|
527
|
+
id,
|
|
528
|
+
method: "subscription.stop"
|
|
529
|
+
});
|
|
530
|
+
signal?.removeEventListener("abort", abort);
|
|
531
|
+
};
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
get connection() {
|
|
535
|
+
return backwardCompatibility(this.activeConnection);
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Manages the reconnection process for the WebSocket using retry logic.
|
|
539
|
+
* Ensures that only one reconnection attempt is active at a time by tracking the current
|
|
540
|
+
* reconnection state in the `reconnecting` promise.
|
|
541
|
+
*/
|
|
542
|
+
reconnecting = null;
|
|
543
|
+
reconnect(closedError) {
|
|
544
|
+
this.connectionState.next({
|
|
545
|
+
type: "state",
|
|
546
|
+
state: "connecting",
|
|
547
|
+
error: TRPCClientError.from(closedError)
|
|
548
|
+
});
|
|
549
|
+
if (this.reconnecting) return;
|
|
550
|
+
const tryReconnect = async (attemptIndex) => {
|
|
551
|
+
try {
|
|
552
|
+
await sleep(this.reconnectRetryDelay(attemptIndex));
|
|
553
|
+
if (this.allowReconnect) {
|
|
554
|
+
await this.activeConnection.close();
|
|
555
|
+
await this.activeConnection.open();
|
|
556
|
+
if (this.requestManager.hasPendingRequests()) this.send(this.requestManager.getPendingRequests().map(({ message }) => message));
|
|
557
|
+
}
|
|
558
|
+
this.reconnecting = null;
|
|
559
|
+
} catch {
|
|
560
|
+
await tryReconnect(attemptIndex + 1);
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
this.reconnecting = tryReconnect(0);
|
|
564
|
+
}
|
|
565
|
+
setupWebSocketListeners(ws) {
|
|
566
|
+
const handleCloseOrError = (cause) => {
|
|
567
|
+
const reqs = this.requestManager.getPendingRequests();
|
|
568
|
+
for (const { message, callbacks } of reqs) {
|
|
569
|
+
if (message.method === "subscription") continue;
|
|
570
|
+
callbacks.error(TRPCClientError.from(cause ?? new TRPCWebSocketClosedError({
|
|
571
|
+
message: "WebSocket closed",
|
|
572
|
+
cause
|
|
573
|
+
})));
|
|
574
|
+
this.requestManager.delete(message.id);
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
ws.addEventListener("open", () => {
|
|
578
|
+
run(async () => {
|
|
579
|
+
if (this.lazyMode) this.inactivityTimeout.start();
|
|
580
|
+
this.callbacks.onOpen?.();
|
|
581
|
+
this.connectionState.next({
|
|
582
|
+
type: "state",
|
|
583
|
+
state: "pending",
|
|
584
|
+
error: null
|
|
585
|
+
});
|
|
586
|
+
}).catch((error) => {
|
|
587
|
+
ws.close(3e3);
|
|
588
|
+
handleCloseOrError(error);
|
|
589
|
+
});
|
|
590
|
+
});
|
|
591
|
+
ws.addEventListener("message", ({ data }) => {
|
|
592
|
+
this.inactivityTimeout.reset();
|
|
593
|
+
if (typeof data !== "string" || ["PING", "PONG"].includes(data)) return;
|
|
594
|
+
const incomingMessage = JSON.parse(data);
|
|
595
|
+
if ("method" in incomingMessage) {
|
|
596
|
+
this.handleIncomingRequest(incomingMessage);
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
this.handleResponseMessage(incomingMessage);
|
|
600
|
+
});
|
|
601
|
+
ws.addEventListener("close", (event) => {
|
|
602
|
+
handleCloseOrError(event);
|
|
603
|
+
this.callbacks.onClose?.(event);
|
|
604
|
+
if (!this.lazyMode || this.requestManager.hasPendingSubscriptions()) this.reconnect(new TRPCWebSocketClosedError({
|
|
605
|
+
message: "WebSocket closed",
|
|
606
|
+
cause: event
|
|
607
|
+
}));
|
|
608
|
+
});
|
|
609
|
+
ws.addEventListener("error", (event) => {
|
|
610
|
+
handleCloseOrError(event);
|
|
611
|
+
this.callbacks.onError?.(event);
|
|
612
|
+
this.reconnect(new TRPCWebSocketClosedError({
|
|
613
|
+
message: "WebSocket closed",
|
|
614
|
+
cause: event
|
|
615
|
+
}));
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
handleResponseMessage(message) {
|
|
619
|
+
const request = this.requestManager.getPendingRequest(message.id);
|
|
620
|
+
if (!request) return;
|
|
621
|
+
request.callbacks.next(message);
|
|
622
|
+
let completed = true;
|
|
623
|
+
if ("result" in message && request.message.method === "subscription") {
|
|
624
|
+
if (message.result.type === "data") request.message.params.lastEventId = message.result.id;
|
|
625
|
+
if (message.result.type !== "stopped") completed = false;
|
|
626
|
+
}
|
|
627
|
+
if (completed) {
|
|
628
|
+
request.callbacks.complete();
|
|
629
|
+
this.requestManager.delete(message.id);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
handleIncomingRequest(message) {
|
|
633
|
+
if (message.method === "reconnect") this.reconnect(new TRPCWebSocketClosedError({ message: "Server requested reconnect" }));
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* Sends a message or batch of messages directly to the server.
|
|
637
|
+
*/
|
|
638
|
+
send(messageOrMessages) {
|
|
639
|
+
if (!this.activeConnection.isOpen()) throw new Error("Active connection is not open");
|
|
640
|
+
const messages = messageOrMessages instanceof Array ? messageOrMessages : [messageOrMessages];
|
|
641
|
+
this.activeConnection.ws.send(JSON.stringify(messages.length === 1 ? messages[0] : messages));
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Groups requests for batch sending.
|
|
645
|
+
*
|
|
646
|
+
* @returns A function to abort the batched request.
|
|
647
|
+
*/
|
|
648
|
+
batchSend(message, callbacks) {
|
|
649
|
+
this.inactivityTimeout.reset();
|
|
650
|
+
run(async () => {
|
|
651
|
+
if (!this.activeConnection.isOpen()) await this.open();
|
|
652
|
+
await sleep(0);
|
|
653
|
+
if (!this.requestManager.hasOutgoingRequests()) return;
|
|
654
|
+
this.send(this.requestManager.flush().map(({ message: message$1 }) => message$1));
|
|
655
|
+
}).catch((err) => {
|
|
656
|
+
this.requestManager.delete(message.id);
|
|
657
|
+
callbacks.error(TRPCClientError.from(err));
|
|
658
|
+
});
|
|
659
|
+
return this.requestManager.register(message, callbacks);
|
|
660
|
+
}
|
|
661
|
+
};
|
|
662
|
+
|
|
663
|
+
//#endregion
|
|
664
|
+
//#region src/links/wsLink/createWsClient.ts
|
|
665
|
+
function createWSClient(opts) {
|
|
666
|
+
return new WsClient(opts);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
//#endregion
|
|
670
|
+
//#region src/links/wsLink/wsLink.ts
|
|
671
|
+
function wsLink(opts) {
|
|
672
|
+
const { client } = opts;
|
|
673
|
+
const transformer = getTransformer(opts.transformer);
|
|
674
|
+
return () => {
|
|
675
|
+
return ({ op }) => {
|
|
676
|
+
return observable((observer) => {
|
|
677
|
+
const connStateSubscription = op.type === "subscription" ? client.connectionState.subscribe({ next(result) {
|
|
678
|
+
observer.next({
|
|
679
|
+
result,
|
|
680
|
+
context: op.context
|
|
681
|
+
});
|
|
682
|
+
} }) : null;
|
|
683
|
+
const requestSubscription = client.request({
|
|
684
|
+
op,
|
|
685
|
+
transformer
|
|
686
|
+
}).subscribe(observer);
|
|
687
|
+
return () => {
|
|
688
|
+
requestSubscription.unsubscribe();
|
|
689
|
+
connStateSubscription?.unsubscribe();
|
|
690
|
+
};
|
|
691
|
+
});
|
|
692
|
+
};
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
//#endregion
|
|
697
|
+
export { createWSClient, resultOf, wsLink };
|
|
698
|
+
//# sourceMappingURL=wsLink-DbSHOzlB.mjs.map
|