@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.
Files changed (97) hide show
  1. package/dist/TRPCClientError.d.ts +1 -1
  2. package/dist/TRPCClientError.d.ts.map +1 -1
  3. package/dist/TRPCClientError.js +19 -1
  4. package/dist/TRPCClientError.mjs +19 -1
  5. package/dist/bundle-analysis.json +119 -93
  6. package/dist/createTRPCClient.d.ts +3 -2
  7. package/dist/createTRPCClient.d.ts.map +1 -1
  8. package/dist/createTRPCClient.js +1 -1
  9. package/dist/createTRPCClient.mjs +1 -1
  10. package/dist/index.js +6 -6
  11. package/dist/index.mjs +2 -2
  12. package/dist/internals/TRPCUntypedClient.d.ts +5 -4
  13. package/dist/internals/TRPCUntypedClient.d.ts.map +1 -1
  14. package/dist/internals/TRPCUntypedClient.js +42 -12
  15. package/dist/internals/TRPCUntypedClient.mjs +42 -12
  16. package/dist/internals/inputWithTrackedEventId.d.ts +2 -0
  17. package/dist/internals/inputWithTrackedEventId.d.ts.map +1 -0
  18. package/dist/internals/inputWithTrackedEventId.js +16 -0
  19. package/dist/internals/inputWithTrackedEventId.mjs +14 -0
  20. package/dist/internals/signals.d.ts +15 -0
  21. package/dist/internals/signals.d.ts.map +1 -0
  22. package/dist/internals/signals.js +47 -0
  23. package/dist/internals/signals.mjs +44 -0
  24. package/dist/internals/transformer.d.ts +2 -2
  25. package/dist/internals/types.d.ts +1 -1
  26. package/dist/internals/types.d.ts.map +1 -1
  27. package/dist/links/HTTPBatchLinkOptions.d.ts +1 -1
  28. package/dist/links/httpBatchLink.d.ts.map +1 -1
  29. package/dist/links/httpBatchLink.js +4 -3
  30. package/dist/links/httpBatchLink.mjs +5 -4
  31. package/dist/links/httpBatchStreamLink.d.ts.map +1 -1
  32. package/dist/links/httpBatchStreamLink.js +6 -4
  33. package/dist/links/httpBatchStreamLink.mjs +7 -5
  34. package/dist/links/httpLink.d.ts +2 -2
  35. package/dist/links/httpLink.js +3 -3
  36. package/dist/links/httpLink.mjs +3 -3
  37. package/dist/links/httpSubscriptionLink.d.ts +11 -6
  38. package/dist/links/httpSubscriptionLink.d.ts.map +1 -1
  39. package/dist/links/httpSubscriptionLink.js +130 -98
  40. package/dist/links/httpSubscriptionLink.mjs +132 -100
  41. package/dist/links/internals/contentTypes.d.ts +2 -2
  42. package/dist/links/internals/contentTypes.d.ts.map +1 -1
  43. package/dist/links/internals/httpUtils.d.ts +1 -8
  44. package/dist/links/internals/httpUtils.d.ts.map +1 -1
  45. package/dist/links/internals/httpUtils.js +1 -30
  46. package/dist/links/internals/httpUtils.mjs +2 -30
  47. package/dist/links/internals/subscriptions.d.ts +20 -0
  48. package/dist/links/internals/subscriptions.d.ts.map +1 -0
  49. package/dist/links/internals/urlWithConnectionParams.d.ts +2 -1
  50. package/dist/links/internals/urlWithConnectionParams.d.ts.map +1 -1
  51. package/dist/links/internals/urlWithConnectionParams.js +3 -2
  52. package/dist/links/internals/urlWithConnectionParams.mjs +3 -2
  53. package/dist/links/loggerLink.d.ts +5 -5
  54. package/dist/links/loggerLink.d.ts.map +1 -1
  55. package/dist/links/loggerLink.js +25 -21
  56. package/dist/links/loggerLink.mjs +25 -21
  57. package/dist/links/retryLink.d.ts +29 -0
  58. package/dist/links/retryLink.d.ts.map +1 -0
  59. package/dist/links/retryLink.js +65 -0
  60. package/dist/links/retryLink.mjs +63 -0
  61. package/dist/links/types.d.ts +4 -23
  62. package/dist/links/types.d.ts.map +1 -1
  63. package/dist/links/wsLink.d.ts +49 -5
  64. package/dist/links/wsLink.d.ts.map +1 -1
  65. package/dist/links/wsLink.js +210 -155
  66. package/dist/links/wsLink.mjs +211 -156
  67. package/dist/links.d.ts +1 -0
  68. package/dist/links.d.ts.map +1 -1
  69. package/dist/unstable-internals.d.ts +1 -0
  70. package/dist/unstable-internals.d.ts.map +1 -1
  71. package/package.json +14 -11
  72. package/src/TRPCClientError.ts +1 -1
  73. package/src/createTRPCClient.ts +28 -23
  74. package/src/internals/TRPCUntypedClient.ts +26 -15
  75. package/src/internals/inputWithTrackedEventId.ts +15 -0
  76. package/src/internals/signals.ts +54 -0
  77. package/src/internals/transformer.ts +2 -2
  78. package/src/internals/types.ts +1 -1
  79. package/src/links/HTTPBatchLinkOptions.ts +1 -1
  80. package/src/links/httpBatchLink.ts +3 -3
  81. package/src/links/httpBatchStreamLink.ts +7 -4
  82. package/src/links/httpLink.ts +2 -2
  83. package/src/links/httpSubscriptionLink.ts +172 -123
  84. package/src/links/internals/httpUtils.ts +1 -41
  85. package/src/links/internals/subscriptions.ts +26 -0
  86. package/src/links/internals/urlWithConnectionParams.ts +8 -2
  87. package/src/links/loggerLink.ts +21 -9
  88. package/src/links/retryLink.ts +101 -0
  89. package/src/links/types.ts +8 -46
  90. package/src/links/wsLink.ts +276 -173
  91. package/src/links.ts +1 -1
  92. package/src/unstable-internals.ts +1 -0
  93. package/dist/links/internals/retryLink.d.ts +0 -9
  94. package/dist/links/internals/retryLink.d.ts.map +0 -1
  95. package/dist/links/types.js +0 -7
  96. package/dist/links/types.mjs +0 -5
  97. package/src/links/internals/retryLink.ts +0 -53
