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