@trpc/client 11.0.0-alpha-tmp-subscription-connection-state.488 → 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 +124 -98
  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 -94
  40. package/dist/links/httpSubscriptionLink.mjs +132 -96
  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 +54 -6
  64. package/dist/links/wsLink.d.ts.map +1 -1
  65. package/dist/links/wsLink.js +244 -175
  66. package/dist/links/wsLink.mjs +245 -176
  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 -115
  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 +308 -181
  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
@@ -98,7 +123,11 @@ function createWSClient(opts) {
98
123
  if (outgoing.some((r)=>r.id === req.op.id)) {
99
124
  return;
100
125
  }
101
- request(req.op, req.callbacks);
126
+ request({
127
+ op: req.op,
128
+ callbacks: req.callbacks,
129
+ lastEventId: req.lastEventId
130
+ });
102
131
  }
103
132
  const startLazyDisconnectTimer = ()=>{
104
133
  if (!lazyOpts.enabled) {
@@ -109,37 +138,69 @@ function createWSClient(opts) {
109
138
  if (!activeConnection) {
110
139
  return;
111
140
  }
112
- if (!hasPendingRequests(activeConnection)) {
141
+ if (!hasPendingRequests()) {
113
142
  activeConnection.ws?.close();
114
143
  activeConnection = null;
144
+ connectionState.next({
145
+ type: 'state',
146
+ state: 'idle',
147
+ error: null
148
+ });
115
149
  }
116
150
  }, lazyOpts.closeMs);
117
151
  };
118
- function createConnection(cause) {
152
+ function createConnection() {
153
+ let pingTimeout = undefined;
154
+ let pongTimeout = undefined;
119
155
  const self = {
120
156
  id: ++connectionIndex,
121
157
  state: 'connecting'
122
158
  };
123
- for (const req of Object.values(pendingRequests)){
124
- if (req.type === 'subscription') {
125
- req.callbacks.next?.({
126
- result: {
127
- type: 'state',
128
- state: 'connecting',
129
- data: cause ?? null
130
- }
131
- });
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();
132
171
  }
172
+ self.state = 'closed';
133
173
  }
134
- clearTimeout(lazyDisconnectTimer);
135
- const onError = (cause)=>{
174
+ const onCloseOrError = (cause)=>{
175
+ clearTimeout(pingTimeout);
176
+ clearTimeout(pongTimeout);
136
177
  self.state = 'closed';
137
- if (self === activeConnection) {
138
- 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
+ }
139
195
  }
140
196
  };
141
- run(async ()=>{
142
- 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) {
143
204
  if (opts.connectionParams) {
144
205
  // append `?connectionParams=1` when connection params are used
145
206
  const prefix = url.includes('?') ? '&' : '?';
@@ -149,51 +210,78 @@ function createWSClient(opts) {
149
210
  self.ws = ws;
150
211
  clearTimeout(connectTimer);
151
212
  connectTimer = undefined;
152
- ws.addEventListener('open', ()=>{
153
- run(async ()=>{
154
- /* istanbul ignore next -- @preserve */ if (activeConnection?.ws !== ws) {
213
+ ws.onopen = ()=>{
214
+ async function sendConnectionParams() {
215
+ if (!opts.connectionParams) {
155
216
  return;
156
217
  }
157
- if (opts.connectionParams) {
158
- const connectMsg = {
159
- method: 'connectionParams',
160
- 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);
161
238
  };
162
- 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;
163
254
  }
255
+ handleKeepAlive();
256
+ await sendConnectionParams();
164
257
  connectAttempt = 0;
165
258
  self.state = 'open';
166
- for (const req of Object.values(pendingRequests)){
167
- if (req.type === 'subscription') {
168
- req.callbacks.next?.({
169
- result: {
170
- type: 'state',
171
- state: 'pending'
172
- }
173
- });
174
- }
175
- }
176
- onOpen?.();
259
+ // Update connection state
260
+ connectionState.next({
261
+ type: 'state',
262
+ state: 'pending',
263
+ error: null
264
+ });
265
+ opts.onOpen?.();
177
266
  dispatch();
178
267
  }).catch((cause)=>{
179
268
  ws.close(// "Status codes in the range 3000-3999 are reserved for use by libraries, frameworks, and applications"
180
- 3000, cause);
181
- onError(cause);
269
+ 3000);
270
+ onCloseOrError(new TRPCWebSocketClosedError({
271
+ message: 'Initialization error',
272
+ cause
273
+ }));
182
274
  });
183
- });
184
- ws.addEventListener('error', (event)=>{
185
- if (globalThis.ErrorEvent && event instanceof ErrorEvent) {
186
- onError(event.error);
187
- } else {
188
- onError(new Error('Unknown WebSocket error'));
189
- }
190
- });
275
+ };
276
+ ws.onerror = onError;
191
277
  const handleIncomingRequest = (req)=>{
192
278
  if (self !== activeConnection) {
193
279
  return;
194
280
  }
195
281
  if (req.method === 'reconnect') {
196
- reconnect(new Error('Server requested reconnect'));
282
+ reconnect(new TRPCWebSocketClosedError({
283
+ message: 'Server requested reconnect'
284
+ }));
197
285
  // notify subscribers
198
286
  for (const pendingReq of Object.values(pendingRequests)){
199
287
  if (pendingReq.type === 'subscription') {
@@ -210,16 +298,29 @@ function createWSClient(opts) {
210
298
  }
211
299
  req.callbacks.next?.(data);
212
300
  if (self === activeConnection && req.connection !== activeConnection) {
213
- // gracefully replace old connection with this
214
- const oldConn = req.connection;
301
+ // gracefully replace old connection with a new connection
215
302
  req.connection = self;
216
- oldConn && closeIfNoPending(oldConn);
303
+ }
304
+ if (req.connection !== self) {
305
+ // the connection has been replaced
306
+ return;
307
+ }
308
+ if ('result' in data && data.result.type === 'data' && typeof data.result.id === 'string') {
309
+ req.lastEventId = data.result.id;
217
310
  }
218
311
  if ('result' in data && data.result.type === 'stopped' && activeConnection === self) {
219
312
  req.callbacks.complete();
220
313
  }
221
314
  };
222
- 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
+ }
223
324
  startLazyDisconnectTimer();
224
325
  const msg = JSON.parse(data);
225
326
  if ('method' in msg) {
@@ -231,57 +332,41 @@ function createWSClient(opts) {
231
332
  // when receiving a message, we close old connection that has no pending requests
232
333
  closeIfNoPending(self);
233
334
  }
234
- });
235
- ws.addEventListener('close', ({ code , reason })=>{
236
- if (self.state === 'open') {
237
- onClose?.({
238
- code
239
- });
240
- }
241
- self.state = 'closed';
242
- if (activeConnection === self) {
243
- // connection might have been replaced already
244
- tryReconnect(self, new Error(reason));
245
- }
246
- for (const [key, req] of Object.entries(pendingRequests)){
247
- if (req.connection !== self) {
248
- continue;
249
- }
250
- if (self.state === 'closed') {
251
- // If the connection was closed, we just call `complete()` on the request
252
- delete pendingRequests[key];
253
- req.callbacks.complete?.();
254
- continue;
255
- }
256
- // The connection was closed either unexpectedly or because of a reconnect
257
- if (req.type === 'subscription') {
258
- // Subscriptions will resume after we've reconnected
259
- resumeSubscriptionOnReconnect(req);
260
- } else {
261
- // Queries and mutations will error if interrupted
262
- delete pendingRequests[key];
263
- req.callbacks.error?.(TRPCClientError.from(new TRPCWebSocketClosedError('WebSocket closed prematurely')));
264
- }
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);
265
344
  }
266
- });
267
- }).catch(onError);
345
+ };
346
+ }
347
+ Promise.resolve(resultOf(opts.url)).then(connect).catch(()=>{
348
+ onCloseOrError(new Error('Failed to resolve url'));
349
+ });
268
350
  return self;
269
351
  }
270
- function request(op, callbacks) {
271
- const { type , input , path , id } = op;
352
+ function request(opts) {
353
+ const { op, callbacks, lastEventId } = opts;
354
+ const { type, input, path, id } = op;
272
355
  const envelope = {
273
356
  id,
274
357
  method: type,
275
358
  params: {
276
359
  input,
277
- path
360
+ path,
361
+ lastEventId
278
362
  }
279
363
  };
280
364
  pendingRequests[id] = {
281
365
  connection: null,
282
366
  type,
283
367
  callbacks,
284
- op
368
+ op,
369
+ lastEventId
285
370
  };
286
371
  // enqueue message
287
372
  outgoing.push(envelope);
@@ -309,10 +394,14 @@ function createWSClient(opts) {
309
394
  req.callbacks.complete();
310
395
  } else if (!req.connection) {
311
396
  // close pending requests that aren't attached to a connection yet
312
- 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
+ })));
313
400
  }
