@trpc/server 11.0.0-rc.373 → 11.0.0-rc.374
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.
- package/dist/bundle-analysis.json +116 -97
- package/dist/unstable-core-do-not-import/clientish/serialize.d.ts +1 -1
- package/dist/unstable-core-do-not-import/clientish/serialize.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/http/resolveResponse.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/http/resolveResponse.js +79 -52
- package/dist/unstable-core-do-not-import/http/resolveResponse.mjs +78 -51
- package/dist/unstable-core-do-not-import/initTRPC.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/initTRPC.js +2 -1
- package/dist/unstable-core-do-not-import/initTRPC.mjs +2 -1
- package/dist/unstable-core-do-not-import/rootConfig.d.ts +6 -0
- package/dist/unstable-core-do-not-import/rootConfig.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/stream/stream.d.ts +94 -0
- package/dist/unstable-core-do-not-import/stream/stream.d.ts.map +1 -0
- package/dist/unstable-core-do-not-import/stream/stream.js +466 -0
- package/dist/unstable-core-do-not-import/stream/stream.mjs +462 -0
- package/dist/unstable-core-do-not-import/utils.d.ts +2 -1
- package/dist/unstable-core-do-not-import/utils.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/utils.js +4 -0
- package/dist/unstable-core-do-not-import/utils.mjs +4 -1
- package/dist/unstable-core-do-not-import.d.ts +1 -0
- package/dist/unstable-core-do-not-import.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import.js +5 -0
- package/dist/unstable-core-do-not-import.mjs +2 -1
- package/package.json +2 -2
- package/src/unstable-core-do-not-import/clientish/serialize.ts +1 -0
- package/src/unstable-core-do-not-import/http/resolveResponse.ts +83 -52
- package/src/unstable-core-do-not-import/initTRPC.ts +1 -0
- package/src/unstable-core-do-not-import/rootConfig.ts +7 -0
- package/src/unstable-core-do-not-import/stream/stream.ts +580 -0
- package/src/unstable-core-do-not-import/utils.ts +7 -1
- package/src/unstable-core-do-not-import.ts +1 -0
|
@@ -9,8 +9,9 @@ import {
|
|
|
9
9
|
type inferRouterError,
|
|
10
10
|
} from '../router';
|
|
11
11
|
import type { TRPCResponse } from '../rpc';
|
|
12
|
+
import { isPromise, jsonlStreamProducer } from '../stream/stream';
|
|
12
13
|
import { transformTRPCResponse } from '../transformer';
|
|
13
|
-
import {
|
|
14
|
+
import { isObject } from '../utils';
|
|
14
15
|
import { getRequestInfo } from './contentType';
|
|
15
16
|
import { getHTTPStatusCode } from './getHTTPStatusCode';
|
|
16
17
|
import type {
|
|
@@ -48,6 +49,7 @@ function initResponse<TRouter extends AnyRouter, TRequest>(initOpts: {
|
|
|
48
49
|
| TRPCResponse<unknown, inferRouterError<TRouter>>[]
|
|
49
50
|
| undefined;
|
|
50
51
|
errors: TRPCError[];
|
|
52
|
+
headers: Headers;
|
|
51
53
|
}) {
|
|
52
54
|
const {
|
|
53
55
|
ctx,
|
|
@@ -56,12 +58,11 @@ function initResponse<TRouter extends AnyRouter, TRequest>(initOpts: {
|
|
|
56
58
|
responseMeta,
|
|
57
59
|
untransformedJSON,
|
|
58
60
|
errors = [],
|
|
61
|
+
headers,
|
|
59
62
|
} = initOpts;
|
|
60
63
|
|
|
61
64
|
let status = untransformedJSON ? getHTTPStatusCode(untransformedJSON) : 200;
|
|
62
65
|
|
|
63
|
-
const headers = new Headers([['Content-Type', 'application/json']]);
|
|
64
|
-
|
|
65
66
|
const eagerGeneration = !untransformedJSON;
|
|
66
67
|
const data = eagerGeneration
|
|
67
68
|
? []
|
|
@@ -106,7 +107,6 @@ function initResponse<TRouter extends AnyRouter, TRequest>(initOpts: {
|
|
|
106
107
|
|
|
107
108
|
return {
|
|
108
109
|
status,
|
|
109
|
-
headers,
|
|
110
110
|
};
|
|
111
111
|
}
|
|
112
112
|
|
|
@@ -159,6 +159,7 @@ export async function resolveResponse<TRouter extends AnyRouter>(
|
|
|
159
159
|
opts: ResolveHTTPRequestOptions<TRouter>,
|
|
160
160
|
): Promise<Response> {
|
|
161
161
|
const { router, req } = opts;
|
|
162
|
+
const headers = new Headers([['vary', 'trpc-accept']]);
|
|
162
163
|
|
|
163
164
|
const url = new URL(req.url);
|
|
164
165
|
|
|
@@ -177,7 +178,10 @@ export async function resolveResponse<TRouter extends AnyRouter>(
|
|
|
177
178
|
let ctx: inferRouterContext<TRouter> | undefined = undefined;
|
|
178
179
|
let info: TRPCRequestInfo | undefined = undefined;
|
|
179
180
|
|
|
180
|
-
const isStreamCall = req.headers.get('trpc-
|
|
181
|
+
const isStreamCall = req.headers.get('trpc-accept') === 'application/jsonl';
|
|
182
|
+
|
|
183
|
+
const experimentalIterablesAndDeferreds =
|
|
184
|
+
router._def._config.experimental?.iterablesAndDeferreds ?? false;
|
|
181
185
|
|
|
182
186
|
try {
|
|
183
187
|
info = getRequestInfo({
|
|
@@ -222,6 +226,27 @@ export async function resolveResponse<TRouter extends AnyRouter>(
|
|
|
222
226
|
type,
|
|
223
227
|
allowMethodOverride,
|
|
224
228
|
});
|
|
229
|
+
|
|
230
|
+
if (
|
|
231
|
+
(!isStreamCall || !experimentalIterablesAndDeferreds) &&
|
|
232
|
+
isObject(data) &&
|
|
233
|
+
(Symbol.asyncIterator in data || Object.values(data).some(isPromise))
|
|
234
|
+
) {
|
|
235
|
+
if (!isStreamCall) {
|
|
236
|
+
throw new TRPCError({
|
|
237
|
+
code: 'UNSUPPORTED_MEDIA_TYPE',
|
|
238
|
+
message:
|
|
239
|
+
'Cannot return async iterable or nested promises in non-streaming response',
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
if (!experimentalIterablesAndDeferreds) {
|
|
243
|
+
throw new TRPCError({
|
|
244
|
+
code: 'INTERNAL_SERVER_ERROR',
|
|
245
|
+
message: 'Missing experimental flag "iterablesAndDeferreds"',
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
225
250
|
return {
|
|
226
251
|
result: {
|
|
227
252
|
data,
|
|
@@ -254,6 +279,7 @@ export async function resolveResponse<TRouter extends AnyRouter>(
|
|
|
254
279
|
}
|
|
255
280
|
});
|
|
256
281
|
if (!isStreamCall) {
|
|
282
|
+
headers.set('content-type', 'application/json');
|
|
257
283
|
/**
|
|
258
284
|
* Non-streaming response:
|
|
259
285
|
* - await all responses in parallel, blocking on the slowest one
|
|
@@ -262,6 +288,7 @@ export async function resolveResponse<TRouter extends AnyRouter>(
|
|
|
262
288
|
*/
|
|
263
289
|
|
|
264
290
|
const untransformedJSON = await Promise.all(promises);
|
|
291
|
+
|
|
265
292
|
const errors = untransformedJSON.flatMap((response) =>
|
|
266
293
|
'error' in response ? [response.error] : [],
|
|
267
294
|
);
|
|
@@ -273,6 +300,7 @@ export async function resolveResponse<TRouter extends AnyRouter>(
|
|
|
273
300
|
responseMeta: opts.responseMeta,
|
|
274
301
|
untransformedJSON,
|
|
275
302
|
errors,
|
|
303
|
+
headers,
|
|
276
304
|
});
|
|
277
305
|
|
|
278
306
|
// return body stuff
|
|
@@ -287,10 +315,12 @@ export async function resolveResponse<TRouter extends AnyRouter>(
|
|
|
287
315
|
|
|
288
316
|
return new Response(body, {
|
|
289
317
|
status: headResponse.status,
|
|
290
|
-
headers
|
|
318
|
+
headers,
|
|
291
319
|
});
|
|
292
320
|
}
|
|
293
321
|
|
|
322
|
+
headers.set('content-type', 'application/json');
|
|
323
|
+
headers.set('transfer-encoding', 'chunked');
|
|
294
324
|
/**
|
|
295
325
|
* Streaming response:
|
|
296
326
|
* - block on none, call `onChunk` as soon as each response is ready
|
|
@@ -303,56 +333,56 @@ export async function resolveResponse<TRouter extends AnyRouter>(
|
|
|
303
333
|
type,
|
|
304
334
|
responseMeta: opts.responseMeta,
|
|
305
335
|
errors: [],
|
|
336
|
+
headers,
|
|
306
337
|
});
|
|
307
338
|
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
const { body } = caughtErrorToData(cause, {
|
|
338
|
-
opts,
|
|
339
|
-
ctx,
|
|
340
|
-
type,
|
|
341
|
-
path: call.path,
|
|
342
|
-
input,
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
await controller.write(formatter(index, body));
|
|
339
|
+
const stream = jsonlStreamProducer({
|
|
340
|
+
/**
|
|
341
|
+
* Example structure for `maxDepth: 4`:
|
|
342
|
+
* {
|
|
343
|
+
* // 1
|
|
344
|
+
* 0: {
|
|
345
|
+
* // 2
|
|
346
|
+
* result: {
|
|
347
|
+
* // 3
|
|
348
|
+
* data: // 4
|
|
349
|
+
* }
|
|
350
|
+
* }
|
|
351
|
+
* }
|
|
352
|
+
*/
|
|
353
|
+
maxDepth: experimentalIterablesAndDeferreds ? 4 : 3,
|
|
354
|
+
data: promises.map(async (it) => {
|
|
355
|
+
const response = await it;
|
|
356
|
+
if ('result' in response) {
|
|
357
|
+
/**
|
|
358
|
+
* Not very pretty, but we need to wrap nested data in promises
|
|
359
|
+
* Our stream producer will only resolve top-level async values or async values that are directly nested in another async value
|
|
360
|
+
*/
|
|
361
|
+
return {
|
|
362
|
+
...response,
|
|
363
|
+
result: Promise.resolve({
|
|
364
|
+
...response.result,
|
|
365
|
+
data: Promise.resolve(response.result.data),
|
|
366
|
+
}),
|
|
367
|
+
};
|
|
346
368
|
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
369
|
+
return response;
|
|
370
|
+
}),
|
|
371
|
+
serialize: opts.router._def._config.transformer.output.serialize,
|
|
372
|
+
onError: (cause) => {
|
|
373
|
+
opts.onError?.({
|
|
374
|
+
error: getTRPCErrorFromUnknown(cause),
|
|
375
|
+
path: undefined,
|
|
376
|
+
input: undefined,
|
|
377
|
+
ctx,
|
|
378
|
+
type,
|
|
379
|
+
req: opts.req,
|
|
380
|
+
});
|
|
381
|
+
},
|
|
382
|
+
});
|
|
353
383
|
|
|
354
384
|
return new Response(stream, {
|
|
355
|
-
headers
|
|
385
|
+
headers,
|
|
356
386
|
status: headResponse.status,
|
|
357
387
|
});
|
|
358
388
|
} catch (cause) {
|
|
@@ -376,11 +406,12 @@ export async function resolveResponse<TRouter extends AnyRouter>(
|
|
|
376
406
|
responseMeta: opts.responseMeta,
|
|
377
407
|
untransformedJSON,
|
|
378
408
|
errors: [error],
|
|
409
|
+
headers,
|
|
379
410
|
});
|
|
380
411
|
|
|
381
412
|
return new Response(body, {
|
|
382
413
|
status: headResponse.status,
|
|
383
|
-
headers
|
|
414
|
+
headers,
|
|
384
415
|
});
|
|
385
416
|
}
|
|
386
417
|
}
|
|
@@ -63,6 +63,13 @@ export interface RootConfig<TTypes extends RootTypes> {
|
|
|
63
63
|
isDev: boolean;
|
|
64
64
|
|
|
65
65
|
defaultMeta?: TTypes['meta'] extends object ? TTypes['meta'] : never;
|
|
66
|
+
|
|
67
|
+
experimental?: {
|
|
68
|
+
/**
|
|
69
|
+
* Enable support for returning async iterables and returning deferred promises when using `httpBatchStreamLink`
|
|
70
|
+
*/
|
|
71
|
+
iterablesAndDeferreds?: boolean;
|
|
72
|
+
};
|
|
66
73
|
}
|
|
67
74
|
|
|
68
75
|
/**
|