@trpc/client 11.0.0-alpha-tmp-subscription-connection-state.489 → 11.0.0-alpha-tmp-12-06-react.665
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.d.ts +1 -1
- package/dist/TRPCClientError.d.ts.map +1 -1
- package/dist/TRPCClientError.js +19 -1
- package/dist/TRPCClientError.mjs +19 -1
- package/dist/bundle-analysis.json +119 -93
- package/dist/createTRPCClient.d.ts +3 -2
- package/dist/createTRPCClient.d.ts.map +1 -1
- package/dist/createTRPCClient.js +1 -1
- package/dist/createTRPCClient.mjs +1 -1
- package/dist/index.js +6 -6
- package/dist/index.mjs +2 -2
- package/dist/internals/TRPCUntypedClient.d.ts +5 -4
- package/dist/internals/TRPCUntypedClient.d.ts.map +1 -1
- package/dist/internals/TRPCUntypedClient.js +42 -12
- package/dist/internals/TRPCUntypedClient.mjs +42 -12
- package/dist/internals/inputWithTrackedEventId.d.ts +2 -0
- package/dist/internals/inputWithTrackedEventId.d.ts.map +1 -0
- package/dist/internals/inputWithTrackedEventId.js +16 -0
- package/dist/internals/inputWithTrackedEventId.mjs +14 -0
- package/dist/internals/signals.d.ts +15 -0
- package/dist/internals/signals.d.ts.map +1 -0
- package/dist/internals/signals.js +47 -0
- package/dist/internals/signals.mjs +44 -0
- package/dist/internals/transformer.d.ts +2 -2
- package/dist/internals/types.d.ts +1 -1
- package/dist/internals/types.d.ts.map +1 -1
- package/dist/links/HTTPBatchLinkOptions.d.ts +1 -1
- package/dist/links/httpBatchLink.d.ts.map +1 -1
- package/dist/links/httpBatchLink.js +4 -3
- package/dist/links/httpBatchLink.mjs +5 -4
- package/dist/links/httpBatchStreamLink.d.ts.map +1 -1
- package/dist/links/httpBatchStreamLink.js +6 -4
- package/dist/links/httpBatchStreamLink.mjs +7 -5
- package/dist/links/httpLink.d.ts +2 -2
- package/dist/links/httpLink.js +3 -3
- package/dist/links/httpLink.mjs +3 -3
- package/dist/links/httpSubscriptionLink.d.ts +11 -6
- package/dist/links/httpSubscriptionLink.d.ts.map +1 -1
- package/dist/links/httpSubscriptionLink.js +130 -98
- package/dist/links/httpSubscriptionLink.mjs +132 -100
- package/dist/links/internals/contentTypes.d.ts +2 -2
- package/dist/links/internals/contentTypes.d.ts.map +1 -1
- package/dist/links/internals/httpUtils.d.ts +1 -8
- package/dist/links/internals/httpUtils.d.ts.map +1 -1
- package/dist/links/internals/httpUtils.js +1 -30
- package/dist/links/internals/httpUtils.mjs +2 -30
- package/dist/links/internals/subscriptions.d.ts +20 -0
- package/dist/links/internals/subscriptions.d.ts.map +1 -0
- package/dist/links/internals/urlWithConnectionParams.d.ts +2 -1
- package/dist/links/internals/urlWithConnectionParams.d.ts.map +1 -1
- package/dist/links/internals/urlWithConnectionParams.js +3 -2
- package/dist/links/internals/urlWithConnectionParams.mjs +3 -2
- package/dist/links/loggerLink.d.ts +5 -5
- package/dist/links/loggerLink.d.ts.map +1 -1
- package/dist/links/loggerLink.js +25 -21
- package/dist/links/loggerLink.mjs +25 -21
- package/dist/links/retryLink.d.ts +29 -0
- package/dist/links/retryLink.d.ts.map +1 -0
- package/dist/links/retryLink.js +65 -0
- package/dist/links/retryLink.mjs +63 -0
- package/dist/links/types.d.ts +4 -23
- package/dist/links/types.d.ts.map +1 -1
- package/dist/links/wsLink.d.ts +49 -5
- package/dist/links/wsLink.d.ts.map +1 -1
- package/dist/links/wsLink.js +210 -155
- package/dist/links/wsLink.mjs +211 -156
- package/dist/links.d.ts +1 -0
- package/dist/links.d.ts.map +1 -1
- package/dist/unstable-internals.d.ts +1 -0
- package/dist/unstable-internals.d.ts.map +1 -1
- package/package.json +14 -11
- package/src/TRPCClientError.ts +1 -1
- package/src/createTRPCClient.ts +28 -23
- package/src/internals/TRPCUntypedClient.ts +26 -15
- package/src/internals/inputWithTrackedEventId.ts +15 -0
- package/src/internals/signals.ts +54 -0
- package/src/internals/transformer.ts +2 -2
- package/src/internals/types.ts +1 -1
- package/src/links/HTTPBatchLinkOptions.ts +1 -1
- package/src/links/httpBatchLink.ts +3 -3
- package/src/links/httpBatchStreamLink.ts +7 -4
- package/src/links/httpLink.ts +2 -2
- package/src/links/httpSubscriptionLink.ts +172 -123
- package/src/links/internals/httpUtils.ts +1 -41
- package/src/links/internals/subscriptions.ts +26 -0
- package/src/links/internals/urlWithConnectionParams.ts +8 -2
- package/src/links/loggerLink.ts +21 -9
- package/src/links/retryLink.ts +101 -0
- package/src/links/types.ts +8 -46
- package/src/links/wsLink.ts +276 -173
- package/src/links.ts +1 -1
- package/src/unstable-internals.ts +1 -0
- package/dist/links/internals/retryLink.d.ts +0 -9
- package/dist/links/internals/retryLink.d.ts.map +0 -1
- package/dist/links/types.js +0 -7
- package/dist/links/types.mjs +0 -5
- package/src/links/internals/retryLink.ts +0 -53
package/dist/links/wsLink.mjs
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { observable } from '@trpc/server/observable';
|
|
1
|
+
import { behaviorSubject, observable } from '@trpc/server/observable';
|
|
2
2
|
import { transformResult } from '@trpc/server/unstable-core-do-not-import';
|
|
3
3
|
import { TRPCClientError } from '../TRPCClientError.mjs';
|
|
4
4
|
import { getTransformer } from '../internals/transformer.mjs';
|
|
5
5
|
import { resultOf } from './internals/urlWithConnectionParams.mjs';
|
|
6
|
-
import { isConnectionStateMessage } from './types.mjs';
|
|
7
6
|
|
|
8
7
|
const run = (fn)=>fn();
|
|
9
8
|
const exponentialBackoff = (attemptIndex)=>attemptIndex === 0 ? 0 : Math.min(1000 * 2 ** attemptIndex, 30000);
|
|
@@ -11,8 +10,13 @@ const lazyDefaults = {
|
|
|
11
10
|
enabled: false,
|
|
12
11
|
closeMs: 0
|
|
13
12
|
};
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
/**
|
|
14
|
+
* @see https://trpc.io/docs/v11/client/links/wsLink
|
|
15
|
+
* @deprecated
|
|
16
|
+
* 🙋♂️ **Contributors needed** to continue supporting WebSockets!
|
|
17
|
+
* See https://github.com/trpc/trpc/issues/6109
|
|
18
|
+
*/ function createWSClient(opts) {
|
|
19
|
+
const { WebSocket: WebSocketImpl = WebSocket, retryDelayMs: retryDelayFn = exponentialBackoff } = opts;
|
|
16
20
|
const lazyOpts = {
|
|
17
21
|
...lazyDefaults,
|
|
18
22
|
...opts.lazy
|
|
@@ -28,12 +32,22 @@ function createWSClient(opts) {
|
|
|
28
32
|
let connectTimer = undefined;
|
|
29
33
|
let connectionIndex = 0;
|
|
30
34
|
let lazyDisconnectTimer = undefined;
|
|
31
|
-
let activeConnection = lazyOpts.enabled ? null : createConnection(
|
|
35
|
+
let activeConnection = lazyOpts.enabled ? null : createConnection();
|
|
36
|
+
const initState = activeConnection ? {
|
|
37
|
+
type: 'state',
|
|
38
|
+
state: 'connecting',
|
|
39
|
+
error: null
|
|
40
|
+
} : {
|
|
41
|
+
type: 'state',
|
|
42
|
+
state: 'idle',
|
|
43
|
+
error: null
|
|
44
|
+
};
|
|
45
|
+
const connectionState = behaviorSubject(initState);
|
|
32
46
|
/**
|
|
33
47
|
* tries to send the list of messages
|
|
34
48
|
*/ function dispatch() {
|
|
35
49
|
if (!activeConnection) {
|
|
36
|
-
|
|
50
|
+
reconnect(null);
|
|
37
51
|
return;
|
|
38
52
|
}
|
|
39
53
|
// using a timeout to batch messages
|
|
@@ -58,11 +72,10 @@ function createWSClient(opts) {
|
|
|
58
72
|
startLazyDisconnectTimer();
|
|
59
73
|
});
|
|
60
74
|
}
|
|
61
|
-
function tryReconnect(
|
|
75
|
+
function tryReconnect(cause) {
|
|
62
76
|
if (!!connectTimer) {
|
|
63
77
|
return;
|
|
64
78
|
}
|
|
65
|
-
conn.state = 'connecting';
|
|
66
79
|
const timeout = retryDelayFn(connectAttempt++);
|
|
67
80
|
reconnectInMs(timeout, cause);
|
|
68
81
|
}
|
|
@@ -75,18 +88,30 @@ function createWSClient(opts) {
|
|
|
75
88
|
}
|
|
76
89
|
function reconnect(cause) {
|
|
77
90
|
if (lazyOpts.enabled && !hasPendingRequests()) {
|
|
78
|
-
// Skip reconnecting if there
|
|
91
|
+
// Skip reconnecting if there aren't pending requests and we're in lazy mode
|
|
79
92
|
return;
|
|
80
93
|
}
|
|
81
94
|
const oldConnection = activeConnection;
|
|
82
|
-
activeConnection = createConnection(
|
|
83
|
-
|
|
95
|
+
activeConnection = createConnection();
|
|
96
|
+
if (oldConnection) {
|
|
97
|
+
closeIfNoPending(oldConnection);
|
|
98
|
+
}
|
|
99
|
+
const currentState = connectionState.get();
|
|
100
|
+
if (currentState.state !== 'connecting') {
|
|
101
|
+
connectionState.next({
|
|
102
|
+
type: 'state',
|
|
103
|
+
state: 'connecting',
|
|
104
|
+
error: cause ? TRPCClientError.from(cause) : null
|
|
105
|
+
});
|
|
106
|
+
}
|
|
84
107
|
}
|
|
85
108
|
function reconnectInMs(ms, cause) {
|
|
86
109
|
if (connectTimer) {
|
|
87
110
|
return;
|
|
88
111
|
}
|
|
89
|
-
connectTimer = setTimeout(
|
|
112
|
+
connectTimer = setTimeout(()=>{
|
|
113
|
+
reconnect(cause);
|
|
114
|
+
}, ms);
|
|
90
115
|
}
|
|
91
116
|
function closeIfNoPending(conn) {
|
|
92
117
|
// disconnect as soon as there are are no pending requests
|
|
@@ -113,37 +138,69 @@ function createWSClient(opts) {
|
|
|
113
138
|
if (!activeConnection) {
|
|
114
139
|
return;
|
|
115
140
|
}
|
|
116
|
-
if (!hasPendingRequests(
|
|
141
|
+
if (!hasPendingRequests()) {
|
|
117
142
|
activeConnection.ws?.close();
|
|
118
143
|
activeConnection = null;
|
|
144
|
+
connectionState.next({
|
|
145
|
+
type: 'state',
|
|
146
|
+
state: 'idle',
|
|
147
|
+
error: null
|
|
148
|
+
});
|
|
119
149
|
}
|
|
120
150
|
}, lazyOpts.closeMs);
|
|
121
151
|
};
|
|
122
|
-
function createConnection(
|
|
152
|
+
function createConnection() {
|
|
153
|
+
let pingTimeout = undefined;
|
|
154
|
+
let pongTimeout = undefined;
|
|
123
155
|
const self = {
|
|
124
156
|
id: ++connectionIndex,
|
|
125
157
|
state: 'connecting'
|
|
126
158
|
};
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
159
|
+
clearTimeout(lazyDisconnectTimer);
|
|
160
|
+
function destroy() {
|
|
161
|
+
const noop = ()=>{
|
|
162
|
+
// no-op
|
|
163
|
+
};
|
|
164
|
+
const { ws } = self;
|
|
165
|
+
if (ws) {
|
|
166
|
+
ws.onclose = noop;
|
|
167
|
+
ws.onerror = noop;
|
|
168
|
+
ws.onmessage = noop;
|
|
169
|
+
ws.onopen = noop;
|
|
170
|
+
ws.close();
|
|
136
171
|
}
|
|
172
|
+
self.state = 'closed';
|
|
137
173
|
}
|
|
138
|
-
|
|
139
|
-
|
|
174
|
+
const onCloseOrError = (cause)=>{
|
|
175
|
+
clearTimeout(pingTimeout);
|
|
176
|
+
clearTimeout(pongTimeout);
|
|
140
177
|
self.state = 'closed';
|
|
141
|
-
if (
|
|
142
|
-
|
|
178
|
+
if (activeConnection === self) {
|
|
179
|
+
// connection might have been replaced already
|
|
180
|
+
tryReconnect(cause);
|
|
181
|
+
}
|
|
182
|
+
for (const [key, req] of Object.entries(pendingRequests)){
|
|
183
|
+
if (req.connection !== self) {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
// The connection was closed either unexpectedly or because of a reconnect
|
|
187
|
+
if (req.type === 'subscription') {
|
|
188
|
+
// Subscriptions will resume after we've reconnected
|
|
189
|
+
resumeSubscriptionOnReconnect(req);
|
|
190
|
+
} else {
|
|
191
|
+
// Queries and mutations will error if interrupted
|
|
192
|
+
delete pendingRequests[key];
|
|
193
|
+
req.callbacks.error?.(TRPCClientError.from(cause ?? new TRPCWebSocketClosedError()));
|
|
194
|
+
}
|
|
143
195
|
}
|
|
144
196
|
};
|
|
145
|
-
|
|
146
|
-
|
|
197
|
+
const onError = (evt)=>{
|
|
198
|
+
onCloseOrError(new TRPCWebSocketClosedError({
|
|
199
|
+
cause: evt
|
|
200
|
+
}));
|
|
201
|
+
opts.onError?.(evt);
|
|
202
|
+
};
|
|
203
|
+
function connect(url) {
|
|
147
204
|
if (opts.connectionParams) {
|
|
148
205
|
// append `?connectionParams=1` when connection params are used
|
|
149
206
|
const prefix = url.includes('?') ? '&' : '?';
|
|
@@ -153,51 +210,78 @@ function createWSClient(opts) {
|
|
|
153
210
|
self.ws = ws;
|
|
154
211
|
clearTimeout(connectTimer);
|
|
155
212
|
connectTimer = undefined;
|
|
156
|
-
ws.
|
|
157
|
-
|
|
158
|
-
|
|
213
|
+
ws.onopen = ()=>{
|
|
214
|
+
async function sendConnectionParams() {
|
|
215
|
+
if (!opts.connectionParams) {
|
|
159
216
|
return;
|
|
160
217
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
218
|
+
const connectMsg = {
|
|
219
|
+
method: 'connectionParams',
|
|
220
|
+
data: await resultOf(opts.connectionParams)
|
|
221
|
+
};
|
|
222
|
+
ws.send(JSON.stringify(connectMsg));
|
|
223
|
+
}
|
|
224
|
+
function handleKeepAlive() {
|
|
225
|
+
if (!opts.keepAlive?.enabled) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const { pongTimeoutMs = 1000, intervalMs = 5000 } = opts.keepAlive;
|
|
229
|
+
const schedulePing = ()=>{
|
|
230
|
+
const schedulePongTimeout = ()=>{
|
|
231
|
+
pongTimeout = setTimeout(()=>{
|
|
232
|
+
const wasOpen = self.state === 'open';
|
|
233
|
+
destroy();
|
|
234
|
+
if (wasOpen) {
|
|
235
|
+
opts.onClose?.();
|
|
236
|
+
}
|
|
237
|
+
}, pongTimeoutMs);
|
|
165
238
|
};
|
|
166
|
-
|
|
239
|
+
pingTimeout = setTimeout(()=>{
|
|
240
|
+
ws.send('PING');
|
|
241
|
+
schedulePongTimeout();
|
|
242
|
+
}, intervalMs);
|
|
243
|
+
};
|
|
244
|
+
ws.addEventListener('message', ()=>{
|
|
245
|
+
clearTimeout(pingTimeout);
|
|
246
|
+
clearTimeout(pongTimeout);
|
|
247
|
+
schedulePing();
|
|
248
|
+
});
|
|
249
|
+
schedulePing();
|
|
250
|
+
}
|
|
251
|
+
run(async ()=>{
|
|
252
|
+
/* istanbul ignore next -- @preserve */ if (activeConnection?.ws !== ws) {
|
|
253
|
+
return;
|
|
167
254
|
}
|
|
255
|
+
handleKeepAlive();
|
|
256
|
+
await sendConnectionParams();
|
|
168
257
|
connectAttempt = 0;
|
|
169
258
|
self.state = 'open';
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
onOpen?.();
|
|
259
|
+
// Update connection state
|
|
260
|
+
connectionState.next({
|
|
261
|
+
type: 'state',
|
|
262
|
+
state: 'pending',
|
|
263
|
+
error: null
|
|
264
|
+
});
|
|
265
|
+
opts.onOpen?.();
|
|
181
266
|
dispatch();
|
|
182
267
|
}).catch((cause)=>{
|
|
183
268
|
ws.close(// "Status codes in the range 3000-3999 are reserved for use by libraries, frameworks, and applications"
|
|
184
|
-
3000
|
|
185
|
-
|
|
269
|
+
3000);
|
|
270
|
+
onCloseOrError(new TRPCWebSocketClosedError({
|
|
271
|
+
message: 'Initialization error',
|
|
272
|
+
cause
|
|
273
|
+
}));
|
|
186
274
|
});
|
|
187
|
-
}
|
|
188
|
-
ws.
|
|
189
|
-
if (globalThis.ErrorEvent && event instanceof ErrorEvent) {
|
|
190
|
-
onError(event.error);
|
|
191
|
-
} else {
|
|
192
|
-
onError(new Error('Unknown WebSocket error'));
|
|
193
|
-
}
|
|
194
|
-
});
|
|
275
|
+
};
|
|
276
|
+
ws.onerror = onError;
|
|
195
277
|
const handleIncomingRequest = (req)=>{
|
|
196
278
|
if (self !== activeConnection) {
|
|
197
279
|
return;
|
|
198
280
|
}
|
|
199
281
|
if (req.method === 'reconnect') {
|
|
200
|
-
reconnect(new
|
|
282
|
+
reconnect(new TRPCWebSocketClosedError({
|
|
283
|
+
message: 'Server requested reconnect'
|
|
284
|
+
}));
|
|
201
285
|
// notify subscribers
|
|
202
286
|
for (const pendingReq of Object.values(pendingRequests)){
|
|
203
287
|
if (pendingReq.type === 'subscription') {
|
|
@@ -214,10 +298,12 @@ function createWSClient(opts) {
|
|
|
214
298
|
}
|
|
215
299
|
req.callbacks.next?.(data);
|
|
216
300
|
if (self === activeConnection && req.connection !== activeConnection) {
|
|
217
|
-
// gracefully replace old connection with
|
|
218
|
-
const oldConn = req.connection;
|
|
301
|
+
// gracefully replace old connection with a new connection
|
|
219
302
|
req.connection = self;
|
|
220
|
-
|
|
303
|
+
}
|
|
304
|
+
if (req.connection !== self) {
|
|
305
|
+
// the connection has been replaced
|
|
306
|
+
return;
|
|
221
307
|
}
|
|
222
308
|
if ('result' in data && data.result.type === 'data' && typeof data.result.id === 'string') {
|
|
223
309
|
req.lastEventId = data.result.id;
|
|
@@ -226,7 +312,15 @@ function createWSClient(opts) {
|
|
|
226
312
|
req.callbacks.complete();
|
|
227
313
|
}
|
|
228
314
|
};
|
|
229
|
-
ws.
|
|
315
|
+
ws.onmessage = (event)=>{
|
|
316
|
+
const { data } = event;
|
|
317
|
+
if (data === 'PONG') {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
if (data === 'PING') {
|
|
321
|
+
ws.send('PONG');
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
230
324
|
startLazyDisconnectTimer();
|
|
231
325
|
const msg = JSON.parse(data);
|
|
232
326
|
if ('method' in msg) {
|
|
@@ -238,45 +332,26 @@ function createWSClient(opts) {
|
|
|
238
332
|
// when receiving a message, we close old connection that has no pending requests
|
|
239
333
|
closeIfNoPending(self);
|
|
240
334
|
}
|
|
241
|
-
}
|
|
242
|
-
ws.
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
// connection might have been replaced already
|
|
251
|
-
tryReconnect(self, new Error(reason));
|
|
252
|
-
}
|
|
253
|
-
for (const [key, req] of Object.entries(pendingRequests)){
|
|
254
|
-
if (req.connection !== self) {
|
|
255
|
-
continue;
|
|
256
|
-
}
|
|
257
|
-
if (self.state === 'closed') {
|
|
258
|
-
// If the connection was closed, we just call `complete()` on the request
|
|
259
|
-
delete pendingRequests[key];
|
|
260
|
-
req.callbacks.complete?.();
|
|
261
|
-
continue;
|
|
262
|
-
}
|
|
263
|
-
// The connection was closed either unexpectedly or because of a reconnect
|
|
264
|
-
if (req.type === 'subscription') {
|
|
265
|
-
// Subscriptions will resume after we've reconnected
|
|
266
|
-
resumeSubscriptionOnReconnect(req);
|
|
267
|
-
} else {
|
|
268
|
-
// Queries and mutations will error if interrupted
|
|
269
|
-
delete pendingRequests[key];
|
|
270
|
-
req.callbacks.error?.(TRPCClientError.from(new TRPCWebSocketClosedError('WebSocket closed prematurely')));
|
|
271
|
-
}
|
|
335
|
+
};
|
|
336
|
+
ws.onclose = (event)=>{
|
|
337
|
+
const wasOpen = self.state === 'open';
|
|
338
|
+
destroy();
|
|
339
|
+
onCloseOrError(new TRPCWebSocketClosedError({
|
|
340
|
+
cause: event
|
|
341
|
+
}));
|
|
342
|
+
if (wasOpen) {
|
|
343
|
+
opts.onClose?.(event);
|
|
272
344
|
}
|
|
273
|
-
}
|
|
274
|
-
}
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
Promise.resolve(resultOf(opts.url)).then(connect).catch(()=>{
|
|
348
|
+
onCloseOrError(new Error('Failed to resolve url'));
|
|
349
|
+
});
|
|
275
350
|
return self;
|
|
276
351
|
}
|
|
277
352
|
function request(opts) {
|
|
278
|
-
const { op
|
|
279
|
-
const { type
|
|
353
|
+
const { op, callbacks, lastEventId } = opts;
|
|
354
|
+
const { type, input, path, id } = op;
|
|
280
355
|
const envelope = {
|
|
281
356
|
id,
|
|
282
357
|
method: type,
|
|
@@ -319,10 +394,14 @@ function createWSClient(opts) {
|
|
|
319
394
|
req.callbacks.complete();
|
|
320
395
|
} else if (!req.connection) {
|
|
321
396
|
// close pending requests that aren't attached to a connection yet
|
|
322
|
-
req.callbacks.error(TRPCClientError.from(new
|
|
397
|
+
req.callbacks.error(TRPCClientError.from(new TRPCWebSocketClosedError({
|
|
398
|
+
message: 'Closed before connection was established'
|
|
399
|
+
})));
|
|
323
400
|
}
|
|
324
401
|
}
|
|
325
|
-
|
|
402
|
+
if (activeConnection) {
|
|
403
|
+
closeIfNoPending(activeConnection);
|
|
404
|
+
}
|
|
326
405
|
clearTimeout(connectTimer);
|
|
327
406
|
connectTimer = undefined;
|
|
328
407
|
activeConnection = null;
|
|
@@ -333,27 +412,43 @@ function createWSClient(opts) {
|
|
|
333
412
|
},
|
|
334
413
|
/**
|
|
335
414
|
* Reconnect to the WebSocket server
|
|
336
|
-
*/ reconnect
|
|
415
|
+
*/ reconnect,
|
|
416
|
+
connectionState: connectionState
|
|
337
417
|
};
|
|
338
418
|
}
|
|
339
419
|
class TRPCWebSocketClosedError extends Error {
|
|
340
|
-
constructor(
|
|
341
|
-
super(message
|
|
420
|
+
constructor(opts){
|
|
421
|
+
super(opts?.message ?? 'WebSocket closed', // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
422
|
+
// @ts-ignore https://github.com/tc39/proposal-error-cause
|
|
423
|
+
{
|
|
424
|
+
cause: opts?.cause
|
|
425
|
+
});
|
|
342
426
|
this.name = 'TRPCWebSocketClosedError';
|
|
343
427
|
Object.setPrototypeOf(this, TRPCWebSocketClosedError.prototype);
|
|
344
428
|
}
|
|
345
429
|
}
|
|
346
430
|
/**
|
|
347
|
-
* @
|
|
431
|
+
* @see https://trpc.io/docs/v11/client/links/wsLink
|
|
432
|
+
* @deprecated
|
|
433
|
+
* 🙋♂️ **Contributors needed** to continue supporting WebSockets!
|
|
434
|
+
* See https://github.com/trpc/trpc/issues/6109
|
|
348
435
|
*/ function wsLink(opts) {
|
|
349
436
|
const transformer = getTransformer(opts.transformer);
|
|
350
437
|
return ()=>{
|
|
351
|
-
const { client
|
|
352
|
-
return ({ op
|
|
438
|
+
const { client } = opts;
|
|
439
|
+
return ({ op })=>{
|
|
353
440
|
return observable((observer)=>{
|
|
354
|
-
const { type
|
|
441
|
+
const { type, path, id, context } = op;
|
|
355
442
|
const input = transformer.input.serialize(op.input);
|
|
356
|
-
const
|
|
443
|
+
const connState = type === 'subscription' ? client.connectionState.subscribe({
|
|
444
|
+
next (result) {
|
|
445
|
+
observer.next({
|
|
446
|
+
result,
|
|
447
|
+
context
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
}) : null;
|
|
451
|
+
const unsubscribeRequest = client.request({
|
|
357
452
|
op: {
|
|
358
453
|
type,
|
|
359
454
|
path,
|
|
@@ -364,58 +459,24 @@ class TRPCWebSocketClosedError extends Error {
|
|
|
364
459
|
},
|
|
365
460
|
callbacks: {
|
|
366
461
|
error (err) {
|
|
367
|
-
observer.next({
|
|
368
|
-
result: {
|
|
369
|
-
type: 'state',
|
|
370
|
-
state: 'error',
|
|
371
|
-
data: err
|
|
372
|
-
},
|
|
373
|
-
context: context
|
|
374
|
-
});
|
|
375
462
|
observer.error(err);
|
|
376
|
-
|
|
463
|
+
unsubscribeRequest();
|
|
377
464
|
},
|
|
378
465
|
complete () {
|
|
379
466
|
observer.complete();
|
|
380
|
-
observer.next({
|
|
381
|
-
result: {
|
|
382
|
-
type: 'state',
|
|
383
|
-
state: 'idle'
|
|
384
|
-
},
|
|
385
|
-
context: context
|
|
386
|
-
});
|
|
387
467
|
},
|
|
388
|
-
next (
|
|
389
|
-
|
|
390
|
-
message.result;
|
|
391
|
-
observer.next({
|
|
392
|
-
result: message.result,
|
|
393
|
-
context: context
|
|
394
|
-
});
|
|
395
|
-
return;
|
|
396
|
-
}
|
|
397
|
-
if (!('id' in message)) return;
|
|
398
|
-
const transformed = transformResult(message, transformer.output);
|
|
468
|
+
next (event) {
|
|
469
|
+
const transformed = transformResult(event, transformer.output);
|
|
399
470
|
if (!transformed.ok) {
|
|
400
|
-
|
|
401
|
-
observer.next({
|
|
402
|
-
result: {
|
|
403
|
-
type: 'state',
|
|
404
|
-
state: 'error',
|
|
405
|
-
data: error
|
|
406
|
-
},
|
|
407
|
-
context: context
|
|
408
|
-
});
|
|
409
|
-
observer.error(TRPCClientError.from(error));
|
|
471
|
+
observer.error(TRPCClientError.from(transformed.error));
|
|
410
472
|
return;
|
|
411
473
|
}
|
|
412
474
|
observer.next({
|
|
413
|
-
result: transformed.result
|
|
414
|
-
context: context
|
|
475
|
+
result: transformed.result
|
|
415
476
|
});
|
|
416
477
|
if (op.type !== 'subscription') {
|
|
417
478
|
// if it isn't a subscription we don't care about next response
|
|
418
|
-
|
|
479
|
+
unsubscribeRequest();
|
|
419
480
|
observer.complete();
|
|
420
481
|
}
|
|
421
482
|
}
|
|
@@ -423,14 +484,8 @@ class TRPCWebSocketClosedError extends Error {
|
|
|
423
484
|
lastEventId: undefined
|
|
424
485
|
});
|
|
425
486
|
return ()=>{
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
result: {
|
|
429
|
-
type: 'state',
|
|
430
|
-
state: 'idle'
|
|
431
|
-
},
|
|
432
|
-
context: context
|
|
433
|
-
});
|
|
487
|
+
unsubscribeRequest();
|
|
488
|
+
connState?.unsubscribe();
|
|
434
489
|
};
|
|
435
490
|
});
|
|
436
491
|
};
|
package/dist/links.d.ts
CHANGED
package/dist/links.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAE9B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,8BAA8B,CAAC"}
|
|
1
|
+
{"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAE9B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,mBAAmB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unstable-internals.d.ts","sourceRoot":"","sources":["../src/unstable-internals.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"unstable-internals.d.ts","sourceRoot":"","sources":["../src/unstable-internals.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,iCAAiC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trpc/client",
|
|
3
|
-
"version": "11.0.0-alpha-tmp-
|
|
3
|
+
"version": "11.0.0-alpha-tmp-12-06-react.665+f3677f632",
|
|
4
4
|
"description": "The tRPC client library",
|
|
5
5
|
"author": "KATT",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"build": "rollup --config rollup.config.ts --configPlugin rollup-plugin-swc3",
|
|
26
26
|
"dev": "pnpm build --watch",
|
|
27
27
|
"codegen-entrypoints": "tsx entrypoints.script.ts",
|
|
28
|
-
"lint": "eslint --cache
|
|
28
|
+
"lint": "eslint --cache src",
|
|
29
29
|
"ts-watch": "tsc --watch"
|
|
30
30
|
},
|
|
31
31
|
"exports": {
|
|
@@ -73,22 +73,25 @@
|
|
|
73
73
|
"package.json",
|
|
74
74
|
"links",
|
|
75
75
|
"unstable-internals",
|
|
76
|
-
"!**/*.test.*"
|
|
76
|
+
"!**/*.test.*",
|
|
77
|
+
"!**/__tests__"
|
|
77
78
|
],
|
|
78
79
|
"peerDependencies": {
|
|
79
|
-
"@trpc/server": "11.0.0-alpha-tmp-
|
|
80
|
+
"@trpc/server": "11.0.0-alpha-tmp-12-06-react.665+f3677f632",
|
|
81
|
+
"typescript": ">=5.6.2"
|
|
80
82
|
},
|
|
81
83
|
"devDependencies": {
|
|
82
|
-
"@trpc/server": "11.0.0-alpha-tmp-
|
|
84
|
+
"@trpc/server": "11.0.0-alpha-tmp-12-06-react.665+f3677f632",
|
|
83
85
|
"@types/isomorphic-fetch": "^0.0.39",
|
|
84
|
-
"@types/node": "^
|
|
85
|
-
"eslint": "^
|
|
86
|
+
"@types/node": "^22.9.0",
|
|
87
|
+
"eslint": "^9.13.0",
|
|
86
88
|
"isomorphic-fetch": "^3.0.0",
|
|
87
89
|
"node-fetch": "^3.3.0",
|
|
88
|
-
"rollup": "^4.
|
|
89
|
-
"tslib": "^2.
|
|
90
|
+
"rollup": "^4.24.4",
|
|
91
|
+
"tslib": "^2.8.1",
|
|
90
92
|
"tsx": "^4.0.0",
|
|
91
|
-
"
|
|
93
|
+
"typescript": "^5.7.0",
|
|
94
|
+
"undici": "^7.0.0"
|
|
92
95
|
},
|
|
93
96
|
"publishConfig": {
|
|
94
97
|
"access": "public"
|
|
@@ -96,5 +99,5 @@
|
|
|
96
99
|
"funding": [
|
|
97
100
|
"https://trpc.io/sponsor"
|
|
98
101
|
],
|
|
99
|
-
"gitHead": "
|
|
102
|
+
"gitHead": "f3677f6326d62400c29d1c358db9f3a68a0dd27d"
|
|
100
103
|
}
|
package/src/TRPCClientError.ts
CHANGED
|
@@ -90,7 +90,7 @@ export class TRPCClientError<TRouterOrProcedure extends InferrableClientTypes>
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
public static from<TRouterOrProcedure extends InferrableClientTypes>(
|
|
93
|
-
_cause: Error | TRPCErrorResponse<any
|
|
93
|
+
_cause: Error | TRPCErrorResponse<any> | object,
|
|
94
94
|
opts: { meta?: Record<string, unknown> } = {},
|
|
95
95
|
): TRPCClientError<TRouterOrProcedure> {
|
|
96
96
|
const cause = _cause as unknown;
|