@trpc/client 11.0.0-rc.449 → 11.0.0-rc.455

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 (49) hide show
  1. package/dist/TRPCClientError.d.ts.map +1 -1
  2. package/dist/TRPCClientError.js +11 -8
  3. package/dist/TRPCClientError.mjs +12 -9
  4. package/dist/bundle-analysis.json +54 -68
  5. package/dist/internals/TRPCUntypedClient.d.ts.map +1 -1
  6. package/dist/internals/TRPCUntypedClient.js +15 -19
  7. package/dist/internals/TRPCUntypedClient.mjs +15 -19
  8. package/dist/internals/dataLoader.d.ts +2 -6
  9. package/dist/internals/dataLoader.d.ts.map +1 -1
  10. package/dist/internals/dataLoader.js +3 -16
  11. package/dist/internals/dataLoader.mjs +3 -16
  12. package/dist/internals/types.d.ts +0 -15
  13. package/dist/internals/types.d.ts.map +1 -1
  14. package/dist/links/httpBatchLink.d.ts.map +1 -1
  15. package/dist/links/httpBatchLink.js +15 -17
  16. package/dist/links/httpBatchLink.mjs +16 -18
  17. package/dist/links/httpBatchStreamLink.d.ts.map +1 -1
  18. package/dist/links/httpBatchStreamLink.js +40 -43
  19. package/dist/links/httpBatchStreamLink.mjs +41 -44
  20. package/dist/links/httpLink.d.ts.map +1 -1
  21. package/dist/links/httpLink.js +3 -2
  22. package/dist/links/httpLink.mjs +3 -2
  23. package/dist/links/httpSubscriptionLink.js +1 -1
  24. package/dist/links/httpSubscriptionLink.mjs +1 -1
  25. package/dist/links/internals/httpUtils.d.ts +14 -11
  26. package/dist/links/internals/httpUtils.d.ts.map +1 -1
  27. package/dist/links/internals/httpUtils.js +39 -33
  28. package/dist/links/internals/httpUtils.mjs +39 -34
  29. package/dist/links/types.d.ts +2 -12
  30. package/dist/links/types.d.ts.map +1 -1
  31. package/dist/links/wsLink.js +2 -1
  32. package/dist/links/wsLink.mjs +2 -1
  33. package/package.json +4 -4
  34. package/src/TRPCClientError.ts +15 -10
  35. package/src/internals/TRPCUntypedClient.ts +18 -28
  36. package/src/internals/dataLoader.ts +4 -22
  37. package/src/internals/types.ts +0 -18
  38. package/src/links/httpBatchLink.ts +16 -19
  39. package/src/links/httpBatchStreamLink.ts +65 -72
  40. package/src/links/httpLink.ts +3 -2
  41. package/src/links/httpSubscriptionLink.ts +1 -1
  42. package/src/links/internals/httpUtils.ts +58 -44
  43. package/src/links/types.ts +2 -13
  44. package/src/links/wsLink.ts +1 -1
  45. package/dist/internals/getAbortController.d.ts +0 -4
  46. package/dist/internals/getAbortController.d.ts.map +0 -1
  47. package/dist/internals/getAbortController.js +0 -16
  48. package/dist/internals/getAbortController.mjs +0 -14
  49. package/src/internals/getAbortController.ts +0 -20
@@ -13,6 +13,7 @@ import {
13
13
  fetchHTTPResponse,
14
14
  getBody,
15
15
  getUrl,
16
+ mergeAbortSignals,
16
17
  resolveHTTPLinkOptions,
17
18
  } from './internals/httpUtils';
18
19
  import type { Operation, TRPCLink } from './types';
@@ -57,90 +58,82 @@ export function unstable_httpBatchStreamLink<TRouter extends AnyRouter>(
57
58
  type,
58
59
  path,
59
60
  inputs,
61
+ signal: null,
60
62
  });
61
63
 
62
64
  return url.length <= maxURLLength;
63
65
  },
