@trpc/server 10.0.0-proxy-alpha.76 → 10.0.0-proxy-alpha.77

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 (56) hide show
  1. package/dist/{TRPCError-281ac25a.mjs → TRPCError-e99e7cbe.mjs} +1 -1
  2. package/dist/adapters/aws-lambda/index.js +2 -2
  3. package/dist/adapters/aws-lambda/index.mjs +3 -3
  4. package/dist/adapters/express.js +4 -3
  5. package/dist/adapters/express.mjs +5 -4
  6. package/dist/adapters/fastify/index.js +3 -2
  7. package/dist/adapters/fastify/index.mjs +4 -3
  8. package/dist/adapters/fetch/index.js +3 -2
  9. package/dist/adapters/fetch/index.mjs +4 -3
  10. package/dist/adapters/next.js +4 -3
  11. package/dist/adapters/next.mjs +5 -4
  12. package/dist/adapters/node-http/index.js +4 -3
  13. package/dist/adapters/node-http/index.mjs +5 -4
  14. package/dist/adapters/standalone.js +4 -3
  15. package/dist/adapters/standalone.mjs +5 -4
  16. package/dist/adapters/ws.mjs +1 -1
  17. package/dist/core/index.d.ts +1 -1
  18. package/dist/core/index.d.ts.map +1 -1
  19. package/dist/core/internals/__generated__/mergeRoutersGeneric.d.ts +0 -40
  20. package/dist/core/internals/__generated__/mergeRoutersGeneric.d.ts.map +1 -1
  21. package/dist/core/internals/procedureBuilder.d.ts.map +1 -1
  22. package/dist/core/procedure.d.ts +3 -0
  23. package/dist/core/procedure.d.ts.map +1 -1
  24. package/dist/core/router.d.ts +17 -32
  25. package/dist/core/router.d.ts.map +1 -1
  26. package/dist/core/types.d.ts +5 -5
  27. package/dist/core/types.d.ts.map +1 -1
  28. package/dist/deprecated/interop.d.ts +20 -43
  29. package/dist/deprecated/interop.d.ts.map +1 -1
  30. package/dist/http/resolveHTTPResponse.d.ts.map +1 -1
  31. package/dist/index.js +23 -23
  32. package/dist/index.mjs +5 -5
  33. package/dist/{nodeHTTPRequestHandler-c3dbb39e.js → nodeHTTPRequestHandler-7295e689.js} +1 -1
  34. package/dist/{nodeHTTPRequestHandler-c30139c8.mjs → nodeHTTPRequestHandler-e4a030ab.mjs} +2 -2
  35. package/dist/{router-6b03ff5f.mjs → resolveHTTPResponse-3955937e.mjs} +411 -601
  36. package/dist/{router-da6086c3.js → resolveHTTPResponse-9a70b9b2.js} +414 -601
  37. package/dist/router-4f222389.mjs +450 -0
  38. package/dist/router-fee6849a.js +452 -0
  39. package/dist/shared/index.d.ts +0 -1
  40. package/dist/shared/index.d.ts.map +1 -1
  41. package/dist/subscription.mjs +1 -1
  42. package/dist/types.d.ts +0 -10
  43. package/dist/types.d.ts.map +1 -1
  44. package/package.json +2 -2
  45. package/src/core/index.ts +4 -0
  46. package/src/core/internals/__generated__/mergeRoutersGeneric.ts +0 -40
  47. package/src/core/internals/procedureBuilder.ts +9 -6
  48. package/src/core/procedure.ts +3 -1
  49. package/src/core/router.ts +22 -38
  50. package/src/core/types.ts +7 -18
  51. package/src/deprecated/interop.ts +30 -78
  52. package/src/http/resolveHTTPResponse.ts +8 -2
  53. package/src/shared/index.ts +0 -2
  54. package/src/types.ts +0 -12
  55. package/dist/resolveHTTPResponse-1b339cff.mjs +0 -260
  56. package/dist/resolveHTTPResponse-d7a8a210.js +0 -264
@@ -1,15 +1,76 @@
1
- import { a as assertNotBrowser, g as getHTTPStatusCodeFromError } from './resolveHTTPResponse-1b339cff.mjs';
2
- import { T as TRPCError, a as getCauseFromUnknown, g as getTRPCErrorFromUnknown } from './TRPCError-281ac25a.mjs';
1
+ import { T as TRPCError, g as getCauseFromUnknown, a as getTRPCErrorFromUnknown } from './TRPCError-e99e7cbe.mjs';
3
2
  import { T as TRPC_ERROR_CODES_BY_KEY } from './codes-aaa7d554.mjs';
4
3
  import { c as createProxy } from './index-47817162.mjs';
4
+ import { t as transformTRPCResponse } from './transformTRPCResponse-c8138d5f.mjs';
5
5
 
