@trpc/client 9.18.0 → 10.0.0-alpha.3

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 (208) hide show
  1. package/dist/TRPCClientError-17b117e1.mjs +81 -0
  2. package/dist/TRPCClientError-ec6bd2ca.js +94 -0
  3. package/dist/{declarations/src/TRPCClientError.d.ts → TRPCClientError.d.ts} +29 -33
  4. package/dist/TRPCClientError.d.ts.map +1 -0
  5. package/dist/createChain-389cc116.mjs +25 -0
  6. package/dist/createChain-864dbb30.js +27 -0
  7. package/dist/{declarations/src/createTRPCClient.d.ts → createTRPCClient.d.ts} +5 -6
  8. package/dist/createTRPCClient.d.ts.map +1 -0
  9. package/dist/{declarations/src/getFetch.d.ts → getFetch.d.ts} +1 -1
  10. package/dist/getFetch.d.ts.map +1 -0
  11. package/dist/httpUtils-1f9e4e3c.js +97 -0
  12. package/dist/httpUtils-c09d7b79.mjs +91 -0
  13. package/dist/{declarations/src/index.d.ts → index.d.ts} +4 -4
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +314 -0
  16. package/dist/index.mjs +299 -0
  17. package/dist/index.ts.js +1 -0
  18. package/dist/{declarations/src/internals → internals}/TRPCClient.d.ts +64 -61
  19. package/dist/internals/TRPCClient.d.ts.map +1 -0
  20. package/dist/{declarations/src/internals → internals}/dataLoader.d.ts +14 -16
  21. package/dist/internals/dataLoader.d.ts.map +1 -0
  22. package/dist/{declarations/src/internals → internals}/fetchHelpers.d.ts +2 -2
  23. package/dist/internals/fetchHelpers.d.ts.map +1 -0
  24. package/dist/{declarations/src/internals → internals}/retryDelay.d.ts +1 -1
  25. package/dist/internals/retryDelay.d.ts.map +1 -0
  26. package/dist/internals/transformRPCResponse.d.ts +15 -0
  27. package/dist/internals/transformRPCResponse.d.ts.map +1 -0
  28. package/dist/links/dedupeLink.d.ts +4 -0
  29. package/dist/links/dedupeLink.d.ts.map +1 -0
  30. package/dist/links/httpBatchLink.d.ts +5 -0
  31. package/dist/links/httpBatchLink.d.ts.map +1 -0
  32. package/dist/links/httpBatchLink.js +189 -0
  33. package/dist/links/httpBatchLink.mjs +185 -0
  34. package/dist/links/httpBatchLink.ts.js +1 -0
  35. package/dist/{declarations/src/links → links}/httpLink.d.ts +4 -3
  36. package/dist/links/httpLink.d.ts.map +1 -0
  37. package/dist/links/httpLink.js +44 -0
  38. package/dist/links/httpLink.mjs +40 -0
  39. package/dist/links/httpLink.ts.js +1 -0
  40. package/dist/links/httpUtils.d.ts +22 -0
  41. package/dist/links/httpUtils.d.ts.map +1 -0
  42. package/dist/links/internals/createChain.d.ts +8 -0
  43. package/dist/links/internals/createChain.d.ts.map +1 -0
  44. package/dist/links/internals/transformOperationResult.d.ts +16 -0
  45. package/dist/links/internals/transformOperationResult.d.ts.map +1 -0
  46. package/dist/{declarations/src/links → links}/loggerLink.d.ts +38 -37
  47. package/dist/links/loggerLink.d.ts.map +1 -0
  48. package/dist/links/loggerLink.js +108 -0
  49. package/dist/links/loggerLink.mjs +99 -0
  50. package/dist/links/loggerLink.ts.js +1 -0
  51. package/dist/links/retryLink.d.ts +6 -0
  52. package/dist/links/retryLink.d.ts.map +1 -0
  53. package/dist/links/splitLink.d.ts +14 -0
  54. package/dist/links/splitLink.d.ts.map +1 -0
  55. package/dist/links/splitLink.js +32 -0
  56. package/dist/links/splitLink.mjs +28 -0
  57. package/dist/links/splitLink.ts.js +1 -0
  58. package/dist/links/transformerLink.d.ts +4 -0
  59. package/dist/links/transformerLink.d.ts.map +1 -0
  60. package/dist/links/transformerLink.js +75 -0
  61. package/dist/links/transformerLink.mjs +67 -0
  62. package/dist/links/transformerLink.ts.js +1 -0
  63. package/dist/links/types.d.ts +40 -0
  64. package/dist/links/types.d.ts.map +1 -0
  65. package/dist/{declarations/src/links → links}/wsLink.d.ts +19 -26
  66. package/dist/links/wsLink.d.ts.map +1 -0
  67. package/dist/links/wsLink.js +384 -0
  68. package/dist/links/wsLink.mjs +370 -0
  69. package/dist/links/wsLink.ts.js +1 -0
  70. package/dist/observable-7e66cb56.mjs +102 -0
  71. package/dist/observable-85669100.js +104 -0
  72. package/dist/rx/index.d.ts +3 -0
  73. package/dist/rx/index.d.ts.map +1 -0
  74. package/dist/rx/index.js +9 -0
  75. package/dist/rx/index.mjs +1 -0
  76. package/dist/rx/index.ts.js +1 -0
  77. package/dist/rx/observable.d.ts +4 -0
  78. package/dist/rx/observable.d.ts.map +1 -0
  79. package/dist/rx/operators/index.d.ts +4 -0
  80. package/dist/rx/operators/index.d.ts.map +1 -0
  81. package/dist/rx/operators/index.js +38 -0
  82. package/dist/rx/operators/index.mjs +32 -0
  83. package/dist/rx/operators/index.ts.js +1 -0
  84. package/dist/rx/operators/map.d.ts +3 -0
  85. package/dist/rx/operators/map.d.ts.map +1 -0
  86. package/dist/rx/operators/share.d.ts +6 -0
  87. package/dist/rx/operators/share.d.ts.map +1 -0
  88. package/dist/rx/operators/tap.d.ts +3 -0
  89. package/dist/rx/operators/tap.d.ts.map +1 -0
  90. package/dist/rx/types.d.ts +29 -0
  91. package/dist/rx/types.d.ts.map +1 -0
  92. package/dist/rx/util/identity.d.ts +2 -0
  93. package/dist/rx/util/identity.d.ts.map +1 -0
  94. package/dist/rx/util/observableToPromise.d.ts +10 -0
  95. package/dist/rx/util/observableToPromise.d.ts.map +1 -0
  96. package/dist/rx/util/pipe.d.ts +4 -0
  97. package/dist/rx/util/pipe.d.ts.map +1 -0
  98. package/dist/share-4d79dc49.js +110 -0
  99. package/dist/share-671b63fa.mjs +108 -0
  100. package/dist/tap-538fa07f.mjs +30 -0
  101. package/dist/tap-799a2d33.js +32 -0
  102. package/links/httpBatchLink/index.d.ts +1 -0
  103. package/links/httpBatchLink/index.js +1 -0
  104. package/links/httpLink/index.d.ts +1 -0
  105. package/links/httpLink/index.js +1 -0
  106. package/links/loggerLink/index.d.ts +1 -0
  107. package/links/loggerLink/index.js +1 -0
  108. package/links/splitLink/index.d.ts +1 -0
  109. package/links/splitLink/index.js +1 -0
  110. package/links/transformerLink/index.d.ts +1 -0
  111. package/links/transformerLink/index.js +1 -0
  112. package/links/wsLink/index.d.ts +1 -0
  113. package/links/wsLink/index.js +1 -0
  114. package/package.json +58 -18
  115. package/rx/dist/trpc-client-rx.cjs.d.ts +1 -0
  116. package/rx/dist/trpc-client-rx.cjs.dev.js +9 -0
  117. package/rx/dist/trpc-client-rx.cjs.js +7 -0
  118. package/rx/dist/trpc-client-rx.cjs.prod.js +9 -0
  119. package/rx/dist/trpc-client-rx.esm.js +1 -0
  120. package/rx/index.d.ts +1 -0
  121. package/rx/index.js +1 -0
  122. package/rx/operators/dist/trpc-client-rx-operators.cjs.d.ts +1 -0
  123. package/rx/operators/dist/trpc-client-rx-operators.cjs.dev.js +39 -0
  124. package/rx/operators/dist/trpc-client-rx-operators.cjs.js +7 -0
  125. package/rx/operators/dist/trpc-client-rx-operators.cjs.prod.js +39 -0
  126. package/rx/operators/dist/trpc-client-rx-operators.esm.js +33 -0
  127. package/rx/operators/index.d.ts +1 -0
  128. package/rx/operators/index.js +1 -0
  129. package/src/TRPCClientError.ts +17 -21
  130. package/src/createTRPCClient.ts +4 -3
  131. package/src/index.ts +1 -1
  132. package/src/internals/TRPCClient.ts +80 -88
  133. package/src/internals/dataLoader.ts +2 -14
  134. package/src/internals/transformRPCResponse.ts +2 -2
  135. package/src/links/dedupeLink.test.ts +134 -0
  136. package/src/links/dedupeLink.ts +53 -0
  137. package/src/links/httpBatchLink.ts +36 -52
  138. package/src/links/httpLink.ts +26 -37
  139. package/src/{internals/httpRequest.ts → links/httpUtils.ts} +30 -21
  140. package/src/links/internals/createChain.test.ts +132 -0
  141. package/src/links/internals/createChain.ts +31 -0
  142. package/src/links/internals/transformOperationResult.ts +25 -0
  143. package/src/links/loggerLink.ts +40 -22
  144. package/src/links/retryLink.ts +45 -14
  145. package/src/links/splitLink.test.ts +56 -0
  146. package/src/links/splitLink.ts +23 -38
  147. package/src/links/transformerLink.ts +70 -0
  148. package/src/links/{core.ts → types.ts} +40 -46
  149. package/src/links/wsLink.ts +56 -77
  150. package/src/rx/index.ts +2 -0
  151. package/src/rx/observable.test.ts +83 -0
  152. package/src/rx/observable.ts +70 -0
  153. package/src/rx/operators/index.ts +3 -0
  154. package/src/rx/operators/map.test.ts +92 -0
  155. package/src/rx/operators/map.ts +25 -0
  156. package/src/rx/operators/share.test.ts +60 -0
  157. package/src/rx/operators/share.ts +67 -0
  158. package/src/rx/operators/tap.ts +26 -0
  159. package/src/rx/types.ts +69 -0
  160. package/src/rx/util/identity.ts +3 -0
  161. package/src/rx/util/observableToPromise.ts +49 -0
  162. package/src/rx/util/pipe.ts +22 -0
  163. package/dist/TRPCClientError-09b8a26b.esm.js +0 -77
  164. package/dist/TRPCClientError-bfee2bf5.cjs.dev.js +0 -79
  165. package/dist/TRPCClientError-e9bf96e9.cjs.prod.js +0 -79
  166. package/dist/declarations/src/TRPCClientError.d.ts.map +0 -1
  167. package/dist/declarations/src/createTRPCClient.d.ts.map +0 -1
  168. package/dist/declarations/src/getFetch.d.ts.map +0 -1
  169. package/dist/declarations/src/index.d.ts.map +0 -1
  170. package/dist/declarations/src/internals/TRPCAbortError.d.ts +0 -4
  171. package/dist/declarations/src/internals/TRPCAbortError.d.ts.map +0 -1
  172. package/dist/declarations/src/internals/TRPCClient.d.ts.map +0 -1
  173. package/dist/declarations/src/internals/dataLoader.d.ts.map +0 -1
  174. package/dist/declarations/src/internals/executeChain.d.ts +0 -8
  175. package/dist/declarations/src/internals/executeChain.d.ts.map +0 -1
  176. package/dist/declarations/src/internals/fetchHelpers.d.ts.map +0 -1
  177. package/dist/declarations/src/internals/httpRequest.d.ts +0 -14
  178. package/dist/declarations/src/internals/httpRequest.d.ts.map +0 -1
  179. package/dist/declarations/src/internals/observable.d.ts +0 -18
  180. package/dist/declarations/src/internals/observable.d.ts.map +0 -1
  181. package/dist/declarations/src/internals/retryDelay.d.ts.map +0 -1
  182. package/dist/declarations/src/internals/transformRPCResponse.d.ts +0 -7
  183. package/dist/declarations/src/internals/transformRPCResponse.d.ts.map +0 -1
  184. package/dist/declarations/src/links/core.d.ts +0 -45
  185. package/dist/declarations/src/links/core.d.ts.map +0 -1
  186. package/dist/declarations/src/links/httpBatchLink.d.ts +0 -7
  187. package/dist/declarations/src/links/httpBatchLink.d.ts.map +0 -1
  188. package/dist/declarations/src/links/httpLink.d.ts.map +0 -1
  189. package/dist/declarations/src/links/loggerLink.d.ts.map +0 -1
  190. package/dist/declarations/src/links/splitLink.d.ts +0 -24
  191. package/dist/declarations/src/links/splitLink.d.ts.map +0 -1
  192. package/dist/declarations/src/links/wsLink.d.ts.map +0 -1
  193. package/dist/transformRPCResponse-57e80136.cjs.dev.js +0 -133
  194. package/dist/transformRPCResponse-739c13d0.cjs.prod.js +0 -133
  195. package/dist/transformRPCResponse-f7f8b0e1.esm.js +0 -129
  196. package/dist/trpc-client.cjs.d.ts +0 -1
  197. package/dist/trpc-client.cjs.dev.js +0 -379
  198. package/dist/trpc-client.cjs.js +0 -7
  199. package/dist/trpc-client.cjs.prod.js +0 -379
  200. package/dist/trpc-client.esm.js +0 -374
  201. package/links/httpBatchLink/package.json +0 -4
  202. package/links/httpLink/package.json +0 -4
  203. package/links/loggerLink/package.json +0 -4
  204. package/links/splitLink/package.json +0 -4
  205. package/links/wsLink/package.json +0 -4
  206. package/src/internals/TRPCAbortError.ts +0 -7
  207. package/src/internals/executeChain.ts +0 -67
  208. package/src/internals/observable.ts +0 -89
