@trpc/client 10.28.2 → 10.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/httpBatchLink-38dcf5f2.js +243 -0
  2. package/dist/httpBatchLink-e66c0674.mjs +240 -0
  3. package/dist/httpBatchLink-f35df745.js +239 -0
  4. package/dist/{httpUtils-00c8b54e.js → httpUtils-145e783b.js} +27 -23
  5. package/dist/{httpUtils-90a6bccb.js → httpUtils-21cbb35d.js} +27 -20
  6. package/dist/{httpUtils-8a5c637a.mjs → httpUtils-b2fcc20c.mjs} +26 -21
  7. package/dist/index.js +147 -2
  8. package/dist/index.mjs +149 -4
  9. package/dist/internals/dataLoader.d.ts +1 -1
  10. package/dist/internals/dataLoader.d.ts.map +1 -1
  11. package/dist/internals/types.d.ts +2 -0
  12. package/dist/internals/types.d.ts.map +1 -1
  13. package/dist/links/HTTPBatchLinkOptions.d.ts +20 -0
  14. package/dist/links/HTTPBatchLinkOptions.d.ts.map +1 -0
  15. package/dist/links/httpBatchLink.d.ts +1 -15
  16. package/dist/links/httpBatchLink.d.ts.map +1 -1
  17. package/dist/links/httpBatchLink.js +5 -217
  18. package/dist/links/httpBatchLink.mjs +4 -220
  19. package/dist/links/httpBatchStreamLink.d.ts +2 -0
  20. package/dist/links/httpBatchStreamLink.d.ts.map +1 -0
  21. package/dist/links/httpLink.js +1 -1
  22. package/dist/links/httpLink.mjs +1 -1
  23. package/dist/links/index.d.ts +2 -0
  24. package/dist/links/index.d.ts.map +1 -1
  25. package/dist/links/internals/createHTTPBatchLink.d.ts +20 -0
  26. package/dist/links/internals/createHTTPBatchLink.d.ts.map +1 -0
  27. package/dist/links/internals/httpUtils.d.ts +3 -1
  28. package/dist/links/internals/httpUtils.d.ts.map +1 -1
  29. package/dist/links/internals/parseJSONStream.d.ts +36 -0
  30. package/dist/links/internals/parseJSONStream.d.ts.map +1 -0
  31. package/package.json +4 -4
  32. package/src/internals/dataLoader.ts +21 -7
  33. package/src/internals/types.ts +1 -0
  34. package/src/links/HTTPBatchLinkOptions.ts +21 -0
  35. package/src/links/httpBatchLink.ts +44 -133
  36. package/src/links/httpBatchStreamLink.ts +47 -0
  37. package/src/links/index.ts +2 -0
  38. package/src/links/internals/createHTTPBatchLink.ts +113 -0
  39. package/src/links/internals/httpUtils.ts +33 -24
  40. package/src/links/internals/parseJSONStream.ts +165 -0
package/dist/index.mjs CHANGED
@@ -4,9 +4,10 @@ export { s as splitLink } from './splitLink-4c75f7be.mjs';
4
4
  import { T as TRPCClientError } from './transformResult-9a244fe7.mjs';
5
5
  export { T as TRPCClientError } from './transformResult-9a244fe7.mjs';
6
6
  import { createFlatProxy, createRecursiveProxy } from '@trpc/server/shared';
7
- import { h as httpRequest } from './httpUtils-8a5c637a.mjs';
8
- export { g as getFetch } from './httpUtils-8a5c637a.mjs';
9
- export { httpBatchLink } from './links/httpBatchLink.mjs';
7
+ import { f as fetchHTTPResponse, g as getUrl, a as getBody$1, h as httpRequest } from './httpUtils-b2fcc20c.mjs';
8
+ export { b as getFetch } from './httpUtils-b2fcc20c.mjs';
9
+ import { c as createHTTPBatchLink } from './httpBatchLink-e66c0674.mjs';
10
+ export { h as httpBatchLink } from './httpBatchLink-e66c0674.mjs';
10
11
  import { httpLinkFactory } from './links/httpLink.mjs';
11
12
  export { httpLink, httpLinkFactory } from './links/httpLink.mjs';
12
13
  export { loggerLink } from './links/loggerLink.mjs';
@@ -163,6 +164,150 @@ function createTRPCProxyClient(opts) {
163
164
  return proxy;
164
165
  }
