@trpc/client 10.0.0-alpha.8 → 10.0.0-proxy-alpha.53

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 (180) hide show
  1. package/README.md +58 -1
  2. package/dist/TRPCClientError.d.ts +16 -20
  3. package/dist/TRPCClientError.d.ts.map +1 -1
  4. package/dist/createTRPCClient.d.ts +2 -3
  5. package/dist/createTRPCClient.d.ts.map +1 -1
  6. package/dist/createTRPCClientProxy.d.ts +37 -0
  7. package/dist/createTRPCClientProxy.d.ts.map +1 -0
  8. package/dist/httpUtils-44781613.mjs +76 -0
  9. package/dist/httpUtils-801112a6.js +79 -0
  10. package/dist/index.d.ts +2 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +260 -280
  13. package/dist/index.mjs +253 -271
  14. package/dist/internals/TRPCClient.d.ts +39 -21
  15. package/dist/internals/TRPCClient.d.ts.map +1 -1
  16. package/dist/internals/dataLoader.d.ts +7 -6
  17. package/dist/internals/dataLoader.d.ts.map +1 -1
  18. package/dist/internals/fetchHelpers.d.ts +1 -1
  19. package/dist/internals/fetchHelpers.d.ts.map +1 -1
  20. package/dist/internals/retryDelay.d.ts.map +1 -1
  21. package/dist/links/dedupeLink.d.ts.map +1 -1
  22. package/dist/links/httpBatchLink.d.ts +2 -2
  23. package/dist/links/httpBatchLink.d.ts.map +1 -1
  24. package/dist/links/httpBatchLink.js +189 -172
  25. package/dist/links/httpBatchLink.mjs +189 -172
  26. package/dist/links/httpLink.d.ts +1 -1
  27. package/dist/links/httpLink.d.ts.map +1 -1
  28. package/dist/links/httpLink.js +31 -35
  29. package/dist/links/httpLink.mjs +31 -35
  30. package/dist/links/index.d.ts +9 -0
  31. package/dist/links/index.d.ts.map +1 -0
  32. package/dist/links/internals/createChain.d.ts.map +1 -1
  33. package/dist/links/internals/httpUtils.d.ts +31 -0
  34. package/dist/links/internals/httpUtils.d.ts.map +1 -0
  35. package/dist/links/internals/transformResult.d.ts +28 -0
  36. package/dist/links/internals/transformResult.d.ts.map +1 -0
  37. package/dist/links/loggerLink.d.ts +3 -3
  38. package/dist/links/loggerLink.d.ts.map +1 -1
  39. package/dist/links/loggerLink.js +90 -96
  40. package/dist/links/loggerLink.mjs +90 -91
  41. package/dist/links/retryLink.d.ts.map +1 -1
  42. package/dist/links/splitLink.d.ts +1 -1
  43. package/dist/links/splitLink.d.ts.map +1 -1
  44. package/dist/links/splitLink.js +3 -25
  45. package/dist/links/splitLink.mjs +2 -28
  46. package/dist/links/types.d.ts +13 -12
  47. package/dist/links/types.d.ts.map +1 -1
  48. package/dist/links/wsLink.d.ts +12 -5
  49. package/dist/links/wsLink.d.ts.map +1 -1
  50. package/dist/links/wsLink.js +250 -358
  51. package/dist/links/wsLink.mjs +250 -348
  52. package/dist/splitLink-695ae288.js +48 -0
  53. package/dist/splitLink-ad44a55d.mjs +45 -0
  54. package/dist/transformResult-106791d7.mjs +62 -0
  55. package/dist/transformResult-e15ccdf6.js +65 -0
  56. package/links/httpBatchLink/dist/trpc-client-links-httpBatchLink.cjs.dev.js +15 -13
  57. package/links/httpBatchLink/dist/trpc-client-links-httpBatchLink.cjs.prod.js +15 -13
  58. package/links/httpBatchLink/dist/trpc-client-links-httpBatchLink.esm.js +12 -10
  59. package/links/httpLink/dist/trpc-client-links-httpLink.cjs.dev.js +4 -4
  60. package/links/httpLink/dist/trpc-client-links-httpLink.cjs.prod.js +4 -4
  61. package/links/httpLink/dist/trpc-client-links-httpLink.esm.js +1 -1
  62. package/links/wsLink/dist/trpc-client-links-wsLink.cjs.dev.js +3 -1
  63. package/links/wsLink/dist/trpc-client-links-wsLink.cjs.prod.js +3 -1
  64. package/links/wsLink/dist/trpc-client-links-wsLink.esm.js +3 -1
  65. package/package.json +23 -34
  66. package/src/TRPCClientError.ts +38 -28
  67. package/src/createTRPCClient.ts +8 -3
  68. package/src/createTRPCClientProxy.ts +113 -0
  69. package/src/index.ts +2 -1
  70. package/src/internals/TRPCClient.ts +118 -77
  71. package/src/internals/dataLoader.ts +116 -53
  72. package/src/internals/fetchHelpers.ts +2 -2
  73. package/src/links/dedupeLink.test.ts +9 -15
  74. package/src/links/dedupeLink.ts +6 -7
  75. package/src/links/httpBatchLink.ts +73 -36
  76. package/src/links/httpLink.ts +18 -6
  77. package/src/links/index.ts +8 -0
  78. package/src/links/internals/createChain.test.ts +23 -38
  79. package/src/links/internals/createChain.ts +8 -3
  80. package/src/links/internals/httpUtils.ts +117 -0
  81. package/src/links/internals/transformResult.ts +40 -0
  82. package/src/links/loggerLink.ts +6 -7
  83. package/src/links/retryLink.ts +2 -3
  84. package/src/links/splitLink.test.ts +3 -3
  85. package/src/links/splitLink.ts +5 -5
  86. package/src/links/types.ts +15 -12
  87. package/src/links/wsLink.ts +57 -23
  88. package/dist/TRPCClientError-17b117e1.mjs +0 -81
  89. package/dist/TRPCClientError-ec6bd2ca.js +0 -94
  90. package/dist/createChain-389cc116.mjs +0 -25
  91. package/dist/createChain-864dbb30.js +0 -27
  92. package/dist/httpUtils-1f9e4e3c.js +0 -97
  93. package/dist/httpUtils-c09d7b79.mjs +0 -91
  94. package/dist/index.ts.js +0 -1
  95. package/dist/internals/transformRPCResponse.d.ts +0 -15
  96. package/dist/internals/transformRPCResponse.d.ts.map +0 -1
  97. package/dist/links/httpBatchLink.ts.js +0 -1
  98. package/dist/links/httpLink.ts.js +0 -1
  99. package/dist/links/httpUtils.d.ts +0 -22
  100. package/dist/links/httpUtils.d.ts.map +0 -1
  101. package/dist/links/internals/transformOperationResult.d.ts +0 -16
  102. package/dist/links/internals/transformOperationResult.d.ts.map +0 -1
  103. package/dist/links/loggerLink.ts.js +0 -1
  104. package/dist/links/splitLink.ts.js +0 -1
  105. package/dist/links/transformerLink.d.ts +0 -4
  106. package/dist/links/transformerLink.d.ts.map +0 -1
  107. package/dist/links/transformerLink.js +0 -75
  108. package/dist/links/transformerLink.mjs +0 -67
  109. package/dist/links/transformerLink.ts.js +0 -1
  110. package/dist/links/wsLink.ts.js +0 -1
  111. package/dist/observable-7e66cb56.mjs +0 -102
  112. package/dist/observable-85669100.js +0 -104
  113. package/dist/rx/index.d.ts +0 -3
  114. package/dist/rx/index.d.ts.map +0 -1
  115. package/dist/rx/index.js +0 -9
  116. package/dist/rx/index.mjs +0 -1
  117. package/dist/rx/index.ts.js +0 -1
  118. package/dist/rx/observable.d.ts +0 -4
  119. package/dist/rx/observable.d.ts.map +0 -1
  120. package/dist/rx/operators/index.d.ts +0 -4
  121. package/dist/rx/operators/index.d.ts.map +0 -1
  122. package/dist/rx/operators/index.js +0 -38
  123. package/dist/rx/operators/index.mjs +0 -32
  124. package/dist/rx/operators/index.ts.js +0 -1
  125. package/dist/rx/operators/map.d.ts +0 -3
  126. package/dist/rx/operators/map.d.ts.map +0 -1
  127. package/dist/rx/operators/share.d.ts +0 -6
  128. package/dist/rx/operators/share.d.ts.map +0 -1
  129. package/dist/rx/operators/tap.d.ts +0 -3
  130. package/dist/rx/operators/tap.d.ts.map +0 -1
  131. package/dist/rx/types.d.ts +0 -29
  132. package/dist/rx/types.d.ts.map +0 -1
  133. package/dist/rx/util/identity.d.ts +0 -2
  134. package/dist/rx/util/identity.d.ts.map +0 -1
  135. package/dist/rx/util/observableToPromise.d.ts +0 -10
  136. package/dist/rx/util/observableToPromise.d.ts.map +0 -1
  137. package/dist/rx/util/pipe.d.ts +0 -4
  138. package/dist/rx/util/pipe.d.ts.map +0 -1
  139. package/dist/share-4d79dc49.js +0 -110
  140. package/dist/share-671b63fa.mjs +0 -108
  141. package/dist/tap-538fa07f.mjs +0 -30
  142. package/dist/tap-799a2d33.js +0 -32
  143. package/links/transformerLink/dist/trpc-client-links-transformerLink.cjs.d.ts +0 -1
  144. package/links/transformerLink/dist/trpc-client-links-transformerLink.cjs.dev.js +0 -67
  145. package/links/transformerLink/dist/trpc-client-links-transformerLink.cjs.js +0 -7
  146. package/links/transformerLink/dist/trpc-client-links-transformerLink.cjs.prod.js +0 -67
  147. package/links/transformerLink/dist/trpc-client-links-transformerLink.esm.js +0 -63
  148. package/links/transformerLink/index.d.ts +0 -1
  149. package/links/transformerLink/index.js +0 -1
  150. package/rx/dist/trpc-client-rx.cjs.d.ts +0 -1
  151. package/rx/dist/trpc-client-rx.cjs.dev.js +0 -9
  152. package/rx/dist/trpc-client-rx.cjs.js +0 -7
  153. package/rx/dist/trpc-client-rx.cjs.prod.js +0 -9
  154. package/rx/dist/trpc-client-rx.esm.js +0 -1
  155. package/rx/index.d.ts +0 -1
  156. package/rx/index.js +0 -1
  157. package/rx/operators/dist/trpc-client-rx-operators.cjs.d.ts +0 -1
  158. package/rx/operators/dist/trpc-client-rx-operators.cjs.dev.js +0 -39
  159. package/rx/operators/dist/trpc-client-rx-operators.cjs.js +0 -7
  160. package/rx/operators/dist/trpc-client-rx-operators.cjs.prod.js +0 -39
  161. package/rx/operators/dist/trpc-client-rx-operators.esm.js +0 -33
  162. package/rx/operators/index.d.ts +0 -1
  163. package/rx/operators/index.js +0 -1
  164. package/src/internals/transformRPCResponse.ts +0 -25
  165. package/src/links/httpUtils.ts +0 -94
  166. package/src/links/internals/transformOperationResult.ts +0 -25
  167. package/src/links/transformerLink.ts +0 -70
  168. package/src/rx/index.ts +0 -2
  169. package/src/rx/observable.test.ts +0 -83
  170. package/src/rx/observable.ts +0 -70
  171. package/src/rx/operators/index.ts +0 -3
  172. package/src/rx/operators/map.test.ts +0 -92
  173. package/src/rx/operators/map.ts +0 -25
  174. package/src/rx/operators/share.test.ts +0 -60
  175. package/src/rx/operators/share.ts +0 -67
  176. package/src/rx/operators/tap.ts +0 -26
  177. package/src/rx/types.ts +0 -69
  178. package/src/rx/util/identity.ts +0 -3
  179. package/src/rx/util/observableToPromise.ts +0 -49
  180. package/src/rx/util/pipe.ts +0 -22