6
- assertNotBrowser();
6
+ /* istanbul ignore file */ function assertNotBrowser() {
7
+ if (typeof window !== 'undefined' && !('Deno' in window) && process.env.NODE_ENV !== 'test' && process.env.JEST_WORKER_ID === undefined) {
8
+ throw new Error('Imported server-only code in the browser');
9
+ }
10
+ }
11
+
12
+ const defaultFormatter = ({ shape })=>{
13
+ return shape;
14
+ };
15
+
16
+ function invert(obj) {
17
+ const newObj = Object.create(null);
18
+ for(const key in obj){
19
+ const v = obj[key];
20
+ newObj[v] = key;
21
+ }
22
+ return newObj;
23
+ }
24
+
25
+ const TRPC_ERROR_CODES_BY_NUMBER = invert(TRPC_ERROR_CODES_BY_KEY);
26
+ const JSONRPC2_TO_HTTP_CODE = {
27
+ PARSE_ERROR: 400,
28
+ BAD_REQUEST: 400,
29
+ NOT_FOUND: 404,
30
+ INTERNAL_SERVER_ERROR: 500,
31
+ UNAUTHORIZED: 401,
32
+ FORBIDDEN: 403,
33
+ TIMEOUT: 408,
34
+ CONFLICT: 409,
35
+ CLIENT_CLOSED_REQUEST: 499,
36
+ PRECONDITION_FAILED: 412,
37
+ PAYLOAD_TOO_LARGE: 413,
38
+ METHOD_NOT_SUPPORTED: 405
39
+ };
40
+ function getStatusCodeFromKey(code) {
41
+ return JSONRPC2_TO_HTTP_CODE[code] ?? 500;
42
+ }
43
+ function getHTTPStatusCode(json) {
44
+ const arr = Array.isArray(json) ? json : [
45
+ json
46
+ ];
47
+ const httpStatuses = new Set(arr.map((res)=>{
48
+ if ('error' in res) {
49
+ const data = res.error.data;
50
+ if (typeof data.httpStatus === 'number') {
51
+ return data.httpStatus;
52
+ }
53
+ const code = TRPC_ERROR_CODES_BY_NUMBER[res.error.code];
54
+ return getStatusCodeFromKey(code);
55
+ }
56
+ return 200;
57
+ }));
58
+ if (httpStatuses.size !== 1) {
59
+ return 207;
60
+ }
61
+ const httpStatus = httpStatuses.values().next().value;
62
+ return httpStatus;
63
+ }
64
+ function getHTTPStatusCodeFromError(error) {
65
+ const { code } = error;
66
+ return getStatusCodeFromKey(code);
67
+ }
7
68
 
8
69
  /* eslint-disable @typescript-eslint/no-explicit-any */ /**
9
70
  * @public
10
71
  */ /**
11
72
  * @internal
12
- */ function getDataTransformer$1(transformer) {
73
+ */ function getDataTransformer(transformer) {
13
74
  if ('input' in transformer) {
14
75
  return transformer;
15
76
  }
@@ -32,232 +93,161 @@ assertNotBrowser();
32
93
  }
33
94
  };
34
95
 
35
- const defaultFormatter = ({ shape })=>{
36
- return shape;
37
- };
96
+ /**
97
+ * Ensures there are no duplicate keys when building a procedure.
98
+ */ function mergeWithoutOverrides(obj1, ...objs) {
99
+ const newObj = Object.assign(Object.create(null), obj1);
100
+ for (const overrides of objs){
101
+ for(const key in overrides){
102
+ if (key in newObj && newObj[key] !== overrides[key]) {
103
+ throw new Error(`Duplicate key ${key}`);
104
+ }
105
+ newObj[key] = overrides[key];
106
+ }
107
+ }
108
+ return newObj;
109
+ }
38
110
 
39
111
  /**
40
- * @deprecated
41
- */ const middlewareMarker$1 = 'middlewareMarker';
112
+ * Create an object without inheriting anything from `Object.prototype`
113
+ * @internal
114
+ */ function omitPrototype(obj1) {
115
+ return Object.assign(Object.create(null), obj1);
116
+ }
42
117
 