@@ -0,0 +1,39 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var share = require('../../../dist/share-5a8c2543.cjs.prod.js');
6
+ var tap = require('../../../dist/tap-d907998d.cjs.prod.js');
7
+ require('@babel/runtime/helpers/createForOfIteratorHelper');
8
+
9
+ function map(project) {
10
+ return function (originalObserver) {
11
+ return {
12
+ subscribe: function subscribe(observer) {
13
+ var index = 0;
14
+ var subscription = originalObserver.subscribe({
15
+ next: function next(value) {
16
+ var _observer$next;
17
+
18
+ (_observer$next = observer.next) === null || _observer$next === void 0 ? void 0 : _observer$next.call(observer, project(value, index++));
19
+ },
20
+ error: function error(_error) {
21
+ var _observer$error;
22
+
23
+ (_observer$error = observer.error) === null || _observer$error === void 0 ? void 0 : _observer$error.call(observer, _error);
24
+ },
25
+ complete: function complete() {
26
+ var _observer$complete;
27
+
28
+ (_observer$complete = observer.complete) === null || _observer$complete === void 0 ? void 0 : _observer$complete.call(observer);
29
+ }
30
+ });
31
+ return subscription;
32
+ }
33
+ };
34
+ };
35
+ }
36
+
37
+ exports.share = share.share;
38
+ exports.tap = tap.tap;
39
+ exports.map = map;
@@ -0,0 +1,33 @@
1
+ export { s as share } from '../../../dist/share-ca585761.esm.js';
2
+ export { t as tap } from '../../../dist/tap-606957cb.esm.js';
3
+ import '@babel/runtime/helpers/createForOfIteratorHelper';
4
+
5
+ function map(project) {
6
+ return function (originalObserver) {
7
+ return {
8
+ subscribe: function subscribe(observer) {
9
+ var index = 0;
10
+ var subscription = originalObserver.subscribe({
11
+ next: function next(value) {
12
+ var _observer$next;
13
+
14
+ (_observer$next = observer.next) === null || _observer$next === void 0 ? void 0 : _observer$next.call(observer, project(value, index++));
15
+ },
16
+ error: function error(_error) {
17
+ var _observer$error;
18
+
19
+ (_observer$error = observer.error) === null || _observer$error === void 0 ? void 0 : _observer$error.call(observer, _error);
20
+ },
21
+ complete: function complete() {
22
+ var _observer$complete;
23
+
24
+ (_observer$complete = observer.complete) === null || _observer$complete === void 0 ? void 0 : _observer$complete.call(observer);
25
+ }
26
+ });
27
+ return subscription;
28
+ }
29
+ };
30
+ };
31
+ }
32
+
33
+ export { map };
@@ -0,0 +1 @@
1
+ export * from '../../dist/rx/operators';
@@ -0,0 +1 @@
1
+ module.exports = require('../../dist/rx/operators/index');
@@ -18,58 +18,54 @@ export class TRPCClientError<TRouter extends AnyRouter>
18
18
  public readonly cause;