@@ -0,0 +1,117 @@
1
+ import { ProcedureType } from '@trpc/server';
2
+ import { TRPCResponse } from '@trpc/server/rpc';
3
+ import { PromiseAndCancel, TRPCClientRuntime } from '../types';
4
+
5
+ export interface HTTPLinkOptions {
6
+ url: string;
7
+ }
8
+
9
+ // https://github.com/trpc/trpc/pull/669
10
+ function arrayToDict(array: unknown[]) {
11
+ const dict: Record<number, unknown> = {};
12
+ for (let index = 0; index < array.length; index++) {
13
+ const element = array[index];
14
+ dict[index] = element;
15
+ }
16
+ return dict;
17
+ }
18
+
19
+ const METHOD = {
20
+ query: 'GET',
21
+ mutation: 'POST',
22
+ subscription: 'PATCH',
23
+ } as const;
24
+
25
+ export interface HTTPResult {
26
+ json: TRPCResponse;
27
+ meta: {
28
+ response: Response;
29
+ };
30
+ }
31
+
32
+ type GetInputOptions = {
33
+ runtime: TRPCClientRuntime;
34
+ } & ({ inputs: unknown[] } | { input: unknown });
35
+
36
+ function getInput(opts: GetInputOptions) {
37
+ return 'input' in opts
38
+ ? opts.runtime.transformer.serialize(opts.input)
39
+ : arrayToDict(
40
+ opts.inputs.map((_input) => opts.runtime.transformer.serialize(_input)),
41
+ );
42
+ }
43
+
44
+ export type HTTPRequestOptions = HTTPLinkOptions &
45
+ GetInputOptions & {
46
+ type: ProcedureType;
47
+ path: string;
48
+ };
49
+
50
+ export function getUrl(opts: HTTPRequestOptions) {
51
+ let url = opts.url + '/' + opts.path;
52
+ const queryParts: string[] = [];
53
+ if ('inputs' in opts) {
54
+ queryParts.push('batch=1');
55
+ }
56
+ if (opts.type === 'query') {
57
+ const input = getInput(opts);
58
+ if (input !== undefined) {
59
+ queryParts.push(`input=${encodeURIComponent(JSON.stringify(input))}`);
60
+ }
61
+ }
62
+ if (queryParts.length) {
63
+ url += '?' + queryParts.join('&');
64
+ }
65
+ return url;
66
+ }
67
+
68
+ type GetBodyOptions = { type: ProcedureType } & GetInputOptions;
69
+
70
+ export function getBody(opts: GetBodyOptions) {
71
+ if (opts.type === 'query') {
72
+ return undefined;
73
+ }
74
+ const input = getInput(opts);
75
+ return input !== undefined ? JSON.stringify(input) : undefined;
76
+ }
77
+
78
+ export function httpRequest(
79
+ opts: HTTPRequestOptions,
80
+ ): PromiseAndCancel<HTTPResult> {
81
+ const { type, runtime } = opts;
82
+ const ac = runtime.AbortController ? new runtime.AbortController() : null;
83
+
84
+ const promise = new Promise<HTTPResult>((resolve, reject) => {
85
+ const url = getUrl(opts);
86
+ const body = getBody(opts);
87
+
88
+ const meta = {} as HTTPResult['meta'];
89
+ Promise.resolve(runtime.headers())
90
+ .then((headers) =>
91
+ runtime.fetch(url, {
92
+ method: METHOD[type],
93
+ signal: ac?.signal,
94
+ body: body,
95
+ headers: {
96
+ 'content-type': 'application/json',
97
+ ...headers,
98
+ },
99
+ }),
100
+ )
101
+ .then((_res) => {
102
+ meta.response = _res;
103
+ return _res.json();
104
+ })
105
+ .then((json) => {
106
+ resolve({
107
+ json,
108
+ meta,
109
+ });
110
+ })
111
+ .catch(reject);
112
+ });
113
+ const cancel = () => {
114
+ ac?.abort();
115
+ };
116
+ return { promise, cancel };
117
+ }
@@ -0,0 +1,40 @@
1
+ import { AnyRouter, inferRouterError } from '@trpc/server';
2
+ import {
3
+ TRPCResponse,
4
+ TRPCResponseMessage,
5
+ TRPCResultMessage,
6
+ } from '@trpc/server/rpc';
7
+ import { TRPCClientRuntime } from '..';
8
+
9
+ // FIXME:
10
+ // - the generics here are probably unnecessary
11
+ // - the RPC-spec could probably be simplified to combine HTTP + WS
12
+ /** @internal */
13
+ export function transformResult<TRouter extends AnyRouter, TOutput>(
14
+ response:
15
+ | TRPCResponseMessage<TOutput, inferRouterError<TRouter>>
16
+ | TRPCResponse<TOutput, inferRouterError<TRouter>>,
17
+ runtime: TRPCClientRuntime,
18
+ ) {
19
+ if ('error' in response) {
20
+ const error = runtime.transformer.deserialize(
21
+ response.error,
22
+ ) as inferRouterError<TRouter>;
23
+ return {
24
+ ok: false,
25
+ error: {
26
+ ...response,
27
+ error,
28
+ },
29
+ } as const;
30
+ }
31
+
32
+ const result = {
33
+ ...response.result,
34
+ ...((!response.result.type || response.result.type === 'data') && {
35
+ type: 'data',
36
+ data: runtime.transformer.deserialize(response.result.data),
37
+ }),
38
+ } as TRPCResultMessage<TOutput>['result'];
39
+ return { ok: true, result } as const;
40
+ }
@@ -1,8 +1,7 @@
1
1
  import { AnyRouter } from '@trpc/server';
