@trpc/server 10.28.1 → 10.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/aws-lambda/index.d.ts +1 -1
- package/dist/adapters/aws-lambda/index.d.ts.map +1 -1
- package/dist/adapters/aws-lambda/index.js +1 -1
- package/dist/adapters/aws-lambda/index.mjs +1 -1
- package/dist/adapters/aws-lambda/utils.d.ts +1 -1
- package/dist/adapters/aws-lambda/utils.d.ts.map +1 -1
- package/dist/adapters/express.d.ts.map +1 -1
- package/dist/adapters/express.js +5 -4
- package/dist/adapters/express.mjs +5 -4
- package/dist/adapters/fastify/fastifyRequestHandler.d.ts +1 -1
- package/dist/adapters/fastify/fastifyRequestHandler.d.ts.map +1 -1
- package/dist/adapters/fastify/index.js +50 -15
- package/dist/adapters/fastify/index.mjs +50 -15
- package/dist/adapters/fetch/fetchRequestHandler.d.ts.map +1 -1
- package/dist/adapters/fetch/index.js +66 -20
- package/dist/adapters/fetch/index.mjs +66 -20
- package/dist/adapters/lambda/index.d.ts +1 -1
- package/dist/adapters/lambda/index.d.ts.map +1 -1
- package/dist/adapters/next.d.ts.map +1 -1
- package/dist/adapters/next.js +3 -2
- package/dist/adapters/next.mjs +3 -2
- package/dist/adapters/node-http/content-type/form-data/index.js +19 -46
- package/dist/adapters/node-http/content-type/form-data/index.mjs +19 -40
- package/dist/adapters/node-http/content-type/form-data/streamSlice.d.ts +7 -3
- package/dist/adapters/node-http/content-type/form-data/streamSlice.d.ts.map +1 -1
- package/dist/adapters/node-http/index.js +5 -4
- package/dist/adapters/node-http/index.mjs +5 -4
- package/dist/adapters/node-http/nodeHTTPRequestHandler.d.ts.map +1 -1
- package/dist/adapters/standalone.js +5 -4
- package/dist/adapters/standalone.mjs +5 -4
- package/dist/batchStreamFormatter-2c1405a1.js +31 -0
- package/dist/batchStreamFormatter-93cdcdd4.js +32 -0
- package/dist/batchStreamFormatter-fc1ffb26.mjs +30 -0
- package/dist/core/initTRPC.d.ts.map +1 -1
- package/dist/core/internals/mergeRouters.d.ts.map +1 -1
- package/dist/core/internals/procedureBuilder.d.ts +1 -1
- package/dist/core/internals/procedureBuilder.d.ts.map +1 -1
- package/dist/core/router.d.ts +1 -1
- package/dist/core/router.d.ts.map +1 -1
- package/dist/deprecated/interop.d.ts.map +1 -1
- package/dist/deprecated/router.d.ts +3 -3
- package/dist/deprecated/router.d.ts.map +1 -1
- package/dist/error/formatter.d.ts +1 -1
- package/dist/error/formatter.d.ts.map +1 -1
- package/dist/http/batchStreamFormatter.d.ts +24 -0
- package/dist/http/batchStreamFormatter.d.ts.map +1 -0
- package/dist/http/getHTTPStatusCode.d.ts +1 -1
- package/dist/http/getHTTPStatusCode.d.ts.map +1 -1
- package/dist/http/index.d.ts +1 -0
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/index.js +3 -1
- package/dist/http/index.mjs +2 -1
- package/dist/http/internals/types.d.ts +8 -1
- package/dist/http/internals/types.d.ts.map +1 -1
- package/dist/http/resolveHTTPResponse.d.ts +36 -2
- package/dist/http/resolveHTTPResponse.d.ts.map +1 -1
- package/dist/internals/types.d.ts +1 -1
- package/dist/internals/types.d.ts.map +1 -1
- package/dist/{nodeHTTPRequestHandler-bd47641d.js → nodeHTTPRequestHandler-53b9fc2d.js} +44 -12
- package/dist/{nodeHTTPRequestHandler-0f979796.mjs → nodeHTTPRequestHandler-bdad2781.mjs} +42 -13
- package/dist/{nodeHTTPRequestHandler-5bbf93f1.js → nodeHTTPRequestHandler-e637755a.js} +42 -13
- package/dist/resolveHTTPResponse-2bdf2cd7.js +256 -0
- package/dist/resolveHTTPResponse-2c307e04.js +284 -0
- package/dist/resolveHTTPResponse-a9be3d96.mjs +282 -0
- package/dist/subscription.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/adapters/aws-lambda/index.ts +2 -2
- package/src/adapters/aws-lambda/utils.ts +1 -1
- package/src/adapters/express.ts +1 -1
- package/src/adapters/fastify/fastifyRequestHandler.ts +64 -17
- package/src/adapters/fastify/fastifyTRPCPlugin.ts +1 -1
- package/src/adapters/fetch/fetchRequestHandler.ts +72 -25
- package/src/adapters/lambda/index.ts +1 -1
- package/src/adapters/next.ts +1 -1
- package/src/adapters/node-http/content-type/form-data/fileUploadHandler.ts +1 -1
- package/src/adapters/node-http/content-type/form-data/index.ts +1 -1
- package/src/adapters/node-http/content-type/form-data/streamSlice.ts +19 -21
- package/src/adapters/node-http/nodeHTTPRequestHandler.ts +51 -12
- package/src/adapters/ws.ts +3 -3
- package/src/core/initTRPC.ts +2 -2
- package/src/core/internals/mergeRouters.ts +1 -1
- package/src/core/internals/procedureBuilder.ts +5 -5
- package/src/core/router.ts +2 -2
- package/src/deprecated/internals/procedure.ts +2 -2
- package/src/deprecated/interop.ts +1 -1
- package/src/deprecated/router.ts +6 -6
- package/src/error/formatter.ts +1 -1
- package/src/http/batchStreamFormatter.ts +29 -0
- package/src/http/getHTTPStatusCode.ts +1 -1
- package/src/http/index.ts +1 -0
- package/src/http/internals/types.ts +9 -1
- package/src/http/resolveHTTPResponse.ts +337 -126
- package/src/internals/types.ts +1 -1
- package/src/subscription.ts +1 -1
- package/dist/resolveHTTPResponse-4e576698.mjs +0 -174
- package/dist/resolveHTTPResponse-9523b4e3.js +0 -176
- package/dist/resolveHTTPResponse-ba557d3e.js +0 -166
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var config = require('./config-f3ce0144.js');
|
|
4
|
+
var TRPCError = require('./TRPCError-16b2e52d.js');
|
|
5
|
+
var transformTRPCResponse = require('./transformTRPCResponse-48d70ef6.js');
|
|
6
|
+
var contentType = require('./contentType-8356d528.js');
|
|
7
|
+
var index = require('./index-4a823936.js');
|
|
8
|
+
|
|
9
|
+
const HTTP_METHOD_PROCEDURE_TYPE_MAP = {
|
|
10
|
+
GET: 'query',
|
|
11
|
+
POST: 'mutation'
|
|
12
|
+
};
|
|
13
|
+
const fallbackContentTypeHandler = {
|
|
14
|
+
getInputs: contentType.getJsonContentTypeInputs
|
|
15
|
+
};
|
|
16
|
+
function initResponse(initOpts) {
|
|
17
|
+
const { ctx , paths , type , responseMeta , untransformedJSON , errors =[] , } = initOpts;
|
|
18
|
+
let status = untransformedJSON ? index.getHTTPStatusCode(untransformedJSON) : 200;
|
|
19
|
+
const headers = {
|
|
20
|
+
'Content-Type': 'application/json'
|
|
21
|
+
};
|
|
22
|
+
const eagerGeneration = !untransformedJSON;
|
|
23
|
+
const data = eagerGeneration ? [] : Array.isArray(untransformedJSON) ? untransformedJSON : [
|
|
24
|
+
untransformedJSON
|
|
25
|
+
];
|
|
26
|
+
const meta = responseMeta?.({
|
|
27
|
+
ctx,
|
|
28
|
+
paths,
|
|
29
|
+
type,
|
|
30
|
+
data,
|
|
31
|
+
errors,
|
|
32
|
+
eagerGeneration
|
|
33
|
+
}) ?? {};
|
|
34
|
+
for (const [key, value] of Object.entries(meta.headers ?? {})){
|
|
35
|
+
headers[key] = value;
|
|
36
|
+
}
|
|
37
|
+
if (meta.status) {
|
|
38
|
+
status = meta.status;
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
status,
|
|
42
|
+
headers
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async function inputToProcedureCall(procedureOpts) {
|
|
46
|
+
const { opts , ctx , type , input , path } = procedureOpts;
|
|
47
|
+
try {
|
|
48
|
+
const data = await config.callProcedure({
|
|
49
|
+
procedures: opts.router._def.procedures,
|
|
50
|
+
path,
|
|
51
|
+
rawInput: input,
|
|
52
|
+
ctx,
|
|
53
|
+
type
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
result: {
|
|
57
|
+
data
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
} catch (cause) {
|
|
61
|
+
const error = TRPCError.getTRPCErrorFromUnknown(cause);
|
|
62
|
+
opts.onError?.({
|
|
63
|
+
error,
|
|
64
|
+
path,
|
|
65
|
+
input,
|
|
66
|
+
ctx,
|
|
67
|
+
type: type,
|
|
68
|
+
req: opts.req
|
|
69
|
+
});
|
|
70
|
+
return {
|
|
71
|
+
error: transformTRPCResponse.getErrorShape({
|
|
72
|
+
config: opts.router._def._config,
|
|
73
|
+
error,
|
|
74
|
+
type,
|
|
75
|
+
path,
|
|
76
|
+
input,
|
|
77
|
+
ctx
|
|
78
|
+
})
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function caughtErrorToData(cause, errorOpts) {
|
|
83
|
+
const { router , req , onError } = errorOpts.opts;
|
|
84
|
+
const error = TRPCError.getTRPCErrorFromUnknown(cause);
|
|
85
|
+
onError?.({
|
|
86
|
+
error,
|
|
87
|
+
path: errorOpts.path,
|
|
88
|
+
input: errorOpts.input,
|
|
89
|
+
ctx: errorOpts.ctx,
|
|
90
|
+
type: errorOpts.type,
|
|
91
|
+
req
|
|
92
|
+
});
|
|
93
|
+
const untransformedJSON = {
|
|
94
|
+
error: transformTRPCResponse.getErrorShape({
|
|
95
|
+
config: router._def._config,
|
|
96
|
+
error,
|
|
97
|
+
type: errorOpts.type,
|
|
98
|
+
path: errorOpts.path,
|
|
99
|
+
input: errorOpts.input,
|
|
100
|
+
ctx: errorOpts.ctx
|
|
101
|
+
})
|
|
102
|
+
};
|
|
103
|
+
const transformedJSON = transformTRPCResponse.transformTRPCResponse(router._def._config, untransformedJSON);
|
|
104
|
+
const body = JSON.stringify(transformedJSON);
|
|
105
|
+
return {
|
|
106
|
+
error,
|
|
107
|
+
untransformedJSON,
|
|
108
|
+
body
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
// implementation
|
|
112
|
+
async function resolveHTTPResponse(opts) {
|
|
113
|
+
const { router , req , onHead , onChunk } = opts;
|
|
114
|
+
if (req.method === 'HEAD') {
|
|
115
|
+
// can be used for lambda warmup
|
|
116
|
+
const headResponse = {
|
|
117
|
+
status: 204
|
|
118
|
+
};
|
|
119
|
+
onHead?.(headResponse);
|
|
120
|
+
onChunk?.([
|
|
121
|
+
-1,
|
|
122
|
+
''
|
|
123
|
+
]);
|
|
124
|
+
return headResponse;
|
|
125
|
+
}
|
|
126
|
+
const contentTypeHandler = opts.contentTypeHandler ?? fallbackContentTypeHandler;
|
|
127
|
+
const batchingEnabled = opts.batching?.enabled ?? true;
|
|
128
|
+
const type = HTTP_METHOD_PROCEDURE_TYPE_MAP[req.method] ?? 'unknown';
|
|
129
|
+
let ctx = undefined;
|
|
130
|
+
let paths;
|
|
131
|
+
const isBatchCall = !!req.query.get('batch');
|
|
132
|
+
const isStreamCall = isBatchCall && onHead && onChunk && req.headers['trpc-batch-mode'] === 'stream';
|
|
133
|
+
try {
|
|
134
|
+
if (opts.error) {
|
|
135
|
+
throw opts.error;
|
|
136
|
+
}
|
|
137
|
+
if (isBatchCall && !batchingEnabled) {
|
|
138
|
+
throw new Error(`Batching is not enabled on the server`);
|
|
139
|
+
}
|
|
140
|
+
/* istanbul ignore if -- @preserve */ if (type === 'subscription') {
|
|
141
|
+
throw new TRPCError.TRPCError({
|
|
142
|
+
message: 'Subscriptions should use wsLink',
|
|
143
|
+
code: 'METHOD_NOT_SUPPORTED'
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
if (type === 'unknown') {
|
|
147
|
+
throw new TRPCError.TRPCError({
|
|
148
|
+
message: `Unexpected request method ${req.method}`,
|
|
149
|
+
code: 'METHOD_NOT_SUPPORTED'
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
const inputs = await contentTypeHandler.getInputs({
|
|
153
|
+
isBatchCall,
|
|
154
|
+
req,
|
|
155
|
+
router,
|
|
156
|
+
preprocessedBody: opts.preprocessedBody ?? false
|
|
157
|
+
});
|
|
158
|
+
paths = isBatchCall ? opts.path.split(',') : [
|
|
159
|
+
opts.path
|
|
160
|
+
];
|
|
161
|
+
ctx = await opts.createContext();
|
|
162
|
+
const promises = paths.map((path, index)=>inputToProcedureCall({
|
|
163
|
+
opts,
|
|
164
|
+
ctx,
|
|
165
|
+
type,
|
|
166
|
+
input: inputs[index],
|
|
167
|
+
path
|
|
168
|
+
}));
|
|
169
|
+
if (!isStreamCall) {
|
|
170
|
+
/**
|
|
171
|
+
* Non-streaming response:
|
|
172
|
+
* - await all responses in parallel, blocking on the slowest one
|
|
173
|
+
* - create headers with known response body
|
|
174
|
+
* - return a complete HTTPResponse
|
|
175
|
+
*/ const untransformedJSON = await Promise.all(promises);
|
|
176
|
+
const errors = untransformedJSON.flatMap((response)=>'error' in response ? [
|
|
177
|
+
response.error
|
|
178
|
+
] : []);
|
|
179
|
+
const headResponse1 = initResponse({
|
|
180
|
+
ctx,
|
|
181
|
+
paths,
|
|
182
|
+
type,
|
|
183
|
+
responseMeta: opts.responseMeta,
|
|
184
|
+
untransformedJSON,
|
|
185
|
+
errors
|
|
186
|
+
});
|
|
187
|
+
onHead?.(headResponse1);
|
|
188
|
+
// return body stuff
|
|
189
|
+
const result = isBatchCall ? untransformedJSON : untransformedJSON[0]; // eslint-disable-line @typescript-eslint/no-non-null-assertion -- `untransformedJSON` should be the length of `paths` which should be at least 1 otherwise there wouldn't be a request at all
|
|
190
|
+
const transformedJSON = transformTRPCResponse.transformTRPCResponse(router._def._config, result);
|
|
191
|
+
const body = JSON.stringify(transformedJSON);
|
|
192
|
+
onChunk?.([
|
|
193
|
+
-1,
|
|
194
|
+
body
|
|
195
|
+
]);
|
|
196
|
+
return {
|
|
197
|
+
status: headResponse1.status,
|
|
198
|
+
headers: headResponse1.headers,
|
|
199
|
+
body
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Streaming response:
|
|
204
|
+
* - block on none, call `onChunk` as soon as each response is ready
|
|
205
|
+
* - create headers with minimal data (cannot know the response body in advance)
|
|
206
|
+
* - return void
|
|
207
|
+
*/ const headResponse2 = initResponse({
|
|
208
|
+
ctx,
|
|
209
|
+
paths,
|
|
210
|
+
type,
|
|
211
|
+
responseMeta: opts.responseMeta
|
|
212
|
+
});
|
|
213
|
+
onHead(headResponse2);
|
|
214
|
+
const indexedPromises = new Map(promises.map((promise, index)=>[
|
|
215
|
+
index,
|
|
216
|
+
promise.then((r)=>[
|
|
217
|
+
index,
|
|
218
|
+
r
|
|
219
|
+
])
|
|
220
|
+
]));
|
|
221
|
+
for(let i = 0; i < paths.length; i++){
|
|
222
|
+
const [index, untransformedJSON1] = await Promise.race(indexedPromises.values());
|
|
223
|
+
indexedPromises.delete(index);
|
|
224
|
+
try {
|
|
225
|
+
const transformedJSON1 = transformTRPCResponse.transformTRPCResponse(router._def._config, untransformedJSON1);
|
|
226
|
+
const body1 = JSON.stringify(transformedJSON1);
|
|
227
|
+
onChunk([
|
|
228
|
+
index,
|
|
229
|
+
body1
|
|
230
|
+
]);
|
|
231
|
+
} catch (cause) {
|
|
232
|
+
const path = paths[index];
|
|
233
|
+
const input = inputs[index];
|
|
234
|
+
const { body: body2 } = caughtErrorToData(cause, {
|
|
235
|
+
opts,
|
|
236
|
+
ctx,
|
|
237
|
+
type,
|
|
238
|
+
path,
|
|
239
|
+
input
|
|
240
|
+
});
|
|
241
|
+
onChunk([
|
|
242
|
+
index,
|
|
243
|
+
body2
|
|
244
|
+
]);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return;
|
|
248
|
+
} catch (cause1) {
|
|
249
|
+
// we get here if
|
|
250
|
+
// - batching is called when it's not enabled
|
|
251
|
+
// - `createContext()` throws
|
|
252
|
+
// - `router._def._config.transformer.output.serialize()` throws
|
|
253
|
+
// - post body is too large
|
|
254
|
+
// - input deserialization fails
|
|
255
|
+
// - `errorFormatter` return value is malformed
|
|
256
|
+
const { error , untransformedJSON: untransformedJSON2 , body: body3 } = caughtErrorToData(cause1, {
|
|
257
|
+
opts,
|
|
258
|
+
ctx,
|
|
259
|
+
type
|
|
260
|
+
});
|
|
261
|
+
const headResponse3 = initResponse({
|
|
262
|
+
ctx,
|
|
263
|
+
paths,
|
|
264
|
+
type,
|
|
265
|
+
responseMeta: opts.responseMeta,
|
|
266
|
+
untransformedJSON: untransformedJSON2,
|
|
267
|
+
errors: [
|
|
268
|
+
error
|
|
269
|
+
]
|
|
270
|
+
});
|
|
271
|
+
onHead?.(headResponse3);
|
|
272
|
+
onChunk?.([
|
|
273
|
+
-1,
|
|
274
|
+
body3
|
|
275
|
+
]);
|
|
276
|
+
return {
|
|
277
|
+
status: headResponse3.status,
|
|
278
|
+
headers: headResponse3.headers,
|
|
279
|
+
body: body3
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
exports.resolveHTTPResponse = resolveHTTPResponse;
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { b as callProcedure } from './config-65c5b6d1.mjs';
|
|
2
|
+
import { T as TRPCError, a as getTRPCErrorFromUnknown } from './TRPCError-2b10c8d2.mjs';
|
|
3
|
+
import { t as transformTRPCResponse, g as getErrorShape } from './transformTRPCResponse-3dca0b20.mjs';
|
|
4
|
+
import { g as getJsonContentTypeInputs } from './contentType-acc3be52.mjs';
|
|
5
|
+
import { b as getHTTPStatusCode } from './index-044a193b.mjs';
|
|
6
|
+
|
|
7
|
+
const HTTP_METHOD_PROCEDURE_TYPE_MAP = {
|
|
8
|
+
GET: 'query',
|
|
9
|
+
POST: 'mutation'
|
|
10
|
+
};
|
|
11
|
+
const fallbackContentTypeHandler = {
|
|
12
|
+
getInputs: getJsonContentTypeInputs
|
|
13
|
+
};
|
|
14
|
+
function initResponse(initOpts) {
|
|
15
|
+
const { ctx , paths , type , responseMeta , untransformedJSON , errors =[] , } = initOpts;
|
|
16
|
+
let status = untransformedJSON ? getHTTPStatusCode(untransformedJSON) : 200;
|
|
17
|
+
const headers = {
|
|
18
|
+
'Content-Type': 'application/json'
|
|
19
|
+
};
|
|
20
|
+
const eagerGeneration = !untransformedJSON;
|
|
21
|
+
const data = eagerGeneration ? [] : Array.isArray(untransformedJSON) ? untransformedJSON : [
|
|
22
|
+
untransformedJSON
|
|
23
|
+
];
|
|
24
|
+
const meta = responseMeta?.({
|
|
25
|
+
ctx,
|
|
26
|
+
paths,
|
|
27
|
+
type,
|
|
28
|
+
data,
|
|
29
|
+
errors,
|
|
30
|
+
eagerGeneration
|
|
31
|
+
}) ?? {};
|
|
32
|
+
for (const [key, value] of Object.entries(meta.headers ?? {})){
|
|
33
|
+
headers[key] = value;
|
|
34
|
+
}
|
|
35
|
+
if (meta.status) {
|
|
36
|
+
status = meta.status;
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
status,
|
|
40
|
+
headers
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
async function inputToProcedureCall(procedureOpts) {
|
|
44
|
+
const { opts , ctx , type , input , path } = procedureOpts;
|
|
45
|
+
try {
|
|
46
|
+
const data = await callProcedure({
|
|
47
|
+
procedures: opts.router._def.procedures,
|
|
48
|
+
path,
|
|
49
|
+
rawInput: input,
|
|
50
|
+
ctx,
|
|
51
|
+
type
|
|
52
|
+
});
|
|
53
|
+
return {
|
|
54
|
+
result: {
|
|
55
|
+
data
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
} catch (cause) {
|
|
59
|
+
const error = getTRPCErrorFromUnknown(cause);
|
|
60
|
+
opts.onError?.({
|
|
61
|
+
error,
|
|
62
|
+
path,
|
|
63
|
+
input,
|
|
64
|
+
ctx,
|
|
65
|
+
type: type,
|
|
66
|
+
req: opts.req
|
|
67
|
+
});
|
|
68
|
+
return {
|
|
69
|
+
error: getErrorShape({
|
|
70
|
+
config: opts.router._def._config,
|
|
71
|
+
error,
|
|
72
|
+
type,
|
|
73
|
+
path,
|
|
74
|
+
input,
|
|
75
|
+
ctx
|
|
76
|
+
})
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function caughtErrorToData(cause, errorOpts) {
|
|
81
|
+
const { router , req , onError } = errorOpts.opts;
|
|
82
|
+
const error = getTRPCErrorFromUnknown(cause);
|
|
83
|
+
onError?.({
|
|
84
|
+
error,
|
|
85
|
+
path: errorOpts.path,
|
|
86
|
+
input: errorOpts.input,
|
|
87
|
+
ctx: errorOpts.ctx,
|
|
88
|
+
type: errorOpts.type,
|
|
89
|
+
req
|
|
90
|
+
});
|
|
91
|
+
const untransformedJSON = {
|
|
92
|
+
error: getErrorShape({
|
|
93
|
+
config: router._def._config,
|
|
94
|
+
error,
|
|
95
|
+
type: errorOpts.type,
|
|
96
|
+
path: errorOpts.path,
|
|
97
|
+
input: errorOpts.input,
|
|
98
|
+
ctx: errorOpts.ctx
|
|
99
|
+
})
|
|
100
|
+
};
|
|
101
|
+
const transformedJSON = transformTRPCResponse(router._def._config, untransformedJSON);
|
|
102
|
+
const body = JSON.stringify(transformedJSON);
|
|
103
|
+
return {
|
|
104
|
+
error,
|
|
105
|
+
untransformedJSON,
|
|
106
|
+
body
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
// implementation
|
|
110
|
+
async function resolveHTTPResponse(opts) {
|
|
111
|
+
const { router , req , onHead , onChunk } = opts;
|
|
112
|
+
if (req.method === 'HEAD') {
|
|
113
|
+
// can be used for lambda warmup
|
|
114
|
+
const headResponse = {
|
|
115
|
+
status: 204
|
|
116
|
+
};
|
|
117
|
+
onHead?.(headResponse);
|
|
118
|
+
onChunk?.([
|
|
119
|
+
-1,
|
|
120
|
+
''
|
|
121
|
+
]);
|
|
122
|
+
return headResponse;
|
|
123
|
+
}
|
|
124
|
+
const contentTypeHandler = opts.contentTypeHandler ?? fallbackContentTypeHandler;
|
|
125
|
+
const batchingEnabled = opts.batching?.enabled ?? true;
|
|
126
|
+
const type = HTTP_METHOD_PROCEDURE_TYPE_MAP[req.method] ?? 'unknown';
|
|
127
|
+
let ctx = undefined;
|
|
128
|
+
let paths;
|
|
129
|
+
const isBatchCall = !!req.query.get('batch');
|
|
130
|
+
const isStreamCall = isBatchCall && onHead && onChunk && req.headers['trpc-batch-mode'] === 'stream';
|
|
131
|
+
try {
|
|
132
|
+
if (opts.error) {
|
|
133
|
+
throw opts.error;
|
|
134
|
+
}
|
|
135
|
+
if (isBatchCall && !batchingEnabled) {
|
|
136
|
+
throw new Error(`Batching is not enabled on the server`);
|
|
137
|
+
}
|
|
138
|
+
/* istanbul ignore if -- @preserve */ if (type === 'subscription') {
|
|
139
|
+
throw new TRPCError({
|
|
140
|
+
message: 'Subscriptions should use wsLink',
|
|
141
|
+
code: 'METHOD_NOT_SUPPORTED'
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
if (type === 'unknown') {
|
|
145
|
+
throw new TRPCError({
|
|
146
|
+
message: `Unexpected request method ${req.method}`,
|
|
147
|
+
code: 'METHOD_NOT_SUPPORTED'
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
const inputs = await contentTypeHandler.getInputs({
|
|
151
|
+
isBatchCall,
|
|
152
|
+
req,
|
|
153
|
+
router,
|
|
154
|
+
preprocessedBody: opts.preprocessedBody ?? false
|
|
155
|
+
});
|
|
156
|
+
paths = isBatchCall ? opts.path.split(',') : [
|
|
157
|
+
opts.path
|
|
158
|
+
];
|
|
159
|
+
ctx = await opts.createContext();
|
|
160
|
+
const promises = paths.map((path, index)=>inputToProcedureCall({
|
|
161
|
+
opts,
|
|
162
|
+
ctx,
|
|
163
|
+
type,
|
|
164
|
+
input: inputs[index],
|
|
165
|
+
path
|
|
166
|
+
}));
|
|
167
|
+
if (!isStreamCall) {
|
|
168
|
+
/**
|
|
169
|
+
* Non-streaming response:
|
|
170
|
+
* - await all responses in parallel, blocking on the slowest one
|
|
171
|
+
* - create headers with known response body
|
|
172
|
+
* - return a complete HTTPResponse
|
|
173
|
+
*/ const untransformedJSON = await Promise.all(promises);
|
|
174
|
+
const errors = untransformedJSON.flatMap((response)=>'error' in response ? [
|
|
175
|
+
response.error
|
|
176
|
+
] : []);
|
|
177
|
+
const headResponse1 = initResponse({
|
|
178
|
+
ctx,
|
|
179
|
+
paths,
|
|
180
|
+
type,
|
|
181
|
+
responseMeta: opts.responseMeta,
|
|
182
|
+
untransformedJSON,
|
|
183
|
+
errors
|
|
184
|
+
});
|
|
185
|
+
onHead?.(headResponse1);
|
|
186
|
+
// return body stuff
|
|
187
|
+
const result = isBatchCall ? untransformedJSON : untransformedJSON[0]; // eslint-disable-line @typescript-eslint/no-non-null-assertion -- `untransformedJSON` should be the length of `paths` which should be at least 1 otherwise there wouldn't be a request at all
|
|
188
|
+
const transformedJSON = transformTRPCResponse(router._def._config, result);
|
|
189
|
+
const body = JSON.stringify(transformedJSON);
|
|
190
|
+
onChunk?.([
|
|
191
|
+
-1,
|
|
192
|
+
body
|
|
193
|
+
]);
|
|
194
|
+
return {
|
|
195
|
+
status: headResponse1.status,
|
|
196
|
+
headers: headResponse1.headers,
|
|
197
|
+
body
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Streaming response:
|
|
202
|
+
* - block on none, call `onChunk` as soon as each response is ready
|
|
203
|
+
* - create headers with minimal data (cannot know the response body in advance)
|
|
204
|
+
* - return void
|
|
205
|
+
*/ const headResponse2 = initResponse({
|
|
206
|
+
ctx,
|
|
207
|
+
paths,
|
|
208
|
+
type,
|
|
209
|
+
responseMeta: opts.responseMeta
|
|
210
|
+
});
|
|
211
|
+
onHead(headResponse2);
|
|
212
|
+
const indexedPromises = new Map(promises.map((promise, index)=>[
|
|
213
|
+
index,
|
|
214
|
+
promise.then((r)=>[
|
|
215
|
+
index,
|
|
216
|
+
r
|
|
217
|
+
])
|
|
218
|
+
]));
|
|
219
|
+
for(let i = 0; i < paths.length; i++){
|
|
220
|
+
const [index, untransformedJSON1] = await Promise.race(indexedPromises.values());
|
|
221
|
+
indexedPromises.delete(index);
|
|
222
|
+
try {
|
|
223
|
+
const transformedJSON1 = transformTRPCResponse(router._def._config, untransformedJSON1);
|
|
224
|
+
const body1 = JSON.stringify(transformedJSON1);
|
|
225
|
+
onChunk([
|
|
226
|
+
index,
|
|
227
|
+
body1
|
|
228
|
+
]);
|
|
229
|
+
} catch (cause) {
|
|
230
|
+
const path = paths[index];
|
|
231
|
+
const input = inputs[index];
|
|
232
|
+
const { body: body2 } = caughtErrorToData(cause, {
|
|
233
|
+
opts,
|
|
234
|
+
ctx,
|
|
235
|
+
type,
|
|
236
|
+
path,
|
|
237
|
+
input
|
|
238
|
+
});
|
|
239
|
+
onChunk([
|
|
240
|
+
index,
|
|
241
|
+
body2
|
|
242
|
+
]);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return;
|
|
246
|
+
} catch (cause1) {
|
|
247
|
+
// we get here if
|
|
248
|
+
// - batching is called when it's not enabled
|
|
249
|
+
// - `createContext()` throws
|
|
250
|
+
// - `router._def._config.transformer.output.serialize()` throws
|
|
251
|
+
// - post body is too large
|
|
252
|
+
// - input deserialization fails
|
|
253
|
+
// - `errorFormatter` return value is malformed
|
|
254
|
+
const { error , untransformedJSON: untransformedJSON2 , body: body3 } = caughtErrorToData(cause1, {
|
|
255
|
+
opts,
|
|
256
|
+
ctx,
|
|
257
|
+
type
|
|
258
|
+
});
|
|
259
|
+
const headResponse3 = initResponse({
|
|
260
|
+
ctx,
|
|
261
|
+
paths,
|
|
262
|
+
type,
|
|
263
|
+
responseMeta: opts.responseMeta,
|
|
264
|
+
untransformedJSON: untransformedJSON2,
|
|
265
|
+
errors: [
|
|
266
|
+
error
|
|
267
|
+
]
|
|
268
|
+
});
|
|
269
|
+
onHead?.(headResponse3);
|
|
270
|
+
onChunk?.([
|
|
271
|
+
-1,
|
|
272
|
+
body3
|
|
273
|
+
]);
|
|
274
|
+
return {
|
|
275
|
+
status: headResponse3.status,
|
|
276
|
+
headers: headResponse3.headers,
|
|
277
|
+
body: body3
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export { resolveHTTPResponse as r };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscription.d.ts","sourceRoot":"","sources":["../src/subscription.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"subscription.d.ts","sourceRoot":"","sources":["../src/subscription.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAc,QAAQ,EAAE,MAAM,cAAc,CAAC;AAEhE;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,IAAI,EAAE;IACrD;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9D,GAAG,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CA2B/B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trpc/server",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.29.0",
|
|
4
4
|
"description": "The tRPC server library",
|
|
5
5
|
"author": "KATT",
|
|
6
6
|
"license": "MIT",
|
|
@@ -143,7 +143,7 @@
|
|
|
143
143
|
"@types/express": "^4.17.17",
|
|
144
144
|
"@types/hash-sum": "^1.0.0",
|
|
145
145
|
"@types/node": "^18.16.16",
|
|
146
|
-
"@types/react": "^18.2.
|
|
146
|
+
"@types/react": "^18.2.8",
|
|
147
147
|
"@types/react-dom": "^18.2.4",
|
|
148
148
|
"@types/ws": "^8.2.0",
|
|
149
149
|
"@web3-storage/multipart-parser": "^1.0.0",
|
|
@@ -164,7 +164,7 @@
|
|
|
164
164
|
"superstruct": "^1.0.0",
|
|
165
165
|
"tslib": "^2.5.0",
|
|
166
166
|
"tsx": "^3.12.7",
|
|
167
|
-
"typescript": "^5.
|
|
167
|
+
"typescript": "^5.1.3",
|
|
168
168
|
"vitest": "^0.28.5",
|
|
169
169
|
"ws": "^8.0.0",
|
|
170
170
|
"yup": "^1.0.0",
|
|
@@ -173,5 +173,5 @@
|
|
|
173
173
|
"funding": [
|
|
174
174
|
"https://trpc.io/sponsor"
|
|
175
175
|
],
|
|
176
|
-
"gitHead": "
|
|
176
|
+
"gitHead": "49b0a55b74b57bbf7451dad5976d315d9fb7785c"
|
|
177
177
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
Context as APIGWContext,
|
|
3
2
|
APIGatewayProxyEvent,
|
|
4
3
|
APIGatewayProxyEventV2,
|
|
5
4
|
APIGatewayProxyResult,
|
|
6
5
|
APIGatewayProxyStructuredResultV2,
|
|
6
|
+
Context as APIGWContext,
|
|
7
7
|
} from 'aws-lambda';
|
|
8
8
|
import { TRPCError } from '../..';
|
|
9
9
|
import { AnyRouter, inferRouterContext } from '../../core';
|
|
@@ -13,12 +13,12 @@ import {
|
|
|
13
13
|
APIGatewayEvent,
|
|
14
14
|
APIGatewayResult,
|
|
15
15
|
AWSLambdaOptions,
|
|
16
|
-
UNKNOWN_PAYLOAD_FORMAT_VERSION_ERROR_MESSAGE,
|
|
17
16
|
getHTTPMethod,
|
|
18
17
|
getPath,
|
|
19
18
|
isPayloadV1,
|
|
20
19
|
isPayloadV2,
|
|
21
20
|
transformHeaders,
|
|
21
|
+
UNKNOWN_PAYLOAD_FORMAT_VERSION_ERROR_MESSAGE,
|
|
22
22
|
} from './utils';
|
|
23
23
|
|
|
24
24
|
export * from './utils';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
Context as APIGWContext,
|
|
3
2
|
APIGatewayProxyEvent,
|
|
4
3
|
APIGatewayProxyEventV2,
|
|
5
4
|
APIGatewayProxyResult,
|
|
6
5
|
APIGatewayProxyStructuredResultV2,
|
|
6
|
+
Context as APIGWContext,
|
|
7
7
|
} from 'aws-lambda';
|
|
8
8
|
import type { AnyRouter, inferRouterContext } from '../../core';
|
|
9
9
|
import { TRPCError } from '../../error/TRPCError';
|
package/src/adapters/express.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type * as express from 'express';
|
|
2
2
|
import { AnyRouter } from '../core';
|
|
3
|
-
import { nodeHTTPRequestHandler } from './node-http';
|
|
4
3
|
import {
|
|
5
4
|
NodeHTTPCreateContextFnOptions,
|
|
6
5
|
NodeHTTPHandlerOptions,
|
|
6
|
+
nodeHTTPRequestHandler,
|
|
7
7
|
} from './node-http';
|
|
8
8
|
|
|
9
9
|
export type CreateExpressContextOptions = NodeHTTPCreateContextFnOptions<
|