64
- fetch(batchOps) {
66
+ async fetch(batchOps) {
65
67
  const path = batchOps.map((op) => op.path).join(',');
66
68
  const inputs = batchOps.map((op) => op.input);
67
69
 
68
- const ac = resolvedOpts.AbortController
69
- ? new resolvedOpts.AbortController()
70
- : null;
71
- const responsePromise = fetchHTTPResponse(
72
- {
73
- ...resolvedOpts,
74
- type,
75
- contentTypeHeader: 'application/json',
76
- trpcAcceptHeader: 'application/jsonl',
77
- getUrl,
78
- getBody,
79
- inputs,
80
- path,
81
- headers() {
82
- if (!opts.headers) {
83
- return {};
84
- }
85
- if (typeof opts.headers === 'function') {
86
- return opts.headers({
87
- opList: batchOps as NonEmptyArray<Operation>,
88
- });
89
- }
90
- return opts.headers;
91
- },
70
+ const ac = mergeAbortSignals(batchOps);
71
+
72
+ const responsePromise = fetchHTTPResponse({
73
+ ...resolvedOpts,
74
+ signal: ac.signal,
75
+ type,
76
+ contentTypeHeader: 'application/json',
77
+ trpcAcceptHeader: 'application/jsonl',
78
+ getUrl,
79
+ getBody,
80
+ inputs,
81
+ path,
82
+ headers() {
83
+ if (!opts.headers) {
84
+ return {};
85
+ }
86
+ if (typeof opts.headers === 'function') {
87
+ return opts.headers({
88
+ opList: batchOps as NonEmptyArray<Operation>,
89
+ });
90
+ }
91
+ return opts.headers;
92
92
  },
93
- ac,
94
- );
93
+ });
95
94
 
96
- return {
97
- promise: responsePromise.then(async (res) => {
98
- const [head] = await jsonlStreamConsumer<
99
- Record<string, Promise<any>>
100
- >({
101
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
102
- from: res.body!,
103
- deserialize: resolvedOpts.transformer.output.deserialize,
104
- // onError: console.error,
105
- formatError(opts) {
106
- const error = opts.error as TRPCErrorShape;
107
- return TRPCClientError.from({
108
- error,
109
- });
110
- },
95
+ const res = await responsePromise;
96
+ const [head] = await jsonlStreamConsumer<
97
+ Record<string, Promise<any>>
98
+ >({
99
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
100
+ from: res.body!,
101
+ deserialize: resolvedOpts.transformer.output.deserialize,
102
+ // onError: console.error,
103
+ formatError(opts) {
104
+ const error = opts.error as TRPCErrorShape;
105
+ return TRPCClientError.from({
106
+ error,
111
107
  });
108
+ },
109
+ abortController: ac,
110
+ });
111
+ const promises = Object.keys(batchOps).map(
112
+ async (key): Promise<HTTPResult> => {
113
+ let json: TRPCResponse = await Promise.resolve(head[key]);
112
114
 
113
- const promises = Object.keys(batchOps).map(
114
- async (key): Promise<HTTPResult> => {
115
- let json: TRPCResponse = await Promise.resolve(head[key]);
116
-
117
- if ('result' in json) {
118
- /**
119
- * Not very pretty, but we need to unwrap nested data as promises
120
- * Our stream producer will only resolve top-level async values or async values that are directly nested in another async value
121
- */
122
- const result = await Promise.resolve(json.result);
123
- json = {
124
- result: {
125
- data: await Promise.resolve(result.data),
126
- },
127
- };
128
- }
115
+ if ('result' in json) {
116
+ /**
117
+ * Not very pretty, but we need to unwrap nested data as promises
118
+ * Our stream producer will only resolve top-level async values or async values that are directly nested in another async value
119
+ */
120
+ const result = await Promise.resolve(json.result);
121
+ json = {
122
+ result: {
123
+ data: await Promise.resolve(result.data),
124
+ },
125
+ };
126
+ }
129
127
 
130
- return {
131
- json,
132
- meta: {
133
- response: res,
134
- },
135
- };
128
+ return {
129
+ json,
130
+ meta: {
131
+ response: res,
136
132
  },
137
- );
138
- return promises;
139
- }),
140
- cancel() {
141
- ac?.abort();
133
+ };
142
134
  },
143
- };
135
+ );
136
+ return promises;
144
137
  },
145
138
  };
146
139
  };
@@ -158,7 +151,7 @@ export function unstable_httpBatchStreamLink<TRouter extends AnyRouter>(
158
151
  );
159
152
  }
160
153
  const loader = loaders[op.type];
161
- const { promise, cancel } = loader.load(op);
154
+ const promise = loader.load(op);
162
155
 
163
156
  let _res = undefined as HTTPResult | undefined;
164
157
  promise
@@ -191,7 +184,7 @@ export function unstable_httpBatchStreamLink<TRouter extends AnyRouter>(
191
184
  });
192
185
 
193
186
  return () => {
194
- cancel();
187
+ // noop
195
188
  };
196
189
  });