@@ -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
- function createWSClient(opts) {
15
- const { WebSocket: WebSocketImpl = WebSocket , retryDelayMs: retryDelayFn = exponentialBackoff , onOpen , onClose , } = opts;
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(null);
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
- activeConnection = createConnection(null);
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(conn, cause) {
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 are pending requests and we're in lazy mode
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(cause);
83
- oldConnection && closeIfNoPending(oldConnection);
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(reconnect, ms, cause);
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(activeConnection)) {
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(cause) {
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
- for (const req of Object.values(pendingRequests)){
128
- if (req.type === 'subscription') {
129
- req.callbacks.next?.({
130
- result: {
131
- type: 'state',
132
- state: 'connecting',
133
- data: cause ?? null
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
- clearTimeout(lazyDisconnectTimer);
139
- const onError = (cause)=>{
174
+ const onCloseOrError = (cause)=>{
175
+ clearTimeout(pingTimeout);
176
+ clearTimeout(pongTimeout);
140
177
  self.state = 'closed';
141
- if (self === activeConnection) {
142
- tryReconnect(self, cause);
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
- run(async ()=>{
146
- let url = await resultOf(opts.url);
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.addEventListener('open', ()=>{
157
- run(async ()=>{
158
- /* istanbul ignore next -- @preserve */ if (activeConnection?.ws !== ws) {
213
+ ws.onopen = ()=>{
214
+ async function sendConnectionParams() {
215
+ if (!opts.connectionParams) {
159
216
  return;
160
217
  }
161
- if (opts.connectionParams) {
162
- const connectMsg = {
163
- method: 'connectionParams',
164
- data: await resultOf(opts.connectionParams)
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
- ws.send(JSON.stringify(connectMsg));
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
- for (const req of Object.values(pendingRequests)){
171
- if (req.type === 'subscription') {
172
- req.callbacks.next?.({
173
- result: {
174
- type: 'state',
175
- state: 'pending'
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, cause);
185
- onError(cause);
269
+ 3000);
270
+ onCloseOrError(new TRPCWebSocketClosedError({
271
+ message: 'Initialization error',
272
+ cause
273
+ }));
186
274
  });
187
- });
188
- ws.addEventListener('error', (event)=>{
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 Error('Server requested reconnect'));
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 this
218
- const oldConn = req.connection;
301
+ // gracefully replace old connection with a new connection
219
302
  req.connection = self;
220
- oldConn && closeIfNoPending(oldConn);
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.addEventListener('message', ({ data })=>{
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.addEventListener('close', ({ code , reason })=>{
243
- if (self.state === 'open') {
244
- onClose?.({
245
- code
246
- });
247
- }
248
- self.state = 'closed';
249
- if (activeConnection === self) {
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
- }).catch(onError);
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 , callbacks , lastEventId } = opts;
279
- const { type , input , path , id } = op;
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 Error('Closed before connection was established')));
397
+ req.callbacks.error(TRPCClientError.from(new TRPCWebSocketClosedError({
398
+ message: 'Closed before connection was established'
399
+ })));
323
400
  }
324
401
  }
325
- activeConnection && closeIfNoPending(activeConnection);
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(message){
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
- * @link https://trpc.io/docs/v11/client/links/wsLink
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 } = opts;
352
- return ({ op })=>{
438
+ const { client } = opts;
439
+ return ({ op })=>{
353
440
  return observable((observer)=>{
354
- const { type , path , id , context } = op;
441
+ const { type, path, id, context } = op;
355
442
  const input = transformer.input.serialize(op.input);
356
- const unsub = client.request({
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
- unsub();
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 (message) {
389
- if ('result' in message && isConnectionStateMessage(message.result)) {
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
- const error = TRPCClientError.from(transformed.error);
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
- unsub();
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
- unsub();
427
- observer.next({
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
@@ -7,4 +7,5 @@ export * from './links/loggerLink';
7
7
  export * from './links/splitLink';
8
8
  export * from './links/wsLink';
9
9
  export * from './links/httpSubscriptionLink';
10
+ export * from './links/retryLink';
10
11
  //# sourceMappingURL=links.d.ts.map
@@ -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,2 +1,3 @@
1
1
  export * from './internals/transformer';
2
+ export * from './links/internals/subscriptions';
2
3
  //# sourceMappingURL=unstable-internals.d.ts.map
@@ -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-subscription-connection-state.489+04c141d1b",
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 --ext \".js,.ts,.tsx\" --ignore-path ../../.gitignore src",
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-subscription-connection-state.489+04c141d1b"
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-subscription-connection-state.489+04c141d1b",
84
+ "@trpc/server": "11.0.0-alpha-tmp-12-06-react.665+f3677f632",
83
85
  "@types/isomorphic-fetch": "^0.0.39",
84
- "@types/node": "^20.10.0",
85
- "eslint": "^8.57.0",
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.9.5",
89
- "tslib": "^2.5.0",
90
+ "rollup": "^4.24.4",
91
+ "tslib": "^2.8.1",
90
92
  "tsx": "^4.0.0",
91
- "undici": "^6.0.1"
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": "04c141d1b4bb50631826aa956a874ba1d363f492"
102
+ "gitHead": "f3677f6326d62400c29d1c358db9f3a68a0dd27d"
100
103
  }
@@ -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;