@trpc/client 10.0.0-alpha.3 → 10.0.0-alpha.32

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 (172) hide show
  1. package/dist/TRPCClientError.d.ts +3 -11
  2. package/dist/TRPCClientError.d.ts.map +1 -1
  3. package/dist/createTRPCClient.d.ts +3 -4
  4. package/dist/createTRPCClient.d.ts.map +1 -1
  5. package/dist/createTRPCClientProxy.d.ts +8 -0
  6. package/dist/createTRPCClientProxy.d.ts.map +1 -0
  7. package/dist/{httpUtils-c09d7b79.mjs → httpUtils-089853f6.mjs} +38 -30
  8. package/dist/{httpUtils-1f9e4e3c.js → httpUtils-a0169eef.js} +38 -29
  9. package/dist/index.d.ts +2 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +266 -104
  12. package/dist/index.mjs +253 -95
  13. package/dist/internals/TRPCClient.d.ts +14 -17
  14. package/dist/internals/TRPCClient.d.ts.map +1 -1
  15. package/dist/internals/dataLoader.d.ts +7 -4
  16. package/dist/internals/dataLoader.d.ts.map +1 -1
  17. package/dist/links/dedupeLink.d.ts.map +1 -1
  18. package/dist/links/httpBatchLink.d.ts +5 -2
  19. package/dist/links/httpBatchLink.d.ts.map +1 -1
  20. package/dist/links/httpBatchLink.js +197 -69
  21. package/dist/links/httpBatchLink.mjs +197 -69
  22. package/dist/links/httpLink.d.ts +1 -1
  23. package/dist/links/httpLink.d.ts.map +1 -1
  24. package/dist/links/httpLink.js +5 -5
  25. package/dist/links/httpLink.mjs +5 -5
  26. package/dist/links/index.d.ts +9 -0
  27. package/dist/links/index.d.ts.map +1 -0
  28. package/dist/links/internals/httpUtils.d.ts +30 -0
  29. package/dist/links/internals/httpUtils.d.ts.map +1 -0
  30. package/dist/links/internals/transformOperationResult.d.ts +17 -3
  31. package/dist/links/internals/transformOperationResult.d.ts.map +1 -1
  32. package/dist/links/loggerLink.d.ts.map +1 -1
  33. package/dist/links/loggerLink.js +2 -3
  34. package/dist/links/loggerLink.mjs +1 -2
  35. package/dist/links/retryLink.d.ts.map +1 -1
  36. package/dist/links/splitLink.d.ts +1 -1
  37. package/dist/links/splitLink.d.ts.map +1 -1
  38. package/dist/links/splitLink.js +3 -25
  39. package/dist/links/splitLink.mjs +2 -28
  40. package/dist/links/types.d.ts +12 -9
  41. package/dist/links/types.d.ts.map +1 -1
  42. package/dist/links/wsLink.d.ts +3 -3
  43. package/dist/links/wsLink.d.ts.map +1 -1
  44. package/dist/links/wsLink.js +11 -376
  45. package/dist/links/wsLink.mjs +9 -369
  46. package/dist/splitLink-62ff9db0.mjs +49 -0
  47. package/dist/splitLink-8202386e.js +52 -0
  48. package/dist/wsLink-69f5adb8.js +451 -0
  49. package/dist/wsLink-9468a563.mjs +436 -0
  50. package/links/httpBatchLink/dist/trpc-client-links-httpBatchLink.cjs.dev.js +81 -15
  51. package/links/httpBatchLink/dist/trpc-client-links-httpBatchLink.cjs.prod.js +81 -15
  52. package/links/httpBatchLink/dist/trpc-client-links-httpBatchLink.esm.js +77 -15
  53. package/links/httpBatchLink/index.d.ts +1 -1
  54. package/links/httpBatchLink/index.js +1 -1
  55. package/links/httpLink/dist/trpc-client-links-httpLink.cjs.dev.js +76 -9
  56. package/links/httpLink/dist/trpc-client-links-httpLink.cjs.prod.js +76 -9
  57. package/links/httpLink/dist/trpc-client-links-httpLink.esm.js +72 -9
  58. package/links/httpLink/index.d.ts +1 -1
  59. package/links/httpLink/index.js +1 -1
  60. package/links/loggerLink/index.d.ts +1 -1
  61. package/links/loggerLink/index.js +1 -1
  62. package/links/splitLink/index.d.ts +1 -1
  63. package/links/splitLink/index.js +1 -1
  64. package/links/wsLink/dist/trpc-client-links-wsLink.cjs.dev.js +3 -1
  65. package/links/wsLink/dist/trpc-client-links-wsLink.cjs.prod.js +3 -1
  66. package/links/wsLink/dist/trpc-client-links-wsLink.esm.js +3 -1
  67. package/links/wsLink/index.d.ts +1 -1
  68. package/links/wsLink/index.js +1 -1
  69. package/package.json +23 -30
  70. package/src/TRPCClientError.ts +5 -13
  71. package/src/createTRPCClient.ts +8 -3
  72. package/src/createTRPCClientProxy.ts +56 -0
  73. package/src/index.ts +2 -1
  74. package/src/internals/TRPCClient.ts +52 -36
  75. package/src/internals/dataLoader.ts +120 -45
  76. package/src/links/dedupeLink.test.ts +1 -1
  77. package/src/links/dedupeLink.ts +3 -5
  78. package/src/links/httpBatchLink.ts +64 -31
  79. package/src/links/httpLink.ts +4 -4
  80. package/src/links/index.ts +8 -0
  81. package/src/links/internals/createChain.test.ts +5 -5
  82. package/src/links/internals/createChain.ts +3 -3
  83. package/src/links/internals/httpUtils.ts +116 -0
  84. package/src/links/internals/transformOperationResult.ts +40 -12
  85. package/src/links/loggerLink.ts +1 -2
  86. package/src/links/retryLink.ts +1 -2
  87. package/src/links/splitLink.test.ts +3 -3
  88. package/src/links/splitLink.ts +5 -5
  89. package/src/links/types.ts +14 -9
  90. package/src/links/wsLink.ts +16 -14
  91. package/dist/TRPCClientError-17b117e1.mjs +0 -81
  92. package/dist/TRPCClientError-ec6bd2ca.js +0 -94
  93. package/dist/createChain-389cc116.mjs +0 -25
  94. package/dist/createChain-864dbb30.js +0 -27
  95. package/dist/internals/transformRPCResponse.d.ts +0 -15
  96. package/dist/internals/transformRPCResponse.d.ts.map +0 -1
  97. package/dist/links/httpUtils.d.ts +0 -22
  98. package/dist/links/httpUtils.d.ts.map +0 -1
  99. package/dist/links/transformerLink.d.ts +0 -4
  100. package/dist/links/transformerLink.d.ts.map +0 -1
  101. package/dist/links/transformerLink.js +0 -75
  102. package/dist/links/transformerLink.mjs +0 -67
  103. package/dist/links/transformerLink.ts.js +0 -1
  104. package/dist/observable-7e66cb56.mjs +0 -102
  105. package/dist/observable-85669100.js +0 -104
  106. package/dist/rx/index.d.ts +0 -3
  107. package/dist/rx/index.d.ts.map +0 -1
  108. package/dist/rx/index.js +0 -9
  109. package/dist/rx/index.mjs +0 -1
  110. package/dist/rx/index.ts.js +0 -1
  111. package/dist/rx/observable.d.ts +0 -4
  112. package/dist/rx/observable.d.ts.map +0 -1
  113. package/dist/rx/operators/index.d.ts +0 -4
  114. package/dist/rx/operators/index.d.ts.map +0 -1
  115. package/dist/rx/operators/index.js +0 -38
  116. package/dist/rx/operators/index.mjs +0 -32
  117. package/dist/rx/operators/index.ts.js +0 -1
  118. package/dist/rx/operators/map.d.ts +0 -3
  119. package/dist/rx/operators/map.d.ts.map +0 -1
  120. package/dist/rx/operators/share.d.ts +0 -6
  121. package/dist/rx/operators/share.d.ts.map +0 -1
  122. package/dist/rx/operators/tap.d.ts +0 -3
  123. package/dist/rx/operators/tap.d.ts.map +0 -1
  124. package/dist/rx/types.d.ts +0 -29
  125. package/dist/rx/types.d.ts.map +0 -1
  126. package/dist/rx/util/identity.d.ts +0 -2
  127. package/dist/rx/util/identity.d.ts.map +0 -1
  128. package/dist/rx/util/observableToPromise.d.ts +0 -10
  129. package/dist/rx/util/observableToPromise.d.ts.map +0 -1
  130. package/dist/rx/util/pipe.d.ts +0 -4
  131. package/dist/rx/util/pipe.d.ts.map +0 -1
  132. package/dist/share-4d79dc49.js +0 -110
  133. package/dist/share-671b63fa.mjs +0 -108
  134. package/dist/tap-538fa07f.mjs +0 -30
  135. package/dist/tap-799a2d33.js +0 -32
  136. package/links/transformerLink/dist/trpc-client-links-transformerLink.cjs.d.ts +0 -1
  137. package/links/transformerLink/dist/trpc-client-links-transformerLink.cjs.dev.js +0 -67
  138. package/links/transformerLink/dist/trpc-client-links-transformerLink.cjs.js +0 -7
  139. package/links/transformerLink/dist/trpc-client-links-transformerLink.cjs.prod.js +0 -67
  140. package/links/transformerLink/dist/trpc-client-links-transformerLink.esm.js +0 -63
  141. package/links/transformerLink/index.d.ts +0 -1
  142. package/links/transformerLink/index.js +0 -1
  143. package/rx/dist/trpc-client-rx.cjs.d.ts +0 -1
  144. package/rx/dist/trpc-client-rx.cjs.dev.js +0 -9
  145. package/rx/dist/trpc-client-rx.cjs.js +0 -7
  146. package/rx/dist/trpc-client-rx.cjs.prod.js +0 -9
  147. package/rx/dist/trpc-client-rx.esm.js +0 -1
  148. package/rx/index.d.ts +0 -1
  149. package/rx/index.js +0 -1
  150. package/rx/operators/dist/trpc-client-rx-operators.cjs.d.ts +0 -1
  151. package/rx/operators/dist/trpc-client-rx-operators.cjs.dev.js +0 -39
  152. package/rx/operators/dist/trpc-client-rx-operators.cjs.js +0 -7
  153. package/rx/operators/dist/trpc-client-rx-operators.cjs.prod.js +0 -39
  154. package/rx/operators/dist/trpc-client-rx-operators.esm.js +0 -33
  155. package/rx/operators/index.d.ts +0 -1
  156. package/rx/operators/index.js +0 -1
  157. package/src/internals/transformRPCResponse.ts +0 -25
  158. package/src/links/httpUtils.ts +0 -94
  159. package/src/links/transformerLink.ts +0 -70
  160. package/src/rx/index.ts +0 -2
  161. package/src/rx/observable.test.ts +0 -83
  162. package/src/rx/observable.ts +0 -70
  163. package/src/rx/operators/index.ts +0 -3
  164. package/src/rx/operators/map.test.ts +0 -92
  165. package/src/rx/operators/map.ts +0 -25
  166. package/src/rx/operators/share.test.ts +0 -60
  167. package/src/rx/operators/share.ts +0 -67
  168. package/src/rx/operators/tap.ts +0 -26
  169. package/src/rx/types.ts +0 -69
  170. package/src/rx/util/identity.ts +0 -3
  171. package/src/rx/util/observableToPromise.ts +0 -49
  172. package/src/rx/util/pipe.ts +0 -22
