@trpc/server 11.0.0-rc.413 → 11.0.0-rc.419

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 (99) hide show
  1. package/dist/@trpc/server/index.d.ts +1 -1
  2. package/dist/@trpc/server/index.d.ts.map +1 -1
  3. package/dist/adapters/aws-lambda/getPlanner.d.ts.map +1 -1
  4. package/dist/adapters/next-app-dir/redirect.d.ts.map +1 -1
  5. package/dist/adapters/node-http/incomingMessageToRequest.d.ts +0 -1
  6. package/dist/adapters/node-http/incomingMessageToRequest.d.ts.map +1 -1
  7. package/dist/adapters/node-http/incomingMessageToRequest.js +3 -1
  8. package/dist/adapters/node-http/incomingMessageToRequest.mjs +3 -1
  9. package/dist/adapters/node-http/nodeHTTPRequestHandler.d.ts.map +1 -1
  10. package/dist/adapters/node-http/nodeHTTPRequestHandler.js +30 -7
  11. package/dist/adapters/node-http/nodeHTTPRequestHandler.mjs +30 -7
  12. package/dist/adapters/node-http/types.d.ts +0 -1
  13. package/dist/adapters/node-http/types.d.ts.map +1 -1
  14. package/dist/adapters/standalone.d.ts +0 -1
  15. package/dist/adapters/standalone.d.ts.map +1 -1
  16. package/dist/adapters/ws.d.ts +1 -2
  17. package/dist/adapters/ws.d.ts.map +1 -1
  18. package/dist/adapters/ws.js +98 -81
  19. package/dist/adapters/ws.mjs +98 -81
  20. package/dist/bundle-analysis.json +209 -150
  21. package/dist/index.js +5 -3
  22. package/dist/index.mjs +2 -1
  23. package/dist/observable/observable.d.ts +1 -0
  24. package/dist/observable/observable.d.ts.map +1 -1
  25. package/dist/observable/observable.js +55 -0
  26. package/dist/observable/observable.mjs +55 -1
  27. package/dist/unstable-core-do-not-import/createProxy.d.ts +1 -1
  28. package/dist/unstable-core-do-not-import/createProxy.d.ts.map +1 -1
  29. package/dist/unstable-core-do-not-import/createProxy.js +8 -6
  30. package/dist/unstable-core-do-not-import/createProxy.mjs +8 -6
  31. package/dist/unstable-core-do-not-import/http/contentType.d.ts +7 -4
  32. package/dist/unstable-core-do-not-import/http/contentType.d.ts.map +1 -1
  33. package/dist/unstable-core-do-not-import/http/contentType.js +55 -17
  34. package/dist/unstable-core-do-not-import/http/contentType.mjs +56 -18
  35. package/dist/unstable-core-do-not-import/http/resolveResponse.d.ts.map +1 -1
  36. package/dist/unstable-core-do-not-import/http/resolveResponse.js +302 -149
  37. package/dist/unstable-core-do-not-import/http/resolveResponse.mjs +301 -148
  38. package/dist/unstable-core-do-not-import/http/types.d.ts +34 -5
  39. package/dist/unstable-core-do-not-import/http/types.d.ts.map +1 -1
  40. package/dist/unstable-core-do-not-import/initTRPC.d.ts +12 -12
  41. package/dist/unstable-core-do-not-import/initTRPC.d.ts.map +1 -1
  42. package/dist/unstable-core-do-not-import/middleware.d.ts +3 -3
  43. package/dist/unstable-core-do-not-import/middleware.d.ts.map +1 -1
  44. package/dist/unstable-core-do-not-import/procedureBuilder.d.ts +3 -1
  45. package/dist/unstable-core-do-not-import/procedureBuilder.d.ts.map +1 -1
  46. package/dist/unstable-core-do-not-import/rootConfig.d.ts +12 -0
  47. package/dist/unstable-core-do-not-import/rootConfig.d.ts.map +1 -1
  48. package/dist/unstable-core-do-not-import/router.d.ts +2 -2
  49. package/dist/unstable-core-do-not-import/router.d.ts.map +1 -1
  50. package/dist/unstable-core-do-not-import/router.js +7 -2
  51. package/dist/unstable-core-do-not-import/router.mjs +7 -2
  52. package/dist/unstable-core-do-not-import/stream/{stream.d.ts → jsonl.d.ts} +5 -5
  53. package/dist/unstable-core-do-not-import/stream/jsonl.d.ts.map +1 -0
  54. package/dist/unstable-core-do-not-import/stream/{stream.js → jsonl.js} +90 -89
  55. package/dist/unstable-core-do-not-import/stream/{stream.mjs → jsonl.mjs} +89 -88
  56. package/dist/unstable-core-do-not-import/stream/sse.d.ts +95 -0
  57. package/dist/unstable-core-do-not-import/stream/sse.d.ts.map +1 -0
  58. package/dist/unstable-core-do-not-import/stream/sse.js +175 -0
  59. package/dist/unstable-core-do-not-import/stream/sse.mjs +169 -0
  60. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.d.ts +18 -0
  61. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.d.ts.map +1 -0
  62. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.js +46 -0
  63. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.mjs +43 -0
  64. package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.d.ts +10 -0
  65. package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.d.ts.map +1 -0
  66. package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.js +31 -0
  67. package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.mjs +29 -0
  68. package/dist/unstable-core-do-not-import/stream/utils/createServer.d.ts +7 -0
  69. package/dist/unstable-core-do-not-import/stream/utils/createServer.d.ts.map +1 -0
  70. package/dist/unstable-core-do-not-import/transformer.d.ts +5 -5
  71. package/dist/unstable-core-do-not-import/utils.d.ts +4 -0
  72. package/dist/unstable-core-do-not-import/utils.d.ts.map +1 -1
  73. package/dist/unstable-core-do-not-import/utils.js +4 -0
  74. package/dist/unstable-core-do-not-import/utils.mjs +4 -1
  75. package/dist/unstable-core-do-not-import.d.ts +2 -1
  76. package/dist/unstable-core-do-not-import.d.ts.map +1 -1
  77. package/dist/unstable-core-do-not-import.js +11 -4
  78. package/dist/unstable-core-do-not-import.mjs +3 -2
  79. package/package.json +4 -4
  80. package/src/@trpc/server/index.ts +1 -0
  81. package/src/adapters/node-http/incomingMessageToRequest.ts +3 -2
  82. package/src/adapters/node-http/nodeHTTPRequestHandler.ts +32 -7
  83. package/src/adapters/ws.ts +101 -75
  84. package/src/observable/observable.ts +63 -0
  85. package/src/unstable-core-do-not-import/createProxy.ts +13 -6
  86. package/src/unstable-core-do-not-import/http/contentType.ts +78 -21
  87. package/src/unstable-core-do-not-import/http/resolveResponse.ts +331 -164
  88. package/src/unstable-core-do-not-import/http/types.ts +42 -5
  89. package/src/unstable-core-do-not-import/procedureBuilder.ts +8 -1
  90. package/src/unstable-core-do-not-import/rootConfig.ts +12 -0
  91. package/src/unstable-core-do-not-import/router.ts +46 -34
  92. package/src/unstable-core-do-not-import/stream/{stream.ts → jsonl.ts} +99 -85
  93. package/src/unstable-core-do-not-import/stream/sse.ts +291 -0
  94. package/src/unstable-core-do-not-import/stream/utils/createDeferred.ts +48 -0
  95. package/src/unstable-core-do-not-import/stream/utils/createReadableStream.ts +31 -0
  96. package/src/unstable-core-do-not-import/stream/utils/createServer.ts +46 -0
  97. package/src/unstable-core-do-not-import/utils.ts +5 -0
  98. package/src/unstable-core-do-not-import.ts +2 -1
  99. package/dist/unstable-core-do-not-import/stream/stream.d.ts.map +0 -1