19
19
  public readonly shape: Maybe<inferRouterError<TRouter>>;
20
20
  public readonly data: Maybe<inferRouterError<TRouter>['data']>;
21
- /**
22
- * Fatal error - expect no more results after this error
23
- * Used for when WebSockets disconnect prematurely.
24
- */
25
- public readonly isDone: boolean;
21
+ public readonly meta;
26
22
 
27
23
  constructor(
28
24
  message: string,
29
- opts: {
25
+ opts?: {
30
26
  result: Maybe<TRPCErrorResponse<inferRouterError<TRouter>>>;
31
27
  /**
32
- * @deprecated use cause
28
+ * @deprecated use `cause`
33
29
  **/
34
30
  originalError?: Maybe<Error>;
35
31
  cause?: Maybe<Error>;
36
- isDone?: boolean;
32
+ meta?: Record<string, unknown>;
37
33
  },
38
34
  ) {
39
- const cause = opts.cause ?? opts.originalError;
35
+ const cause = opts?.cause ?? opts?.originalError;
40
36
 
41
37
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
42
38
  // @ts-ignore https://github.com/tc39/proposal-error-cause
43
39
  super(message, { cause });
44
40
 
45
- this.isDone = opts.isDone ?? false;
41
+ this.meta = opts?.meta;
46
42
 
47
43
  this.cause = this.originalError = cause;
48
- this.shape = opts.result?.error;
49
- this.data = opts.result?.error.data;
44
+ this.shape = opts?.result?.error;
45
+ this.data = opts?.result?.error.data;
50
46
  this.name = 'TRPCClientError';
51
47
 
52
48
  Object.setPrototypeOf(this, TRPCClientError.prototype);
53
49
  }
54
50
 
55
51
  public static from<TRouter extends AnyRouter>(
56
- result: Error | TRPCErrorResponse<any>,
57
- opts: { isDone?: boolean } = {},
52
+ cause: Error | TRPCErrorResponse<any>,
53
+ opts: { meta?: Record<string, unknown> } = {},
58
54
  ): TRPCClientError<TRouter> {
59
- if (!(result instanceof Error)) {
60
- return new TRPCClientError<TRouter>((result.error as any).message ?? '', {
55
+ if (!(cause instanceof Error)) {
56
+ return new TRPCClientError<TRouter>((cause.error as any).message ?? '', {
61
57
  ...opts,
62
58
  cause: null,
63
- result: result,
59
+ result: cause,
64
60
  });
65
61
  }
66
- if (result.name === 'TRPCClientError') {
67
- return result as TRPCClientError<any>;
62
+ if (cause.name === 'TRPCClientError') {
63
+ return cause as TRPCClientError<any>;
68
64
  }
69
65
 
70
- return new TRPCClientError<TRouter>(result.message, {
66
+ return new TRPCClientError<TRouter>(cause.message, {
71
67
  ...opts,
72
- cause: result,
68
+ cause,
73
69
  result: null,
74
70
  });
75
71
  }
@@ -11,8 +11,9 @@ export function createTRPCClient<TRouter extends AnyRouter>(
11
11
  return new Client<TRouter>(opts);
12
12
  }
13
13
 
14
- export type { CreateTRPCClientOptions } from './internals/TRPCClient';
15
-
16
14
  export type TRPCClient<TRouter extends AnyRouter> = Client<TRouter>;
17
15
 
18
- export type { TRPCRequestOptions } from './internals/TRPCClient';
16
+ export type {
17
+ TRPCRequestOptions,
18
+ CreateTRPCClientOptions,
19
+ } from './internals/TRPCClient';
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export * from './createTRPCClient';
2
2
  export * from './getFetch';
3
- export * from './links/core';
3
+ export * from './links/types';
4
4
  export * from './TRPCClientError';
@@ -1,28 +1,30 @@
1
1
  import {
2
2
  AnyRouter,
3
- ClientDataTransformerOptions,
4
- DataTransformer,
5
3
  inferHandlerInput,
6
4
  inferProcedureInput,
7
5
  inferProcedureOutput,
8
6
  inferSubscriptionOutput,
9
7
  } from '@trpc/server';
10
8
  import { TRPCResult } from '@trpc/server/rpc';
11
- import { executeChain } from './executeChain';
12
- import { getAbortController } from './fetchHelpers';
9
+ import { CancelFn } from '..';
13
10
  import { getFetch } from '../getFetch';
14
- import { ObservableCallbacks, UnsubscribeFn } from './observable';
15
- import { TRPCAbortError } from './TRPCAbortError';
11
+ import { httpBatchLink } from '../links/httpBatchLink';
12
+ import { createChain } from '../links/internals/createChain';
13
+ import { transformOperationResult } from '../links/internals/transformOperationResult';
16
14
  import {
17
- CancelFn,
18
15
  HTTPHeaders,
19
- LinkRuntimeOptions,
16
+ LinkRuntime,
20
17
  OperationContext,
21
18
  OperationLink,
22
19
  TRPCLink,
23
- } from '../links/core';
24
- import { httpBatchLink } from '../links/httpBatchLink';
20
+ } from '../links/types';
21
+ import { UnsubscribeFn } from '../rx';
22
+ import { inferObservableValue } from '../rx/observable';
23
+ import { share } from '../rx/operators';
24
+ import { Observer } from '../rx/types';
25
+ import { observableToPromise } from '../rx/util/observableToPromise';
25
26
  import { TRPCClientError } from '../TRPCClientError';
27
+ import { getAbortController } from './fetchHelpers';
26
28
 
27
29
  type CancellablePromise<T = unknown> = Promise<T> & {
28
30
  cancel: CancelFn;
@@ -39,8 +41,7 @@ let idCounter = 0;
39
41
  function getRequestId() {
40
42
  return ++idCounter;
41
43
  }
42
-
43
- export type CreateTRPCClientOptions<TRouter extends AnyRouter> = {
44
+ interface CreateTRPCClientBaseOptions {
44
45
  /**
45
46
  * Add ponyfill for fetch
46
47
  */
@@ -53,25 +54,26 @@ export type CreateTRPCClientOptions<TRouter extends AnyRouter> = {
53
54
  * headers to be set on outgoing requests / callback that of said headers
54
55
  */
55
56
  headers?: HTTPHeaders | (() => HTTPHeaders | Promise<HTTPHeaders>);
57
+ }
58
+
59
+ /** @internal */
60
+ export interface CreateTRPCClientWithURLOptions
61
+ extends CreateTRPCClientBaseOptions {
56
62
  /**
57
- * Data transformer
58
- * @link http://localhost:3000/docs/data-transformers
63
+ * HTTP URL of API
59
64
  **/
60
- transformer?: ClientDataTransformerOptions;
61
- } & (
62
- | {
63
- /**
64
- * HTTP URL of API
65
- **/
66
- url: string;
67
- }
68
- | {
69
- /**
70
- * @link http://localhost:3000/docs/links
71
- **/
72
- links: TRPCLink<TRouter>[];
73
- }
74
- );
65
+ url: string;
66
+ }
67
+
68
+ /** @internal */
69
+ export interface CreateTRPCClientWithLinksOptions<TRouter extends AnyRouter>
70
+ extends CreateTRPCClientBaseOptions {
71
+ /**
72
+ * @link http://localhost:3000/docs/links
73
+ **/
74
+ links: TRPCLink<TRouter>[];
75
+ }
76
+
75
77
  type TRPCType = 'subscription' | 'query' | 'mutation';
76
78
  export interface TRPCRequestOptions {
77
79
  /**
@@ -79,27 +81,20 @@ export interface TRPCRequestOptions {
79
81
  */
80
82
  context?: OperationContext;
81
83
  }
84
+
85
+ /** @internal */
86
+ export type CreateTRPCClientOptions<TRouter extends AnyRouter> =
87
+ | CreateTRPCClientWithLinksOptions<TRouter>
88
+ | CreateTRPCClientWithURLOptions;
82
89
  export class TRPCClient<TRouter extends AnyRouter> {
83
90
  private readonly links: OperationLink<TRouter>[];
84
- public readonly runtime: LinkRuntimeOptions;
91
+ public readonly runtime: LinkRuntime;
85
92
 
86
93
  constructor(opts: CreateTRPCClientOptions<TRouter>) {
87
- const transformer: DataTransformer = opts.transformer
88
- ? 'input' in opts.transformer
89
- ? {
90
- serialize: opts.transformer.input.serialize,
91
- deserialize: opts.transformer.output.deserialize,
92
- }
93
- : opts.transformer
94
- : {
95
- serialize: (data) => data,
96
- deserialize: (data) => data,
97
- };
98
-
99
94
  const _fetch = getFetch(opts?.fetch);
100
95
  const AC = getAbortController(opts?.AbortController);
101
96
 
102
- function getHeadersFn(): LinkRuntimeOptions['headers'] {
97
+ function getHeadersFn(): LinkRuntime['headers'] {
103
98
  if (opts.headers) {
104
99
  const headers = opts.headers;
105
100
  return typeof headers === 'function' ? headers : () => headers;
@@ -107,7 +102,6 @@ export class TRPCClient<TRouter extends AnyRouter> {
107
102
  return () => ({});
108
103
  }
109
104
  this.runtime = {
110
- transformer,
111
105
  AbortController: AC as any,
112
106
  fetch: _fetch,
113
107
  headers: getHeadersFn(),
@@ -135,8 +129,8 @@ export class TRPCClient<TRouter extends AnyRouter> {
135
129
  path: string;
136
130
  context?: OperationContext;
137
131
  }) {
138
- const $result = executeChain<TRouter, TInput, TOutput>({
139
- links: this.links as any,
132
+ const chain$ = createChain<TRouter, TInput, TOutput>({
133
+ links: this.links as OperationLink<any, any, any>[],
140
134
  op: {
141
135
  id: getRequestId(),
142
136
  type,
@@ -145,8 +139,7 @@ export class TRPCClient<TRouter extends AnyRouter> {
145
139
  context,
146
140
  },
147
141
  });
148
-
149
- return $result;
142
+ return chain$.pipe(share());
150
143
  }
151
144
  private requestAsPromise<TInput = unknown, TOutput = unknown>(opts: {
152
145
  type: TRPCType;
@@ -154,38 +147,29 @@ export class TRPCClient<TRouter extends AnyRouter> {
154
147
  path: string;
155
148
  context?: OperationContext;
156
149
  }): CancellablePromise<TOutput> {
157
- const $result = this.$request<TInput, TOutput>(opts);
150
+ const req$ = this.$request<TInput, TOutput>(opts);
151
+ type TValue = inferObservableValue<typeof req$>;
152
+ const { promise, abort } = observableToPromise<TValue>(req$);
158
153
 
159
- const promise = new Promise<TOutput>((resolve, reject) => {
160
- const res = $result.get();
161
- if (res?.type === 'data') {
162
- resolve(res.data);
163
- $result.done();
164
- return;
165
- }
166
- $result.subscribe({
167
- onNext: (result) => {
168
- if (result?.type !== 'data') {
169
- return;
170
- }
171
- resolve(result.data);
172
-
173
- $result.done();
174
- },
175
- onError(err) {
176
- reject(err);
177
- $result.done();
178
- },
179
- onDone() {
180
- reject(TRPCClientError.from(new TRPCAbortError()));
181
- },
182
- });
183
- }) as CancellablePromise<TOutput>;
184
- promise.cancel = () => {
185
- $result.done();
186
- };
154
+ const cancellablePromise: CancellablePromise<any> = new Promise<TOutput>(
155
+ (resolve, reject) => {
156
+ promise
157
+ .then((result) => {
158
+ const transformed = transformOperationResult(result);
159
+ if (transformed.ok) {
160
+ resolve(transformed.data as any);
161
+ return;
162
+ }
163
+ reject(transformed.error);
164
+ })
165
+ .catch((err) => {
166
+ reject(TRPCClientError.from(err));
167
+ });
168
+ },
169
+ ) as any;
170
+ cancellablePromise.cancel = abort;
187
171
 
188
- return promise;
172
+ return cancellablePromise;
189
173
  }
190
174
  public query<
191
175
  TQueries extends TRouter['_def']['queries'],
@@ -233,27 +217,35 @@ export class TRPCClient<TRouter extends AnyRouter> {
233
217
  path: TPath,
234
218
  input: TInput,
235
219
  opts: TRPCRequestOptions &
236
- ObservableCallbacks<TRPCResult<TOutput>, TRPCClientError<TRouter>>,
220
+ Partial<Observer<TRPCResult<TOutput>, TRPCClientError<TRouter>>>,
237
221
  ): UnsubscribeFn {
238
- const $res = this.$request<TInput, TOutput>({
222
+ const observable$ = this.$request<TInput, TOutput>({
239
223
  type: 'subscription',
240
224
  path,
241
225
  input,
242
226
  context: opts.context,
243
227
  });
244
- $res.subscribe({
245
- onNext(output) {
246
- if (output) {
247
- opts.onNext?.(output);
228
+ const observer = observable$.subscribe({
229
+ next(result) {
230
+ if ('error' in result.data) {
231
+ const err = TRPCClientError.from(result.data, {
232
+ meta: result.context,
233
+ });
234
+
235
+ opts.error?.(err);
236
+ return;
248
237
  }
238
+ opts.next?.(result.data.result);
239
+ },
240
+ error(err) {
241
+ opts.error?.(err);
249
242
  },
250
- onError(err) {
251
- opts.onError?.(err);
243
+ complete() {
244
+ opts.complete?.();
252
245
  },
253
- onDone: opts.onDone,
254
246
  });
255
247
  return () => {
256
- $res.done();
248
+ observer.unsubscribe();
257
249
  };
258
250
  }
259
251
  }
@@ -1,4 +1,4 @@
1
- import { CancelFn, PromiseAndCancel } from '../links/core';
1
+ import { CancelFn, PromiseAndCancel } from '../links/types';
2
2
 
3
3
  type BatchItem<TKey, TValue> = {
4
4
  cancelled: boolean;
@@ -20,10 +20,7 @@ type BatchLoadFn<TKey, TValue> = (keys: TKey[]) => {
20
20
  * Less configuration, no caching, and allows you to cancel requests
21
21
  * When cancelling a single fetch the whole batch will be cancelled only when _all_ items are cancelled
22
22
  */
23
- export function dataLoader<TKey, TValue>(
24
- fetchMany: BatchLoadFn<TKey, TValue>,
25
- opts?: { maxBatchSize?: number },
26
- ) {
23
+ export function dataLoader<TKey, TValue>(fetchMany: BatchLoadFn<TKey, TValue>) {
27
24
  let batch: Batch<TKey, TValue> | null = null;
28
25
  let dispatchTimer: NodeJS.Timer | number | null = null;
29
26
 
@@ -72,16 +69,7 @@ export function dataLoader<TKey, TValue>(
72
69
  item.reject = reject;
73
70
  item.resolve = resolve;
74
71
  thisBatch.items.push(item);
75
-
76
- if (
77
- typeof opts?.maxBatchSize !== 'undefined' &&
78
- thisBatch.items.length >= opts.maxBatchSize
79
- ) {
80
- dispatch();
81
- return;
82
- }
83
72
  });
84
-
85
73
  if (!dispatchTimer) {
86
74
  dispatchTimer = setTimeout(dispatch);
87
75
  }
@@ -1,13 +1,13 @@
1
1
  import { TRPCResponse } from '@trpc/server/rpc';
2
2
  import { TRPCClientError } from '../TRPCClientError';
3
- import { LinkRuntimeOptions } from '../links/core';
3
+ import { LinkRuntime } from '../links/types';
4
4
 
5
5
  export function transformRPCResponse({
6
6
  envelope,
7
7
  runtime,
8
8
  }: {
9
9
  envelope: TRPCResponse;
10
- runtime: LinkRuntimeOptions;
10
+ runtime: LinkRuntime;
11
11
  }) {
12
12
  if ('error' in envelope) {
13
13
  return TRPCClientError.from({
@@ -0,0 +1,134 @@
1
+ import { waitFor } from '@testing-library/dom';
2
+ import { AnyRouter } from '@trpc/server';
3
+ import { OperationLink } from '..';
4
+ import { observable } from '../rx/observable';
5
+ import { dedupeLink } from './dedupeLink';
6
+ import { createChain } from './internals/createChain';
7
+
8
+ test('dedupeLink', async () => {
9
+ const endingLinkTriggered = jest.fn();
10
+ const timerTriggered = jest.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
+ data: {
21
+ id: null,
22
+ result: {
23
+ type: 'data',
24
+ data: {
25
+ input: op.input,
26
+ },
27
+ },
28
+ },
29
+ });
30
+ subscribe.complete();
31
+ }, 1);
32
+ return () => clearTimeout(timer);
33
+ });
34
+ },
35
+ ];
36
+ {
37
+ const call1 = createChain<AnyRouter, unknown, unknown>({
38
+ links,
39
+ op: {
40
+ type: 'query',
41
+ id: 1,
42
+ input: 'world',
43
+ path: 'hello',
44
+ context: {},
45
+ },
46
+ });
47
+
48
+ const call2 = createChain<AnyRouter, unknown, unknown>({
49
+ links,
50
+ op: {
51
+ type: 'query',
52
+ id: 1,
53
+ input: 'world',
54
+ path: 'hello',
55
+ context: {},
56
+ },
57
+ });
58
+ const next = jest.fn();
59
+ call1.subscribe({ next });
60
+ call2.subscribe({ next });
61
+
62
+ expect(endingLinkTriggered).toHaveBeenCalledTimes(1);
63
+ await waitFor(() => {
64
+ expect(timerTriggered).toHaveBeenCalledTimes(1);
65
+ });
66
+
67
+ expect(next).toHaveBeenCalledTimes(2);
68
+ }
69
+ });
70
+
71
+ test('dedupe - cancel one does not cancel the other', async () => {
72
+ const endingLinkTriggered = jest.fn();
73
+ const timerTriggered = jest.fn();
74
+ const links: OperationLink<AnyRouter, any, any>[] = [
75
+ // "dedupe link"
76
+ dedupeLink()(null as any),
77
+ ({ op }) => {
78
+ return observable((subscribe) => {
79
+ endingLinkTriggered();
80
+ const timer = setTimeout(() => {
81
+ timerTriggered();
82
+ subscribe.next({
83
+ data: {
84
+ id: null,
85
+ result: {
86
+ type: 'data',
87
+ data: {
88
+ input: op.input,
89
+ },
90
+ },
91
+ },
92
+ });
93
+ subscribe.complete();
94
+ }, 1);
95
+ return () => clearTimeout(timer);
96
+ });
97
+ },
98
+ ];
99
+
100
+ {
101
+ const call1 = createChain<AnyRouter, unknown, unknown>({
102
+ links,
103
+ op: {
104
+ type: 'query',
105
+ id: 1,
106
+ input: 'world',
107
+ path: 'hello',
108
+ context: {},
109
+ },
110
+ });
111
+
112
+ const call2 = createChain<AnyRouter, unknown, unknown>({
113
+ links,
114
+ op: {
115
+ type: 'query',
116
+ id: 1,
117
+ input: 'world',
118
+ path: 'hello',
119
+ context: {},
120
+ },
121
+ });
122
+ const next = jest.fn();
123
+ const call1$ = call1.subscribe({ next });
124
+ call2.subscribe({ next });
125
+ call1$.unsubscribe();
126
+
127
+ expect(endingLinkTriggered).toHaveBeenCalledTimes(1);
128
+ await waitFor(() => {
129
+ expect(timerTriggered).toHaveBeenCalledTimes(1);
130
+
131
+ expect(next).toHaveBeenCalledTimes(1);
132
+ });
133
+ }
134
+ });
@@ -0,0 +1,53 @@
1
+ import { AnyRouter } from '@trpc/server';
2
+ import { observable } from '../rx/observable';
3
+ import { share } from '../rx/operators';
4
+ import { Observable } from '../rx/types';
5
+ import { TRPCLink } from './types';
6
+
7
+ export function dedupeLink<
8
+ TRouter extends AnyRouter = AnyRouter,
9
+ >(): TRPCLink<TRouter> {
10
+ // initialized config
11
+ return () => {
12
+ // initialized in app
13
+ const pending: Record<string, Observable<any, any>> = {};
14
+ return ({ op, next }) => {
15
+ // initialized for request
16
+
17
+ if (op.type !== 'query') {
18
+ // pass through
19
+ return next(op);
20
+ }
21
+ const key = JSON.stringify([op.path, op.input]);
22
+ if (pending[key]) {
23
+ // console.log('hooking into pending', { op });
24
+ return observable((observer) => pending[key].subscribe(observer));
25
+ }
26
+
27
+ const shared$ = observable((observer) => {
28
+ function reset() {
29
+ delete pending[key];
30
+ }
31
+ const next$ = next(op).subscribe({
32
+ next(v) {
33
+ observer.next(v);
34
+ },
35
+ error(e) {
36
+ reset();
37
+ observer.error(e);
38
+ },
39
+ complete() {
40
+ reset();
41
+ observer.complete();
42
+ },
43
+ });
44
+ return () => {
45
+ reset();
46
+ next$.unsubscribe();
47
+ };
48
+ }).pipe(share());
49
+ pending[key] = shared$;
50
+ return shared$;
51
+ };
52
+ };
53
+ }