197
190
  };
@@ -92,6 +92,7 @@ export function httpLink<TRouter extends AnyRouter = AnyRouter>(
92
92
  type,
93
93
  path,
94
94
  input,
95
+ signal: op.signal,
95
96
  headers() {
96
97
  if (!opts.headers) {
97
98
  return {};
@@ -105,7 +106,7 @@ export function httpLink<TRouter extends AnyRouter = AnyRouter>(
105
106
  },
106
107
  });
107
108
  let meta: HTTPResult['meta'] | undefined = undefined;
108
- request.promise
109
+ request
109
110
  .then((res) => {
110
111
  meta = res.meta;
111
112
  const transformed = transformResult(
@@ -132,7 +133,7 @@ export function httpLink<TRouter extends AnyRouter = AnyRouter>(
132
133
  });
133
134
 
134
135
  return () => {
135
- request.cancel();
136
+ // noop
136
137
  };
137
138
  });
138
139
  };
@@ -69,7 +69,7 @@ export function unstable_httpSubscriptionLink<
69
69
  input,
70
70
  path,
71
71
  type,
72
- AbortController: null,
72
+ signal: null,
73
73
  });
74
74
 
75
75
  /* istanbul ignore if -- @preserve */
@@ -1,23 +1,20 @@
1
1
  import type {
2
2
  AnyClientTypes,
3
3
  CombinedDataTransformer,
4
+ Maybe,
4
5
  ProcedureType,
5
6
  TRPCAcceptHeader,
6
7
  TRPCResponse,
7
8
  } from '@trpc/server/unstable-core-do-not-import';
8
9
  import { getFetch } from '../../getFetch';
9
- import { getAbortController } from '../../internals/getAbortController';
10
10
  import type {
11
- AbortControllerEsque,
12
- AbortControllerInstanceEsque,
13
11
  FetchEsque,
14
12
  RequestInitEsque,
15
13
  ResponseEsque,
16
14
  } from '../../internals/types';
17
- import { TRPCClientError } from '../../TRPCClientError';
18
15
  import type { TransformerOptions } from '../../unstable-internals';
19
16
  import { getTransformer } from '../../unstable-internals';
20
- import type { HTTPHeaders, PromiseAndCancel } from '../types';
17
+ import type { HTTPHeaders } from '../types';
21
18
 
22
19
  /**
23
20
  * @internal
@@ -30,10 +27,6 @@ export type HTTPLinkBaseOptions<
30
27
  * Add ponyfill for fetch
31
28
  */
32
29
  fetch?: FetchEsque;