2
+ import { observable, tap } from '@trpc/server/observable';
2
3
  import { TRPCClientError } from '..';
3
- import { observable } from '../rx/observable';
4
- import { tap } from '../rx/operators';
5
- import { Operation, OperationResult, TRPCLink } from './types';
4
+ import { Operation, OperationResultEnvelope, TRPCLink } from './types';
6
5
 
7
6
  type ConsoleEsque = {
8
7
  log: (...args: any[]) => void;
@@ -15,7 +14,7 @@ type EnableFnOptions<TRouter extends AnyRouter> =
15
14
  })
16
15
  | {
17
16
  direction: 'down';
18
- result: OperationResult<TRouter, unknown> | TRPCClientError<TRouter>;
17
+ result: OperationResultEnvelope<unknown> | TRPCClientError<TRouter>;
19
18
  };
20
19
  type EnabledFn<TRouter extends AnyRouter> = (
21
20
  opts: EnableFnOptions<TRouter>,
@@ -34,7 +33,7 @@ type LogFnOptions<TRouter extends AnyRouter> = Operation &
34
33
  * Request result
35
34
  */
36
35
  direction: 'down';
37
- result: OperationResult<TRouter, unknown> | TRPCClientError<TRouter>;
36
+ result: OperationResultEnvelope<unknown> | TRPCClientError<TRouter>;
38
37
  elapsedMs: number;
39
38
  }