43
- assertNotBrowser();
44
- function getParseFn$1(procedureParser) {
45
- const parser = procedureParser;
46
- if (typeof parser === 'function') {
47
- // ProcedureParserCustomValidatorEsque
48
- return parser;
49
- }
50
- if (typeof parser.parseAsync === 'function') {
51
- // ProcedureParserZodEsque
52
- return parser.parseAsync.bind(parser);
53
- }
54
- if (typeof parser.parse === 'function') {
55
- // ProcedureParserZodEsque
56
- return parser.parse.bind(parser);
57
- }
58
- if (typeof parser.validateSync === 'function') {
59
- // ProcedureParserYupEsque
60
- return parser.validateSync.bind(parser);
61
- }
62
- if (typeof parser.create === 'function') {
63
- // ProcedureParserSuperstructEsque
64
- return parser.create.bind(parser);
65
- }
66
- throw new Error('Could not find a validator fn');
118
+ const procedureTypes = [
119
+ 'query',
120
+ 'mutation',
121
+ 'subscription'
122
+ ];
123
+
124
+ function isRouter(procedureOrRouter) {
125
+ return 'router' in procedureOrRouter._def;
67
126
  }
127
+ const emptyRouter = {
128
+ _ctx: null,
129
+ _errorShape: null,
130
+ _meta: null,
131
+ queries: {},
132
+ mutations: {},
133
+ subscriptions: {},
134
+ errorFormatter: defaultFormatter,
135
+ transformer: defaultTransformer
136
+ };
68
137
  /**
138
+ *
69
139
  * @internal
70
- * @deprecated
71
- */ class Procedure {
72
- _def() {
73
- return {
74
- middlewares: this.middlewares,
75
- resolver: this.resolver,
76
- inputParser: this.inputParser,
77
- outputParser: this.outputParser,
78
- meta: this.meta
79
- };
80
- }
81
- async parseInput(rawInput) {
82
- try {
83
- return await this.parseInputFn(rawInput);
84
- } catch (cause) {
85
- throw new TRPCError({
86
- code: 'BAD_REQUEST',
87
- cause: getCauseFromUnknown(cause)
88
- });
89
- }
90
- }
91
- async parseOutput(rawOutput) {
92
- try {
93
- return await this.parseOutputFn(rawOutput);
94
- } catch (cause) {
95
- throw new TRPCError({
96
- code: 'INTERNAL_SERVER_ERROR',
97
- cause: getCauseFromUnknown(cause),
98
- message: 'Output validation failed'
99
- });
140
+ */ function createRouterFactory(defaults) {
141
+ return function createRouterInner(opts) {
142
+ const routerProcedures = omitPrototype({});
143
+ function recursiveGetPaths(procedures, path = '') {
144
+ for (const [key, procedureOrRouter] of Object.entries(procedures ?? {})){
145
+ const newPath = `${path}${key}`;
146
+ if (isRouter(procedureOrRouter)) {
147
+ recursiveGetPaths(procedureOrRouter._def.procedures, `${newPath}.`);
148
+ continue;
149
+ }
150
+ routerProcedures[newPath] = procedureOrRouter;
151
+ }
100
152
  }
101
- }
102
- /**
103
- * Trigger middlewares in order, parse raw input, call resolver & parse raw output
104
- * @internal
105
- */ async call(opts) {
106
- // wrap the actual resolver and treat as the last "middleware"
107
- const middlewaresWithResolver = this.middlewares.concat([
108
- async ({ ctx })=>{
109
- const input = await this.parseInput(opts.rawInput);
110
- const rawOutput = await this.resolver({
111
- ...opts,
112
- ctx,
113
- input
114
- });
115
- const data = await this.parseOutput(rawOutput);
116
- return {
117
- marker: middlewareMarker$1,
118
- ok: true,
119
- data,
120
- ctx
121
- };
122
- },
123
- ]);
124
- // run the middlewares recursively with the resolver as the last one
125
- const callRecursive = async (callOpts = {
126
- index: 0,
127
- ctx: opts.ctx
128
- })=>{
129
- try {
130
- const result = await middlewaresWithResolver[callOpts.index]({
131
- ctx: callOpts.ctx,
132
- type: opts.type,
133
- path: opts.path,
134
- rawInput: opts.rawInput,
135
- meta: this.meta,
136
- next: async (nextOpts)=>{
137
- return await callRecursive({
138
- index: callOpts.index + 1,
139
- ctx: nextOpts ? nextOpts.ctx : callOpts.ctx
153
+ recursiveGetPaths(opts);
154
+ const result = mergeWithoutOverrides({
155
+ transformer: defaults?.transformer ?? defaultTransformer,
156
+ errorFormatter: defaults?.errorFormatter ?? defaultFormatter
157
+ }, {
158
+ procedures: routerProcedures
159
+ });
160
+ const _def = {
161
+ router: true,
162
+ procedures: {},
163
+ ...emptyRouter,
164
+ ...result,
165
+ record: opts,
166
+ queries: Object.entries(result.procedures || {}).filter((pair)=>pair[1]._def.query).reduce((acc, [key, val])=>({
167
+ ...acc,
168
+ [key]: val
169
+ }), {}),
170
+ mutations: Object.entries(result.procedures || {}).filter((pair)=>pair[1]._def.mutation).reduce((acc, [key, val])=>({
171
+ ...acc,
172
+ [key]: val
173
+ }), {}),
174
+ subscriptions: Object.entries(result.procedures || {}).filter((pair)=>pair[1]._def.subscription).reduce((acc, [key, val])=>({
175
+ ...acc,
176
+ [key]: val
177
+ }), {})
178
+ };
179
+ const router = {
180
+ ...opts,
181
+ _def,
182
+ transformer: _def.transformer,
183
+ errorFormatter: _def.errorFormatter,
184
+ createCaller (ctx) {
185
+ const proxy = createProxy(({ path , args })=>{
186
+ // interop mode
187
+ if (path.length === 1 && procedureTypes.includes(path[0])) {
188
+ return callProcedure({
189
+ procedures: _def.procedures,
190
+ path: args[0],
191
+ rawInput: args[1],
192
+ ctx,
193
+ type: path[0]
140
194
  });
141
195
  }
196
+ const fullPath = path.join('.');
197
+ const procedure = _def.procedures[fullPath];
198
+ let type = 'query';
199
+ if (procedure._def.mutation) {
200
+ type = 'mutation';
201
+ } else if (procedure._def.subscription) {
202
+ type = 'subscription';
203
+ }
204
+ return procedure({
205
+ path: fullPath,
206
+ rawInput: args[0],
207
+ ctx,
208
+ type
209
+ });
142
210
  });
143
- return result;
144
- } catch (cause) {
145
- return {
146
- ctx: callOpts.ctx,
147
- ok: false,
148
- error: getTRPCErrorFromUnknown(cause),
149
- marker: middlewareMarker$1
211
+ return proxy;
212
+ },
213
+ getErrorShape (opts) {
214
+ const { path , error } = opts;
215
+ const { code } = opts.error;
216
+ const shape = {
217
+ message: error.message,
218
+ code: TRPC_ERROR_CODES_BY_KEY[code],
219
+ data: {
220
+ code,
221
+ httpStatus: getHTTPStatusCodeFromError(error)
222
+ }
150
223
  };
224
+ if (process.env.NODE_ENV !== 'production' && typeof opts.error.stack === 'string') {
225
+ shape.data.stack = opts.error.stack;
226
+ }
227
+ if (typeof path === 'string') {
228
+ shape.data.path = path;
229
+ }
230
+ return this._def.errorFormatter({
231
+ ...opts,
232
+ shape
233
+ });
151
234
  }
152
235
  };
153
- // there's always at least one "next" since we wrap this.resolver in a middleware
154
- const result = await callRecursive();
155
- if (!result) {
156
- throw new TRPCError({
157
- code: 'INTERNAL_SERVER_ERROR',
158
- message: 'No result from middlewares - did you forget to `return next()`?'
159
- });
160
- }
161
- if (!result.ok) {
162
- // re-throw original error
163
- throw result.error;
164
- }
165
- return result.data;
166
- }
167
- /**
168
- * Create new procedure with passed middlewares
169
- * @param middlewares
170
- */ inheritMiddlewares(middlewares) {
171
- const Constructor = this.constructor;
172
- const instance = new Constructor({
173
- middlewares: [
174
- ...middlewares,
175
- ...this.middlewares
176
- ],
177
- resolver: this.resolver,
178
- inputParser: this.inputParser,
179
- outputParser: this.outputParser,
180
- meta: this.meta
181
- });
182
- return instance;
183
- }
184
- constructor(opts){
185
- this.middlewares = opts.middlewares;
186
- this.resolver = opts.resolver;
187
- this.inputParser = opts.inputParser;
188
- this.parseInputFn = getParseFn$1(this.inputParser);
189
- this.outputParser = opts.outputParser;
190
- this.parseOutputFn = getParseFn$1(this.outputParser);
191
- this.meta = opts.meta;
192
- }
193
- }
194
- function createProcedure(opts) {
195
- const inputParser = 'input' in opts ? opts.input : (input)=>{
196
- if (input != null) {
197
- throw new TRPCError({
198
- code: 'BAD_REQUEST',
199
- message: 'No input expected'
200
- });
201
- }
202
- return undefined;
236
+ return router;
203
237
  };
204
- const outputParser = 'output' in opts && opts.output ? opts.output : (output)=>output;
205
- return new Procedure({
206
- inputParser: inputParser,
207
- resolver: opts.resolve,
208
- middlewares: [],
209
- outputParser: outputParser,
210
- meta: opts.meta
211
- });
212
- }
213
-
214
- function getParseFn(procedureParser) {
215
- const parser = procedureParser;
216
- if (typeof parser === 'function') {
217
- // ProcedureParserCustomValidatorEsque
218
- return parser;
219
- }
220
- if (typeof parser.parseAsync === 'function') {
221
- // ProcedureParserZodEsque
222
- return parser.parseAsync.bind(parser);
223
- }
224
- if (typeof parser.parse === 'function') {
225
- // ProcedureParserZodEsque
226
- return parser.parse.bind(parser);
227
- }
228
- if (typeof parser.validateSync === 'function') {
229
- // ProcedureParserYupEsque
230
- return parser.validateSync.bind(parser);
231
- }
232
- if (typeof parser.create === 'function') {
233
- // ProcedureParserSuperstructEsque
234
- return parser.create.bind(parser);
235
- }
236
- throw new Error('Could not find a validator fn');
237
238
  }
238
239
  /**
239
- * @deprecated only for backwards compat
240
240
  * @internal
241
- */ function getParseFnOrPassThrough(procedureParser) {
242
- if (!procedureParser) {
243
- return (v)=>v;
244
- }
245
- return getParseFn(procedureParser);
246
- }
247
-
248
- /**
249
- * Ensures there are no duplicate keys when building a procedure.
250
- */ function mergeWithoutOverrides(obj1, ...objs) {
251
- const newObj = Object.assign(Object.create(null), obj1);
252
- for (const overrides of objs){
253
- for(const key in overrides){
254
- if (key in newObj && newObj[key] !== overrides[key]) {
255
- throw new Error(`Duplicate key ${key}`);
256
- }
257
- newObj[key] = overrides[key];
258
- }
241
+ */ function callProcedure(opts) {
242
+ const { type , path } = opts;
243
+ if (!(path in opts.procedures) || !opts.procedures[path]?._def[type]) {
244
+ throw new TRPCError({
245
+ code: 'NOT_FOUND',
246
+ message: `No "${type}"-procedure on path "${path}"`
247
+ });
259
248
  }
260
- return newObj;
249
+ const procedure = opts.procedures[path];
250
+ return procedure(opts);
261
251
  }
262
252
 
263
253
  /**
@@ -325,6 +315,40 @@ function isPlainObject(obj) {
325
315
  return outputMiddleware;
326
316
  }
327
317
 
318
+ function getParseFn(procedureParser) {
319
+ const parser = procedureParser;
320
+ if (typeof parser === 'function') {
321
+ // ProcedureParserCustomValidatorEsque
322
+ return parser;
323
+ }
324
+ if (typeof parser.parseAsync === 'function') {
325
+ // ProcedureParserZodEsque
326
+ return parser.parseAsync.bind(parser);
327
+ }
328
+ if (typeof parser.parse === 'function') {
329
+ // ProcedureParserZodEsque
330
+ return parser.parse.bind(parser);
331
+ }
332
+ if (typeof parser.validateSync === 'function') {
333
+ // ProcedureParserYupEsque
334
+ return parser.validateSync.bind(parser);
335
+ }
336
+ if (typeof parser.create === 'function') {
337
+ // ProcedureParserSuperstructEsque
338
+ return parser.create.bind(parser);
339
+ }
340
+ throw new Error('Could not find a validator fn');
341
+ }
342
+ /**
343
+ * @deprecated only for backwards compat
344
+ * @internal
345
+ */ function getParseFnOrPassThrough(procedureParser) {
346
+ if (!procedureParser) {
347
+ return (v)=>v;
348
+ }
349
+ return getParseFn(procedureParser);
350
+ }
351
+
328
352
  /**
329
353
  * @internal
330
354
  */ const middlewareMarker = 'middlewareMarker';
@@ -493,419 +517,205 @@ function createProcedureCaller(_def) {
493
517
  return procedure;
494
518
  }
495
519
 
496
- /**
497
- * Create an object without inheriting anything from `Object.prototype`
498
- * @internal
499
- */ function omitPrototype(obj1) {
500
- return Object.assign(Object.create(null), obj1);
501
- }
502
-
503
- const procedureTypes = [
504
- 'query',
505
- 'mutation',
506
- 'subscription'
507
- ];
508
-
509
- function isRouter(procedureOrRouter) {
510
- return 'router' in procedureOrRouter._def;
511
- }
512
- const emptyRouter = {
513
- _ctx: null,
514
- _errorShape: null,
515
- _meta: null,
516
- queries: {},
517
- mutations: {},
518
- subscriptions: {},
519
- errorFormatter: defaultFormatter,
520
- transformer: defaultTransformer
520
+ const HTTP_METHOD_PROCEDURE_TYPE_MAP = {
521
+ GET: 'query',
522
+ POST: 'mutation'
521
523
  };
522
- /**
523
- *
524
- * @internal
525
- */ function createRouterFactory(defaults) {
526
- return function createRouterInner(opts) {
527
- const routerProcedures = omitPrototype({});
528
- function recursiveGetPaths(procedures, path = '') {
529
- for (const [key, procedureOrRouter] of Object.entries(procedures ?? {})){
530
- const newPath = `${path}${key}`;
531
- if (isRouter(procedureOrRouter)) {
532
- recursiveGetPaths(procedureOrRouter._def.procedures, `${newPath}.`);
533
- continue;
534
- }
535
- routerProcedures[newPath] = procedureOrRouter;
524
+ function getRawProcedureInputOrThrow(req) {
525
+ try {
526
+ if (req.method === 'GET') {
527
+ if (!req.query.has('input')) {
528
+ return undefined;
536
529
  }
530
+ const raw = req.query.get('input');
531
+ return JSON.parse(raw);
537
532
  }
538
- recursiveGetPaths(opts);
539
- const result = mergeWithoutOverrides({
540
- transformer: defaults?.transformer ?? defaultTransformer,
541
- errorFormatter: defaults?.errorFormatter ?? defaultFormatter
542
- }, {
543
- procedures: routerProcedures
544
- });
545
- const _def = {
546
- router: true,
547
- legacy: {},
548
- procedures: {},
549
- ...emptyRouter,
550
- ...result,
551
- record: opts,
552
- queries: Object.entries(result.procedures || {}).filter((pair)=>pair[1]._def.query).reduce((acc, [key, val])=>({
553
- ...acc,
554
- [key]: val
555
- }), {}),
556
- mutations: Object.entries(result.procedures || {}).filter((pair)=>pair[1]._def.mutation).reduce((acc, [key, val])=>({
557
- ...acc,
558
- [key]: val
559
- }), {}),
560
- subscriptions: Object.entries(result.procedures || {}).filter((pair)=>pair[1]._def.subscription).reduce((acc, [key, val])=>({
561
- ...acc,
562
- [key]: val
563
- }), {}),
564
- routers: Object.entries(result.procedures || {}).filter((pair)=>pair[1]._def._router).reduce((acc, [key, val])=>({
565
- ...acc,
566
- [key]: val
567
- }), {})
568
- };
569
- const router = {
570
- ...opts,
571
- _def,
572
- transformer: _def.transformer,
573
- errorFormatter: _def.errorFormatter,
574
- createCaller (ctx) {
575
- const proxy = createProxy(({ path , args })=>{
576
- // interop mode
577
- if (path.length === 1 && procedureTypes.includes(path[0])) {
578
- return callProcedure({
579
- procedures: _def.procedures,
580
- path: args[0],
581
- rawInput: args[1],
582
- ctx,
583
- type: path[0]
584
- });
585
- }
586
- const fullPath = path.join('.');
587
- const procedure = _def.procedures[fullPath];
588
- let type = 'query';
589
- if (procedure._def.mutation) {
590
- type = 'mutation';
591
- } else if (procedure._def.subscription) {
592
- type = 'subscription';
593
- }
594
- return procedure({
595
- path: fullPath,
596
- rawInput: args[0],
597
- ctx,
598
- type
599
- });
600
- });
601
- return proxy;
602
- },
603
- getErrorShape (opts) {
604
- const { path , error } = opts;
605
- const { code } = opts.error;
606
- const shape = {
607
- message: error.message,
608
- code: TRPC_ERROR_CODES_BY_KEY[code],
609
- data: {
610
- code,
611
- httpStatus: getHTTPStatusCodeFromError(error)
612
- }
613
- };
614
- if (process.env.NODE_ENV !== 'production' && typeof opts.error.stack === 'string') {
615
- shape.data.stack = opts.error.stack;
616
- }
617
- if (typeof path === 'string') {
618
- shape.data.path = path;
619
- }
620
- return this._def.errorFormatter({
621
- ...opts,
622
- shape
623
- });
624
- }
625
- };
626
- return router;
627
- };
628
- }
629
- /**
630
- * @internal
631
- */ function callProcedure(opts) {
632
- const { type , path } = opts;
633
- if (!(path in opts.procedures) || !opts.procedures[path]?._def[type]) {
533
+ if (typeof req.body === 'string') {
534
+ // A mutation with no inputs will have req.body === ''
535
+ return req.body.length === 0 ? undefined : JSON.parse(req.body);
536
+ }
537
+ return req.body;
538
+ } catch (err) {
634
539
  throw new TRPCError({
635
- code: 'NOT_FOUND',
636
- message: `No "${type}"-procedure on path "${path}"`
540
+ code: 'PARSE_ERROR',
541
+ cause: getCauseFromUnknown(err)
637
542
  });
638
543
  }
639
- const procedure = opts.procedures[path];
640
- return procedure(opts);
641
- }
642
-
643
- function migrateProcedure(oldProc, type) {
644
- const def = oldProc._def();
645
- const inputParser = getParseFnOrPassThrough(def.inputParser);
646
- const outputParser = getParseFnOrPassThrough(def.outputParser);
647
- const inputMiddleware = createInputMiddleware(inputParser);
648
- const builder = createBuilder({
649
- inputs: [
650
- def.inputParser
651
- ],
652
- middlewares: [
653
- ...def.middlewares,
654
- inputMiddleware,
655
- createOutputMiddleware(outputParser),
656
- ],
657
- meta: def.meta,
658
- output: def.outputParser,
659
- mutation: type === 'mutation',
660
- query: type === 'query',
661
- subscription: type === 'subscription'
662
- });
663
- const proc = builder[type]((opts)=>def.resolver(opts));
664
- return proc;
665
- }
666
- function migrateRouter(oldRouter) {
667
- const errorFormatter = oldRouter._def.errorFormatter;
668
- const transformer = oldRouter._def.transformer;
669
- const queries = {};
670
- const mutations = {};
671
- const subscriptions = {};
672
- for (const [name, procedure] of Object.entries(oldRouter._def.queries)){
673
- queries[name] = migrateProcedure(procedure, 'query');
674
- }
675
- for (const [name1, procedure1] of Object.entries(oldRouter._def.mutations)){
676
- mutations[name1] = migrateProcedure(procedure1, 'mutation');
677
- }
678
- for (const [name2, procedure2] of Object.entries(oldRouter._def.subscriptions)){
679
- subscriptions[name2] = migrateProcedure(procedure2, 'subscription');
680
- }
681
- const procedures = mergeWithoutOverrides(queries, mutations, subscriptions);
682
- const newRouter = createRouterFactory({
683
- transformer,
684
- errorFormatter
685
- })(procedures);
686
- return newRouter;
687
- }
688
-
689
- assertNotBrowser();
690
- function getDataTransformer(transformer) {
691
- if ('input' in transformer) {
692
- return transformer;
693
- }
694
- return {
695
- input: transformer,
696
- output: transformer
697
- };
698
- }
699
- const PROCEDURE_DEFINITION_MAP = {
700
- query: 'queries',
701
- mutation: 'mutations',
702
- subscription: 'subscriptions'
703
- };
704
- function safeObject(...args) {
705
- return Object.assign(Object.create(null), ...args);
706
544
  }
707
- /**
708
- * @internal The type signature of this class may change without warning.
709
- * @deprecated
710
- */ class Router {
711
- static prefixProcedures(procedures, prefix) {
712
- const eps = safeObject();
713
- for (const [key, procedure] of Object.entries(procedures)){
714
- eps[prefix + key] = procedure;
715
- }
716
- return eps;
717
- }
718
- query(path, procedure) {
719
- const router = new Router({
720
- queries: safeObject({
721
- [path]: createProcedure(procedure)
722
- })
723
- });
724
- return this.merge(router);
725
- }
726
- mutation(path, procedure) {
727
- const router = new Router({
728
- mutations: safeObject({
729
- [path]: createProcedure(procedure)
730
- })
731
- });
732
- return this.merge(router);
733
- }
734
- subscription(path, procedure) {
735
- const router = new Router({
736
- subscriptions: safeObject({
737
- [path]: createProcedure(procedure)
738
- })
739
- });
740
- return this.merge(router);
545
+ async function resolveHTTPResponse(opts) {
546
+ const { createContext , onError , router , req } = opts;
547
+ const batchingEnabled = opts.batching?.enabled ?? true;
548
+ if (req.method === 'HEAD') {
549
+ // can be used for lambda warmup
550
+ return {
551
+ status: 204
552
+ };
741
553
  }
742
- merge(prefixOrRouter, maybeRouter) {
743
- let prefix = '';
744
- let childRouter;
745
- if (typeof prefixOrRouter === 'string' && maybeRouter instanceof Router) {
746
- prefix = prefixOrRouter;
747
- childRouter = maybeRouter;
748
- } else if (prefixOrRouter instanceof Router) {
749
- childRouter = prefixOrRouter;
750
- } else {
751
- throw new Error('Invalid args');
554
+ const type = HTTP_METHOD_PROCEDURE_TYPE_MAP[req.method] ?? 'unknown';
555
+ let ctx = undefined;
556
+ let paths = undefined;
557
+ const isBatchCall = !!req.query.get('batch');
558
+ function endResponse(untransformedJSON, errors) {
559
+ let status = getHTTPStatusCode(untransformedJSON);
560
+ const headers = {
561
+ 'Content-Type': 'application/json'
562
+ };
563
+ const meta = opts.responseMeta?.({
564
+ ctx,
565
+ paths,
566
+ type,
567
+ data: Array.isArray(untransformedJSON) ? untransformedJSON : [
568
+ untransformedJSON
569
+ ],
570
+ errors
571
+ }) ?? {};
572
+ for (const [key, value] of Object.entries(meta.headers ?? {})){
573
+ headers[key] = value;
752
574
  }
753
- const duplicateQueries = Object.keys(childRouter._def.queries).filter((key)=>!!this._def['queries'][prefix + key]);
754
- const duplicateMutations = Object.keys(childRouter._def.mutations).filter((key)=>!!this._def['mutations'][prefix + key]);
755
- const duplicateSubscriptions = Object.keys(childRouter._def.subscriptions).filter((key)=>!!this._def['subscriptions'][prefix + key]);
756
- const duplicates = [
757
- ...duplicateQueries,
758
- ...duplicateMutations,
759
- ...duplicateSubscriptions,
760
- ];
761
- if (duplicates.length) {
762
- throw new Error(`Duplicate endpoint(s): ${duplicates.join(', ')}`);
575
+ if (meta.status) {
576
+ status = meta.status;
763
577
  }
764
- const mergeProcedures = (defs)=>{
765
- const newDefs = safeObject();
766
- for (const [key, procedure] of Object.entries(defs)){
767
- const newProcedure = procedure.inheritMiddlewares(this._def.middlewares);
768
- newDefs[key] = newProcedure;
769
- }
770
- return Router.prefixProcedures(newDefs, prefix);
578
+ const transformedJSON = transformTRPCResponse(router, untransformedJSON);
579
+ const body = JSON.stringify(transformedJSON);
580
+ return {
581
+ body,
582
+ status,
583
+ headers
771
584
  };
772
- return new Router({
773
- ...this._def,
774
- queries: safeObject(this._def.queries, mergeProcedures(childRouter._def.queries)),
775
- mutations: safeObject(this._def.mutations, mergeProcedures(childRouter._def.mutations)),
776
- subscriptions: safeObject(this._def.subscriptions, mergeProcedures(childRouter._def.subscriptions))
777
- });
778
585
  }
779
- /**
780
- * Invoke procedure. Only for internal use within library.
781
- */ async call(opts) {
782
- const { type , path } = opts;
783
- const defTarget = PROCEDURE_DEFINITION_MAP[type];
784
- const defs = this._def[defTarget];
785
- const procedure = defs[path];
786
- if (!procedure) {
586
+ try {
587
+ if (opts.error) {
588
+ throw opts.error;
589
+ }
590
+ if (isBatchCall && !batchingEnabled) {
591
+ throw new Error(`Batching is not enabled on the server`);
592
+ }
593
+ if (type === 'subscription') {
787
594
  throw new TRPCError({
788
- code: 'NOT_FOUND',
789
- message: `No "${type}"-procedure on path "${path}"`
595
+ message: 'Subscriptions should use wsLink',
596
+ code: 'METHOD_NOT_SUPPORTED'
790
597
  });
791
598
  }
792
- return procedure.call(opts);
793
- }
794
- createCaller(ctx) {
795
- return {
796
- query: (path, ...args)=>{
797
- return this.call({
798
- type: 'query',
799
- ctx,
800
- path,
801
- rawInput: args[0]
599
+ if (type === 'unknown') {
600
+ throw new TRPCError({
601
+ message: `Unexpected request method ${req.method}`,
602
+ code: 'METHOD_NOT_SUPPORTED'
603
+ });
604
+ }
605
+ const rawInput = getRawProcedureInputOrThrow(req);
606
+ paths = isBatchCall ? opts.path.split(',') : [
607
+ opts.path
608
+ ];
609
+ ctx = await createContext();
610
+ const deserializeInputValue = (rawValue)=>{
611
+ return typeof rawValue !== 'undefined' ? router._def.transformer.input.deserialize(rawValue) : rawValue;
612
+ };
613
+ const getInputs = ()=>{
614
+ if (!isBatchCall) {
615
+ return {
616
+ 0: deserializeInputValue(rawInput)
617
+ };
618
+ }
619
+ if (rawInput == null || typeof rawInput !== 'object' || Array.isArray(rawInput)) {
620
+ throw new TRPCError({
621
+ code: 'BAD_REQUEST',
622
+ message: '"input" needs to be an object when doing a batch call'
802
623
  });
803
- },
804
- mutation: (path, ...args)=>{
805
- return this.call({
806
- type: 'mutation',
807
- ctx,
624
+ }
625
+ const input = {};
626
+ for(const key in rawInput){
627
+ const k = key;
628
+ const rawValue = rawInput[k];
629
+ const value = deserializeInputValue(rawValue);
630
+ input[k] = value;
631
+ }
632
+ return input;
633
+ };
634
+ const inputs = getInputs();
635
+ const rawResults = await Promise.all(paths.map(async (path, index)=>{
636
+ const input = inputs[index];
637
+ try {
638
+ const output = await callProcedure({
639
+ procedures: router._def.procedures,
808
640
  path,
809
- rawInput: args[0]
810
- });
811
- },
812
- subscription: (path, ...args)=>{
813
- return this.call({
814
- type: 'subscription',
641
+ rawInput: input,
815
642
  ctx,
643
+ type
644
+ });
645
+ return {
646
+ input,
647
+ path,
648
+ data: output
649
+ };
650
+ } catch (cause) {
651
+ const error = getTRPCErrorFromUnknown(cause);
652
+ onError?.({
653
+ error,
816
654
  path,
817
- rawInput: args[0]
655
+ input,
656
+ ctx,
657
+ type: type,
658
+ req
818
659
  });
660
+ return {
661
+ input,
662
+ path,
663
+ error
664
+ };
819
665
  }
820
- };
821
- }
822
- /**
823
- * Function to be called before any procedure is invoked
824
- * @link https://trpc.io/docs/middlewares
825
- */ middleware(middleware) {
826
- return new Router({
827
- ...this._def,
828
- middlewares: [
829
- ...this._def.middlewares,
830
- middleware
831
- ]
832
- });
833
- }
834
- /**
835
- * Format errors
836
- * @link https://trpc.io/docs/error-formatting
837
- */ formatError(errorFormatter) {
838
- if (this._def.errorFormatter !== defaultFormatter) {
839
- throw new Error('You seem to have double `formatError()`-calls in your router tree');
840
- }
841
- return new Router({
842
- ...this._def,
843
- errorFormatter: errorFormatter
844
- });
845
- }
846
- getErrorShape(opts) {
847
- const { path , error } = opts;
848
- const { code } = opts.error;
849
- const shape = {
850
- message: error.message,
851
- code: TRPC_ERROR_CODES_BY_KEY[code],
852
- data: {
853
- code,
854
- httpStatus: getHTTPStatusCodeFromError(error)
666
+ }));
667
+ const errors = rawResults.flatMap((obj)=>obj.error ? [
668
+ obj.error
669
+ ] : []);
670
+ const resultEnvelopes = rawResults.map((obj)=>{
671
+ const { path , input } = obj;
672
+ if (obj.error) {
673
+ return {
674
+ error: router.getErrorShape({
675
+ error: obj.error,
676
+ type,
677
+ path,
678
+ input,
679
+ ctx
680
+ })
681
+ };
682
+ } else {
683
+ return {
684
+ result: {
685
+ data: obj.data
686
+ }
687
+ };
855
688
  }
856
- };
857
- if (process.env.NODE_ENV !== 'production' && typeof opts.error.stack === 'string') {
858
- shape.data.stack = opts.error.stack;
859
- }
860
- if (typeof path === 'string') {
861
- shape.data.path = path;
862
- }
863
- return this._def.errorFormatter({
864
- ...opts,
865
- shape
866
689
  });
867
- }
868
- /**
869
- * Add data transformer to serialize/deserialize input args + output
870
- * @link https://trpc.io/docs/data-transformers
871
- */ transformer(_transformer) {
872
- const transformer = getDataTransformer(_transformer);
873
- if (this._def.transformer !== defaultTransformer) {
874
- throw new Error('You seem to have double `transformer()`-calls in your router tree');
875
- }
876
- return new Router({
877
- ...this._def,
878
- transformer
690
+ const result = isBatchCall ? resultEnvelopes : resultEnvelopes[0];
691
+ return endResponse(result, errors);
692
+ } catch (cause) {
693
+ // we get here if
694
+ // - batching is called when it's not enabled
695
+ // - `createContext()` throws
696
+ // - post body is too large
697
+ // - input deserialization fails
698
+ const error = getTRPCErrorFromUnknown(cause);
699
+ onError?.({
700
+ error,
701
+ path: undefined,
702
+ input: undefined,
703
+ ctx,
704
+ type: type,
705
+ req
879
706
  });
707
+ return endResponse({
708
+ error: router.getErrorShape({
709
+ error,
710
+ type,
711
+ path: undefined,
712
+ input: undefined,
713
+ ctx
714
+ })
715
+ }, [
716
+ error
717
+ ]);
880
718
  }
881
- /**
882
- * Flattens the generics of TQueries/TMutations/TSubscriptions.
883
- * ⚠️ Experimental - might disappear. ⚠️
884
- *
885
- * @alpha
886
- */ flat() {
887
- return this;
888
- }
889
- /**
890
- * Interop mode for v9.x -> v10.x
891
- */ interop() {
892
- return migrateRouter(this);
893
- }
894
- constructor(def){
895
- this._def = {
896
- queries: def?.queries ?? safeObject(),
897
- mutations: def?.mutations ?? safeObject(),
898
- subscriptions: def?.subscriptions ?? safeObject(),
899
- middlewares: def?.middlewares ?? [],
900
- errorFormatter: def?.errorFormatter ?? defaultFormatter,
901
- transformer: def?.transformer ?? defaultTransformer
902
- };
903
- }
904
- }
905
- /**
906
- * @deprecated
907
- */ function router() {
908
- return new Router();
909
719
  }
910
720
 
911
- export { defaultTransformer as a, createBuilder as b, createRouterFactory as c, defaultFormatter as d, createMiddlewareFactory as e, callProcedure as f, getDataTransformer$1 as g, createInputMiddleware as h, createOutputMiddleware as i, mergeWithoutOverrides as m, procedureTypes as p, router as r };
721
+ export { defaultTransformer as a, createBuilder as b, createRouterFactory as c, defaultFormatter as d, createMiddlewareFactory as e, assertNotBrowser as f, getDataTransformer as g, callProcedure as h, createInputMiddleware as i, createOutputMiddleware as j, getParseFnOrPassThrough as k, getHTTPStatusCodeFromError as l, mergeWithoutOverrides as m, procedureTypes as p, resolveHTTPResponse as r };