33
- /**
34
- * Add ponyfill for AbortController
35
- */
36
- AbortController?: AbortControllerEsque | null;
37
30
  /**
38
31
  * Send all requests `as POST`s requests regardless of the procedure type
39
32
  * The HTTP handler must separately allow overriding the method. See:
@@ -45,7 +38,6 @@ export type HTTPLinkBaseOptions<
45
38
  export interface ResolvedHTTPLinkOptions {
46
39
  url: string;
47
40
  fetch?: FetchEsque;
48
- AbortController: AbortControllerEsque | null;
49
41
  transformer: CombinedDataTransformer;
50
42
  methodOverride?: 'POST';
51
43
  }
@@ -56,7 +48,6 @@ export function resolveHTTPLinkOptions(
56
48
  return {
57
49
  url: opts.url.toString(),
58
50
  fetch: opts.fetch,
59
- AbortController: getAbortController(opts.AbortController),
60
51
  transformer: getTransformer(opts.transformer),
61
52
  methodOverride: opts.methodOverride,
62
53
  };
@@ -102,6 +93,7 @@ export type HTTPBaseRequestOptions = GetInputOptions &
102
93
  ResolvedHTTPLinkOptions & {
103
94
  type: ProcedureType;
104
95
  path: string;
96
+ signal: Maybe<AbortSignal>;
105
97
  };
106
98
 
107
99
  type GetUrl = (opts: HTTPBaseRequestOptions) => string;
@@ -151,7 +143,7 @@ export type Requester = (
151
143
  opts: HTTPBaseRequestOptions & {
152
144
  headers: () => HTTPHeaders | Promise<HTTPHeaders>;
153
145
  },
154
- ) => PromiseAndCancel<HTTPResult>;
146
+ ) => Promise<HTTPResult>;
155
147
 
156
148
  export const jsonHttpRequester: Requester = (opts) => {
157
149
  return httpRequest({
@@ -167,10 +159,8 @@ export type HTTPRequestOptions = ContentOptions &
167
159
  headers: () => HTTPHeaders | Promise<HTTPHeaders>;
168
160
  };
169
161
 
170
- export async function fetchHTTPResponse(
171
- opts: HTTPRequestOptions,
172
- ac?: AbortControllerInstanceEsque | null,
173
- ) {
162
+ export async function fetchHTTPResponse(opts: HTTPRequestOptions) {
163
+ opts.signal?.throwIfAborted();
174
164
  const url = opts.getUrl(opts);
175
165
  const body = opts.getBody(opts);
176
166
  const { type } = opts;
@@ -193,42 +183,66 @@ export async function fetchHTTPResponse(
193
183
 
194
184
  return getFetch(opts.fetch)(url, {
195
185
  method: opts.methodOverride ?? METHOD[type],
196
- signal: ac?.signal,
186
+ signal: opts.signal,
197
187
  body,
198
188
  headers,
199
189
  });
200
190
  }
201
191
 
202
- export function httpRequest(
192
+ export async function httpRequest(
203
193
  opts: HTTPRequestOptions,
204
- ): PromiseAndCancel<HTTPResult> {
205
- const ac = opts.AbortController ? new opts.AbortController() : null;
194
+ ): Promise<HTTPResult> {
206
195
  const meta = {} as HTTPResult['meta'];
207
196
 
208
- let done = false;
209
- const promise = new Promise<HTTPResult>((resolve, reject) => {
210
- fetchHTTPResponse(opts, ac)
211
- .then((_res) => {
212
- meta.response = _res;
213
- done = true;
214
- return _res.json();
215
- })
216
- .then((json) => {
217
- meta.responseJSON = json;
218
- resolve({
219
- json: json as TRPCResponse,
220
- meta,
221
- });
222
- })
223
- .catch((err) => {
224
- done = true;
225
- reject(TRPCClientError.from(err, { meta }));
226
- });
227
- });
228
- const cancel = () => {
229
- if (!done) {
230
- ac?.abort();
197
+ const res = await fetchHTTPResponse(opts);
198
+ meta.response = res;
199
+
200
+ const json = await res.json();
201
+
202
+ meta.responseJSON = json;
203
+
204
+ return {
205
+ json: json as TRPCResponse,
206
+ meta,
207
+ };
208
+ }
209
+
210
+ /**
211
+ * Merges multiple abort signals into a single one
212
+ * - When all signals have been aborted, the merged signal will be aborted
213
+ */
214
+ export function mergeAbortSignals(
215
+ opts: {
216
+ signal: Maybe<AbortSignal>;
217
+ }[],
218
+ ): AbortController {
219
+ const ac = new AbortController();
220
+
221
+ if (opts.some((o) => !o.signal)) {
222
+ return ac;
223
+ }
224
+
225
+ const count = opts.length;
226
+
227
+ let abortedCount = 0;
228
+
229
+ const onAbort = () => {
230
+ if (++abortedCount === count) {
231
+ ac.abort();
231
232
  }
232
233
  };
233
- return { promise, cancel };
234
+
235
+ for (const o of opts) {
236
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
237
+ const signal = o.signal!;
238
+ if (signal.aborted) {
239
+ onAbort();
240
+ } else {
241
+ signal.addEventListener('abort', onAbort, {
242
+ once: true,
243
+ });
244
+ }
245
+ }
246
+
247
+ return ac;
234
248
  }