@@ -1,7 +1,5 @@
1
1
  import { AnyRouter } from '@trpc/server';
2
- import { observable } from '../rx/observable';
3
- import { share } from '../rx/operators';
4
- import { Observable } from '../rx/types';
2
+ import { Observable, observable, share } from '@trpc/server/observable';
5
3
  import { TRPCLink } from './types';
6
4
 
7
5
  export function dedupeLink<
@@ -28,7 +26,7 @@ export function dedupeLink<
28
26
  function reset() {
29
27
  delete pending[key];
30
28
  }
31
- const next$ = next(op).subscribe({
29
+ const subscription = next(op).subscribe({
32
30
  next(v) {
33
31
  observer.next(v);
34
32
  },
@@ -43,7 +41,7 @@ export function dedupeLink<
43
41
  });
44
42
  return () => {
45
43
  reset();
46
- next$.unsubscribe();
44
+ subscription.unsubscribe();
47
45
  };
48
46
  }).pipe(share());
49
47
  pending[key] = shared$;
@@ -1,47 +1,80 @@
1
1
  import { AnyRouter, ProcedureType } from '@trpc/server';
2
+ import { observable } from '@trpc/server/observable';
2
3
  import { dataLoader } from '../internals/dataLoader';
3
- import { observable } from '../rx/observable';
4
+ import {
5
+ HTTPLinkOptions,
6
+ ResponseShape,
7
+ getUrl,
8
+ httpRequest,
9
+ } from './internals/httpUtils';
4
10
  import { TRPCLink } from './types';