165
166
 
167
+ // Stream parsing adapted from https://www.loginradius.com/blog/engineering/guest-post/http-streaming-with-nodejs-and-fetch-api/
168
+ /**
169
+ * @internal
170
+ * @description Take a stream of bytes and call `onLine` with
171
+ * a JSON object for each line in the stream. Expected stream
172
+ * format is:
173
+ * ```json
174
+ * {"1": {...}
175
+ * ,"0": {...}
176
+ * }
177
+ * ```
178
+ */ async function parseJSONStream(opts) {
179
+ const parse = opts.parse ?? JSON.parse;
180
+ const onLine = (line)=>{
181
+ if (opts.signal?.aborted) return;
182
+ if (!line || line === '}') {
183
+ return;
184
+ }
185
+ /**
186
+ * At this point, `line` can be one of two things:
187
+ * - The first line of the stream `{"2":{...}`
188
+ * - A line in the middle of the stream `,"2":{...}`
189
+ */ const indexOfColon = line.indexOf(':');
190
+ const indexAsStr = line.substring(2, indexOfColon - 1);
191
+ const text = line.substring(indexOfColon + 1);
192
+ opts.onSingle(Number(indexAsStr), parse(text));
193
+ };
194
+ await readLines(opts.readableStream, onLine);
195
+ }
196
+ const textDecoder = new TextDecoder();
197
+ /**
198
+ * Handle transforming a stream of bytes into lines of text.
199
+ * To avoid using AsyncIterators / AsyncGenerators,
200
+ * we use a callback for each line.
201
+ *
202
+ * @param readableStream can be a NodeJS stream or a WebAPI stream
203
+ * @param onLine will be called for every line ('\n' delimited) in the stream
204
+ */ async function readLines(readableStream, onLine) {
205
+ let partOfLine = '';
206
+ const onChunk = (chunk)=>{
207
+ const chunkText = textDecoder.decode(chunk);
208
+ const chunkLines = chunkText.split('\n');
209
+ if (chunkLines.length === 1) {
210
+ partOfLine += chunkLines[0];
211
+ } else if (chunkLines.length > 1) {
212
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length checked on line above
213
+ onLine(partOfLine + chunkLines[0]);
214
+ for(let i = 1; i < chunkLines.length - 1; i++){
215
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length checked on line above
216
+ onLine(chunkLines[i]);
217
+ }
218
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length doesn't change, so is necessarily > 1
219
+ partOfLine = chunkLines[chunkLines.length - 1];
220
+ }
221
+ };
222
+ // we handle 2 different types of streams, this if where we figure out which one we have
223
+ if ('getReader' in readableStream) {
224
+ await readStandardChunks(readableStream, onChunk);
225
+ } else {
226
+ await readNodeChunks(readableStream, onChunk);
227
+ }
228
+ onLine(partOfLine);
229
+ }
230
+ /**
231
+ * Handle NodeJS stream
232
+ */ function readNodeChunks(stream, onChunk) {
233
+ return new Promise((resolve)=>{
234
+ stream.on('data', onChunk);
235
+ stream.on('end', resolve);
236
+ });
237
+ }
238
+ /**
239
+ * Handle WebAPI stream
240
+ */ async function readStandardChunks(stream, onChunk) {
241
+ const reader = stream.getReader();
242
+ let readResult = await reader.read();
243
+ while(!readResult.done){
244
+ onChunk(readResult.value);
245
+ readResult = await reader.read();
246
+ }
247
+ }
248
+ const streamingJsonHttpRequester = (opts, onSingle)=>{
249
+ const ac = opts.AbortController ? new opts.AbortController() : null;
250
+ const responsePromise = fetchHTTPResponse({
251
+ ...opts,
252
+ contentTypeHeader: 'application/json',
253
+ batchModeHeader: 'stream',
254
+ getUrl,
255
+ getBody: getBody$1
256
+ }, ac);
257
+ const cancel = ()=>ac?.abort();
258
+ const promise = responsePromise.then(async (res)=>{
259
+ if (!res.body) throw new Error('Received response without body');
260
+ const meta = {
261
+ response: res
262
+ };
263
+ return parseJSONStream({
264
+ readableStream: res.body,
265
+ onSingle,
266
+ parse: (string)=>({
267
+ json: JSON.parse(string),
268
+ meta
269
+ }),
270
+ signal: ac?.signal
271
+ });
272
+ });
273
+ return {
274
+ cancel,
275
+ promise
276
+ };
277
+ };
278
+
279
+ const streamRequester = (requesterOpts)=>{
280
+ return (batchOps, unitResolver)=>{
281
+ const path = batchOps.map((op)=>op.path).join(',');
282
+ const inputs = batchOps.map((op)=>op.input);
283
+ const { cancel , promise } = streamingJsonHttpRequester({
284
+ ...requesterOpts,
285
+ path,
286
+ inputs,
287
+ headers () {
288
+ if (!requesterOpts.opts.headers) {
289
+ return {};
290
+ }
291
+ if (typeof requesterOpts.opts.headers === 'function') {
292
+ return requesterOpts.opts.headers({
293
+ opList: batchOps
294
+ });
295
+ }
296
+ return requesterOpts.opts.headers;
297
+ }
298
+ }, (index, res)=>unitResolver(index, res));
299
+ return {
300
+ /**
301
+ * return an empty array because the batchLoader expects an array of results
302
+ * but we've already called the `unitResolver` for each of them, there's
303
+ * nothing left to do here.
304
+ */ promise: promise.then(()=>[]),
305
+ cancel
306
+ };
307
+ };
308
+ };
309
+ const unstable_httpBatchStreamLink = createHTTPBatchLink(streamRequester);
310
+
166
311
  const getBody = (opts)=>{
167
312
  if (!('input' in opts)) {
168
313
  return undefined;
@@ -189,4 +334,4 @@ const experimental_formDataLink = httpLinkFactory({
189
334
  requester: formDataRequester
190
335
  });
191
336
 
192
- export { clientCallTypeToProcedureType, createTRPCClient, createTRPCClientProxy, createTRPCProxyClient, createTRPCUntypedClient, experimental_formDataLink };
337
+ export { clientCallTypeToProcedureType, createTRPCClient, createTRPCClientProxy, createTRPCProxyClient, createTRPCUntypedClient, experimental_formDataLink, unstable_httpBatchStreamLink };
@@ -1,7 +1,7 @@
1
1
  import { CancelFn, PromiseAndCancel } from '../links/types';
2
2
  type BatchLoader<TKey, TValue> = {
3
3
  validate: (keys: TKey[]) => boolean;
4
- fetch: (keys: TKey[]) => {
4
+ fetch: (keys: TKey[], unitResolver: (index: number, value: NonNullable<TValue>) => void) => {
5
5
  promise: Promise<TValue[]>;
6
6
  cancel: CancelFn;
7
7
  };
@@ -1 +1 @@
1
- {"version":3,"file":"dataLoader.d.ts","sourceRoot":"","sources":["../../src/internals/dataLoader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAa5D,KAAK,WAAW,CAAC,IAAI,EAAE,MAAM,IAAI;IAC/B,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,OAAO,CAAC;IACpC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK;QACvB,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC3B,MAAM,EAAE,QAAQ,CAAC;KAClB,CAAC;CACH,CAAC;AAWF;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EACrC,WAAW,EAAE,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC;gBA2FnB,IAAI,KAAG,iBAAiB,MAAM,CAAC;EAsCnD"}
1
+ {"version":3,"file":"dataLoader.d.ts","sourceRoot":"","sources":["../../src/internals/dataLoader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAa5D,KAAK,WAAW,CAAC,IAAI,EAAE,MAAM,IAAI;IAC/B,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,OAAO,CAAC;IACpC,KAAK,EAAE,CACL,IAAI,EAAE,IAAI,EAAE,EACZ,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,KAAK,IAAI,KAC9D;QACH,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC3B,MAAM,EAAE,QAAQ,CAAC;KAClB,CAAC;CACH,CAAC;AAWF;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EACrC,WAAW,EAAE,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC;gBAsGnB,IAAI,KAAG,iBAAiB,MAAM,CAAC;EAsCnD"}
@@ -1,3 +1,4 @@
1
+ /// <reference types="node" />
1
2
  export interface AbortControllerEsque {
2
3
  new (): AbortControllerInstanceEsque;
3
4
  }
@@ -61,6 +62,7 @@ export interface RequestInitEsque {
61
62
  * @see Response from lib.dom.d.ts
62
63
  */
63
64
  export interface ResponseEsque {
65
+ readonly body?: ReadableStream<Uint8Array> | NodeJS.ReadableStream | null;
64
66
  /**
65
67
  * @remarks
66
68
  * The built-in Response::json() method returns Promise<any>, but
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/internals/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACnC,QAAQ,4BAA4B,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAE7B;;;OAGG;IACH,KAAK,IAAI,IAAI,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAAG,CACvB,KAAK,EAAE,WAAW,GAAG,GAAG,GAAG,MAAM,EACjC,IAAI,CAAC,EAAE,WAAW,GAAG,gBAAgB,KAClC,OAAO,CAAC,aAAa,CAAC,CAAC;AAE5B;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAC7B,GAAG,EAAE,MAAM,GAAG,GAAG,EACjB,IAAI,CAAC,EAAE,yBAAyB,KAC7B,OAAO,CAAC,aAAa,CAAC,CAAC;AAE5B,MAAM,WAAW,yBAAyB;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,cAAc,GAAG,QAAQ,GAAG,IAAI,CAAC;IAEjD;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEtD;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/internals/types.ts"],"names":[],"mappings":";AAAA,MAAM,WAAW,oBAAoB;IACnC,QAAQ,4BAA4B,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAE7B;;;OAGG;IACH,KAAK,IAAI,IAAI,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAAG,CACvB,KAAK,EAAE,WAAW,GAAG,GAAG,GAAG,MAAM,EACjC,IAAI,CAAC,EAAE,WAAW,GAAG,gBAAgB,KAClC,OAAO,CAAC,aAAa,CAAC,CAAC;AAE5B;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAC7B,GAAG,EAAE,MAAM,GAAG,GAAG,EACjB,IAAI,CAAC,EAAE,yBAAyB,KAC7B,OAAO,CAAC,aAAa,CAAC,CAAC;AAE5B,MAAM,WAAW,yBAAyB;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,cAAc,GAAG,QAAQ,GAAG,IAAI,CAAC;IAEjD;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEtD;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC;IAC1E;;;;;OAKG;IACH,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { NonEmptyArray } from '../internals/types';
2
+ import { HTTPLinkBaseOptions } from './internals/httpUtils';
3
+ import { HTTPHeaders, Operation } from './types';
4
+ export interface HTTPBatchLinkOptions extends HTTPLinkBaseOptions {
5
+ maxURLLength?: number;
6
+ /**
7
+ * Headers to be set on outgoing requests or a callback that of said headers
8
+ * @link http://trpc.io/docs/client/headers
9
+ */
10
+ headers?: HTTPHeaders | ((opts: {
11
+ opList: NonEmptyArray<Operation>;
12
+ }) => HTTPHeaders | Promise<HTTPHeaders>);
13
+ }
14
+ /**
15
+ * @alias HttpBatchLinkOptions
16
+ * @deprecated use `HTTPBatchLinkOptions` instead
17
+ */
18
+ export interface HttpBatchLinkOptions extends HTTPBatchLinkOptions {
19
+ }
20
+ //# sourceMappingURL=HTTPBatchLinkOptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HTTPBatchLinkOptions.d.ts","sourceRoot":"","sources":["../../src/links/HTTPBatchLinkOptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEjD,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,OAAO,CAAC,EACJ,WAAW,GACX,CAAC,CAAC,IAAI,EAAE;QACN,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;KAClC,KAAK,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;CAC/C;AACD;;;GAGG;AACH,MAAM,WAAW,oBAAqB,SAAQ,oBAAoB;CAAG"}
@@ -1,16 +1,2 @@
1
- import { AnyRouter } from '@trpc/server';
2
- import { NonEmptyArray } from '../internals/types';
3
- import { HTTPLinkBaseOptions } from './internals/httpUtils';
4
- import { HTTPHeaders, Operation, TRPCLink } from './types';
5
- export interface HttpBatchLinkOptions extends HTTPLinkBaseOptions {
6
- maxURLLength?: number;
7
- /**
8
- * Headers to be set on outgoing requests or a callback that of said headers
9
- * @link http://trpc.io/docs/client/headers
10
- */
11
- headers?: HTTPHeaders | ((opts: {
12
- opList: NonEmptyArray<Operation>;
13
- }) => HTTPHeaders | Promise<HTTPHeaders>);
14
- }
15
- export declare function httpBatchLink<TRouter extends AnyRouter>(opts: HttpBatchLinkOptions): TRPCLink<TRouter>;
1
+ export declare const httpBatchLink: <TRouter extends import("@trpc/server").AnyRouter>(opts: import("./HTTPBatchLinkOptions").HTTPBatchLinkOptions) => import("./types").TRPCLink<TRouter>;
16
2
  //# sourceMappingURL=httpBatchLink.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"httpBatchLink.d.ts","sourceRoot":"","sources":["../../src/links/httpBatchLink.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAiB,MAAM,cAAc,CAAC;AAGxD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,OAAO,EAEL,mBAAmB,EAIpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE3D,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,OAAO,CAAC,EACJ,WAAW,GACX,CAAC,CAAC,IAAI,EAAE;QACN,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;KAClC,KAAK,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;CAC/C;AAED,wBAAgB,aAAa,CAAC,OAAO,SAAS,SAAS,EACrD,IAAI,EAAE,oBAAoB,GACzB,QAAQ,CAAC,OAAO,CAAC,CA2GnB"}
1
+ {"version":3,"file":"httpBatchLink.d.ts","sourceRoot":"","sources":["../../src/links/httpBatchLink.ts"],"names":[],"mappings":"AAgDA,eAAO,MAAM,aAAa,wJAAsC,CAAC"}
@@ -2,223 +2,11 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var observable = require('@trpc/server/observable');
6
- var transformResult = require('../transformResult-70f95ffb.js');
7
- var httpUtils = require('../httpUtils-90a6bccb.js');
5
+ var links_httpBatchLink = require('../httpBatchLink-38dcf5f2.js');
6
+ require('../httpUtils-21cbb35d.js');
7
+ require('@trpc/server/observable');
8
+ require('../transformResult-70f95ffb.js');
8
9
 
9
- /* eslint-disable @typescript-eslint/no-non-null-assertion */ /**
10
- * A function that should never be called unless we messed something up.
11
- */ const throwFatalError = ()=>{
12
- throw new Error('Something went wrong. Please submit an issue at https://github.com/trpc/trpc/issues/new');
13
- };
14
- /**
15
- * Dataloader that's very inspired by https://github.com/graphql/dataloader
16
- * Less configuration, no caching, and allows you to cancel requests
17
- * When cancelling a single fetch the whole batch will be cancelled only when _all_ items are cancelled
18
- */ function dataLoader(batchLoader) {
19
- let pendingItems = null;
20
- let dispatchTimer = null;
21
- const destroyTimerAndPendingItems = ()=>{
22
- clearTimeout(dispatchTimer);
23
- dispatchTimer = null;
24
- pendingItems = null;
25
- };
26
- /**
27
- * Iterate through the items and split them into groups based on the `batchLoader`'s validate function
28
- */ function groupItems(items) {
29
- const groupedItems = [
30
- []
31
- ];
32
- let index = 0;
33
- while(true){
34
- const item = items[index];
35
- if (!item) {
36
- break;
37
- }
38
- const lastGroup = groupedItems[groupedItems.length - 1];
39
- if (item.aborted) {
40
- // Item was aborted before it was dispatched
41
- item.reject(new Error('Aborted'));
42
- index++;
43
- continue;
44
- }
45
- const isValid = batchLoader.validate(lastGroup.concat(item).map((it)=>it.key));
46
- if (isValid) {
47
- lastGroup.push(item);
48
- index++;
49
- continue;
50
- }
51
- if (lastGroup.length === 0) {
52
- item.reject(new Error('Input is too big for a single dispatch'));
53
- index++;
54
- continue;
55
- }
56
- // Create new group, next iteration will try to add the item to that
57
- groupedItems.push([]);
58
- }
59
- return groupedItems;
60
- }
61
- function dispatch() {
62
- const groupedItems = groupItems(pendingItems);
63
- destroyTimerAndPendingItems();
64
- // Create batches for each group of items
65
- for (const items of groupedItems){
66
- if (!items.length) {
67
- continue;
68
- }
69
- const batch = {
70
- items,
71
- cancel: throwFatalError
72
- };
73
- for (const item of items){
74
- item.batch = batch;
75
- }
76
- const { promise , cancel } = batchLoader.fetch(batch.items.map((_item)=>_item.key));
77
- batch.cancel = cancel;
78
- promise.then((result)=>{
79
- for(let i = 0; i < result.length; i++){
80
- const value = result[i];
81
- const item = batch.items[i];
82
- item.resolve(value);
83
- item.batch = null;
84
- }
85
- }).catch((cause)=>{
86
- for (const item of batch.items){
87
- item.reject(cause);
88
- item.batch = null;
89
- }
90
- });
91
- }
92
- }
93
- function load(key) {
94
- const item = {
95
- aborted: false,
96
- key,
97
- batch: null,
98
- resolve: throwFatalError,
99
- reject: throwFatalError
100
- };
101
- const promise = new Promise((resolve, reject)=>{
102
- item.reject = reject;
103
- item.resolve = resolve;
104
- if (!pendingItems) {
105
- pendingItems = [];
106
- }
107
- pendingItems.push(item);
108
- });
109
- if (!dispatchTimer) {
110
- dispatchTimer = setTimeout(dispatch);
111
- }
112
- const cancel = ()=>{
113
- item.aborted = true;
114
- if (item.batch?.items.every((item)=>item.aborted)) {
115
- // All items in the batch have been cancelled
116
- item.batch.cancel();
117
- item.batch = null;
118
- }
119
- };
120
- return {
121
- promise,
122
- cancel
123
- };
124
- }
125
- return {
126
- load
127
- };
128
- }
129
10
 
130
- function httpBatchLink(opts) {
131
- const resolvedOpts = httpUtils.resolveHTTPLinkOptions(opts);
132
- // initialized config
133
- return (runtime)=>{
134
- const maxURLLength = opts.maxURLLength || Infinity;
135
- const batchLoader = (type)=>{
136
- const validate = (batchOps)=>{
137
- if (maxURLLength === Infinity) {
138
- // escape hatch for quick calcs
139
- return true;
140
- }
141
- const path = batchOps.map((op)=>op.path).join(',');
142
- const inputs = batchOps.map((op)=>op.input);
143
- const url = httpUtils.getUrl({
144
- ...resolvedOpts,
145
- runtime,
146
- type,
147
- path,
148
- inputs
149
- });
150
- return url.length <= maxURLLength;
151
- };
152
- const fetch = (batchOps)=>{
153
- const path = batchOps.map((op)=>op.path).join(',');
154
- const inputs = batchOps.map((op)=>op.input);
155
- const { promise , cancel } = httpUtils.jsonHttpRequester({
156
- ...resolvedOpts,
157
- runtime,
158
- type,
159
- path,
160
- inputs,
161
- headers () {
162
- if (!opts.headers) {
163
- return {};
164
- }
165
- if (typeof opts.headers === 'function') {
166
- return opts.headers({
167
- opList: batchOps
168
- });
169
- }
170
- return opts.headers;
171
- }
172
- });
173
- return {
174
- promise: promise.then((res)=>{
175
- const resJSON = Array.isArray(res.json) ? res.json : batchOps.map(()=>res.json);
176
- const result = resJSON.map((item)=>({
177
- meta: res.meta,
178
- json: item
179
- }));
180
- return result;
181
- }),
182
- cancel
183
- };
184
- };
185
- return {
186
- validate,
187
- fetch
188
- };
189
- };
190
- const query = dataLoader(batchLoader('query'));
191
- const mutation = dataLoader(batchLoader('mutation'));
192
- const subscription = dataLoader(batchLoader('subscription'));
193
- const loaders = {
194
- query,
195
- subscription,
196
- mutation
197
- };
198
- return ({ op })=>{
199
- return observable.observable((observer)=>{
200
- const loader = loaders[op.type];
201
- const { promise , cancel } = loader.load(op);
202
- promise.then((res)=>{
203
- const transformed = transformResult.transformResult(res.json, runtime);
204
- if (!transformed.ok) {
205
- observer.error(transformResult.TRPCClientError.from(transformed.error, {
206
- meta: res.meta
207
- }));
208
- return;
209
- }
210
- observer.next({
211
- context: res.meta,
212
- result: transformed.result
213
- });
214
- observer.complete();
215
- }).catch((err)=>observer.error(transformResult.TRPCClientError.from(err)));
216
- return ()=>{
217
- cancel();
218
- };
219
- });
220
- };
221
- };
222
- }
223
11
 
224
- exports.httpBatchLink = httpBatchLink;
12
+ exports.httpBatchLink = links_httpBatchLink.httpBatchLink;