@@ -1,20 +1,42 @@
1
1
  'use strict';
2
2
 
3
+ var observable = require('../../observable/observable.js');
3
4
  var getErrorShape = require('../error/getErrorShape.js');
4
5
  var TRPCError = require('../error/TRPCError.js');
5
- var router = require('../router.js');
6
- var stream = require('../stream/stream.js');
6
+ var jsonl = require('../stream/jsonl.js');
7
+ var sse = require('../stream/sse.js');
7
8
  var transformer = require('../transformer.js');
8
9
  var utils = require('../utils.js');
9
10
  var contentType = require('./contentType.js');
10
11
  var getHTTPStatusCode = require('./getHTTPStatusCode.js');
11
12
 
12
- const HTTP_METHOD_PROCEDURE_TYPE_MAP = {
13
- GET: 'query',
14
- POST: 'mutation'
13
+ const TYPE_ACCEPTED_METHOD_MAP = {
14
+ mutation: [
15
+ 'POST'
16
+ ],
17
+ query: [
18
+ 'GET'
19
+ ],
20
+ subscription: [
21
+ 'GET'
22
+ ]
23
+ };
24
+ const TYPE_ACCEPTED_METHOD_MAP_WITH_METHOD_OVERRIDE = {
25
+ // never allow GET to do a mutation
26
+ mutation: [
27
+ 'POST'
28
+ ],
29
+ query: [
30
+ 'GET',
31
+ 'POST'
32
+ ],
33
+ subscription: [
34
+ 'GET',
35
+ 'POST'
36
+ ]
15
37
  };
16
38
  function initResponse(initOpts) {
17
- const { ctx , info , type , responseMeta , untransformedJSON , errors =[] , headers , } = initOpts;
39
+ const { ctx , info , responseMeta , untransformedJSON , errors =[] , headers , } = initOpts;
18
40
  let status = untransformedJSON ? getHTTPStatusCode.getHTTPStatusCode(untransformedJSON) : 200;
19
41
  const eagerGeneration = !untransformedJSON;
20
42
  const data = eagerGeneration ? [] : Array.isArray(untransformedJSON) ? untransformedJSON : [
@@ -24,10 +46,10 @@ function initResponse(initOpts) {
24
46
  ctx,
25
47
  info,
26
48
  paths: info?.calls.map((call)=>call.path),
27
- type,
28
49
  data,
29
50
  errors,
30
- eagerGeneration
51
+ eagerGeneration,
52
+ type: info?.calls.find((call)=>call.procedure?._def.type)?.procedure?._def.type ?? 'unknown'
31
53
  }) ?? {};
32
54
  if (meta.headers) {
33
55
  if (meta.headers instanceof Headers) {
@@ -84,15 +106,28 @@ function caughtErrorToData(cause, errorOpts) {
84
106
  body
85
107
  };
86
108
  }
109
+ /**
110
+ * Check if a value is a stream-like object
111
+ * - if it's an async iterable
112
+ * - if it's an object with async iterables or promises
113
+ */ function isDataStream(v) {
114
+ if (!utils.isObject(v)) {
115
+ return false;
116
+ }
117
+ if (utils.isAsyncIterable(v)) {
118
+ return true;
119
+ }
120
+ return Object.values(v).some(jsonl.isPromise) || Object.values(v).some(utils.isAsyncIterable);
121
+ }
87
122
  async function resolveResponse(opts) {
88
- const { router: router$1 , req } = opts;
123
+ const { router , req } = opts;
89
124
  const headers = new Headers([
90
125
  [
91
126
  'vary',
92
127
  'trpc-accept'
93
128
  ]
94
129
  ]);
95
- const config = router$1._def._config;
130
+ const config = router._def._config;
96
131
  const url = new URL(req.url);
97
132
  if (req.method === 'HEAD') {
98
133
  // can be used for lambda warmup
@@ -102,17 +137,21 @@ async function resolveResponse(opts) {
102
137
  }
103
138
  const allowBatching = opts.allowBatching ?? opts.batching?.enabled ?? true;
104
139
  const allowMethodOverride = (opts.allowMethodOverride ?? false) && req.method === 'POST';
105
- const type = HTTP_METHOD_PROCEDURE_TYPE_MAP[req.method] ?? 'unknown';
106
140
  let ctx = undefined;
107
141
  let info = undefined;
108
- const isStreamCall = req.headers.get('trpc-accept') === 'application/jsonl';
109
- const experimentalIterablesAndDeferreds = config.experimental?.iterablesAndDeferreds ?? false;
142
+ const methodMapper = allowMethodOverride ? TYPE_ACCEPTED_METHOD_MAP_WITH_METHOD_OVERRIDE : TYPE_ACCEPTED_METHOD_MAP;
143
+ /**
144
+ * @deprecated
145
+ */ const isStreamCall = req.headers.get('trpc-accept') === 'application/jsonl';
146
+ const experimentalIterablesAndDeferreds = router._def._config.experimental?.iterablesAndDeferreds ?? true;
147
+ const experimentalSSE = router._def._config.experimental?.sseSubscriptions?.enabled ?? true;
110
148
  try {
111
149
  info = contentType.getRequestInfo({
112
150
  req,
113
151
  path: decodeURIComponent(opts.path),
114
- config: config,
115
- searchParams: url.searchParams
152
+ router,
153
+ searchParams: url.searchParams,
154
+ headers: opts.req.headers
116
155
  });
117
156
  // we create context early so that error handlers may access context information
118
157
  ctx = await opts.createContext({
@@ -127,166 +166,281 @@ async function resolveResponse(opts) {
127
166
  message: `Batching is not enabled on the server`
128
167
  });
129
168
  }
130
- if (type === 'unknown') {
169
+ /* istanbul ignore if -- @preserve */ if (isStreamCall && !info.isBatchCall) {
131
170
  throw new TRPCError.TRPCError({
132
- message: `Unexpected request method ${req.method}`,
133
- code: 'METHOD_NOT_SUPPORTED'
171
+ message: `Streaming requests must be batched (you can do a batch of 1)`,
172
+ code: 'BAD_REQUEST'
134
173
  });
135
174
  }
136
- const errors = [];
137
- const promises = info.calls.map(async (call)=>{
175
+ const rpcCalls = info.calls.map(async (call)=>{
176
+ const proc = call.procedure;
138
177
  try {
139
- const data = await router.callProcedure({
140
- procedures: opts.router._def.procedures,
178
+ if (!proc) {
179
+ throw new TRPCError.TRPCError({
180
+ code: 'NOT_FOUND',
181
+ message: `No procedure found on path "${call.path}"`
182
+ });
183
+ }
184
+ if (!methodMapper[proc._def.type].includes(req.method)) {
185
+ throw new TRPCError.TRPCError({
186
+ code: 'METHOD_NOT_SUPPORTED',
187
+ message: `Unsupported ${req.method}-request to ${proc._def.type} procedure at path "${call.path}"`
188
+ });
189
+ }
190
+ /* istanbul ignore if -- @preserve */ if (proc._def.type === 'subscription' && info.isBatchCall) {
191
+ throw new TRPCError.TRPCError({
192
+ code: 'BAD_REQUEST',
193
+ message: `Cannot batch subscription calls`
194
+ });
195
+ }
196
+ const data = await proc({
141
197
  path: call.path,
142
198
  getRawInput: call.getRawInput,
143
199
  ctx,
144
- type,
145
- allowMethodOverride
200
+ type: proc._def.type
146
201
  });
147
- if ((!isStreamCall || !experimentalIterablesAndDeferreds) && utils.isObject(data) && (Symbol.asyncIterator in data || Object.values(data).some(stream.isPromise))) {
148
- if (!isStreamCall) {
149
- throw new TRPCError.TRPCError({
150
- code: 'UNSUPPORTED_MEDIA_TYPE',
151
- message: 'Cannot return async iterable or nested promises in non-streaming response'
152
- });
153
- }
154
- if (!experimentalIterablesAndDeferreds) {
155
- throw new TRPCError.TRPCError({
156
- code: 'INTERNAL_SERVER_ERROR',
157
- message: 'Missing experimental flag "iterablesAndDeferreds"'
158
- });
159
- }
160
- }
161
- return {
162
- result: {
163
- data
164
- }
165
- };
202
+ return [
203
+ data
204
+ ];
166
205
  } catch (cause) {
167
206
  const error = TRPCError.getTRPCErrorFromUnknown(cause);
168
- errors.push(error);
169
207
  const input = call.result();
170
208
  opts.onError?.({
171
209
  error,
172
210
  path: call.path,
173
211
  input,
174
212
  ctx,
175
- type: type,
213
+ type: call.procedure?._def.type ?? 'unknown',
176
214
  req: opts.req
177
215
  });
178
- return {
179
- error: getErrorShape.getErrorShape({
180
- config,
181
- error,
182
- type,
183
- path: call.path,
184
- input,
185
- ctx
186
- })
187
- };
216
+ return [
217
+ null,
218
+ error
219
+ ];
188
220
  }
189
221
  });
190
- if (!isStreamCall) {
222
+ // ----------- response handlers -----------
223
+ if (!info.isBatchCall) {
224
+ const [call] = info.calls;
225
+ const [data, error] = await rpcCalls[0];
226
+ switch(info.type){
227
+ case 'unknown':
228
+ case 'mutation':
229
+ case 'query':
230
+ {
231
+ // httpLink
232
+ headers.set('content-type', 'application/json');
233
+ if (isDataStream(data)) {
234
+ throw new TRPCError.TRPCError({
235
+ code: 'UNSUPPORTED_MEDIA_TYPE',
236
+ message: 'Cannot use stream-like response in non-streaming request - use httpBatchStreamLink'
237
+ });
238
+ }
239
+ const res = error ? {
240
+ error: getErrorShape.getErrorShape({
241
+ config,
242
+ ctx,
243
+ error,
244
+ input: call.result(),
245
+ path: call.path,
246
+ type: info.type
247
+ })
248
+ } : {
249
+ result: {
250
+ data
251
+ }
252
+ };
253
+ const headResponse = initResponse({
254
+ ctx,
255
+ info,
256
+ responseMeta: opts.responseMeta,
257
+ errors: error ? [
258
+ error
259
+ ] : [],
260
+ headers,
261
+ untransformedJSON: [
262
+ res
263
+ ]
264
+ });
265
+ return new Response(JSON.stringify(transformer.transformTRPCResponse(config, res)), {
266
+ status: headResponse.status,
267
+ headers
268
+ });
269
+ }
270
+ case 'subscription':
271
+ {
272
+ // httpSubscriptionLink
273
+ if (!experimentalSSE) {
274
+ throw new TRPCError.TRPCError({
275
+ code: 'METHOD_NOT_SUPPORTED',
276
+ message: 'Missing experimental flag "sseSubscriptions"'
277
+ });
278
+ }
279
+ if (!observable.isObservable(data) && !utils.isAsyncIterable(data)) {
280
+ throw new TRPCError.TRPCError({
281
+ message: `Subscription ${call.path} did not return an observable or a AsyncGenerator`,
282
+ code: 'INTERNAL_SERVER_ERROR'
283
+ });
284
+ }
285
+ const dataAsIterable = observable.isObservable(data) ? observable.observableToAsyncIterable(data) : data;
286
+ const stream = sse.sseStreamProducer({
287
+ data: dataAsIterable,
288
+ serialize: (v)=>config.transformer.output.serialize(v)
289
+ });
290
+ for (const [key, value] of Object.entries(sse.sseHeaders)){
291
+ headers.set(key, value);
292
+ }
293
+ const headResponse1 = initResponse({
294
+ ctx,
295
+ info,
296
+ responseMeta: opts.responseMeta,
297
+ errors: [],
298
+ headers,
299
+ untransformedJSON: null
300
+ });
301
+ return new Response(stream, {
302
+ headers,
303
+ status: headResponse1.status
304
+ });
305
+ }
306
+ }
307
+ }
308
+ // batch response handlers
309
+ if (info.accept === 'application/jsonl') {
310
+ // httpBatchStreamLink
191
311
  headers.set('content-type', 'application/json');
192
- /**
193
- * Non-streaming response:
194
- * - await all responses in parallel, blocking on the slowest one
195
- * - create headers with known response body
196
- * - return a complete HTTPResponse
197
- */ const untransformedJSON = await Promise.all(promises);
198
- const errors1 = untransformedJSON.flatMap((response)=>'error' in response ? [
199
- response.error
200
- ] : []);
201
- const headResponse = initResponse({
312
+ headers.set('transfer-encoding', 'chunked');
313
+ const headResponse2 = initResponse({
202
314
  ctx,
203
315
  info,
204
- type,
205
316
  responseMeta: opts.responseMeta,
206
- untransformedJSON,
207
- errors: errors1,
208
- headers
317
+ errors: [],
318
+ headers,
319
+ untransformedJSON: null
209
320
  });
210
- // return body stuff
211
- const result = info.isBatchCall ? untransformedJSON : untransformedJSON[0];
212
- const transformedJSON = transformer.transformTRPCResponse(router$1._def._config, result);
213
- const body = JSON.stringify(transformedJSON);
214
- return new Response(body, {
215
- status: headResponse.status,
216
- headers
217
- });
218
- }
219
- headers.set('content-type', 'application/json');
220
- headers.set('transfer-encoding', 'chunked');
221
- /**
222
- * Streaming response:
223
- * - block on none, call `onChunk` as soon as each response is ready
224
- * - create headers with minimal data (cannot know the response body in advance)
225
- * - return void
226
- */ const headResponse1 = initResponse({
227
- ctx,
228
- info,
229
- type,
230
- responseMeta: opts.responseMeta,
231
- errors: [],
232
- headers
233
- });
234
- const stream$1 = stream.jsonlStreamProducer({
235
- /**
236
- * Example structure for `maxDepth: 4`:
237
- * {
238
- * // 1
239
- * 0: {
240
- * // 2
241
- * result: {
242
- * // 3
243
- * data: // 4
244
- * }
245
- * }
246
- * }
247
- */ maxDepth: experimentalIterablesAndDeferreds ? 4 : 3,
248
- formatError (errorOpts) {
249
- const call = info?.calls[errorOpts.path[0]];
250
- return getErrorShape.getErrorShape({
251
- config,
252
- ctx,
253
- error: TRPCError.getTRPCErrorFromUnknown(errorOpts.error),
254
- input: call?.result(),
255
- path: call?.path,
256
- type
257
- });
258
- },
259
- data: promises.map(async (it)=>{
260
- const response = await it;
261
- if ('result' in response) {
321
+ const stream1 = jsonl.jsonlStreamProducer({
322
+ /**
323
+ * Example structure for `maxDepth: 4`:
324
+ * {
325
+ * // 1
326
+ * 0: {
327
+ * // 2
328
+ * result: {
329
+ * // 3
330
+ * data: // 4
331
+ * }
332
+ * }
333
+ * }
334
+ */ maxDepth: experimentalIterablesAndDeferreds ? 4 : 3,
335
+ data: rpcCalls.map(async (res)=>{
336
+ const [result, error] = await res;
337
+ const call = info.calls[0];
338
+ if (error) {
339
+ return {
340
+ error: getErrorShape.getErrorShape({
341
+ config,
342
+ ctx,
343
+ error,
344
+ input: call.result(),
345
+ path: call.path,
346
+ type: call.procedure?._def.type ?? 'unknown'
347
+ })
348
+ };
349
+ }
262
350
  /**
263
351
  * Not very pretty, but we need to wrap nested data in promises
264
352
  * Our stream producer will only resolve top-level async values or async values that are directly nested in another async value
265
- */ return {
266
- ...response,
353
+ */ const data = observable.isObservable(result) ? observable.observableToAsyncIterable(result) : Promise.resolve(result);
354
+ return {
267
355
  result: Promise.resolve({
268
- ...response.result,
269
- data: Promise.resolve(response.result.data)
356
+ data
270
357
  })
271
358
  };
359
+ }),
360
+ serialize: config.transformer.output.serialize,
361
+ onError: (cause)=>{
362
+ opts.onError?.({
363
+ error: TRPCError.getTRPCErrorFromUnknown(cause),
364
+ path: undefined,
365
+ input: undefined,
366
+ ctx,
367
+ req: opts.req,
368
+ type: info?.type ?? 'unknown'
369
+ });
370
+ },
371
+ formatError (errorOpts) {
372
+ const call = info?.calls[errorOpts.path[0]];
373
+ const shape = getErrorShape.getErrorShape({
374
+ config,
375
+ ctx,
376
+ error: TRPCError.getTRPCErrorFromUnknown(errorOpts.error),
377
+ input: call?.result(),
378
+ path: call?.path,
379
+ type: call?.procedure?._def.type ?? 'unknown'
380
+ });
381
+ return shape;
272
382
  }
273
- return response;
274
- }),
275
- serialize: config.transformer.output.serialize,
276
- onError: (cause)=>{
277
- opts.onError?.({
278
- error: TRPCError.getTRPCErrorFromUnknown(cause),
279
- path: undefined,
280
- input: undefined,
281
- ctx,
282
- type,
283
- req: opts.req
284
- });
383
+ });
384
+ return new Response(stream1, {
385
+ headers,
386
+ status: headResponse2.status
387
+ });
388
+ }
389
+ // httpBatchLink
390
+ /**
391
+ * Non-streaming response:
392
+ * - await all responses in parallel, blocking on the slowest one
393
+ * - create headers with known response body
394
+ * - return a complete HTTPResponse
395
+ */ headers.set('content-type', 'application/json');
396
+ const results = (await Promise.all(rpcCalls)).map((res)=>{
397
+ const [data, error] = res;
398
+ if (error) {
399
+ return res;
285
400
  }
401
+ if (isDataStream(data)) {
402
+ return [
403
+ null,
404
+ new TRPCError.TRPCError({
405
+ code: 'UNSUPPORTED_MEDIA_TYPE',
406
+ message: 'Cannot use stream-like response in non-streaming request - use httpBatchStreamLink'
407
+ })
408
+ ];
409
+ }
410
+ return res;
286
411
  });
287
- return new Response(stream$1, {
288
- headers,
289
- status: headResponse1.status
412
+ const resultAsRPCResponse = results.map(([data, error], index)=>{
413
+ const call = info.calls[index];
414
+ if (error) {
415
+ return {
416
+ error: getErrorShape.getErrorShape({
417
+ config,
418
+ ctx,
419
+ error,
420
+ input: call.result(),
421
+ path: call.path,
422
+ type: call.procedure?._def.type ?? 'unknown'
423
+ })
424
+ };
425
+ }
426
+ return {
427
+ result: {
428
+ data
429
+ }
430
+ };
431
+ });
432
+ const errors = results.map(([_, error])=>error).filter(Boolean);
433
+ const headResponse3 = initResponse({
434
+ ctx,
435
+ info,
436
+ responseMeta: opts.responseMeta,
437
+ untransformedJSON: resultAsRPCResponse,
438
+ errors,
439
+ headers
440
+ });
441
+ return new Response(JSON.stringify(transformer.transformTRPCResponse(config, resultAsRPCResponse)), {
442
+ status: headResponse3.status,
443
+ headers
290
444
  });
291
445
  } catch (cause) {
292
446
  // we get here if
@@ -296,24 +450,23 @@ async function resolveResponse(opts) {
296
450
  // - post body is too large
297
451
  // - input deserialization fails
298
452
  // - `errorFormatter` return value is malformed
299
- const { error , untransformedJSON: untransformedJSON1 , body: body1 } = caughtErrorToData(cause, {
453
+ const { error: error1 , untransformedJSON , body } = caughtErrorToData(cause, {
300
454
  opts,
301
455
  ctx,
302
- type
456
+ type: info?.type ?? 'unknown'
303
457
  });
304
- const headResponse2 = initResponse({
458
+ const headResponse4 = initResponse({
305
459
  ctx,
306
460
  info,
307
- type,
308
461
  responseMeta: opts.responseMeta,
309
- untransformedJSON: untransformedJSON1,
462
+ untransformedJSON,
310
463
  errors: [
311
- error
464
+ error1
312
465
  ],
313
466
  headers
314
467
  });
315
- return new Response(body1, {
316
- status: headResponse2.status,
468
+ return new Response(body, {
469
+ status: headResponse4.status,
317
470
  headers
318
471
  });
319
472
  }