40
39
  );
@@ -93,7 +92,7 @@ const defaultLogger =
93
92
  const fn: 'error' | 'log' =
94
93
  props.direction === 'down' &&
95
94
  props.result &&
96
- (props.result instanceof Error || 'error' in props.result.data)
95
+ (props.result instanceof Error || 'error' in props.result.result)
97
96
  ? 'error'
98
97
  : 'log';
99
98
 
@@ -117,7 +116,7 @@ export function loggerLink<TRouter extends AnyRouter = AnyRouter>(
117
116
  });
118
117
  const requestStartTime = Date.now();
119
118
  function logResult(
120
- result: OperationResult<TRouter, unknown> | TRPCClientError<TRouter>,
119
+ result: OperationResultEnvelope<unknown> | TRPCClientError<TRouter>,
121
120
  ) {
122
121
  const elapsedMs = Date.now() - requestStartTime;
123
122
 
@@ -1,6 +1,5 @@
1
1
  import { AnyRouter } from '@trpc/server';
2
- import { observable } from '../rx/observable';
3
- import { Unsubscribable } from '../rx/types';
2
+ import { Unsubscribable, observable } from '@trpc/server/observable';
4
3
  import { TRPCLink } from './types';
5
4
 
6
5
  export function retryLink<TRouter extends AnyRouter = AnyRouter>(opts: {
@@ -27,7 +26,7 @@ export function retryLink<TRouter extends AnyRouter = AnyRouter>(opts: {
27
26
  attempt();
28
27
  },
29
28
  next(result) {
30
- if ('result' in result.data) {
29
+ if ('result' in result.result) {
31
30
  isDone = true;
32
31
  observer.next(result);
33
32
  return;
@@ -1,9 +1,9 @@
1
1
  /* eslint-disable @typescript-eslint/no-empty-function */
2
+ import { observable } from '@trpc/server/observable';
3
+ import { splitLink } from '../';
4
+ import { OperationLink, TRPCLink } from '../';
2
5
  import { AnyRouter } from '../../../server/src';
3
6
  import { createChain } from '../links/internals/createChain';
4
- import { splitLink } from '../links/splitLink';
5
- import { OperationLink, TRPCLink } from '../links/types';
6
- import { observable } from '../rx';
7
7
 
8
8
  test('splitLink', () => {
9
9
  const wsLinkSpy = jest.fn();
@@ -1,7 +1,7 @@
1
1
  import { AnyRouter } from '@trpc/server';
2
- import { observable } from '../rx/observable';
3
- import { TRPCLink, Operation } from './types';
2
+ import { observable } from '@trpc/server/observable';
4
3
  import { createChain } from './internals/createChain';
4
+ import { Operation, TRPCLink } from './types';
5
5
 
6
6
  function asArray<T>(value: T | T[]) {
7
7
  return Array.isArray(value) ? value : [value];
@@ -17,9 +17,9 @@ export function splitLink<TRouter extends AnyRouter = AnyRouter>(opts: {
17
17
  */
18
18
  false: TRPCLink<TRouter> | TRPCLink<TRouter>[];
19
19
  }): TRPCLink<TRouter> {
20
- return (rt) => {
21
- const yes = asArray(opts.true).map((link) => link(rt));
22
- const no = asArray(opts.false).map((link) => link(rt));
20
+ return (runtime) => {
21
+ const yes = asArray(opts.true).map((link) => link(runtime));
22
+ const no = asArray(opts.false).map((link) => link(runtime));
23
23
  return (props) => {
24
24
  return observable((observer) => {
25
25
  const links = opts.condition(props.op) ? yes : no;
@@ -1,6 +1,6 @@
1
- import { AnyRouter, inferRouterError, Dict } from '@trpc/server';
2
- import { TRPCResponse } from '@trpc/server/rpc';
3
- import { Observable, Observer } from '../rx/types';
1
+ import { AnyRouter, DataTransformer } from '@trpc/server';
2
+ import { Observable, Observer } from '@trpc/server/observable';
3
+ import { TRPCResultMessage, TRPCSuccessResponse } from '@trpc/server/rpc';
4
4
  import { TRPCClientError } from '../TRPCClientError';
5
5
 
6
6
  export type CancelFn = () => void;
@@ -16,10 +16,10 @@ export type Operation<TInput = unknown> = {
16
16
  type: 'query' | 'mutation' | 'subscription';
17
17
  input: TInput;
18
18
  path: string;
19
- context?: OperationContext;
19
+ context: OperationContext;
20
20
  };
21
21
 
22
- export type HTTPHeaders = Dict<string | string[]>;
22
+ export type HTTPHeaders = Record<string, string | string[]>;
23
23
 
24
24
  /**
25
25
  * The default `fetch` implementation has an overloaded signature. By convention this library
@@ -30,26 +30,29 @@ export type TRPCFetch = (
30
30
  options?: RequestInit,
31
31
  ) => Promise<Response>;
32
32
 
33
- export interface LinkRuntime {
34
- headers: () => HTTPHeaders | Promise<HTTPHeaders>;
33
+ export interface TRPCClientRuntime {
35
34
  fetch: TRPCFetch;
36
35
  AbortController?: typeof AbortController;
36
+ headers: () => HTTPHeaders | Promise<HTTPHeaders>;
37
+ transformer: DataTransformer;
37
38
  }
38
39
 
39
- export interface OperationResult<TRouter extends AnyRouter, TOutput> {
40
- data: TRPCResponse<TOutput, inferRouterError<TRouter>>;
40
+ export interface OperationResultEnvelope<TOutput> {
41
+ result:
42
+ | TRPCSuccessResponse<TOutput>['result']
43
+ | TRPCResultMessage<TOutput>['result'];
41
44
  context?: OperationContext;
42
45
  }
43
46
 
44
47
  export type OperationResultObservable<
45
48
  TRouter extends AnyRouter,
46
49
  TOutput,
47
- > = Observable<OperationResult<TRouter, TOutput>, TRPCClientError<TRouter>>;
50
+ > = Observable<OperationResultEnvelope<TOutput>, TRPCClientError<TRouter>>;
48
51
 
49
52
  export type OperationResultObserver<
50
53
  TRouter extends AnyRouter,
51
54
  TOutput,
52
- > = Observer<OperationResult<TRouter, TOutput>, TRPCClientError<TRouter>>;
55
+ > = Observer<OperationResultEnvelope<TOutput>, TRPCClientError<TRouter>>;
53
56
 
54
57
  export type OperationLink<
55
58
  TRouter extends AnyRouter,
@@ -61,5 +64,5 @@ export type OperationLink<
61
64
  }) => OperationResultObservable<TRouter, TOutput>;
62
65
 
63
66
  export type TRPCLink<TRouter extends AnyRouter> = (
64
- opts: LinkRuntime,
67
+ opts: TRPCClientRuntime,
65
68
  ) => OperationLink<TRouter>;
@@ -1,26 +1,42 @@
1
- import { AnyRouter, ProcedureType } from '@trpc/server';
1
+ import { AnyRouter, ProcedureType, inferRouterError } from '@trpc/server';
2
+ import { Observer, UnsubscribeFn, observable } from '@trpc/server/observable';
2
3
  import {
3
4
  TRPCClientIncomingMessage,
4
5
  TRPCClientIncomingRequest,
5
- TRPCRequest,
6
- TRPCResponse,
6
+ TRPCClientOutgoingMessage,
7
+ TRPCRequestMessage,
8
+ TRPCResponseMessage,
7
9
  } from '@trpc/server/rpc';
8
- import { retryDelay } from '../internals/retryDelay';
9
- import { UnsubscribeFn } from '../rx';
10
- import { observable } from '../rx/observable';
11
10
  import { TRPCClientError } from '../TRPCClientError';
12
- import { Operation, OperationResultObserver, TRPCLink } from './types';
11
+ import { retryDelay } from '../internals/retryDelay';
12
+ import { transformResult } from './internals/transformResult';
13
+ import { Operation, TRPCLink } from './types';
14
+
15
+ type WSCallbackResult<TRouter extends AnyRouter, TOutput> = TRPCResponseMessage<
16
+ TOutput,
17
+ inferRouterError<TRouter>
18
+ >;
19
+
20
+ type WSCallbackObserver<TRouter extends AnyRouter, TOutput> = Observer<
21
+ WSCallbackResult<TRouter, TOutput>,
22
+ TRPCClientError<TRouter>
23
+ >;
13
24
 
14
25
  export interface WebSocketClientOptions {
15
26
  url: string;
16
- WebSocket?: WebSocket;
27
+ WebSocket?: typeof WebSocket;
17
28
  retryDelayMs?: typeof retryDelay;
29
+ onOpen?: () => void;
30
+ onClose?: () => void;
18
31
  }
32
+
19
33
  export function createWSClient(opts: WebSocketClientOptions) {
20
34
  const {
21
35
  url,
22
36
  WebSocket: WebSocketImpl = WebSocket,
23
37
  retryDelayMs: retryDelayFn = retryDelay,
38
+ onOpen,
39
+ onClose,
24
40
  } = opts;
25
41
  /* istanbul ignore next */
26
42
  if (!WebSocketImpl) {
@@ -31,11 +47,11 @@ export function createWSClient(opts: WebSocketClientOptions) {
31
47
  /**
32
48
  * outgoing messages buffer whilst not open
33
49
  */
34
- let outgoing: TRPCRequest[] = [];
50
+ let outgoing: TRPCClientOutgoingMessage[] = [];
35
51
  /**
36
52
  * pending outgoing requests that are awaiting callback
37
53
  */
38
- type TCallbacks = OperationResultObserver<AnyRouter, unknown>;
54
+ type TCallbacks = WSCallbackObserver<AnyRouter, unknown>;
39
55
  type TRequest = {
40
56
  /**
41
57
  * Reference to the WebSocket instance this request was made to
@@ -112,7 +128,7 @@ export function createWSClient(opts: WebSocketClientOptions) {
112
128
  }
113
129
 
114
130
  function createWS() {
115
- const conn = new WebSocket(url);
131
+ const conn = new WebSocketImpl(url);
116
132
  clearTimeout(connectTimer as any);
117
133
  connectTimer = null;
118
134
 
@@ -123,6 +139,7 @@ export function createWSClient(opts: WebSocketClientOptions) {
123
139
  }
124
140
  connectAttempt = 0;
125
141
  state = 'open';
142
+ onOpen?.();
126
143
  dispatch();
127
144
  });
128
145
  conn.addEventListener('error', () => {
@@ -132,6 +149,9 @@ export function createWSClient(opts: WebSocketClientOptions) {
132
149
  });
133
150
  const handleIncomingRequest = (req: TRPCClientIncomingRequest) => {
134
151
  if (req.method === 'reconnect' && conn === activeConnection) {
152
+ if (state === 'open') {
153
+ onClose?.();
154
+ }
135
155
  reconnect();
136
156
  // notify subscribers
137
157
  for (const pendingReq of Object.values(pendingRequests)) {
@@ -141,14 +161,14 @@ export function createWSClient(opts: WebSocketClientOptions) {
141
161
  }
142
162
  }
143
163
  };
144
- const handleIncomingResponse = (data: TRPCResponse) => {
164
+ const handleIncomingResponse = (data: TRPCResponseMessage) => {
145
165
  const req = data.id !== null && pendingRequests[data.id];
146
166
  if (!req) {
147
167
  // do something?
148
168
  return;
149
169
  }
150
170
 
151
- req.callbacks.next?.({ data });
171
+ req.callbacks.next?.(data);
152
172
  if (req.ws !== activeConnection && conn === activeConnection) {
153
173
  const oldWs = req.ws;
154
174
  // gracefully replace old connection with this
@@ -179,13 +199,16 @@ export function createWSClient(opts: WebSocketClientOptions) {
179
199
  });
180
200
 
181
201
  conn.addEventListener('close', () => {
202
+ if (state === 'open') {
203
+ onClose?.();
204
+ }
205
+
182
206
  if (activeConnection === conn) {
183
207
  // connection might have been replaced already
184
208
  tryReconnect();
185
209
  }
186
210
 
187
- for (const key in pendingRequests) {
188
- const req = pendingRequests[key];
211
+ for (const [key, req] of Object.entries(pendingRequests)) {
189
212
  if (req.ws !== conn) {
190
213
  continue;
191
214
  }
@@ -208,9 +231,8 @@ export function createWSClient(opts: WebSocketClientOptions) {
208
231
 
209
232
  function request(op: Operation, callbacks: TCallbacks): UnsubscribeFn {
210
233
  const { type, input, path, id } = op;
211
- const envelope: TRPCRequest = {
234
+ const envelope: TRPCRequestMessage = {
212
235
  id,
213
- jsonrpc: '2.0',
214
236
  method: type,
215
237
  params: {
216
238
  input,
@@ -238,7 +260,6 @@ export function createWSClient(opts: WebSocketClientOptions) {
238
260
  outgoing.push({
239
261
  id,
240
262
  method: 'subscription.stop',
241
- params: undefined,
242
263
  });
243
264
  dispatch();
244
265
  }
@@ -247,7 +268,10 @@ export function createWSClient(opts: WebSocketClientOptions) {
247
268
  return {
248
269
  close: () => {
249
270
  state = 'closed';
271
+ onClose?.();
250
272
  closeIfNoPending(activeConnection);
273
+ clearTimeout(connectTimer as any);
274
+ connectTimer = null;
251
275
  },
252
276
  request,
253
277
  getConnection() {
@@ -279,11 +303,13 @@ class TRPCSubscriptionEndedError extends Error {
279
303
  export function wsLink<TRouter extends AnyRouter>(
280
304
  opts: WebSocketLinkOptions,
281
305
  ): TRPCLink<TRouter> {
282
- return () => {
306
+ return (runtime) => {
283
307
  const { client } = opts;
284
308
  return ({ op }) => {
285
309
  return observable((observer) => {
286
- const { type, input, path, id, context } = op;
310
+ const { type, path, id, context } = op;
311
+
312
+ const input = runtime.transformer.serialize(op.input);
287
313
 
288
314
  let isDone = false;
289
315
  const unsub = client.request(
@@ -291,7 +317,7 @@ export function wsLink<TRouter extends AnyRouter>(
291
317
  {
292
318
  error(err) {
293
319
  isDone = true;
294
- observer.error(err);
320
+ observer.error(err as TRPCClientError<any>);
295
321
  unsub();
296
322
  },
297
323
  complete() {
@@ -308,8 +334,16 @@ export function wsLink<TRouter extends AnyRouter>(
308
334
  observer.complete();
309
335
  }
310
336
  },
311
- next(result) {
312
- observer.next(result);
337
+ next(message) {
338
+ const transformed = transformResult(message, runtime);
339
+
340
+ if (!transformed.ok) {
341
+ observer.error(TRPCClientError.from(transformed.error));
342
+ return;
343
+ }
344
+ observer.next({
345
+ result: transformed.result,
346
+ });
313
347
 
314
348
  if (op.type !== 'subscription') {
315
349
  // if it isn't a subscription we don't care about next response
@@ -1,81 +0,0 @@
1
- import _defineProperty from '@babel/runtime/helpers/defineProperty';
2
- import _classCallCheck from '@babel/runtime/helpers/classCallCheck';
3
- import _createClass from '@babel/runtime/helpers/createClass';
4
- import _assertThisInitialized from '@babel/runtime/helpers/assertThisInitialized';
5
- import _inherits from '@babel/runtime/helpers/inherits';
6
- import _possibleConstructorReturn from '@babel/runtime/helpers/possibleConstructorReturn';
7
- import _getPrototypeOf from '@babel/runtime/helpers/getPrototypeOf';
8
- import _wrapNativeSuper from '@babel/runtime/helpers/wrapNativeSuper';
9
-
10
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
11
-
12
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
13
-
14
- function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
15
-
16
- function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
17
-
18
- var TRPCClientError = /*#__PURE__*/function (_Error) {
19
- _inherits(TRPCClientError, _Error);
20
-
21
- var _super = /*#__PURE__*/_createSuper(TRPCClientError);
22
-
23
- /**
24
- * @deprecated use `cause`
25
- */
26
- function TRPCClientError(message, opts) {
27
- var _opts$cause, _opts$result, _opts$result2;
28
-
29
- var _this;
30
-
31
- _classCallCheck(this, TRPCClientError);
32
-
33
- var cause = (_opts$cause = opts === null || opts === void 0 ? void 0 : opts.cause) !== null && _opts$cause !== void 0 ? _opts$cause : opts === null || opts === void 0 ? void 0 : opts.originalError; // eslint-disable-next-line @typescript-eslint/ban-ts-comment
34
- // @ts-ignore https://github.com/tc39/proposal-error-cause
35
-
36
- _this = _super.call(this, message, {
37
- cause: cause
38
- });
39
- _this.originalError = void 0;
40
- _this.cause = void 0;
41
- _this.shape = void 0;
42
- _this.data = void 0;
43
- _this.meta = void 0;
44
- _this.meta = opts === null || opts === void 0 ? void 0 : opts.meta;
45
- _this.cause = _this.originalError = cause;
46
- _this.shape = opts === null || opts === void 0 ? void 0 : (_opts$result = opts.result) === null || _opts$result === void 0 ? void 0 : _opts$result.error;
47
- _this.data = opts === null || opts === void 0 ? void 0 : (_opts$result2 = opts.result) === null || _opts$result2 === void 0 ? void 0 : _opts$result2.error.data;
48
- _this.name = 'TRPCClientError';
49
- Object.setPrototypeOf(_assertThisInitialized(_this), TRPCClientError.prototype);
50
- return _this;
51
- }
52
-
53
- _createClass(TRPCClientError, null, [{
54
- key: "from",
55
- value: function from(cause) {
56
- var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
57
-
58
- if (!(cause instanceof Error)) {
59
- var _message;
60
-
61
- return new TRPCClientError((_message = cause.error.message) !== null && _message !== void 0 ? _message : '', _objectSpread(_objectSpread({}, opts), {}, {
62
- cause: null,
63
- result: cause
64
- }));
65
- }
66
-
67
- if (cause.name === 'TRPCClientError') {
68
- return cause;
69
- }
70
-
71
- return new TRPCClientError(cause.message, _objectSpread(_objectSpread({}, opts), {}, {
72
- cause: cause,
73
- result: null
74
- }));
75
- }
76
- }]);
77
-
78
- return TRPCClientError;
79
- }( /*#__PURE__*/_wrapNativeSuper(Error));
80
-
81
- export { TRPCClientError as T };