@trpc/client 11.18.1-canary.9 → 11.19.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/bin/intent.js +0 -0
- package/dist/TRPCClientError-CmHlBkPF.cjs +56 -0
- package/dist/{TRPCClientError-apv8gw59.mjs → TRPCClientError-CxFRO7Js.mjs} +11 -14
- package/dist/TRPCClientError-CxFRO7Js.mjs.map +1 -0
- package/dist/{httpBatchLink-LhidKAPw.mjs → httpBatchLink-BMtWxLJV.mjs} +25 -72
- package/dist/httpBatchLink-BMtWxLJV.mjs.map +1 -0
- package/dist/{httpBatchLink.d-7jyWtY5H.d.cts → httpBatchLink-Br-pzPXf.d.cts} +4 -8
- package/dist/httpBatchLink-Br-pzPXf.d.cts.map +1 -0
- package/dist/{httpBatchLink-BGZRsGNf.cjs → httpBatchLink-DO3WQoxu.cjs} +37 -104
- package/dist/{httpBatchLink.d-p8Y9QM8p.d.mts → httpBatchLink-nvc48L_N.d.mts} +4 -8
- package/dist/httpBatchLink-nvc48L_N.d.mts.map +1 -0
- package/dist/{httpLink.d-CjpPCq4q.d.mts → httpLink-D5FQijY2.d.cts} +4 -7
- package/dist/httpLink-D5FQijY2.d.cts.map +1 -0
- package/dist/{httpLink-B8Iv31Ee.cjs → httpLink-MDJTSlpi.cjs} +39 -38
- package/dist/{httpLink-lG_6juPY.mjs → httpLink-Tm93WWFA.mjs} +17 -14
- package/dist/httpLink-Tm93WWFA.mjs.map +1 -0
- package/dist/{httpLink.d-D5qR9haY.d.cts → httpLink-eSAq8J9S.d.mts} +4 -7
- package/dist/httpLink-eSAq8J9S.d.mts.map +1 -0
- package/dist/{httpUtils.d-BqmeKEGo.d.cts → httpUtils-C37jRVnj.d.mts} +4 -6
- package/dist/httpUtils-C37jRVnj.d.mts.map +1 -0
- package/dist/{httpUtils-pyf5RF99.mjs → httpUtils-CB_100ND.mjs} +51 -14
- package/dist/httpUtils-CB_100ND.mjs.map +1 -0
- package/dist/{httpUtils.d-C5t5to0D.d.mts → httpUtils-CUqAubVD.d.cts} +4 -6
- package/dist/httpUtils-CUqAubVD.d.cts.map +1 -0
- package/dist/{httpUtils-wv2o-njD.cjs → httpUtils-cggqcHz0.cjs} +102 -49
- package/dist/index.cjs +248 -309
- package/dist/index.d.cts +38 -41
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +38 -41
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +212 -272
- package/dist/index.mjs.map +1 -1
- package/dist/links/httpBatchLink.cjs +3 -7
- package/dist/links/httpBatchLink.d.cts +1 -5
- package/dist/links/httpBatchLink.d.mts +1 -5
- package/dist/links/httpBatchLink.mjs +2 -7
- package/dist/links/httpLink.cjs +3 -7
- package/dist/links/httpLink.d.cts +1 -5
- package/dist/links/httpLink.d.mts +1 -5
- package/dist/links/httpLink.mjs +2 -7
- package/dist/links/loggerLink.cjs +113 -4
- package/dist/links/loggerLink.d.cts +1 -3
- package/dist/links/loggerLink.d.mts +1 -3
- package/dist/links/loggerLink.mjs +113 -3
- package/dist/links/loggerLink.mjs.map +1 -0
- package/dist/links/splitLink.cjs +3 -3
- package/dist/links/splitLink.d.cts +1 -3
- package/dist/links/splitLink.d.mts +1 -3
- package/dist/links/splitLink.mjs +2 -3
- package/dist/links/wsLink/wsLink.cjs +3 -6
- package/dist/links/wsLink/wsLink.d.cts +2 -5
- package/dist/links/wsLink/wsLink.d.mts +2 -5
- package/dist/links/wsLink/wsLink.mjs +2 -6
- package/dist/{loggerLink.d-0ABgt7oh.d.mts → loggerLink-2o-uZ3r1.d.cts} +3 -4
- package/dist/loggerLink-2o-uZ3r1.d.cts.map +1 -0
- package/dist/{loggerLink.d-BxSIj5kx.d.cts → loggerLink-CFercTVc.d.mts} +3 -4
- package/dist/loggerLink-CFercTVc.d.mts.map +1 -0
- package/dist/objectSpread2-D-dJi1gK.cjs +73 -0
- package/dist/objectSpread2-weooBxVk.mjs +62 -0
- package/dist/{splitLink-B7Cuf2c_.mjs → splitLink-BZPioDdG.mjs} +6 -11
- package/dist/splitLink-BZPioDdG.mjs.map +1 -0
- package/dist/{splitLink.d-BBFK_mCw.d.cts → splitLink-CJdcmEmS.d.cts} +3 -6
- package/dist/splitLink-CJdcmEmS.d.cts.map +1 -0
- package/dist/{splitLink.d-CkHNg1Se.d.mts → splitLink-CixmF14P.d.mts} +3 -6
- package/dist/splitLink-CixmF14P.d.mts.map +1 -0
- package/dist/{splitLink-BMgxggng.cjs → splitLink-MXnaFlEb.cjs} +17 -24
- package/dist/{subscriptions.d-Ciljg_dH.d.cts → subscriptions-DcqRZc4h.d.cts} +2 -2
- package/dist/subscriptions-DcqRZc4h.d.cts.map +1 -0
- package/dist/{subscriptions.d-Dlr1nWGD.d.mts → subscriptions-DcqRZc4h.d.mts} +2 -2
- package/dist/subscriptions-DcqRZc4h.d.mts.map +1 -0
- package/dist/{types.d-CAr6snH0.d.mts → types-BxbMkv6C.d.cts} +4 -15
- package/dist/types-BxbMkv6C.d.cts.map +1 -0
- package/dist/{types.d-Dmmedc5G.d.cts → types-CAPs7vhA.d.mts} +4 -15
- package/dist/types-CAPs7vhA.d.mts.map +1 -0
- package/dist/{unstable-internals.d-BOmV7EK1.d.mts → unstable-internals-CE8gFBQ9.d.cts} +2 -4
- package/dist/unstable-internals-CE8gFBQ9.d.cts.map +1 -0
- package/dist/{unstable-internals.d-kWsZTlQq.d.cts → unstable-internals-CE8gFBQ9.d.mts} +2 -4
- package/dist/unstable-internals-CE8gFBQ9.d.mts.map +1 -0
- package/dist/unstable-internals.cjs +28 -3
- package/dist/unstable-internals.d.cts +2 -2
- package/dist/unstable-internals.d.mts +2 -2
- package/dist/unstable-internals.mjs +28 -2
- package/dist/unstable-internals.mjs.map +1 -0
- package/dist/{wsLink-DSf4KOdW.mjs → wsLink-Bm5LKL6z.mjs} +73 -94
- package/dist/wsLink-Bm5LKL6z.mjs.map +1 -0
- package/dist/{wsLink-CobRSm6C.cjs → wsLink-CKAsNP9P.cjs} +100 -123
- package/dist/{wsLink.d-pFN64NkG.d.mts → wsLink-DoiyfDgJ.d.cts} +11 -31
- package/dist/wsLink-DoiyfDgJ.d.cts.map +1 -0
- package/dist/{wsLink.d-DzZZZGZQ.d.cts → wsLink-U8pJ7LD2.d.mts} +11 -31
- package/dist/wsLink-U8pJ7LD2.d.mts.map +1 -0
- package/package.json +10 -10
- package/src/getFetch.ts +3 -2
- package/src/links/httpBatchLink.ts +12 -3
- package/src/links/httpBatchStreamLink.ts +7 -8
- package/src/links/httpLink.ts +9 -2
- package/src/links/httpSubscriptionLink.ts +1 -3
- package/src/links/internals/subscriptions.ts +3 -2
- package/src/links/types.ts +1 -2
- package/src/links/wsLink/wsClient/wsClient.ts +8 -1
- package/dist/TRPCClientError-CQrTQLrk.cjs +0 -61
- package/dist/TRPCClientError-apv8gw59.mjs.map +0 -1
- package/dist/chunk-DWy1uDak.cjs +0 -39
- package/dist/httpBatchLink-LhidKAPw.mjs.map +0 -1
- package/dist/httpBatchLink.d-7jyWtY5H.d.cts.map +0 -1
- package/dist/httpBatchLink.d-p8Y9QM8p.d.mts.map +0 -1
- package/dist/httpLink-lG_6juPY.mjs.map +0 -1
- package/dist/httpLink.d-CjpPCq4q.d.mts.map +0 -1
- package/dist/httpLink.d-D5qR9haY.d.cts.map +0 -1
- package/dist/httpUtils-pyf5RF99.mjs.map +0 -1
- package/dist/httpUtils.d-BqmeKEGo.d.cts.map +0 -1
- package/dist/httpUtils.d-C5t5to0D.d.mts.map +0 -1
- package/dist/loggerLink-CuYvRzyH.cjs +0 -123
- package/dist/loggerLink-ineCN1PO.mjs +0 -118
- package/dist/loggerLink-ineCN1PO.mjs.map +0 -1
- package/dist/loggerLink.d-0ABgt7oh.d.mts.map +0 -1
- package/dist/loggerLink.d-BxSIj5kx.d.cts.map +0 -1
- package/dist/objectSpread2-Bsvh_OqM.cjs +0 -100
- package/dist/objectSpread2-BvkFp-_Y.mjs +0 -114
- package/dist/objectSpread2-BvkFp-_Y.mjs.map +0 -1
- package/dist/splitLink-B7Cuf2c_.mjs.map +0 -1
- package/dist/splitLink.d-BBFK_mCw.d.cts.map +0 -1
- package/dist/splitLink.d-CkHNg1Se.d.mts.map +0 -1
- package/dist/subscriptions.d-Ciljg_dH.d.cts.map +0 -1
- package/dist/subscriptions.d-Dlr1nWGD.d.mts.map +0 -1
- package/dist/types.d-CAr6snH0.d.mts.map +0 -1
- package/dist/types.d-Dmmedc5G.d.cts.map +0 -1
- package/dist/unstable-internals-Bg7n9BBj.mjs +0 -29
- package/dist/unstable-internals-Bg7n9BBj.mjs.map +0 -1
- package/dist/unstable-internals-M84gUQCV.cjs +0 -34
- package/dist/unstable-internals.d-BOmV7EK1.d.mts.map +0 -1
- package/dist/unstable-internals.d-kWsZTlQq.d.cts.map +0 -1
- package/dist/wsLink-DSf4KOdW.mjs.map +0 -1
- package/dist/wsLink.d-DzZZZGZQ.d.cts.map +0 -1
- package/dist/wsLink.d-pFN64NkG.d.mts.map +0 -1
|
@@ -1,3 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/internals/transformer.ts
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
function getTransformer(transformer) {
|
|
10
|
+
const _transformer = transformer;
|
|
11
|
+
if (!_transformer) return {
|
|
12
|
+
input: {
|
|
13
|
+
serialize: (data) => data,
|
|
14
|
+
deserialize: (data) => data
|
|
15
|
+
},
|
|
16
|
+
output: {
|
|
17
|
+
serialize: (data) => data,
|
|
18
|
+
deserialize: (data) => data
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
if ("input" in _transformer) return _transformer;
|
|
22
|
+
return {
|
|
23
|
+
input: _transformer,
|
|
24
|
+
output: _transformer
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
exports.getTransformer = getTransformer;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { TRPCConnectionState } from "./subscriptions
|
|
2
|
-
import {
|
|
1
|
+
import { t as TRPCConnectionState } from "./subscriptions-DcqRZc4h.cjs";
|
|
2
|
+
import { n as TransformerOptions, r as getTransformer, t as CoercedTransformerParameters } from "./unstable-internals-CE8gFBQ9.cjs";
|
|
3
3
|
export { CoercedTransformerParameters, TRPCConnectionState, TransformerOptions, getTransformer };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { TRPCConnectionState } from "./subscriptions
|
|
2
|
-
import {
|
|
1
|
+
import { t as TRPCConnectionState } from "./subscriptions-DcqRZc4h.mjs";
|
|
2
|
+
import { n as TransformerOptions, r as getTransformer, t as CoercedTransformerParameters } from "./unstable-internals-CE8gFBQ9.mjs";
|
|
3
3
|
export { CoercedTransformerParameters, TRPCConnectionState, TransformerOptions, getTransformer };
|
|
@@ -1,3 +1,29 @@
|
|
|
1
|
-
|
|
1
|
+
//#region src/internals/transformer.ts
|
|
2
|
+
/**
|
|
3
|
+
* @internal
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
function getTransformer(transformer) {
|
|
9
|
+
const _transformer = transformer;
|
|
10
|
+
if (!_transformer) return {
|
|
11
|
+
input: {
|
|
12
|
+
serialize: (data) => data,
|
|
13
|
+
deserialize: (data) => data
|
|
14
|
+
},
|
|
15
|
+
output: {
|
|
16
|
+
serialize: (data) => data,
|
|
17
|
+
deserialize: (data) => data
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
if ("input" in _transformer) return _transformer;
|
|
21
|
+
return {
|
|
22
|
+
input: _transformer,
|
|
23
|
+
output: _transformer
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { getTransformer };
|
|
2
28
|
|
|
3
|
-
|
|
29
|
+
//# sourceMappingURL=unstable-internals.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unstable-internals.mjs","names":[],"sources":["../src/internals/transformer.ts"],"sourcesContent":["import type {\n AnyClientTypes,\n CombinedDataTransformer,\n DataTransformerOptions,\n TypeError,\n} from '@trpc/server/unstable-core-do-not-import';\n\n/**\n * @internal\n */\nexport type CoercedTransformerParameters = {\n transformer?: DataTransformerOptions;\n};\n\ntype TransformerOptionYes = {\n /**\n * Data transformer\n *\n * You must use the same transformer on the backend and frontend\n * @see https://trpc.io/docs/v11/data-transformers\n **/\n transformer: DataTransformerOptions;\n};\ntype TransformerOptionNo = {\n /**\n * Data transformer\n *\n * You must use the same transformer on the backend and frontend\n * @see https://trpc.io/docs/v11/data-transformers\n **/\n transformer?: TypeError<'You must define a transformer on your your `initTRPC`-object first'>;\n};\n\n/**\n * @internal\n */\nexport type TransformerOptions<\n TRoot extends Pick<AnyClientTypes, 'transformer'>,\n> = TRoot['transformer'] extends true\n ? TransformerOptionYes\n : TransformerOptionNo;\n/**\n * @internal\n */\n\n/**\n * @internal\n */\nexport function getTransformer(\n transformer:\n | TransformerOptions<{ transformer: false }>['transformer']\n | TransformerOptions<{ transformer: true }>['transformer']\n | undefined,\n): CombinedDataTransformer {\n const _transformer =\n transformer as CoercedTransformerParameters['transformer'];\n if (!_transformer) {\n return {\n input: {\n serialize: (data) => data,\n deserialize: (data) => data,\n },\n output: {\n serialize: (data) => data,\n deserialize: (data) => data,\n },\n };\n }\n if ('input' in _transformer) {\n return _transformer;\n }\n return {\n input: _transformer,\n output: _transformer,\n };\n}\n"],"mappings":";;;;;;;AAgDA,SAAgB,eACd,aAIyB;CACzB,MAAM,eACJ;CACF,IAAI,CAAC,cACH,OAAO;EACL,OAAO;GACL,YAAY,SAAS;GACrB,cAAc,SAAS;EACzB;EACA,QAAQ;GACN,YAAY,SAAS;GACrB,cAAc,SAAS;EACzB;CACF;CAEF,IAAI,WAAW,cACb,OAAO;CAET,OAAO;EACL,OAAO;EACP,QAAQ;CACV;AACF"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { TRPCClientError } from "./TRPCClientError-
|
|
3
|
-
import { getTransformer } from "./unstable-internals
|
|
1
|
+
import { n as _defineProperty, t as _objectSpread2 } from "./objectSpread2-weooBxVk.mjs";
|
|
2
|
+
import { t as TRPCClientError } from "./TRPCClientError-CxFRO7Js.mjs";
|
|
3
|
+
import { getTransformer } from "./unstable-internals.mjs";
|
|
4
4
|
import { behaviorSubject, observable } from "@trpc/server/observable";
|
|
5
5
|
import { run, sleep, transformResult } from "@trpc/server/unstable-core-do-not-import";
|
|
6
|
-
|
|
7
6
|
//#region src/links/wsLink/wsClient/encoder.ts
|
|
8
7
|
const jsonEncoder = {
|
|
9
8
|
encode: (data) => JSON.stringify(data),
|
|
@@ -12,7 +11,6 @@ const jsonEncoder = {
|
|
|
12
11
|
return JSON.parse(data);
|
|
13
12
|
}
|
|
14
13
|
};
|
|
15
|
-
|
|
16
14
|
//#endregion
|
|
17
15
|
//#region src/links/wsLink/wsClient/options.ts
|
|
18
16
|
const lazyDefaults = {
|
|
@@ -32,7 +30,6 @@ const keepAliveDefaults = {
|
|
|
32
30
|
const exponentialBackoff = (attemptIndex) => {
|
|
33
31
|
return attemptIndex === 0 ? 0 : Math.min(1e3 * 2 ** attemptIndex, 3e4);
|
|
34
32
|
};
|
|
35
|
-
|
|
36
33
|
//#endregion
|
|
37
34
|
//#region src/links/internals/urlWithConnectionParams.ts
|
|
38
35
|
/**
|
|
@@ -42,10 +39,8 @@ const exponentialBackoff = (attemptIndex) => {
|
|
|
42
39
|
const resultOf = (value, ...args) => {
|
|
43
40
|
return typeof value === "function" ? value(...args) : value;
|
|
44
41
|
};
|
|
45
|
-
|
|
46
42
|
//#endregion
|
|
47
43
|
//#region src/links/wsLink/wsClient/utils.ts
|
|
48
|
-
var import_defineProperty$3 = __toESM(require_defineProperty(), 1);
|
|
49
44
|
var TRPCWebSocketClosedError = class TRPCWebSocketClosedError extends Error {
|
|
50
45
|
constructor(opts) {
|
|
51
46
|
super(opts.message, { cause: opts.cause });
|
|
@@ -61,7 +56,7 @@ var ResettableTimeout = class {
|
|
|
61
56
|
constructor(onTimeout, timeoutMs) {
|
|
62
57
|
this.onTimeout = onTimeout;
|
|
63
58
|
this.timeoutMs = timeoutMs;
|
|
64
|
-
(
|
|
59
|
+
_defineProperty(this, "timeout", void 0);
|
|
65
60
|
}
|
|
66
61
|
/**
|
|
67
62
|
* Resets the current timeout, restarting it with the same duration.
|
|
@@ -84,12 +79,11 @@ var ResettableTimeout = class {
|
|
|
84
79
|
function withResolvers() {
|
|
85
80
|
let resolve;
|
|
86
81
|
let reject;
|
|
87
|
-
const promise = new Promise((res, rej) => {
|
|
88
|
-
resolve = res;
|
|
89
|
-
reject = rej;
|
|
90
|
-
});
|
|
91
82
|
return {
|
|
92
|
-
promise,
|
|
83
|
+
promise: new Promise((res, rej) => {
|
|
84
|
+
resolve = res;
|
|
85
|
+
reject = rej;
|
|
86
|
+
}),
|
|
93
87
|
resolve,
|
|
94
88
|
reject
|
|
95
89
|
};
|
|
@@ -102,9 +96,7 @@ function withResolvers() {
|
|
|
102
96
|
async function prepareUrl(urlOptions) {
|
|
103
97
|
const url = await resultOf(urlOptions.url);
|
|
104
98
|
if (!urlOptions.connectionParams) return url;
|
|
105
|
-
|
|
106
|
-
const connectionParams = `${prefix}connectionParams=1`;
|
|
107
|
-
return url + connectionParams;
|
|
99
|
+
return url + `${url.includes("?") ? "&" : "?"}connectionParams=1`;
|
|
108
100
|
}
|
|
109
101
|
async function buildConnectionMessage(connectionParams, encoder) {
|
|
110
102
|
const message = {
|
|
@@ -113,10 +105,8 @@ async function buildConnectionMessage(connectionParams, encoder) {
|
|
|
113
105
|
};
|
|
114
106
|
return encoder.encode(message);
|
|
115
107
|
}
|
|
116
|
-
|
|
117
108
|
//#endregion
|
|
118
109
|
//#region src/links/wsLink/wsClient/requestManager.ts
|
|
119
|
-
var import_defineProperty$2 = __toESM(require_defineProperty(), 1);
|
|
120
110
|
/**
|
|
121
111
|
* Manages WebSocket requests, tracking their lifecycle and providing utility methods
|
|
122
112
|
* for handling outgoing and pending requests.
|
|
@@ -127,8 +117,8 @@ var import_defineProperty$2 = __toESM(require_defineProperty(), 1);
|
|
|
127
117
|
*/
|
|
128
118
|
var RequestManager = class {
|
|
129
119
|
constructor() {
|
|
130
|
-
(
|
|
131
|
-
(
|
|
120
|
+
_defineProperty(this, "outgoingRequests", new Array());
|
|
121
|
+
_defineProperty(this, "pendingRequests", {});
|
|
132
122
|
}
|
|
133
123
|
/**
|
|
134
124
|
* Registers a new request by adding it to the outgoing queue and setting up
|
|
@@ -241,10 +231,8 @@ var RequestManager = class {
|
|
|
241
231
|
return this.outgoingRequests.length > 0;
|
|
242
232
|
}
|
|
243
233
|
};
|
|
244
|
-
|
|
245
234
|
//#endregion
|
|
246
235
|
//#region src/links/wsLink/wsClient/wsConnection.ts
|
|
247
|
-
var import_defineProperty$1 = __toESM(require_defineProperty(), 1);
|
|
248
236
|
/**
|
|
249
237
|
* Opens a WebSocket connection asynchronously and returns a promise
|
|
250
238
|
* that resolves when the connection is successfully established.
|
|
@@ -308,13 +296,13 @@ function setupPingInterval(ws, { intervalMs, pongTimeoutMs }) {
|
|
|
308
296
|
var WsConnection = class WsConnection {
|
|
309
297
|
constructor(opts) {
|
|
310
298
|
var _opts$WebSocketPonyfi;
|
|
311
|
-
(
|
|
312
|
-
(
|
|
313
|
-
(
|
|
314
|
-
(
|
|
315
|
-
(
|
|
316
|
-
(
|
|
317
|
-
(
|
|
299
|
+
_defineProperty(this, "id", ++WsConnection.connectCount);
|
|
300
|
+
_defineProperty(this, "WebSocketPonyfill", void 0);
|
|
301
|
+
_defineProperty(this, "urlOptions", void 0);
|
|
302
|
+
_defineProperty(this, "keepAliveOpts", void 0);
|
|
303
|
+
_defineProperty(this, "encoder", void 0);
|
|
304
|
+
_defineProperty(this, "wsObservable", behaviorSubject(null));
|
|
305
|
+
_defineProperty(this, "openPromise", null);
|
|
318
306
|
this.WebSocketPonyfill = (_opts$WebSocketPonyfi = opts.WebSocketPonyfill) !== null && _opts$WebSocketPonyfi !== void 0 ? _opts$WebSocketPonyfi : WebSocket;
|
|
319
307
|
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");
|
|
320
308
|
this.urlOptions = opts.urlOptions;
|
|
@@ -340,27 +328,26 @@ var WsConnection = class WsConnection {
|
|
|
340
328
|
return !!this.ws && (this.ws.readyState === this.WebSocketPonyfill.CLOSING || this.ws.readyState === this.WebSocketPonyfill.CLOSED);
|
|
341
329
|
}
|
|
342
330
|
async open() {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
_this.ws = ws;
|
|
331
|
+
if (this.openPromise) return this.openPromise;
|
|
332
|
+
this.id = ++WsConnection.connectCount;
|
|
333
|
+
const wsPromise = prepareUrl(this.urlOptions).then((url) => new this.WebSocketPonyfill(url));
|
|
334
|
+
this.openPromise = wsPromise.then(async (ws) => {
|
|
335
|
+
this.ws = ws;
|
|
349
336
|
ws.binaryType = "arraybuffer";
|
|
350
337
|
ws.addEventListener("message", function({ data }) {
|
|
351
338
|
if (data === "PING") this.send("PONG");
|
|
352
339
|
});
|
|
353
|
-
if (
|
|
340
|
+
if (this.keepAliveOpts.enabled) setupPingInterval(ws, this.keepAliveOpts);
|
|
354
341
|
ws.addEventListener("close", () => {
|
|
355
|
-
if (
|
|
342
|
+
if (this.ws === ws) this.ws = null;
|
|
356
343
|
});
|
|
357
344
|
await asyncWsOpen(ws);
|
|
358
|
-
if (
|
|
345
|
+
if (this.urlOptions.connectionParams) ws.send(await buildConnectionMessage(this.urlOptions.connectionParams, this.encoder));
|
|
359
346
|
});
|
|
360
347
|
try {
|
|
361
|
-
await
|
|
348
|
+
await this.openPromise;
|
|
362
349
|
} finally {
|
|
363
|
-
|
|
350
|
+
this.openPromise = null;
|
|
364
351
|
}
|
|
365
352
|
}
|
|
366
353
|
/**
|
|
@@ -368,16 +355,15 @@ var WsConnection = class WsConnection {
|
|
|
368
355
|
* Waits for any ongoing open operation to complete before closing.
|
|
369
356
|
*/
|
|
370
357
|
async close() {
|
|
371
|
-
var _this2 = this;
|
|
372
358
|
try {
|
|
373
|
-
await
|
|
359
|
+
await this.openPromise;
|
|
374
360
|
} finally {
|
|
375
361
|
var _this$ws;
|
|
376
|
-
(_this$ws =
|
|
362
|
+
(_this$ws = this.ws) === null || _this$ws === void 0 || _this$ws.close();
|
|
377
363
|
}
|
|
378
364
|
}
|
|
379
365
|
};
|
|
380
|
-
(
|
|
366
|
+
_defineProperty(WsConnection, "connectCount", 0);
|
|
381
367
|
/**
|
|
382
368
|
* Provides a backward-compatible representation of the connection state.
|
|
383
369
|
*/
|
|
@@ -399,11 +385,8 @@ function backwardCompatibility(connection) {
|
|
|
399
385
|
ws: connection.ws
|
|
400
386
|
};
|
|
401
387
|
}
|
|
402
|
-
|
|
403
388
|
//#endregion
|
|
404
389
|
//#region src/links/wsLink/wsClient/wsClient.ts
|
|
405
|
-
var import_defineProperty = __toESM(require_defineProperty(), 1);
|
|
406
|
-
var import_objectSpread2 = __toESM(require_objectSpread2(), 1);
|
|
407
390
|
/**
|
|
408
391
|
* A WebSocket client for managing TRPC operations, supporting lazy initialization,
|
|
409
392
|
* reconnection, keep-alive, and request management.
|
|
@@ -411,23 +394,23 @@ var import_objectSpread2 = __toESM(require_objectSpread2(), 1);
|
|
|
411
394
|
var WsClient = class {
|
|
412
395
|
constructor(opts) {
|
|
413
396
|
var _opts$experimental_en, _opts$retryDelayMs;
|
|
414
|
-
(
|
|
415
|
-
(
|
|
416
|
-
(
|
|
417
|
-
(
|
|
418
|
-
(
|
|
419
|
-
(
|
|
420
|
-
(
|
|
421
|
-
(
|
|
422
|
-
(
|
|
423
|
-
(
|
|
397
|
+
_defineProperty(this, "connectionState", void 0);
|
|
398
|
+
_defineProperty(this, "allowReconnect", false);
|
|
399
|
+
_defineProperty(this, "requestManager", new RequestManager());
|
|
400
|
+
_defineProperty(this, "activeConnection", void 0);
|
|
401
|
+
_defineProperty(this, "reconnectRetryDelay", void 0);
|
|
402
|
+
_defineProperty(this, "inactivityTimeout", void 0);
|
|
403
|
+
_defineProperty(this, "callbacks", void 0);
|
|
404
|
+
_defineProperty(this, "lazyMode", void 0);
|
|
405
|
+
_defineProperty(this, "encoder", void 0);
|
|
406
|
+
_defineProperty(this, "reconnecting", null);
|
|
424
407
|
this.encoder = (_opts$experimental_en = opts.experimental_encoder) !== null && _opts$experimental_en !== void 0 ? _opts$experimental_en : jsonEncoder;
|
|
425
408
|
this.callbacks = {
|
|
426
409
|
onOpen: opts.onOpen,
|
|
427
410
|
onClose: opts.onClose,
|
|
428
411
|
onError: opts.onError
|
|
429
412
|
};
|
|
430
|
-
const lazyOptions = (
|
|
413
|
+
const lazyOptions = _objectSpread2(_objectSpread2({}, lazyDefaults), opts.lazy);
|
|
431
414
|
this.inactivityTimeout = new ResettableTimeout(() => {
|
|
432
415
|
if (this.requestManager.hasOutgoingRequests() || this.requestManager.hasPendingRequests()) {
|
|
433
416
|
this.inactivityTimeout.reset();
|
|
@@ -438,7 +421,7 @@ var WsClient = class {
|
|
|
438
421
|
this.activeConnection = new WsConnection({
|
|
439
422
|
WebSocketPonyfill: opts.WebSocket,
|
|
440
423
|
urlOptions: opts,
|
|
441
|
-
keepAlive: (
|
|
424
|
+
keepAlive: _objectSpread2(_objectSpread2({}, keepAliveDefaults), opts.keepAlive),
|
|
442
425
|
encoder: this.encoder
|
|
443
426
|
});
|
|
444
427
|
this.activeConnection.wsObservable.subscribe({ next: (ws) => {
|
|
@@ -459,21 +442,20 @@ var WsClient = class {
|
|
|
459
442
|
* the connection state accordingly.
|
|
460
443
|
*/
|
|
461
444
|
async open() {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
if (_this.connectionState.get().state === "idle") _this.connectionState.next({
|
|
445
|
+
this.allowReconnect = true;
|
|
446
|
+
if (this.connectionState.get().state === "idle") this.connectionState.next({
|
|
465
447
|
type: "state",
|
|
466
448
|
state: "connecting",
|
|
467
449
|
error: null
|
|
468
450
|
});
|
|
469
451
|
try {
|
|
470
|
-
await
|
|
452
|
+
await this.activeConnection.open();
|
|
471
453
|
} catch (error) {
|
|
472
|
-
|
|
454
|
+
this.reconnect(new TRPCWebSocketClosedError({
|
|
473
455
|
message: "Initialization error",
|
|
474
456
|
cause: error
|
|
475
457
|
}));
|
|
476
|
-
return
|
|
458
|
+
return this.reconnecting;
|
|
477
459
|
}
|
|
478
460
|
}
|
|
479
461
|
/**
|
|
@@ -481,16 +463,15 @@ var WsClient = class {
|
|
|
481
463
|
* Ensures all outgoing and pending requests are properly finalized.
|
|
482
464
|
*/
|
|
483
465
|
async close() {
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
_this2.inactivityTimeout.stop();
|
|
466
|
+
this.allowReconnect = false;
|
|
467
|
+
this.inactivityTimeout.stop();
|
|
487
468
|
const requestsToAwait = [];
|
|
488
|
-
for (const request of
|
|
469
|
+
for (const request of this.requestManager.getRequests()) if (request.message.method === "subscription") request.callbacks.complete();
|
|
489
470
|
else if (request.state === "outgoing") request.callbacks.error(TRPCClientError.from(new TRPCWebSocketClosedError({ message: "Closed before connection was established" })));
|
|
490
471
|
else requestsToAwait.push(request.end);
|
|
491
472
|
await Promise.all(requestsToAwait).catch(() => null);
|
|
492
|
-
await
|
|
493
|
-
|
|
473
|
+
await this.activeConnection.close().catch(() => null);
|
|
474
|
+
this.connectionState.next({
|
|
494
475
|
type: "state",
|
|
495
476
|
state: "idle",
|
|
496
477
|
error: null
|
|
@@ -516,7 +497,7 @@ var WsClient = class {
|
|
|
516
497
|
path,
|
|
517
498
|
lastEventId
|
|
518
499
|
}
|
|
519
|
-
}, (
|
|
500
|
+
}, _objectSpread2(_objectSpread2({}, observer), {}, { next(event) {
|
|
520
501
|
const transformed = transformResult(event, transformer.output);
|
|
521
502
|
if (!transformed.ok) {
|
|
522
503
|
observer.error(TRPCClientError.from(transformed.error));
|
|
@@ -524,13 +505,16 @@ var WsClient = class {
|
|
|
524
505
|
}
|
|
525
506
|
observer.next({ result: transformed.result });
|
|
526
507
|
} }));
|
|
508
|
+
const onAbort = () => observer.complete();
|
|
509
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) onAbort();
|
|
510
|
+
else signal === null || signal === void 0 || signal.addEventListener("abort", onAbort, { once: true });
|
|
527
511
|
return () => {
|
|
528
512
|
abort();
|
|
529
513
|
if (type === "subscription" && this.activeConnection.isOpen()) this.send({
|
|
530
514
|
id,
|
|
531
515
|
method: "subscription.stop"
|
|
532
516
|
});
|
|
533
|
-
signal === null || signal === void 0 || signal.removeEventListener("abort",
|
|
517
|
+
signal === null || signal === void 0 || signal.removeEventListener("abort", onAbort);
|
|
534
518
|
};
|
|
535
519
|
});
|
|
536
520
|
}
|
|
@@ -538,7 +522,6 @@ var WsClient = class {
|
|
|
538
522
|
return backwardCompatibility(this.activeConnection);
|
|
539
523
|
}
|
|
540
524
|
reconnect(closedError) {
|
|
541
|
-
var _this3 = this;
|
|
542
525
|
this.connectionState.next({
|
|
543
526
|
type: "state",
|
|
544
527
|
state: "connecting",
|
|
@@ -547,13 +530,13 @@ var WsClient = class {
|
|
|
547
530
|
if (this.reconnecting) return;
|
|
548
531
|
const tryReconnect = async (attemptIndex) => {
|
|
549
532
|
try {
|
|
550
|
-
await sleep(
|
|
551
|
-
if (
|
|
552
|
-
await
|
|
553
|
-
await
|
|
554
|
-
if (
|
|
533
|
+
await sleep(this.reconnectRetryDelay(attemptIndex));
|
|
534
|
+
if (this.allowReconnect) {
|
|
535
|
+
await this.activeConnection.close();
|
|
536
|
+
await this.activeConnection.open();
|
|
537
|
+
if (this.requestManager.hasPendingRequests()) this.send(this.requestManager.getPendingRequests().map(({ message }) => message));
|
|
555
538
|
}
|
|
556
|
-
|
|
539
|
+
this.reconnecting = null;
|
|
557
540
|
} catch (_unused) {
|
|
558
541
|
await tryReconnect(attemptIndex + 1);
|
|
559
542
|
}
|
|
@@ -561,7 +544,6 @@ var WsClient = class {
|
|
|
561
544
|
this.reconnecting = tryReconnect(0);
|
|
562
545
|
}
|
|
563
546
|
setupWebSocketListeners(ws) {
|
|
564
|
-
var _this4 = this;
|
|
565
547
|
const handleCloseOrError = (cause) => {
|
|
566
548
|
const reqs = this.requestManager.getPendingRequests();
|
|
567
549
|
for (const { message, callbacks } of reqs) {
|
|
@@ -576,9 +558,9 @@ var WsClient = class {
|
|
|
576
558
|
ws.addEventListener("open", () => {
|
|
577
559
|
run(async () => {
|
|
578
560
|
var _this$callbacks$onOpe, _this$callbacks;
|
|
579
|
-
if (
|
|
580
|
-
(_this$callbacks$onOpe = (_this$callbacks =
|
|
581
|
-
|
|
561
|
+
if (this.lazyMode) this.inactivityTimeout.start();
|
|
562
|
+
(_this$callbacks$onOpe = (_this$callbacks = this.callbacks).onOpen) === null || _this$callbacks$onOpe === void 0 || _this$callbacks$onOpe.call(_this$callbacks);
|
|
563
|
+
this.connectionState.next({
|
|
582
564
|
type: "state",
|
|
583
565
|
state: "pending",
|
|
584
566
|
error: null
|
|
@@ -648,13 +630,12 @@ var WsClient = class {
|
|
|
648
630
|
* @returns A function to abort the batched request.
|
|
649
631
|
*/
|
|
650
632
|
batchSend(message, callbacks) {
|
|
651
|
-
var _this5 = this;
|
|
652
633
|
this.inactivityTimeout.reset();
|
|
653
634
|
run(async () => {
|
|
654
|
-
if (!
|
|
635
|
+
if (!this.activeConnection.isOpen()) await this.open();
|
|
655
636
|
await sleep(0);
|
|
656
|
-
if (!
|
|
657
|
-
|
|
637
|
+
if (!this.requestManager.hasOutgoingRequests()) return;
|
|
638
|
+
this.send(this.requestManager.flush().map(({ message }) => message));
|
|
658
639
|
}).catch((err) => {
|
|
659
640
|
this.requestManager.delete(message.id);
|
|
660
641
|
callbacks.error(TRPCClientError.from(err));
|
|
@@ -662,13 +643,11 @@ var WsClient = class {
|
|
|
662
643
|
return this.requestManager.register(message, callbacks);
|
|
663
644
|
}
|
|
664
645
|
};
|
|
665
|
-
|
|
666
646
|
//#endregion
|
|
667
647
|
//#region src/links/wsLink/createWsClient.ts
|
|
668
648
|
function createWSClient(opts) {
|
|
669
649
|
return new WsClient(opts);
|
|
670
650
|
}
|
|
671
|
-
|
|
672
651
|
//#endregion
|
|
673
652
|
//#region src/links/wsLink/wsLink.ts
|
|
674
653
|
function wsLink(opts) {
|
|
@@ -695,7 +674,7 @@ function wsLink(opts) {
|
|
|
695
674
|
};
|
|
696
675
|
};
|
|
697
676
|
}
|
|
698
|
-
|
|
699
677
|
//#endregion
|
|
700
|
-
export {
|
|
701
|
-
|
|
678
|
+
export { jsonEncoder as i, createWSClient as n, resultOf as r, wsLink as t };
|
|
679
|
+
|
|
680
|
+
//# sourceMappingURL=wsLink-Bm5LKL6z.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wsLink-Bm5LKL6z.mjs","names":[],"sources":["../src/links/wsLink/wsClient/encoder.ts","../src/links/wsLink/wsClient/options.ts","../src/links/internals/urlWithConnectionParams.ts","../src/links/wsLink/wsClient/utils.ts","../src/links/wsLink/wsClient/requestManager.ts","../src/links/wsLink/wsClient/wsConnection.ts","../src/links/wsLink/wsClient/wsClient.ts","../src/links/wsLink/createWsClient.ts","../src/links/wsLink/wsLink.ts"],"sourcesContent":["import type { Encoder } from '@trpc/server/adapters/ws';\n\nexport type { Encoder };\n\nexport const jsonEncoder: Encoder = {\n encode: (data) => JSON.stringify(data),\n decode: (data) => {\n if (typeof data !== 'string') {\n throw new Error(\n 'jsonEncoder received binary data. JSON uses text frames. ' +\n 'Use a binary encoder for binary data.',\n );\n }\n return JSON.parse(data);\n },\n};\n","import type { UrlOptionsWithConnectionParams } from '../../internals/urlWithConnectionParams';\nimport type { Encoder } from './encoder';\n\nexport interface WebSocketClientOptions extends UrlOptionsWithConnectionParams {\n /**\n * Ponyfill which WebSocket implementation to use\n */\n WebSocket?: typeof WebSocket;\n /**\n * The number of milliseconds before a reconnect is attempted.\n * @default {@link exponentialBackoff}\n */\n retryDelayMs?: (attemptIndex: number) => number;\n /**\n * Triggered when a WebSocket connection is established\n */\n onOpen?: () => void;\n /**\n * Triggered when a WebSocket connection encounters an error\n */\n onError?: (evt?: Event) => void;\n /**\n * Triggered when a WebSocket connection is closed\n */\n onClose?: (cause?: { code?: number }) => void;\n /**\n * Lazy mode will close the WebSocket automatically after a period of inactivity (no messages sent or received and no pending requests)\n */\n lazy?: {\n /**\n * Enable lazy mode\n * @default false\n */\n enabled: boolean;\n /**\n * Close the WebSocket after this many milliseconds\n * @default 0\n */\n closeMs: number;\n };\n /**\n * Send ping messages to the server and kill the connection if no pong message is returned\n */\n keepAlive?: {\n /**\n * @default false\n */\n enabled: boolean;\n /**\n * Send a ping message every this many milliseconds\n * @default 5_000\n */\n intervalMs?: number;\n /**\n * Close the WebSocket after this many milliseconds if the server does not respond\n * @default 1_000\n */\n pongTimeoutMs?: number;\n };\n /**\n * Custom encoder for wire encoding (e.g. custom binary formats)\n * @default jsonEncoder\n */\n experimental_encoder?: Encoder;\n}\n\n/**\n * Default options for lazy WebSocket connections.\n * Determines whether the connection should be established lazily and defines the delay before closure.\n */\nexport type LazyOptions = Required<NonNullable<WebSocketClientOptions['lazy']>>;\nexport const lazyDefaults: LazyOptions = {\n enabled: false,\n closeMs: 0,\n};\n\n/**\n * Default options for the WebSocket keep-alive mechanism.\n * Configures whether keep-alive is enabled and specifies the timeout and interval for ping-pong messages.\n */\nexport type KeepAliveOptions = Required<\n NonNullable<WebSocketClientOptions['keepAlive']>\n>;\nexport const keepAliveDefaults: KeepAliveOptions = {\n enabled: false,\n pongTimeoutMs: 1_000,\n intervalMs: 5_000,\n};\n\n/**\n * Calculates a delay for exponential backoff based on the retry attempt index.\n * The delay starts at 0 for the first attempt and doubles for each subsequent attempt,\n * capped at 30 seconds.\n */\nexport const exponentialBackoff = (attemptIndex: number) => {\n return attemptIndex === 0 ? 0 : Math.min(1000 * 2 ** attemptIndex, 30000);\n};\n","import { type TRPCRequestInfo } from '@trpc/server/http';\n\n/**\n * Get the result of a value or function that returns a value\n * It also optionally accepts typesafe arguments for the function\n */\nexport const resultOf = <T, TArgs extends any[]>(\n value: T | ((...args: TArgs) => T),\n ...args: TArgs\n): T => {\n return typeof value === 'function'\n ? (value as (...args: TArgs) => T)(...args)\n : value;\n};\n\n/**\n * A value that can be wrapped in callback\n */\nexport type CallbackOrValue<T> = T | (() => T | Promise<T>);\n\nexport interface UrlOptionsWithConnectionParams {\n /**\n * The URL to connect to (can be a function that returns a URL)\n */\n url: CallbackOrValue<string>;\n\n /**\n * Connection params that are available in `createContext()`\n * - For `wsLink`/`wsClient`, these are sent as the first message\n * - For `httpSubscriptionLink`, these are serialized as part of the URL under the `connectionParams` query\n */\n connectionParams?: CallbackOrValue<TRPCRequestInfo['connectionParams']>;\n}\n","import type {\n TRPCConnectionParamsMessage,\n TRPCRequestInfo,\n} from '@trpc/server/unstable-core-do-not-import';\nimport type {\n CallbackOrValue,\n UrlOptionsWithConnectionParams,\n} from '../../internals/urlWithConnectionParams';\nimport { resultOf } from '../../internals/urlWithConnectionParams';\nimport type { Encoder } from './encoder';\n\nexport class TRPCWebSocketClosedError extends Error {\n constructor(opts: { message: string; cause?: unknown }) {\n super(opts.message, {\n cause: opts.cause,\n });\n this.name = 'TRPCWebSocketClosedError';\n Object.setPrototypeOf(this, TRPCWebSocketClosedError.prototype);\n }\n}\n\n/**\n * Utility class for managing a timeout that can be started, stopped, and reset.\n * Useful for scenarios where the timeout duration is reset dynamically based on events.\n */\nexport class ResettableTimeout {\n private timeout: ReturnType<typeof setTimeout> | undefined;\n\n constructor(\n private readonly onTimeout: () => void,\n private readonly timeoutMs: number,\n ) {}\n\n /**\n * Resets the current timeout, restarting it with the same duration.\n * Does nothing if no timeout is active.\n */\n public reset() {\n if (!this.timeout) return;\n\n clearTimeout(this.timeout);\n this.timeout = setTimeout(this.onTimeout, this.timeoutMs);\n }\n\n public start() {\n clearTimeout(this.timeout);\n this.timeout = setTimeout(this.onTimeout, this.timeoutMs);\n }\n\n public stop() {\n clearTimeout(this.timeout);\n this.timeout = undefined;\n }\n}\n\n// Ponyfill for Promise.withResolvers https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers\nexport function withResolvers<T>() {\n let resolve: (value: T | PromiseLike<T>) => void;\n let reject: (reason?: any) => void;\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return { promise, resolve: resolve!, reject: reject! };\n}\n\n/**\n * Resolves a WebSocket URL and optionally appends connection parameters.\n *\n * If connectionParams are provided, appends 'connectionParams=1' query parameter.\n */\nexport async function prepareUrl(urlOptions: UrlOptionsWithConnectionParams) {\n const url = await resultOf(urlOptions.url);\n\n if (!urlOptions.connectionParams) return url;\n\n // append `?connectionParams=1` when connection params are used\n const prefix = url.includes('?') ? '&' : '?';\n const connectionParams = `${prefix}connectionParams=1`;\n\n return url + connectionParams;\n}\n\nexport async function buildConnectionMessage(\n connectionParams: CallbackOrValue<TRPCRequestInfo['connectionParams']>,\n encoder: Encoder,\n) {\n const message: TRPCConnectionParamsMessage = {\n method: 'connectionParams',\n data: await resultOf(connectionParams),\n };\n\n return encoder.encode(message);\n}\n","import type { AnyTRPCRouter, inferRouterError } from '@trpc/server';\nimport type { Observer } from '@trpc/server/observable';\nimport type {\n TRPCClientOutgoingMessage,\n TRPCResponseMessage,\n} from '@trpc/server/unstable-core-do-not-import';\nimport type { TRPCClientError } from '../../../TRPCClientError';\nimport { withResolvers } from './utils';\n\nexport type TCallbacks = Observer<\n TRPCResponseMessage<unknown, inferRouterError<AnyTRPCRouter>>,\n TRPCClientError<AnyTRPCRouter>\n>;\n\ntype MessageId = string;\ntype MessageIdLike = string | number | null;\n\n/**\n * Represents a WebSocket request managed by the RequestManager.\n * Combines the network message, a utility promise (`end`) that mirrors the lifecycle\n * handled by `callbacks`, and a set of state monitoring callbacks.\n */\ninterface Request {\n message: TRPCClientOutgoingMessage;\n end: Promise<void>;\n callbacks: TCallbacks;\n}\n\n/**\n * Manages WebSocket requests, tracking their lifecycle and providing utility methods\n * for handling outgoing and pending requests.\n *\n * - **Outgoing requests**: Requests that are queued and waiting to be sent.\n * - **Pending requests**: Requests that have been sent and are in flight awaiting a response.\n * For subscriptions, multiple responses may be received until the subscription is closed.\n */\nexport class RequestManager {\n /**\n * Stores requests that are outgoing, meaning they are registered but not yet sent over the WebSocket.\n */\n private outgoingRequests = new Array<Request & { id: MessageId }>();\n\n /**\n * Stores requests that are pending (in flight), meaning they have been sent over the WebSocket\n * and are awaiting responses. For subscriptions, this includes requests\n * that may receive multiple responses.\n */\n private pendingRequests: Record<MessageId, Request> = {};\n\n /**\n * Registers a new request by adding it to the outgoing queue and setting up\n * callbacks for lifecycle events such as completion or error.\n *\n * @param message - The outgoing message to be sent.\n * @param callbacks - Callback functions to observe the request's state.\n * @returns A cleanup function to manually remove the request.\n */\n public register(message: TRPCClientOutgoingMessage, callbacks: TCallbacks) {\n const { promise: end, resolve } = withResolvers<void>();\n\n this.outgoingRequests.push({\n id: String(message.id),\n message,\n end,\n callbacks: {\n next: callbacks.next,\n complete: () => {\n callbacks.complete();\n resolve();\n },\n error: (e) => {\n callbacks.error(e);\n resolve();\n },\n },\n });\n\n return () => {\n this.delete(message.id);\n callbacks.complete();\n resolve();\n };\n }\n\n /**\n * Deletes a request from both the outgoing and pending collections, if it exists.\n */\n public delete(messageId: MessageIdLike) {\n if (messageId === null) return;\n\n this.outgoingRequests = this.outgoingRequests.filter(\n ({ id }) => id !== String(messageId),\n );\n delete this.pendingRequests[String(messageId)];\n }\n\n /**\n * Moves all outgoing requests to the pending state and clears the outgoing queue.\n *\n * The caller is expected to handle the actual sending of the requests\n * (e.g., sending them over the network) after this method is called.\n *\n * @returns The list of requests that were transitioned to the pending state.\n */\n public flush() {\n const requests = this.outgoingRequests;\n this.outgoingRequests = [];\n\n for (const request of requests) {\n this.pendingRequests[request.id] = request;\n }\n return requests;\n }\n\n /**\n * Retrieves all currently pending requests, which are in flight awaiting responses\n * or handling ongoing subscriptions.\n */\n public getPendingRequests() {\n return Object.values(this.pendingRequests);\n }\n\n /**\n * Retrieves a specific pending request by its message ID.\n */\n public getPendingRequest(messageId: MessageIdLike) {\n if (messageId === null) return null;\n\n return this.pendingRequests[String(messageId)];\n }\n\n /**\n * Retrieves all outgoing requests, which are waiting to be sent.\n */\n public getOutgoingRequests() {\n return this.outgoingRequests;\n }\n\n /**\n * Retrieves all requests, both outgoing and pending, with their respective states.\n *\n * @returns An array of all requests with their state (\"outgoing\" or \"pending\").\n */\n public getRequests() {\n return [\n ...this.getOutgoingRequests().map((request) => ({\n state: 'outgoing' as const,\n message: request.message,\n end: request.end,\n callbacks: request.callbacks,\n })),\n ...this.getPendingRequests().map((request) => ({\n state: 'pending' as const,\n message: request.message,\n end: request.end,\n callbacks: request.callbacks,\n })),\n ];\n }\n\n /**\n * Checks if there are any pending requests, including ongoing subscriptions.\n */\n public hasPendingRequests() {\n return this.getPendingRequests().length > 0;\n }\n\n /**\n * Checks if there are any pending subscriptions\n */\n public hasPendingSubscriptions() {\n return this.getPendingRequests().some(\n (request) => request.message.method === 'subscription',\n );\n }\n\n /**\n * Checks if there are any outgoing requests waiting to be sent.\n */\n public hasOutgoingRequests() {\n return this.outgoingRequests.length > 0;\n }\n}\n","import { behaviorSubject } from '@trpc/server/observable';\nimport type { UrlOptionsWithConnectionParams } from '../../internals/urlWithConnectionParams';\nimport type { Encoder } from './encoder';\nimport { buildConnectionMessage, prepareUrl, withResolvers } from './utils';\n\n/**\n * Opens a WebSocket connection asynchronously and returns a promise\n * that resolves when the connection is successfully established.\n * The promise rejects if an error occurs during the connection attempt.\n */\nfunction asyncWsOpen(ws: WebSocket) {\n const { promise, resolve, reject } = withResolvers<void>();\n\n ws.addEventListener('open', () => {\n ws.removeEventListener('error', reject);\n resolve();\n });\n ws.addEventListener('error', reject);\n\n return promise;\n}\n\ninterface PingPongOptions {\n /**\n * The interval (in milliseconds) between \"PING\" messages.\n */\n intervalMs: number;\n\n /**\n * The timeout (in milliseconds) to wait for a \"PONG\" response before closing the connection.\n */\n pongTimeoutMs: number;\n}\n\n/**\n * Sets up a periodic ping-pong mechanism to keep the WebSocket connection alive.\n *\n * - Sends \"PING\" messages at regular intervals defined by `intervalMs`.\n * - If a \"PONG\" response is not received within the `pongTimeoutMs`, the WebSocket is closed.\n * - The ping timer resets upon receiving any message to maintain activity.\n * - Automatically starts the ping process when the WebSocket connection is opened.\n * - Cleans up timers when the WebSocket is closed.\n *\n * @param ws - The WebSocket instance to manage.\n * @param options - Configuration options for ping-pong intervals and timeouts.\n */\nfunction setupPingInterval(\n ws: WebSocket,\n { intervalMs, pongTimeoutMs }: PingPongOptions,\n) {\n let pingTimeout: ReturnType<typeof setTimeout> | undefined;\n let pongTimeout: ReturnType<typeof setTimeout> | undefined;\n\n function start() {\n pingTimeout = setTimeout(() => {\n ws.send('PING');\n pongTimeout = setTimeout(() => {\n ws.close();\n }, pongTimeoutMs);\n }, intervalMs);\n }\n\n function reset() {\n clearTimeout(pingTimeout);\n start();\n }\n\n function pong() {\n clearTimeout(pongTimeout);\n reset();\n }\n\n ws.addEventListener('open', start);\n ws.addEventListener('message', ({ data }) => {\n clearTimeout(pingTimeout);\n start();\n\n if (data === 'PONG') {\n pong();\n }\n });\n ws.addEventListener('close', () => {\n clearTimeout(pingTimeout);\n clearTimeout(pongTimeout);\n });\n}\n\nexport interface WebSocketConnectionOptions {\n WebSocketPonyfill?: typeof WebSocket;\n urlOptions: UrlOptionsWithConnectionParams;\n keepAlive: PingPongOptions & {\n enabled: boolean;\n };\n encoder: Encoder;\n}\n\n/**\n * Manages a WebSocket connection with support for reconnection, keep-alive mechanisms,\n * and observable state tracking.\n */\nexport class WsConnection {\n static connectCount = 0;\n public id = ++WsConnection.connectCount;\n\n private readonly WebSocketPonyfill: typeof WebSocket;\n private readonly urlOptions: UrlOptionsWithConnectionParams;\n private readonly keepAliveOpts: WebSocketConnectionOptions['keepAlive'];\n private readonly encoder: Encoder;\n public readonly wsObservable = behaviorSubject<WebSocket | null>(null);\n\n constructor(opts: WebSocketConnectionOptions) {\n this.WebSocketPonyfill = opts.WebSocketPonyfill ?? WebSocket;\n if (!this.WebSocketPonyfill) {\n throw new Error(\n \"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\",\n );\n }\n\n this.urlOptions = opts.urlOptions;\n this.keepAliveOpts = opts.keepAlive;\n this.encoder = opts.encoder;\n }\n\n public get ws() {\n return this.wsObservable.get();\n }\n\n private set ws(ws) {\n this.wsObservable.next(ws);\n }\n\n /**\n * Checks if the WebSocket connection is open and ready to communicate.\n */\n public isOpen(): this is { ws: WebSocket } {\n return (\n !!this.ws &&\n this.ws.readyState === this.WebSocketPonyfill.OPEN &&\n !this.openPromise\n );\n }\n\n /**\n * Checks if the WebSocket connection is closed or in the process of closing.\n */\n public isClosed(): this is { ws: WebSocket } {\n return (\n !!this.ws &&\n (this.ws.readyState === this.WebSocketPonyfill.CLOSING ||\n this.ws.readyState === this.WebSocketPonyfill.CLOSED)\n );\n }\n\n /**\n * Manages the WebSocket opening process, ensuring that only one open operation\n * occurs at a time. Tracks the ongoing operation with `openPromise` to avoid\n * redundant calls and ensure proper synchronization.\n *\n * Sets up the keep-alive mechanism and necessary event listeners for the connection.\n *\n * @returns A promise that resolves once the WebSocket connection is successfully opened.\n */\n private openPromise: Promise<void> | null = null;\n public async open() {\n if (this.openPromise) return this.openPromise;\n\n this.id = ++WsConnection.connectCount;\n const wsPromise = prepareUrl(this.urlOptions).then(\n (url) => new this.WebSocketPonyfill(url),\n );\n this.openPromise = wsPromise.then(async (ws) => {\n this.ws = ws;\n\n // Set binaryType to handle both text and binary messages consistently\n ws.binaryType = 'arraybuffer';\n\n // Setup ping listener\n ws.addEventListener('message', function ({ data }) {\n if (data === 'PING') {\n this.send('PONG');\n }\n });\n\n if (this.keepAliveOpts.enabled) {\n setupPingInterval(ws, this.keepAliveOpts);\n }\n\n ws.addEventListener('close', () => {\n if (this.ws === ws) {\n this.ws = null;\n }\n });\n\n await asyncWsOpen(ws);\n\n if (this.urlOptions.connectionParams) {\n ws.send(\n await buildConnectionMessage(\n this.urlOptions.connectionParams,\n this.encoder,\n ),\n );\n }\n });\n\n try {\n await this.openPromise;\n } finally {\n this.openPromise = null;\n }\n }\n\n /**\n * Closes the WebSocket connection gracefully.\n * Waits for any ongoing open operation to complete before closing.\n */\n public async close() {\n try {\n await this.openPromise;\n } finally {\n this.ws?.close();\n }\n }\n}\n\n/**\n * Provides a backward-compatible representation of the connection state.\n */\nexport function backwardCompatibility(connection: WsConnection) {\n if (connection.isOpen()) {\n return {\n id: connection.id,\n state: 'open',\n ws: connection.ws,\n } as const;\n }\n\n if (connection.isClosed()) {\n return {\n id: connection.id,\n state: 'closed',\n ws: connection.ws,\n } as const;\n }\n\n if (!connection.ws) {\n return null;\n }\n\n return {\n id: connection.id,\n state: 'connecting',\n ws: connection.ws,\n } as const;\n}\n","import type { AnyTRPCRouter } from '@trpc/server';\nimport type { BehaviorSubject } from '@trpc/server/observable';\nimport { behaviorSubject, observable } from '@trpc/server/observable';\nimport type {\n CombinedDataTransformer,\n TRPCClientIncomingMessage,\n TRPCClientIncomingRequest,\n TRPCClientOutgoingMessage,\n TRPCResponseMessage,\n} from '@trpc/server/unstable-core-do-not-import';\nimport {\n run,\n sleep,\n transformResult,\n} from '@trpc/server/unstable-core-do-not-import';\nimport { TRPCClientError } from '../../../TRPCClientError';\nimport type { TRPCConnectionState } from '../../internals/subscriptions';\nimport type { Operation, OperationResultEnvelope } from '../../types';\nimport type { Encoder } from './encoder';\nimport { jsonEncoder } from './encoder';\nimport type { WebSocketClientOptions } from './options';\nimport { exponentialBackoff, keepAliveDefaults, lazyDefaults } from './options';\nimport type { TCallbacks } from './requestManager';\nimport { RequestManager } from './requestManager';\nimport { ResettableTimeout, TRPCWebSocketClosedError } from './utils';\nimport { backwardCompatibility, WsConnection } from './wsConnection';\n\n/**\n * A WebSocket client for managing TRPC operations, supporting lazy initialization,\n * reconnection, keep-alive, and request management.\n */\nexport class WsClient {\n /**\n * Observable tracking the current connection state, including errors.\n */\n public readonly connectionState: BehaviorSubject<\n TRPCConnectionState<TRPCClientError<AnyTRPCRouter>>\n >;\n\n private allowReconnect = false;\n private requestManager = new RequestManager();\n private readonly activeConnection: WsConnection;\n private readonly reconnectRetryDelay: (attemptIndex: number) => number;\n private inactivityTimeout: ResettableTimeout;\n private readonly callbacks: Pick<\n WebSocketClientOptions,\n 'onOpen' | 'onClose' | 'onError'\n >;\n private readonly lazyMode: boolean;\n private readonly encoder: Encoder;\n\n constructor(opts: WebSocketClientOptions) {\n this.encoder = opts.experimental_encoder ?? jsonEncoder;\n // Initialize callbacks, connection parameters, and options.\n this.callbacks = {\n onOpen: opts.onOpen,\n onClose: opts.onClose,\n onError: opts.onError,\n };\n\n const lazyOptions = {\n ...lazyDefaults,\n ...opts.lazy,\n };\n\n // Set up inactivity timeout for lazy connections.\n this.inactivityTimeout = new ResettableTimeout(() => {\n if (\n this.requestManager.hasOutgoingRequests() ||\n this.requestManager.hasPendingRequests()\n ) {\n this.inactivityTimeout.reset();\n return;\n }\n\n this.close().catch(() => null);\n }, lazyOptions.closeMs);\n\n // Initialize the WebSocket connection.\n this.activeConnection = new WsConnection({\n WebSocketPonyfill: opts.WebSocket,\n urlOptions: opts,\n keepAlive: {\n ...keepAliveDefaults,\n ...opts.keepAlive,\n },\n encoder: this.encoder,\n });\n this.activeConnection.wsObservable.subscribe({\n next: (ws) => {\n if (!ws) return;\n this.setupWebSocketListeners(ws);\n },\n });\n this.reconnectRetryDelay = opts.retryDelayMs ?? exponentialBackoff;\n\n this.lazyMode = lazyOptions.enabled;\n\n this.connectionState = behaviorSubject<\n TRPCConnectionState<TRPCClientError<AnyTRPCRouter>>\n >({\n type: 'state',\n state: lazyOptions.enabled ? 'idle' : 'connecting',\n error: null,\n });\n\n // Automatically open the connection if lazy mode is disabled.\n if (!this.lazyMode) {\n this.open().catch(() => null);\n }\n }\n\n /**\n * Opens the WebSocket connection. Handles reconnection attempts and updates\n * the connection state accordingly.\n */\n private async open() {\n this.allowReconnect = true;\n if (this.connectionState.get().state === 'idle') {\n this.connectionState.next({\n type: 'state',\n state: 'connecting',\n error: null,\n });\n }\n\n try {\n await this.activeConnection.open();\n } catch (error) {\n this.reconnect(\n new TRPCWebSocketClosedError({\n message: 'Initialization error',\n cause: error,\n }),\n );\n return this.reconnecting;\n }\n }\n\n /**\n * Closes the WebSocket connection and stops managing requests.\n * Ensures all outgoing and pending requests are properly finalized.\n */\n public async close() {\n this.allowReconnect = false;\n this.inactivityTimeout.stop();\n\n const requestsToAwait: Promise<void>[] = [];\n for (const request of this.requestManager.getRequests()) {\n if (request.message.method === 'subscription') {\n request.callbacks.complete();\n } else if (request.state === 'outgoing') {\n request.callbacks.error(\n TRPCClientError.from(\n new TRPCWebSocketClosedError({\n message: 'Closed before connection was established',\n }),\n ),\n );\n } else {\n requestsToAwait.push(request.end);\n }\n }\n\n await Promise.all(requestsToAwait).catch(() => null);\n await this.activeConnection.close().catch(() => null);\n\n this.connectionState.next({\n type: 'state',\n state: 'idle',\n error: null,\n });\n }\n\n /**\n * Method to request the server.\n * Handles data transformation, batching of requests, and subscription lifecycle.\n *\n * @param op - The operation details including id, type, path, input and signal\n * @param transformer - Data transformer for serializing requests and deserializing responses\n * @param lastEventId - Optional ID of the last received event for subscriptions\n *\n * @returns An observable that emits operation results and handles cleanup\n */\n public request({\n op: { id, type, path, input, signal },\n transformer,\n lastEventId,\n }: {\n op: Pick<Operation, 'id' | 'type' | 'path' | 'input' | 'signal'>;\n transformer: CombinedDataTransformer;\n lastEventId?: string;\n }) {\n return observable<\n OperationResultEnvelope<unknown, TRPCClientError<AnyTRPCRouter>>,\n TRPCClientError<AnyTRPCRouter>\n >((observer) => {\n const abort = this.batchSend(\n {\n id,\n method: type,\n params: {\n input: transformer.input.serialize(input),\n path,\n lastEventId,\n },\n },\n {\n ...observer,\n next(event) {\n const transformed = transformResult(event, transformer.output);\n\n if (!transformed.ok) {\n observer.error(TRPCClientError.from(transformed.error));\n return;\n }\n\n observer.next({\n result: transformed.result,\n });\n },\n },\n );\n\n const onAbort = () => observer.complete();\n if (signal?.aborted) {\n onAbort();\n } else {\n signal?.addEventListener('abort', onAbort, { once: true });\n }\n\n return () => {\n abort();\n\n if (type === 'subscription' && this.activeConnection.isOpen()) {\n this.send({\n id,\n method: 'subscription.stop',\n });\n }\n\n signal?.removeEventListener('abort', onAbort);\n };\n });\n }\n\n public get connection() {\n return backwardCompatibility(this.activeConnection);\n }\n\n /**\n * Manages the reconnection process for the WebSocket using retry logic.\n * Ensures that only one reconnection attempt is active at a time by tracking the current\n * reconnection state in the `reconnecting` promise.\n */\n private reconnecting: Promise<void> | null = null;\n private reconnect(closedError: TRPCWebSocketClosedError) {\n this.connectionState.next({\n type: 'state',\n state: 'connecting',\n error: TRPCClientError.from(closedError),\n });\n if (this.reconnecting) return;\n\n const tryReconnect = async (attemptIndex: number) => {\n try {\n await sleep(this.reconnectRetryDelay(attemptIndex));\n if (this.allowReconnect) {\n await this.activeConnection.close();\n await this.activeConnection.open();\n\n if (this.requestManager.hasPendingRequests()) {\n this.send(\n this.requestManager\n .getPendingRequests()\n .map(({ message }) => message),\n );\n }\n }\n this.reconnecting = null;\n } catch {\n await tryReconnect(attemptIndex + 1);\n }\n };\n\n this.reconnecting = tryReconnect(0);\n }\n\n private setupWebSocketListeners(ws: WebSocket) {\n const handleCloseOrError = (cause: unknown) => {\n const reqs = this.requestManager.getPendingRequests();\n for (const { message, callbacks } of reqs) {\n if (message.method === 'subscription') continue;\n\n callbacks.error(\n TRPCClientError.from(\n cause ??\n new TRPCWebSocketClosedError({\n message: 'WebSocket closed',\n cause,\n }),\n ),\n );\n this.requestManager.delete(message.id);\n }\n };\n\n ws.addEventListener('open', () => {\n run(async () => {\n if (this.lazyMode) {\n this.inactivityTimeout.start();\n }\n\n this.callbacks.onOpen?.();\n\n this.connectionState.next({\n type: 'state',\n state: 'pending',\n error: null,\n });\n }).catch((error) => {\n ws.close(3000);\n handleCloseOrError(error);\n });\n });\n\n ws.addEventListener('message', ({ data }) => {\n this.inactivityTimeout.reset();\n\n // Handle PING/PONG as text regardless of encoder\n if (['PING', 'PONG'].includes(data)) return;\n\n const incomingMessage = this.encoder.decode(\n data,\n ) as TRPCClientIncomingMessage;\n if ('method' in incomingMessage) {\n this.handleIncomingRequest(incomingMessage);\n return;\n }\n\n this.handleResponseMessage(incomingMessage);\n });\n\n ws.addEventListener('close', (event) => {\n handleCloseOrError(event);\n this.callbacks.onClose?.(event);\n\n if (!this.lazyMode || this.requestManager.hasPendingSubscriptions()) {\n this.reconnect(\n new TRPCWebSocketClosedError({\n message: 'WebSocket closed',\n cause: event,\n }),\n );\n }\n });\n\n ws.addEventListener('error', (event) => {\n handleCloseOrError(event);\n this.callbacks.onError?.(event);\n\n this.reconnect(\n new TRPCWebSocketClosedError({\n message: 'WebSocket closed',\n cause: event,\n }),\n );\n });\n }\n\n private handleResponseMessage(message: TRPCResponseMessage) {\n const request = this.requestManager.getPendingRequest(message.id);\n if (!request) return;\n\n request.callbacks.next(message);\n\n let completed = true;\n if ('result' in message && request.message.method === 'subscription') {\n if (message.result.type === 'data') {\n request.message.params.lastEventId = message.result.id;\n }\n\n if (message.result.type !== 'stopped') {\n completed = false;\n }\n }\n\n if (completed) {\n request.callbacks.complete();\n this.requestManager.delete(message.id);\n }\n }\n\n private handleIncomingRequest(message: TRPCClientIncomingRequest) {\n if (message.method === 'reconnect') {\n this.reconnect(\n new TRPCWebSocketClosedError({\n message: 'Server requested reconnect',\n }),\n );\n }\n }\n\n /**\n * Sends a message or batch of messages directly to the server.\n */\n private send(\n messageOrMessages: TRPCClientOutgoingMessage | TRPCClientOutgoingMessage[],\n ) {\n if (!this.activeConnection.isOpen()) {\n throw new Error('Active connection is not open');\n }\n\n const messages =\n messageOrMessages instanceof Array\n ? messageOrMessages\n : [messageOrMessages];\n this.activeConnection.ws.send(\n this.encoder.encode(messages.length === 1 ? messages[0] : messages),\n );\n }\n\n /**\n * Groups requests for batch sending.\n *\n * @returns A function to abort the batched request.\n */\n private batchSend(message: TRPCClientOutgoingMessage, callbacks: TCallbacks) {\n this.inactivityTimeout.reset();\n\n run(async () => {\n if (!this.activeConnection.isOpen()) {\n await this.open();\n }\n await sleep(0);\n\n if (!this.requestManager.hasOutgoingRequests()) return;\n\n this.send(this.requestManager.flush().map(({ message }) => message));\n }).catch((err) => {\n this.requestManager.delete(message.id);\n callbacks.error(TRPCClientError.from(err));\n });\n\n return this.requestManager.register(message, callbacks);\n }\n}\n","import type { Encoder } from './wsClient/encoder';\nimport { jsonEncoder } from './wsClient/encoder';\nimport type { WebSocketClientOptions } from './wsClient/options';\nimport { WsClient } from './wsClient/wsClient';\n\nexport function createWSClient(opts: WebSocketClientOptions) {\n return new WsClient(opts);\n}\n\nexport type TRPCWebSocketClient = ReturnType<typeof createWSClient>;\n\nexport { jsonEncoder, type Encoder, type WebSocketClientOptions };\n","import { observable } from '@trpc/server/observable';\nimport type {\n AnyRouter,\n inferClientTypes,\n} from '@trpc/server/unstable-core-do-not-import';\nimport type { TransformerOptions } from '../../unstable-internals';\nimport { getTransformer } from '../../unstable-internals';\nimport type { TRPCLink } from '../types';\nimport type {\n Encoder,\n TRPCWebSocketClient,\n WebSocketClientOptions,\n} from './createWsClient';\nimport { createWSClient, jsonEncoder } from './createWsClient';\n\nexport type WebSocketLinkOptions<TRouter extends AnyRouter> = {\n client: TRPCWebSocketClient;\n} & TransformerOptions<inferClientTypes<TRouter>>;\n\nexport function wsLink<TRouter extends AnyRouter>(\n opts: WebSocketLinkOptions<TRouter>,\n): TRPCLink<TRouter> {\n const { client } = opts;\n const transformer = getTransformer(opts.transformer);\n return () => {\n return ({ op }) => {\n return observable((observer) => {\n const connStateSubscription =\n op.type === 'subscription'\n ? client.connectionState.subscribe({\n next(result) {\n observer.next({\n result,\n context: op.context,\n });\n },\n })\n : null;\n\n const requestSubscription = client\n .request({\n op,\n transformer,\n })\n .subscribe(observer);\n\n return () => {\n requestSubscription.unsubscribe();\n connStateSubscription?.unsubscribe();\n };\n });\n };\n };\n}\n\nexport {\n createWSClient,\n jsonEncoder,\n type Encoder,\n type TRPCWebSocketClient,\n type WebSocketClientOptions,\n};\n"],"mappings":"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"}
|