5
- import { HTTPLinkOptions, httpRequest, ResponseShape } from './httpUtils';
11
+
12
+ export interface HttpBatchLinkOptions extends HTTPLinkOptions {
13
+ maxURLLength?: number;
14
+ }
6
15
 
7
16
  export function httpBatchLink<TRouter extends AnyRouter>(
8
- opts: HTTPLinkOptions,
17
+ opts: HttpBatchLinkOptions,
9
18
  ): TRPCLink<TRouter> {
10
- const { url } = opts;
19
+ // initialized config
11
20
  return (runtime) => {
12
- type Key = { id: number; path: string; input: unknown };
13
- const fetcher = (type: ProcedureType) => (keyInputPairs: Key[]) => {
14
- const path = keyInputPairs.map((op) => op.path).join(',');
15
- const inputs = keyInputPairs.map((op) => op.input);
21
+ type BatchOperation = { id: number; path: string; input: unknown };
16
22
 
17
- const { promise, cancel } = httpRequest({
18
- url,
19
- inputs,
20
- path,
21
- runtime,
22
- type,
23
- });
23
+ const maxURLLength = opts.maxURLLength || Infinity;
24
+
25
+ const batchLoader = (type: ProcedureType) => {
26
+ const validate = (batchOps: BatchOperation[]) => {
27
+ if (maxURLLength === Infinity) {
28
+ // escape hatch for quick calcs
29
+ return true;
30
+ }
31
+ const path = batchOps.map((op) => op.path).join(',');
32
+ const inputs = batchOps.map((op) => op.input);
33
+
34
+ const url = getUrl({ url: opts.url, runtime, type, path, inputs });
35
+ return url.length <= maxURLLength;
36
+ };
37
+
38
+ const fetch = (batchOps: BatchOperation[]) => {
39
+ const path = batchOps.map((op) => op.path).join(',');
40
+ const inputs = batchOps.map((op) => op.input);
24
41
 
25
- return {
26
- promise: promise.then((res) => {
27
- const resJSON = Array.isArray(res.json)
28
- ? res.json
29
- : keyInputPairs.map(() => res.json);
42
+ const { promise, cancel } = httpRequest({
43
+ url: opts.url,
44
+ runtime,
45
+ type,
46
+ path,
47
+ inputs,
48
+ });
30
49
 
31
- const result = resJSON.map((item) => ({
32
- meta: res.meta,
33
- json: item,
34
- }));
50
+ return {
51
+ promise: promise.then((res) => {
52
+ const resJSON = Array.isArray(res.json)
53
+ ? res.json
54
+ : batchOps.map(() => res.json);
35
55
 
36
- return result;
37
- }),
38
- cancel,
56
+ const result = resJSON.map((item) => ({
57
+ meta: res.meta,
58
+ json: item,
59
+ }));
60
+
61
+ return result;
62
+ }),
63
+ cancel,
64
+ };
39
65
  };
66
+
67
+ return { validate, fetch };
40
68
  };
41
- const query = dataLoader<Key, ResponseShape>(fetcher('query'));
42
- const mutation = dataLoader<Key, ResponseShape>(fetcher('mutation'));
43
- const subscription = dataLoader<Key, ResponseShape>(
44
- fetcher('subscription'),
69
+
70
+ const query = dataLoader<BatchOperation, ResponseShape>(
71
+ batchLoader('query'),
72
+ );
73
+ const mutation = dataLoader<BatchOperation, ResponseShape>(
74
+ batchLoader('mutation'),
75
+ );
76
+ const subscription = dataLoader<BatchOperation, ResponseShape>(
77
+ batchLoader('subscription'),
45
78
  );
46
79
 
47
80
  const loaders = { query, subscription, mutation };
@@ -1,7 +1,7 @@
1
1
  import { AnyRouter } from '@trpc/server';
2
- import { observable } from '../rx/observable';
2
+ import { observable } from '@trpc/server/observable';
3
+ import { HTTPLinkOptions, httpRequest } from './internals/httpUtils';
3
4
  import { TRPCLink } from './types';
4
- import { HTTPLinkOptions, httpRequest } from './httpUtils';
5
5
 
6
6
  export function httpLink<TRouter extends AnyRouter>(
7
7
  opts: HTTPLinkOptions,
@@ -12,11 +12,11 @@ export function httpLink<TRouter extends AnyRouter>(
12
12
  observable((observer) => {
13
13
  const { path, input, type } = op;
14
14
  const { promise, cancel } = httpRequest({
15
+ url,
15
16
  runtime,
17
+ type,
16
18
  path,
17
19
  input,
18
- type,
19
- url,
20
20
  });
21
21
  promise
22
22
  .then((res) => {
@@ -0,0 +1,8 @@
1
+ export * from './dedupeLink';
2
+ export * from './httpBatchLink';
3
+ export * from './httpLink';
4
+ export * from './loggerLink';
5
+ export * from './retryLink';
6
+ export * from './splitLink';
7
+ export * from './wsLink';
8
+ export * from './types';
@@ -1,6 +1,6 @@
1
+ import { observable } from '@trpc/server/observable';
1
2
  import { AnyRouter } from '@trpc/server/src';
2
3
  import { createChain } from './createChain';
3
- import { observable } from '../../rx/observable';
4
4
 
5
5
  describe('chain', () => {
6
6
  test('trivial', () => {
@@ -8,9 +8,9 @@ describe('chain', () => {
8
8
  links: [
9
9
  ({ next, op }) => {
10
10
  return observable((observer) => {
11
- const next$ = next(op).subscribe(observer);
11
+ const subscription = next(op).subscribe(observer);
12
12
  return () => {
13
- next$.unsubscribe();
13
+ subscription.unsubscribe();
14
14
  };
15
15
  });
16
16
  },
@@ -62,9 +62,9 @@ describe('chain', () => {
62
62
  },
63
63
  },
64
64
  });
65
- const next$ = next(op).subscribe(observer);
65
+ const subscription = next(op).subscribe(observer);
66
66
  return () => {
67
- next$.unsubscribe();
67
+ subscription.unsubscribe();
68
68
  };
69
69
  });
70
70
  },
@@ -1,5 +1,5 @@
1
1
  import { AnyRouter } from '@trpc/server';
2
- import { observable } from '../../rx/observable';
2
+ import { observable } from '@trpc/server/observable';
3
3
  import { Operation, OperationLink, OperationResultObservable } from '../types';
4
4
 
5
5
  /** @internal */
@@ -14,7 +14,7 @@ export function createChain<
14
14
  return observable((observer) => {
15
15
  function execute(index = 0, op = opts.op) {
16
16
  const next = opts.links[index];
17
- const next$ = next({
17
+ const subscription = next({
18
18
  op,
19
19
  next(nextOp) {
20
20
  const nextObserver = execute(index + 1, nextOp);
@@ -22,7 +22,7 @@ export function createChain<
22
22
  return nextObserver;
23
23
  },
24
24
  });
25
- return next$;
25
+ return subscription;
26
26
  }
27
27
 
28
28
  const obs$ = execute();
@@ -0,0 +1,116 @@
1
+ import { ProcedureType } from '@trpc/server';
2
+ import { PromiseAndCancel, TRPCClientRuntime } from '../types';
3
+
4
+ export interface HTTPLinkOptions {
5
+ url: string;
6
+ }
7
+
8
+ // https://github.com/trpc/trpc/pull/669
9
+ function arrayToDict(array: unknown[]) {
10
+ const dict: Record<number, unknown> = {};
11
+ for (let index = 0; index < array.length; index++) {
12
+ const element = array[index];
13
+ dict[index] = element;
14
+ }
15
+ return dict;
16
+ }
17
+
18
+ const METHOD = {
19
+ query: 'GET',
20
+ mutation: 'POST',
21
+ subscription: 'PATCH',
22
+ } as const;
23
+
24
+ export interface ResponseShape {
25
+ json: unknown;
26
+ meta: {
27
+ response: Response;
28
+ };
29
+ }
30
+
31
+ type GetInputOptions = {
32
+ runtime: TRPCClientRuntime;
33
+ } & ({ inputs: unknown[] } | { input: unknown });
34
+
35
+ function getInput(opts: GetInputOptions) {
36
+ return 'input' in opts
37
+ ? opts.runtime.transformer.serialize(opts.input)
38
+ : arrayToDict(
39
+ opts.inputs.map((_input) => opts.runtime.transformer.serialize(_input)),
40
+ );
41
+ }
42
+
43
+ export type HTTPRequestOptions = HTTPLinkOptions &
44
+ GetInputOptions & {
45
+ type: ProcedureType;
46
+ path: string;
47
+ };
48
+
49
+ export function getUrl(opts: HTTPRequestOptions) {
50
+ let url = opts.url + '/' + opts.path;
51
+ const queryParts: string[] = [];
52
+ if ('inputs' in opts) {
53
+ queryParts.push('batch=1');
54
+ }
55
+ if (opts.type === 'query') {
56
+ const input = getInput(opts);
57
+ if (input !== undefined) {
58
+ queryParts.push(`input=${encodeURIComponent(JSON.stringify(input))}`);
59
+ }
60
+ }
61
+ if (queryParts.length) {
62
+ url += '?' + queryParts.join('&');
63
+ }
64
+ return url;
65
+ }
66
+
67
+ type GetBodyOptions = { type: ProcedureType } & GetInputOptions;
68
+
69
+ export function getBody(opts: GetBodyOptions) {
70
+ if (opts.type === 'query') {
71
+ return undefined;
72
+ }
73
+ const input = getInput(opts);
74
+ return input !== undefined ? JSON.stringify(input) : undefined;
75
+ }
76
+
77
+ export function httpRequest(
78
+ opts: HTTPRequestOptions,
79
+ ): PromiseAndCancel<ResponseShape> {
80
+ const { type, runtime } = opts;
81
+ const ac = runtime.AbortController ? new runtime.AbortController() : null;
82
+
83
+ const promise = new Promise<ResponseShape>((resolve, reject) => {
84
+ const url = getUrl(opts);
85
+ const body = getBody(opts);
86
+
87
+ const meta = {} as any as ResponseShape['meta'];
88
+ Promise.resolve(runtime.headers())
89
+ .then((headers) =>
90
+ runtime.fetch(url, {
91
+ method: METHOD[type],
92
+ signal: ac?.signal,
93
+ body: body,
94
+ headers: {
95
+ 'content-type': 'application/json',
96
+ ...headers,
97
+ },
98
+ }),
99
+ )
100
+ .then((_res) => {
101
+ meta.response = _res;
102
+ return _res.json();
103
+ })
104
+ .then((json) => {
105
+ resolve({
106
+ json,
107
+ meta,
108
+ });
109
+ })
110
+ .catch(reject);
111
+ });
112
+ const cancel = () => {
113
+ ac?.abort();
114
+ };
115
+ return { promise, cancel };
116
+ }
@@ -1,25 +1,53 @@
1
1
  import { AnyRouter } from '@trpc/server';
2
+ import { TRPCResultMessage } from '@trpc/server/rpc';
3
+ import { TRPCClientRuntime } from '..';
2
4
  import { TRPCClientError } from '../../TRPCClientError';
3
5
  import { OperationResult } from '../types';
4
6
 
5
7
  /** @internal */
6
8
  export function transformOperationResult<TRouter extends AnyRouter, TOutput>(
7
9
  result: OperationResult<TRouter, TOutput>,
10
+ runtime: TRPCClientRuntime,
8
11
  ) {
9
12
  const { context } = result;
10
13
 
11
14
  if ('error' in result.data) {
12
- const error = TRPCClientError.from<TRouter>(result.data);
13
- return {
14
- ok: false,
15
- error,
16
- context,
17
- } as const;
15
+ const error = TRPCClientError.from<TRouter>({
16
+ ...result.data,
17
+ error: runtime.transformer.deserialize(result.data.error),
18
+ });
19
+ return { ok: false, error, context } as const;
18
20
  }
19
- const data = (result.data.result as any).data as TOutput;
20
- return {
21
- ok: true,
22
- data,
23
- context,
24
- } as const;
21
+
22
+ const data = runtime.transformer.deserialize(
23
+ (result.data.result as any).data,
24
+ ) as TOutput;
25
+ return { ok: true, data, context } as const;
26
+ }
27
+
28
+ /** @internal */
29
+ export function transformSubscriptionOperationResult<
30
+ TRouter extends AnyRouter,
31
+ TOutput,
32
+ >(result: OperationResult<TRouter, TOutput>, runtime: TRPCClientRuntime) {
33
+ const { context } = result;
34
+
35
+ if ('error' in result.data) {
36
+ const error = TRPCClientError.from<TRouter>(
37
+ {
38
+ ...result.data,
39
+ error: runtime.transformer.deserialize(result.data.error),
40
+ },
41
+ { meta: context },
42
+ );
43
+ return { ok: false, error, context } as const;
44
+ }
45
+
46
+ const data = {
47
+ ...result.data.result,
48
+ ...((result.data.result as any).type === 'data' && {
49
+ data: runtime.transformer.deserialize((result.data.result as any).data),
50
+ }),
51
+ } as TRPCResultMessage<TOutput>;
52
+ return { ok: true, data, context } as const;
25
53
  }
@@ -1,7 +1,6 @@
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
4
  import { Operation, OperationResult, TRPCLink } from './types';
6
5
 
7
6
  type ConsoleEsque = {
@@ -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: {
@@ -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, inferRouterError } from '@trpc/server';
2
+ import { Observable, Observer } from '@trpc/server/observable';
3
+ import { TRPCResponse, TRPCResponseMessage } 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,14 +30,19 @@ 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
 
40
+ type OperationResultData<TRouter extends AnyRouter, TOutput> =
41
+ | TRPCResponse<TOutput, inferRouterError<TRouter>>
42
+ | TRPCResponseMessage<TOutput, inferRouterError<TRouter>>;
43
+
39
44
  export interface OperationResult<TRouter extends AnyRouter, TOutput> {
40
- data: TRPCResponse<TOutput, inferRouterError<TRouter>>;
45
+ data: OperationResultData<TRouter, TOutput>;
41
46
  context?: OperationContext;
42
47
  }
43
48
 
@@ -61,5 +66,5 @@ export type OperationLink<
61
66
  }) => OperationResultObservable<TRouter, TOutput>;
62
67
 
63
68
  export type TRPCLink<TRouter extends AnyRouter> = (
64
- opts: LinkRuntime,
69
+ opts: TRPCClientRuntime,
65
70
  ) => OperationLink<TRouter>;
@@ -1,19 +1,19 @@
1
1
  import { AnyRouter, ProcedureType } from '@trpc/server';
2
+ import { 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';
11
+ import { retryDelay } from '../internals/retryDelay';
12
12
  import { Operation, OperationResultObserver, TRPCLink } from './types';
13
13
 
14
14
  export interface WebSocketClientOptions {
15
15
  url: string;
16
- WebSocket?: WebSocket;
16
+ WebSocket?: typeof WebSocket;
17
17
  retryDelayMs?: typeof retryDelay;
18
18
  }
19
19
  export function createWSClient(opts: WebSocketClientOptions) {
@@ -31,7 +31,7 @@ export function createWSClient(opts: WebSocketClientOptions) {
31
31
  /**
32
32
  * outgoing messages buffer whilst not open
33
33
  */
34
- let outgoing: TRPCRequest[] = [];
34
+ let outgoing: TRPCClientOutgoingMessage[] = [];
35
35
  /**
36
36
  * pending outgoing requests that are awaiting callback
37
37
  */
@@ -112,7 +112,7 @@ export function createWSClient(opts: WebSocketClientOptions) {
112
112
  }
113
113
 
114
114
  function createWS() {
115
- const conn = new WebSocket(url);
115
+ const conn = new WebSocketImpl(url);
116
116
  clearTimeout(connectTimer as any);
117
117
  connectTimer = null;
118
118
 
@@ -141,7 +141,7 @@ export function createWSClient(opts: WebSocketClientOptions) {
141
141
  }
142
142
  }
143
143
  };
144
- const handleIncomingResponse = (data: TRPCResponse) => {
144
+ const handleIncomingResponse = (data: TRPCResponseMessage) => {
145
145
  const req = data.id !== null && pendingRequests[data.id];
146
146
  if (!req) {
147
147
  // do something?
@@ -208,9 +208,8 @@ export function createWSClient(opts: WebSocketClientOptions) {
208
208
 
209
209
  function request(op: Operation, callbacks: TCallbacks): UnsubscribeFn {
210
210
  const { type, input, path, id } = op;
211
- const envelope: TRPCRequest = {
211
+ const envelope: TRPCRequestMessage = {
212
212
  id,
213
- jsonrpc: '2.0',
214
213
  method: type,
215
214
  params: {
216
215
  input,
@@ -238,7 +237,6 @@ export function createWSClient(opts: WebSocketClientOptions) {
238
237
  outgoing.push({
239
238
  id,
240
239
  method: 'subscription.stop',
241
- params: undefined,
242
240
  });
243
241
  dispatch();
244
242
  }
@@ -248,6 +246,8 @@ export function createWSClient(opts: WebSocketClientOptions) {
248
246
  close: () => {
249
247
  state = 'closed';
250
248
  closeIfNoPending(activeConnection);
249
+ clearTimeout(connectTimer as any);
250
+ connectTimer = null;
251
251
  },
252
252
  request,
253
253
  getConnection() {
@@ -279,11 +279,13 @@ class TRPCSubscriptionEndedError extends Error {
279
279
  export function wsLink<TRouter extends AnyRouter>(
280
280
  opts: WebSocketLinkOptions,
281
281
  ): TRPCLink<TRouter> {
282
- return () => {
282
+ return (runtime) => {
283
283
  const { client } = opts;
284
284
  return ({ op }) => {
285
285
  return observable((observer) => {
286
- const { type, input, path, id, context } = op;
286
+ const { type, path, id, context } = op;
287
+
288
+ const input = runtime.transformer.serialize(op.input);
287
289
 
288
290
  let isDone = false;
289
291
  const unsub = client.request(