@trpc/client 10.27.3 → 10.28.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.
@@ -1 +1 @@
1
- {"version":3,"file":"wsLink.d.ts","sourceRoot":"","sources":["../../src/links/wsLink.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAiB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAc,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EAKL,mBAAmB,EACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE9C,aAAK,gBAAgB,CAAC,OAAO,SAAS,SAAS,EAAE,OAAO,IAAI,mBAAmB,CAC7E,OAAO,EACP,gBAAgB,CAAC,OAAO,CAAC,CAC1B,CAAC;AAEF,aAAK,kBAAkB,CAAC,OAAO,SAAS,SAAS,EAAE,OAAO,IAAI,QAAQ,CACpE,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,EAClC,eAAe,CAAC,OAAO,CAAC,CACzB,CAAC;AAEF,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,SAAS,CAAC;IAC7B,YAAY,CAAC,EAAE,OAAO,UAAU,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAC/C;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,sBAAsB;;kBAgNpC,SAAS,wDAA0B,aAAa;;EAoDtE;AACD,oBAAY,mBAAmB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAEpE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,mBAAmB,CAAC;CAC7B;AAiBD,wBAAgB,MAAM,CAAC,OAAO,SAAS,SAAS,EAC9C,IAAI,EAAE,oBAAoB,GACzB,QAAQ,CAAC,OAAO,CAAC,CA4DnB"}
1
+ {"version":3,"file":"wsLink.d.ts","sourceRoot":"","sources":["../../src/links/wsLink.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAiB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAc,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EAKL,mBAAmB,EACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE9C,aAAK,gBAAgB,CAAC,OAAO,SAAS,SAAS,EAAE,OAAO,IAAI,mBAAmB,CAC7E,OAAO,EACP,gBAAgB,CAAC,OAAO,CAAC,CAC1B,CAAC;AAEF,aAAK,kBAAkB,CAAC,OAAO,SAAS,SAAS,EAAE,OAAO,IAAI,QAAQ,CACpE,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,EAClC,eAAe,CAAC,OAAO,CAAC,CACzB,CAAC;AAEF,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,SAAS,CAAC;IAC7B,YAAY,CAAC,EAAE,OAAO,UAAU,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAC/C;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,sBAAsB;;kBAwNpC,SAAS,wDAA0B,aAAa;;EAqDtE;AACD,oBAAY,mBAAmB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAEpE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,mBAAmB,CAAC;CAC7B;AASD,wBAAgB,MAAM,CAAC,OAAO,SAAS,SAAS,EAC9C,IAAI,EAAE,oBAAoB,GACzB,QAAQ,CAAC,OAAO,CAAC,CA6CnB"}
@@ -67,6 +67,13 @@ function createWSClient(opts) {
67
67
  conn.close();
68
68
  }
69
69
  }
70
+ function closeActiveSubscriptions() {
71
+ Object.values(pendingRequests).forEach((req)=>{
72
+ if (req.type === 'subscription') {
73
+ req.callbacks.complete();
74
+ }
75
+ });
76
+ }
70
77
  function resumeSubscriptionOnReconnect(req) {
71
78
  if (outgoing.some((r)=>r.id === req.op.id)) {
72
79
  return;
@@ -205,6 +212,7 @@ function createWSClient(opts) {
205
212
  close: ()=>{
206
213
  state = 'closed';
207
214
  onClose?.();
215
+ closeActiveSubscriptions();
208
216
  closeIfNoPending(activeConnection);
209
217
  clearTimeout(connectTimer);
210
218
  connectTimer = null;
@@ -222,13 +230,6 @@ class TRPCWebSocketClosedError extends Error {
222
230
  Object.setPrototypeOf(this, TRPCWebSocketClosedError.prototype);
223
231
  }
224
232
  }
225
- class TRPCSubscriptionEndedError extends Error {
226
- constructor(message){
227
- super(message);
228
- this.name = 'TRPCSubscriptionEndedError';
229
- Object.setPrototypeOf(this, TRPCSubscriptionEndedError.prototype);
230
- }
231
- }
232
233
  function wsLink(opts) {
233
234
  return (runtime)=>{
234
235
  const { client } = opts;
@@ -236,7 +237,6 @@ function wsLink(opts) {
236
237
  return observable.observable((observer)=>{
237
238
  const { type , path , id , context } = op;
238
239
  const input = runtime.transformer.serialize(op.input);
239
- let isDone = false;
240
240
  const unsub = client.request({
241
241
  type,
242
242
  path,
@@ -245,17 +245,11 @@ function wsLink(opts) {
245
245
  context
246
246
  }, {
247
247
  error (err) {
248
- isDone = true;
249
248
  observer.error(err);
250
249
  unsub();
251
250
  },
252
251
  complete () {
253
- if (!isDone) {
254
- isDone = true;
255
- observer.error(transformResult.TRPCClientError.from(new TRPCSubscriptionEndedError('Operation ended prematurely')));
256
- } else {
257
- observer.complete();
258
- }
252
+ observer.complete();
259
253
  },
260
254
  next (message) {
261
255
  const transformed = transformResult.transformResult(message, runtime);
@@ -268,14 +262,12 @@ function wsLink(opts) {
268
262
  });
269
263
  if (op.type !== 'subscription') {
270
264
  // if it isn't a subscription we don't care about next response
271
- isDone = true;
272
265
  unsub();
273
266
  observer.complete();
274
267
  }
275
268
  }
276
269
  });
277
270
  return ()=>{
278
- isDone = true;
279
271
  unsub();
280
272
  };
281
273
  });
@@ -63,6 +63,13 @@ function createWSClient(opts) {
63
63
  conn.close();
64
64
  }
65
65
  }
66
+ function closeActiveSubscriptions() {
67
+ Object.values(pendingRequests).forEach((req)=>{
68
+ if (req.type === 'subscription') {
69
+ req.callbacks.complete();
70
+ }
71
+ });
72
+ }
66
73
  function resumeSubscriptionOnReconnect(req) {
67
74
  if (outgoing.some((r)=>r.id === req.op.id)) {
68
75
  return;
@@ -201,6 +208,7 @@ function createWSClient(opts) {
201
208
  close: ()=>{
202
209
  state = 'closed';
203
210
  onClose?.();
211
+ closeActiveSubscriptions();
204
212
  closeIfNoPending(activeConnection);
205
213
  clearTimeout(connectTimer);
206
214
  connectTimer = null;
@@ -218,13 +226,6 @@ class TRPCWebSocketClosedError extends Error {
218
226
  Object.setPrototypeOf(this, TRPCWebSocketClosedError.prototype);
219
227
  }
220
228
  }
221
- class TRPCSubscriptionEndedError extends Error {
222
- constructor(message){
223
- super(message);
224
- this.name = 'TRPCSubscriptionEndedError';
225
- Object.setPrototypeOf(this, TRPCSubscriptionEndedError.prototype);
226
- }
227
- }
228
229
  function wsLink(opts) {
229
230
  return (runtime)=>{
230
231
  const { client } = opts;
@@ -232,7 +233,6 @@ function wsLink(opts) {
232
233
  return observable((observer)=>{
233
234
  const { type , path , id , context } = op;
234
235
  const input = runtime.transformer.serialize(op.input);
235
- let isDone = false;
236
236
  const unsub = client.request({
237
237
  type,
238
238
  path,
@@ -241,17 +241,11 @@ function wsLink(opts) {
241
241
  context
242
242
  }, {
243
243
  error (err) {
244
- isDone = true;
245
244
  observer.error(err);
246
245
  unsub();
247
246
  },
248
247
  complete () {
249
- if (!isDone) {
250
- isDone = true;
251
- observer.error(TRPCClientError.from(new TRPCSubscriptionEndedError('Operation ended prematurely')));
252
- } else {
253
- observer.complete();
254
- }
248
+ observer.complete();
255
249
  },
256
250
  next (message) {
257
251
  const transformed = transformResult(message, runtime);
@@ -264,14 +258,12 @@ function wsLink(opts) {
264
258
  });
265
259
  if (op.type !== 'subscription') {
266
260
  // if it isn't a subscription we don't care about next response
267
- isDone = true;
268
261
  unsub();
269
262
  observer.complete();
270
263
  }
271
264
  }
272
265
  });
273
266
  return ()=>{
274
- isDone = true;
275
267
  unsub();
276
268
  };
277
269
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trpc/client",
3
- "version": "10.27.3",
3
+ "version": "10.28.0",
4
4
  "description": "The tRPC client library",
5
5
  "author": "KATT",
6
6
  "license": "MIT",
@@ -72,14 +72,15 @@
72
72
  "README.md",
73
73
  "package.json",
74
74
  "links",
75
- "shared"
75
+ "shared",
76
+ "!**/*.test.*"
76
77
  ],
77
78
  "peerDependencies": {
78
- "@trpc/server": "10.27.3"
79
+ "@trpc/server": "10.28.0"
79
80
  },
80
81
  "devDependencies": {
81
82
  "@testing-library/dom": "^9.0.0",
82
- "@trpc/server": "10.27.3",
83
+ "@trpc/server": "10.28.0",
83
84
  "@types/isomorphic-fetch": "^0.0.36",
84
85
  "@types/node": "^18.7.20",
85
86
  "eslint": "^8.40.0",
@@ -94,5 +95,8 @@
94
95
  "publishConfig": {
95
96
  "access": "public"
96
97
  },
97
- "gitHead": "a7bca8888003f0a2f3e8b966e44442bb576bfff2"
98
+ "funding": [
99
+ "https://trpc.io/sponsor"
100
+ ],
101
+ "gitHead": "7aadb24ce0bc20ae27f32bd80891ef6da5885e5e"
98
102
  }
@@ -120,6 +120,14 @@ export function createWSClient(opts: WebSocketClientOptions) {
120
120
  }
121
121
  }
122
122
 
123
+ function closeActiveSubscriptions() {
124
+ Object.values(pendingRequests).forEach((req) => {
125
+ if (req.type === 'subscription') {
126
+ req.callbacks.complete();
127
+ }
128
+ });
129
+ }
130
+
123
131
  function resumeSubscriptionOnReconnect(req: TRequest) {
124
132
  if (outgoing.some((r) => r.id === req.op.id)) {
125
133
  return;
@@ -281,6 +289,7 @@ export function createWSClient(opts: WebSocketClientOptions) {
281
289
  close: () => {
282
290
  state = 'closed';
283
291
  onClose?.();
292
+ closeActiveSubscriptions();
284
293
  closeIfNoPending(activeConnection);
285
294
  clearTimeout(connectTimer as any);
286
295
  connectTimer = null;
@@ -304,14 +313,6 @@ class TRPCWebSocketClosedError extends Error {
304
313
  }
305
314
  }
306
315
 
307
- class TRPCSubscriptionEndedError extends Error {
308
- constructor(message: string) {
309
- super(message);
310
- this.name = 'TRPCSubscriptionEndedError';
311
- Object.setPrototypeOf(this, TRPCSubscriptionEndedError.prototype);
312
- }
313
- }
314
-
315
316
  export function wsLink<TRouter extends AnyRouter>(
316
317
  opts: WebSocketLinkOptions,
317
318
  ): TRPCLink<TRouter> {
@@ -323,28 +324,15 @@ export function wsLink<TRouter extends AnyRouter>(
323
324
 
324
325
  const input = runtime.transformer.serialize(op.input);
325
326
 
326
- let isDone = false;
327
327
  const unsub = client.request(
328
328
  { type, path, input, id, context },
329
329
  {
330
330
  error(err) {
331
- isDone = true;
332
331
  observer.error(err as TRPCClientError<any>);
333
332
  unsub();
334
333
  },
335
334
  complete() {
336
- if (!isDone) {
337
- isDone = true;
338
- observer.error(
339
- TRPCClientError.from(
340
- new TRPCSubscriptionEndedError(
341
- 'Operation ended prematurely',
342
- ),
343
- ),
344
- );
345
- } else {
346
- observer.complete();
347
- }
335
+ observer.complete();
348
336
  },
349
337
  next(message) {
350
338
  const transformed = transformResult(message, runtime);
@@ -360,7 +348,6 @@ export function wsLink<TRouter extends AnyRouter>(
360
348
  if (op.type !== 'subscription') {
361
349
  // if it isn't a subscription we don't care about next response
362
350
 
363
- isDone = true;
364
351
  unsub();
365
352
  observer.complete();
366
353
  }
@@ -368,7 +355,6 @@ export function wsLink<TRouter extends AnyRouter>(
368
355
  },
369
356
  );
370
357
  return () => {
371
- isDone = true;
372
358
  unsub();
373
359
  };
374
360
  });
@@ -1,66 +0,0 @@
1
- import isomorphicFetch from 'isomorphic-fetch';
2
- import nodeFetch from 'node-fetch';
3
- import type { fetch as undiciFetch } from 'undici';
4
- import { createTRPCProxyClient } from '../createTRPCClientProxy';
5
- import { getFetch } from '../getFetch';
6
- import { httpBatchLink } from '../links/httpBatchLink';
7
- import { getAbortController } from './getAbortController';
8
- import {
9
- AbortControllerEsque,
10
- AbortControllerInstanceEsque,
11
- FetchEsque,
12
- ResponseEsque,
13
- } from './types';
14
-
15
- describe('AbortController', () => {
16
- test('AbortControllerEsque', () => {
17
- expectTypeOf(
18
- getAbortController,
19
- ).returns.toEqualTypeOf<AbortControllerEsque | null>();
20
-
21
- expectTypeOf(() => {
22
- const AbortController = getAbortController(undefined)!;
23
- return new AbortController();
24
- }).returns.toEqualTypeOf<AbortControllerInstanceEsque>();
25
- });
26
- });
27
-
28
- describe('fetch', () => {
29
- test('parameters', () => {
30
- createTRPCProxyClient({
31
- links: [
32
- httpBatchLink({
33
- url: 'YOUR_SERVER_URL',
34
- fetch(url, options) {
35
- return fetch(url, options);
36
- },
37
- }),
38
- ],
39
- });
40
- });
41
-
42
- test('FetchEsque', () => {
43
- expectTypeOf(getFetch).returns.toEqualTypeOf<FetchEsque>();
44
-
45
- expectTypeOf(() =>
46
- getFetch()('', {
47
- body: '',
48
- headers: Math.random() > 0.5 ? [['a', 'b']] : { a: 'b' },
49
- method: 'GET',
50
- signal: new AbortSignal(),
51
- }),
52
- ).returns.toEqualTypeOf<Promise<ResponseEsque>>();
53
-
54
- getFetch({} as unknown as typeof fetch);
55
- });
56
-
57
- test('NativeFetchEsque', () => {
58
- getFetch(isomorphicFetch);
59
- getFetch(nodeFetch as any);
60
-
61
- // Passing in undiciFetch directly in Node v18.7.0 gives:
62
- // ReferenceError: TextEncoder is not defined
63
- // 🤷
64
- getFetch({} as unknown as typeof undiciFetch);
65
- });
66
- });
@@ -1,128 +0,0 @@
1
- import { waitFor } from '@testing-library/dom';
2
- import { OperationLink } from '..';
3
- import { AnyRouter } from '../../../server/src';
4
- import { observable } from '../../../server/src/observable';
5
- import { dedupeLink } from './dedupeLink';
6
- import { createChain } from './internals/createChain';
7
-
8
- test('dedupeLink', async () => {
9
- const endingLinkTriggered = vi.fn();
10
- const timerTriggered = vi.fn();
11
- const links: OperationLink<AnyRouter, any, any>[] = [
12
- // "dedupe link"
13
- dedupeLink()(null as any),
14
- ({ op }) => {
15
- return observable((subscribe) => {
16
- endingLinkTriggered();
17
- const timer = setTimeout(() => {
18
- timerTriggered();
19
- subscribe.next({
20
- result: {
21
- type: 'data',
22
- data: {
23
- input: op.input,
24
- },
25
- },
26
- });
27
- subscribe.complete();
28
- }, 1);
29
- return () => clearTimeout(timer);
30
- });
31
- },
32
- ];
33
- {
34
- const call1 = createChain<AnyRouter, unknown, unknown>({
35
- links,
36
- op: {
37
- type: 'query',
38
- id: 1,
39
- input: 'world',
40
- path: 'hello',
41
- context: {},
42
- },
43
- });
44
-
45
- const call2 = createChain<AnyRouter, unknown, unknown>({
46
- links,
47
- op: {
48
- type: 'query',
49
- id: 1,
50
- input: 'world',
51
- path: 'hello',
52
- context: {},
53
- },
54
- });
55
- const next = vi.fn();
56
- call1.subscribe({ next });
57
- call2.subscribe({ next });
58
-
59
- expect(endingLinkTriggered).toHaveBeenCalledTimes(1);
60
- await waitFor(() => {
61
- expect(timerTriggered).toHaveBeenCalledTimes(1);
62
- });
63
-
64
- expect(next).toHaveBeenCalledTimes(2);
65
- }
66
- });
67
-
68
- test('dedupe - cancel one does not cancel the other', async () => {
69
- const endingLinkTriggered = vi.fn();
70
- const timerTriggered = vi.fn();
71
- const links: OperationLink<AnyRouter, any, any>[] = [
72
- // "dedupe link"
73
- dedupeLink()(null as any),
74
- ({ op }) => {
75
- return observable((subscribe) => {
76
- endingLinkTriggered();
77
- const timer = setTimeout(() => {
78
- timerTriggered();
79
- subscribe.next({
80
- result: {
81
- type: 'data',
82
- data: {
83
- input: op.input,
84
- },
85
- },
86
- });
87
- subscribe.complete();
88
- }, 1);
89
- return () => clearTimeout(timer);
90
- });
91
- },
92
- ];
93
-
94
- {
95
- const call1 = createChain<AnyRouter, unknown, unknown>({
96
- links,
97
- op: {
98
- type: 'query',
99
- id: 1,
100
- input: 'world',
101
- path: 'hello',
102
- context: {},
103
- },
104
- });
105
-
106
- const call2 = createChain<AnyRouter, unknown, unknown>({
107
- links,
108
- op: {
109
- type: 'query',
110
- id: 1,
111
- input: 'world',
112
- path: 'hello',
113
- context: {},
114
- },
115
- });
116
- const next = vi.fn();
117
- const call1$ = call1.subscribe({ next });
118
- call2.subscribe({ next });
119
- call1$.unsubscribe();
120
-
121
- expect(endingLinkTriggered).toHaveBeenCalledTimes(1);
122
- await waitFor(() => {
123
- expect(timerTriggered).toHaveBeenCalledTimes(1);
124
-
125
- expect(next).toHaveBeenCalledTimes(1);
126
- });
127
- }
128
- });
@@ -1,117 +0,0 @@
1
- import { observable } from '@trpc/server/observable';
2
- import { AnyRouter } from '@trpc/server/src';
3
- import { createChain } from './createChain';
4
-
5
- describe('chain', () => {
6
- test('trivial', () => {
7
- const result$ = createChain<AnyRouter, unknown, unknown>({
8
- links: [
9
- ({ next, op }) => {
10
- return observable((observer) => {
11
- const subscription = next(op).subscribe(observer);
12
- return () => {
13
- subscription.unsubscribe();
14
- };
15
- });
16
- },
17
- ({ op }) => {
18
- return observable((observer) => {
19
- observer.next({
20
- context: {},
21
- result: {
22
- type: 'data',
23
- data: {
24
- input: op.input,
25
- },
26
- },
27
- });
28
- observer.complete();
29
- });
30
- },
31
- ],
32
- op: {
33
- type: 'query',
34
- id: 1,
35
- input: 'world',
36
- path: 'hello',
37
- context: {},
38
- },
39
- });
40
-
41
- const next = vi.fn();
42
-
43
- result$.subscribe({ next });
44
- // console.log(next.mock.calls);
45
- expect(next).toHaveBeenCalledTimes(1);
46
- });
47
- test('multiple responses', () => {
48
- const result$ = createChain<AnyRouter, unknown, unknown>({
49
- links: [
50
- ({ next, op }) => {
51
- return observable((observer) => {
52
- observer.next({
53
- context: {},
54
- result: {
55
- type: 'data',
56
- data: 'from cache',
57
- },
58
- });
59
- const subscription = next(op).subscribe(observer);
60
- return () => {
61
- subscription.unsubscribe();
62
- };
63
- });
64
- },
65
- ({ op }) => {
66
- return observable((observer) => {
67
- observer.next({
68
- result: {
69
- type: 'data',
70
- data: {
71
- input: op.input,
72
- },
73
- },
74
- });
75
- observer.complete();
76
- });
77
- },
78
- ],
79
- op: {
80
- type: 'query',
81
- id: 1,
82
- input: 'world',
83
- path: 'hello',
84
- context: {},
85
- },
86
- });
87
-
88
- const next = vi.fn();
89
-
90
- result$.subscribe({ next });
91
-
92
- expect(next).toHaveBeenCalledTimes(2);
93
- expect(next.mock.calls[0]).toMatchInlineSnapshot(`
94
- Array [
95
- Object {
96
- "context": Object {},
97
- "result": Object {
98
- "data": "from cache",
99
- "type": "data",
100
- },
101
- },
102
- ]
103
- `);
104
- expect(next.mock.calls[1]).toMatchInlineSnapshot(`
105
- Array [
106
- Object {
107
- "result": Object {
108
- "data": Object {
109
- "input": "world",
110
- },
111
- "type": "data",
112
- },
113
- },
114
- ]
115
- `);
116
- });
117
- });
@@ -1,55 +0,0 @@
1
- import { observable } from '@trpc/server/observable';
2
- import { splitLink } from '../';
3
- import { OperationLink, TRPCLink } from '../';
4
- import { AnyRouter } from '../../../server/src';
5
- import { createChain } from '../links/internals/createChain';
6
-
7
- test('splitLink', () => {
8
- const wsLinkSpy = vi.fn();
9
- const wsLink: TRPCLink<any> = () => () =>
10
- observable(() => {
11
- wsLinkSpy();
12
- });
13
- const httpLinkSpy = vi.fn();
14
- const httpLink: TRPCLink<any> = () => () =>
15
- observable(() => {
16
- httpLinkSpy();
17
- });
18
- const links: OperationLink<AnyRouter, any, any>[] = [
19
- // "dedupe link"
20
- splitLink({
21
- condition(op) {
22
- return op.type === 'subscription';
23
- },
24
- true: wsLink,
25
- false: [httpLink],
26
- })(null as any),
27
- ];
28
-
29
- createChain({
30
- links,
31
- op: {
32
- type: 'query',
33
- input: null,
34
- path: '.',
35
- id: 0,
36
- context: {},
37
- },
38
- }).subscribe({});
39
- expect(httpLinkSpy).toHaveBeenCalledTimes(1);
40
- expect(wsLinkSpy).toHaveBeenCalledTimes(0);
41
- vi.resetAllMocks();
42
-
43
- createChain({
44
- links,
45
- op: {
46
- type: 'subscription',
47
- input: null,
48
- path: '.',
49
- id: 0,
50
- context: {},
51
- },
52
- }).subscribe({});
53
- expect(httpLinkSpy).toHaveBeenCalledTimes(0);
54
- expect(wsLinkSpy).toHaveBeenCalledTimes(1);
55
- });