@@ -1,6 +1,7 @@
1
1
  import type { Observable, Observer } from '@trpc/server/observable';
2
2
  import type {
3
3
  InferrableClientTypes,
4
+ Maybe,
4
5
  TRPCResultMessage,
5
6
  TRPCSuccessResponse,
6
7
  } from '@trpc/server/unstable-core-do-not-import';
@@ -13,19 +14,6 @@ export {
13
14
  isOctetType,
14
15
  } from './internals/contentTypes';
15
16
 
16
- /**
17
- * @internal
18
- */
19
- export type CancelFn = () => void;
20
-
21
- /**
22
- * @internal
23
- */
24
- export type PromiseAndCancel<TValue> = {
25
- promise: Promise<TValue>;
26
- cancel: CancelFn;
27
- };
28
-
29
17
  /**
30
18
  * @internal
31
19
  */
@@ -40,6 +28,7 @@ export type Operation<TInput = unknown> = {
40
28
  input: TInput;
41
29
  path: string;
42
30
  context: OperationContext;
31
+ signal: Maybe<AbortSignal>;
43
32
  };
44
33
 
45
34
  interface HeadersInitEsque {
@@ -486,7 +486,7 @@ export function wsLink<TRouter extends AnyRouter>(
486
486
  const input = transformer.input.serialize(op.input);
487
487
 
488
488
  const unsub = client.request(
489
- { type, path, input, id, context },
489
+ { type, path, input, id, context, signal: null },
490
490
  {
491
491
  error(err) {
492
492
  observer.error(err as TRPCClientError<any>);
@@ -1,4 +0,0 @@
1
- import type { Maybe } from '@trpc/server/unstable-core-do-not-import';
2
- import type { AbortControllerEsque } from './types';
3
- export declare function getAbortController(customAbortControllerImpl: Maybe<AbortControllerEsque>): AbortControllerEsque | null;
4
- //# sourceMappingURL=getAbortController.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"getAbortController.d.ts","sourceRoot":"","sources":["../../src/internals/getAbortController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0CAA0C,CAAC;AACtE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAEpD,wBAAgB,kBAAkB,CAChC,yBAAyB,EAAE,KAAK,CAAC,oBAAoB,CAAC,GACrD,oBAAoB,GAAG,IAAI,CAc7B"}
@@ -1,16 +0,0 @@
1
- 'use strict';
2
-
3
- function getAbortController(customAbortControllerImpl) {
4
- if (customAbortControllerImpl) {
5
- return customAbortControllerImpl;
6
- }
7
- if (typeof window !== 'undefined' && window.AbortController) {
8
- return window.AbortController;
9
- }
10
- if (typeof globalThis !== 'undefined' && globalThis.AbortController) {
11
- return globalThis.AbortController;
12
- }
13
- return null;
14
- }
15
-
16
- exports.getAbortController = getAbortController;
@@ -1,14 +0,0 @@
1
- function getAbortController(customAbortControllerImpl) {
2
- if (customAbortControllerImpl) {
3
- return customAbortControllerImpl;
4
- }
5
- if (typeof window !== 'undefined' && window.AbortController) {
6
- return window.AbortController;
7
- }
8
- if (typeof globalThis !== 'undefined' && globalThis.AbortController) {
9
- return globalThis.AbortController;
10
- }
11
- return null;
12
- }
13
-
14
- export { getAbortController };
@@ -1,20 +0,0 @@
1
- import type { Maybe } from '@trpc/server/unstable-core-do-not-import';
2
- import type { AbortControllerEsque } from './types';
3
-
4
- export function getAbortController(
5
- customAbortControllerImpl: Maybe<AbortControllerEsque>,
6
- ): AbortControllerEsque | null {
7
- if (customAbortControllerImpl) {
8
- return customAbortControllerImpl;
9
- }
10
-
11
- if (typeof window !== 'undefined' && window.AbortController) {
12
- return window.AbortController;
13
- }
14
-
15
- if (typeof globalThis !== 'undefined' && globalThis.AbortController) {
16
- return globalThis.AbortController;
17
- }
18
-
19
- return null;
20
- }