314
401
  }
315
- activeConnection && closeIfNoPending(activeConnection);
402
+ if (activeConnection) {
403
+ closeIfNoPending(activeConnection);
404
+ }
316
405
  clearTimeout(connectTimer);
317
406
  connectTimer = undefined;
318
407
  activeConnection = null;
@@ -323,100 +412,80 @@ function createWSClient(opts) {
323
412
  },
324
413
  /**
325
414
  * Reconnect to the WebSocket server
326
- */ reconnect
415
+ */ reconnect,
416
+ connectionState: connectionState
327
417
  };
328
418
  }
329
419
  class TRPCWebSocketClosedError extends Error {
330
- constructor(message){
331
- 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
+ });
332
426
  this.name = 'TRPCWebSocketClosedError';
333
427
  Object.setPrototypeOf(this, TRPCWebSocketClosedError.prototype);
334
428
  }
335
429
  }
336
430
  /**
337
- * @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
338
435
  */ function wsLink(opts) {
339
436
  const transformer = getTransformer(opts.transformer);
340
437
  return ()=>{
341
- const { client } = opts;
342
- return ({ op })=>{
438
+ const { client } = opts;
439
+ return ({ op })=>{
343
440
  return observable((observer)=>{
344
- const { type , path , id , context } = op;
441
+ const { type, path, id, context } = op;
345
442
  const input = transformer.input.serialize(op.input);
346
- const unsub = client.request({
347
- type,
348
- path,
349
- input,
350
- id,
351
- context,
352
- signal: null
353
- }, {
354
- error (err) {
355
- observer.next({
356
- result: {
357
- type: 'state',
358
- state: 'error',
359
- data: err
360
- },
361
- context: context
362
- });
363
- observer.error(err);
364
- unsub();
365
- },
366
- complete () {
367
- observer.complete();
443
+ const connState = type === 'subscription' ? client.connectionState.subscribe({
444
+ next (result) {
368
445
  observer.next({
369
- result: {
370
- type: 'state',
371
- state: 'idle'
372
- },
373
- context: context
446
+ result,
447
+ context
374
448
  });
449
+ }
450
+ }) : null;
451
+ const unsubscribeRequest = client.request({
452
+ op: {
453
+ type,
454
+ path,
455
+ input,
456
+ id,
457
+ context,
458
+ signal: null
375
459
  },
376
- next (message) {
377
- if ('result' in message && isConnectionStateMessage(message.result)) {
378
- message.result;
379
- observer.next({
380
- result: message.result,
381
- context: context
382
- });
383
- return;
384
- }
385
- if (!('id' in message)) return;
386
- const transformed = transformResult(message, transformer.output);
387
- if (!transformed.ok) {
388
- const error = TRPCClientError.from(transformed.error);
460
+ callbacks: {
461
+ error (err) {
462
+ observer.error(err);
463
+ unsubscribeRequest();
464
+ },
465
+ complete () {
466
+ observer.complete();
467
+ },
468
+ next (event) {
469
+ const transformed = transformResult(event, transformer.output);
470
+ if (!transformed.ok) {
471
+ observer.error(TRPCClientError.from(transformed.error));
472
+ return;
473
+ }
389
474
  observer.next({
390
- result: {
391
- type: 'state',
392
- state: 'error',
393
- data: error
394
- },
395
- context: context
475
+ result: transformed.result
396
476
  });
397
- observer.error(TRPCClientError.from(error));
398
- return;
399
- }
400
- observer.next({
401
- result: transformed.result,
402
- context: context
403
- });
404
- if (op.type !== 'subscription') {
405
- // if it isn't a subscription we don't care about next response
406
- unsub();
407
- observer.complete();
477
+ if (op.type !== 'subscription') {
478
+ // if it isn't a subscription we don't care about next response
479
+ unsubscribeRequest();
480
+ observer.complete();
481
+ }
408
482
  }
409
- }
483
+ },
484
+ lastEventId: undefined
410
485
  });
411
486
  return ()=>{
412
- unsub();
413
- observer.next({
414
- result: {
415
- type: 'state',
416
- state: 'idle'
417
- },
418
- context: context
419
- });
487
+ unsubscribeRequest();
488
+ connState?.unsubscribe();
420
489
  };
421
490
  });
422
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.488+70f6f6f44",
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.488+70f6f6f44"
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.488+70f6f6f44",
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.56.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": "70f6f6f44439bcb258420096517570e8369b3d69"
102
+ "gitHead": "f3677f6326d62400c29d1c358db9f3a68a0dd27d"
100
103
  }