@orpc/server 2.0.0-beta.2 → 2.0.0-beta.21
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/README.md +32 -21
- package/dist/adapters/crossws/index.d.mts +11 -8
- package/dist/adapters/crossws/index.d.ts +11 -8
- package/dist/adapters/crossws/index.mjs +10 -7
- package/dist/adapters/fetch/index.d.mts +8 -56
- package/dist/adapters/fetch/index.d.ts +8 -56
- package/dist/adapters/fetch/index.mjs +6 -136
- package/dist/adapters/message-port/index.d.mts +11 -13
- package/dist/adapters/message-port/index.d.ts +11 -13
- package/dist/adapters/message-port/index.mjs +28 -32
- package/dist/adapters/node/index.d.mts +7 -37
- package/dist/adapters/node/index.d.ts +7 -37
- package/dist/adapters/node/index.mjs +6 -112
- package/dist/adapters/standard/index.d.mts +6 -6
- package/dist/adapters/standard/index.d.ts +6 -6
- package/dist/adapters/standard/index.mjs +3 -3
- package/dist/adapters/standard-peer/index.d.mts +2 -2
- package/dist/adapters/standard-peer/index.d.ts +2 -2
- package/dist/adapters/websocket/index.d.mts +36 -26
- package/dist/adapters/websocket/index.d.ts +36 -26
- package/dist/adapters/websocket/index.mjs +33 -25
- package/dist/extensions/callable.d.mts +1 -1
- package/dist/extensions/callable.d.ts +1 -1
- package/dist/extensions/callable.mjs +2 -2
- package/dist/helpers/index.d.mts +3 -3
- package/dist/helpers/index.d.ts +3 -3
- package/dist/helpers/index.mjs +13 -5
- package/dist/index.d.mts +19 -16
- package/dist/index.d.ts +19 -16
- package/dist/index.mjs +36 -22
- package/dist/plugins/index.d.mts +136 -5
- package/dist/plugins/index.d.ts +136 -5
- package/dist/plugins/index.mjs +394 -6
- package/dist/shared/{server.BsNNjG5J.d.mts → server.15O7oC1p.d.mts} +1 -1
- package/dist/shared/{server.B_U9y00a.d.mts → server.B4BnEWWm.d.mts} +6 -5
- package/dist/shared/{server.EOHJ3NJr.d.ts → server.BhsVw7m7.d.ts} +2 -2
- package/dist/shared/{server.BwHnWUuN.mjs → server.BoiFpNT7.mjs} +4 -2
- package/dist/shared/{server.GDpX6Df8.mjs → server.COPVXhDG.mjs} +3 -3
- package/dist/shared/{server.BL22TloH.d.mts → server.CcR4kgje.d.mts} +25 -3
- package/dist/shared/{server.BL22TloH.d.ts → server.CcR4kgje.d.ts} +25 -3
- package/dist/shared/{server.T9F3bzZx.d.ts → server.CnN50DHH.d.ts} +6 -5
- package/dist/shared/{server.CjOb6ItT.mjs → server.DBs0rrf9.mjs} +1 -1
- package/dist/shared/{server.BB_Ik9Ph.d.mts → server.DDFizwfU.d.mts} +2 -2
- package/dist/shared/{server.CrlKQucM.mjs → server.DofEOwf-.mjs} +11 -7
- package/dist/shared/{server.Pa0F03f_.d.ts → server.m3szVJGU.d.ts} +1 -1
- package/package.json +9 -10
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { toArray, value } from '@orpc/shared';
|
|
2
|
-
import { flattenStandardHeader, parseStandardUrl, mergeStandardHeaders } from '@standardserver/core';
|
|
1
|
+
import { toArray, value, isCompressibleContentType, isAsyncIteratorObject, stringifyJSON } from '@orpc/shared';
|
|
2
|
+
import { flattenStandardHeader, parseStandardUrl, generateContentDisposition, mergeStandardHeaders } from '@standardserver/core';
|
|
3
3
|
import { isClientPeerSendMessage, ServerPeer, encodePeerMessage } from '@standardserver/peer';
|
|
4
4
|
export { C as CSRFGuardHandlerPlugin } from '../shared/server.D_QauotT.mjs';
|
|
5
|
-
import { toFetchHeaders, toStandardHeaders } from '@standardserver/fetch';
|
|
6
|
-
import '@orpc/client';
|
|
5
|
+
import { toFetchHeaders, toStandardBody, toStandardHeaders } from '@standardserver/fetch';
|
|
6
|
+
import { ORPCError } from '@orpc/client';
|
|
7
7
|
|
|
8
8
|
class BatchHandlerPlugin {
|
|
9
9
|
name = "~batch";
|
|
@@ -16,6 +16,8 @@ class BatchHandlerPlugin {
|
|
|
16
16
|
mapSubrequest;
|
|
17
17
|
successStatus;
|
|
18
18
|
headers;
|
|
19
|
+
keepAliveEnabled;
|
|
20
|
+
keepAliveInterval;
|
|
19
21
|
constructor(options = {}) {
|
|
20
22
|
this.maxSize = options.maxSize ?? 10;
|
|
21
23
|
this.mapSubrequest = options.mapSubrequest ?? ((subRequest, { request: batchRequest }) => ({
|
|
@@ -29,6 +31,8 @@ class BatchHandlerPlugin {
|
|
|
29
31
|
}));
|
|
30
32
|
this.successStatus = options.successStatus ?? 207;
|
|
31
33
|
this.headers = options.headers ?? {};
|
|
34
|
+
this.keepAliveEnabled = options.keepAlive?.enabled ?? true;
|
|
35
|
+
this.keepAliveInterval = options.keepAlive?.interval ?? 15e3;
|
|
32
36
|
}
|
|
33
37
|
init(options) {
|
|
34
38
|
const routingInterceptor = async (interceptorOptions) => {
|
|
@@ -127,9 +131,35 @@ class BatchHandlerPlugin {
|
|
|
127
131
|
};
|
|
128
132
|
}
|
|
129
133
|
let streamController;
|
|
134
|
+
let keepAliveTimer;
|
|
135
|
+
const clearKeepAlive = () => {
|
|
136
|
+
if (keepAliveTimer !== void 0) {
|
|
137
|
+
clearInterval(keepAliveTimer);
|
|
138
|
+
keepAliveTimer = void 0;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
const scheduleKeepAlive = () => {
|
|
142
|
+
if (!this.keepAliveEnabled) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
clearKeepAlive();
|
|
146
|
+
keepAliveTimer = setInterval(() => {
|
|
147
|
+
try {
|
|
148
|
+
const lengthBuffer = new ArrayBuffer(4);
|
|
149
|
+
new DataView(lengthBuffer).setUint32(0, 0, false);
|
|
150
|
+
streamController.enqueue(new Uint8Array(lengthBuffer));
|
|
151
|
+
} catch {
|
|
152
|
+
clearKeepAlive();
|
|
153
|
+
}
|
|
154
|
+
}, this.keepAliveInterval);
|
|
155
|
+
};
|
|
130
156
|
const stream = new ReadableStream({
|
|
131
157
|
start(controller) {
|
|
132
158
|
streamController = controller;
|
|
159
|
+
scheduleKeepAlive();
|
|
160
|
+
},
|
|
161
|
+
cancel() {
|
|
162
|
+
clearKeepAlive();
|
|
133
163
|
}
|
|
134
164
|
});
|
|
135
165
|
const peer = new ServerPeer(async (message) => {
|
|
@@ -139,11 +169,14 @@ class BatchHandlerPlugin {
|
|
|
139
169
|
new DataView(lengthBuffer).setUint32(0, bytes.byteLength, false);
|
|
140
170
|
streamController.enqueue(new Uint8Array(lengthBuffer));
|
|
141
171
|
streamController.enqueue(bytes);
|
|
172
|
+
scheduleKeepAlive();
|
|
142
173
|
});
|
|
143
174
|
Promise.all(messages.map((msg) => peer.message(msg, handleIndividualRequest))).then(async () => {
|
|
175
|
+
clearKeepAlive();
|
|
144
176
|
streamController.close();
|
|
145
177
|
await peer.close();
|
|
146
178
|
}).catch(async (error) => {
|
|
179
|
+
clearKeepAlive();
|
|
147
180
|
streamController.error(error);
|
|
148
181
|
await peer.close(error);
|
|
149
182
|
});
|
|
@@ -193,7 +226,10 @@ class CORSHandlerPlugin {
|
|
|
193
226
|
if (allowedOrigins.includes(origin)) {
|
|
194
227
|
resHeaders["access-control-allow-origin"] = origin;
|
|
195
228
|
}
|
|
196
|
-
|
|
229
|
+
const existingVary = flattenStandardHeader(resHeaders.vary);
|
|
230
|
+
if (!existingVary?.split(",").some((v) => v.trim().toLowerCase() === "origin")) {
|
|
231
|
+
resHeaders.vary = existingVary ? `${existingVary}, Origin` : "Origin";
|
|
232
|
+
}
|
|
197
233
|
}
|
|
198
234
|
const allowedTimingOrigins = toArray(await value(this.options.timingOrigin, origin, interceptorOptions));
|
|
199
235
|
if (allowedTimingOrigins.includes("*")) {
|
|
@@ -244,6 +280,69 @@ class CORSHandlerPlugin {
|
|
|
244
280
|
}
|
|
245
281
|
}
|
|
246
282
|
|
|
283
|
+
class RequestCompressionHandlerPlugin {
|
|
284
|
+
name = "~request-compression";
|
|
285
|
+
/**
|
|
286
|
+
* Should decompress the original batch request body instead of sub-requests.
|
|
287
|
+
*/
|
|
288
|
+
after = ["~batch"];
|
|
289
|
+
init(options) {
|
|
290
|
+
const routingInterceptor = async ({ next, ...interceptorOptions }) => {
|
|
291
|
+
const encodings = parseContentEncodings(
|
|
292
|
+
flattenStandardHeader(interceptorOptions.request.headers["content-encoding"])
|
|
293
|
+
);
|
|
294
|
+
if (encodings.length === 0 || !encodings.every(isSupportedEncoding)) {
|
|
295
|
+
return next();
|
|
296
|
+
}
|
|
297
|
+
const decompressedHeaders = {
|
|
298
|
+
...interceptorOptions.request.headers,
|
|
299
|
+
"content-length": void 0,
|
|
300
|
+
"content-encoding": void 0
|
|
301
|
+
};
|
|
302
|
+
return next({
|
|
303
|
+
...interceptorOptions,
|
|
304
|
+
request: {
|
|
305
|
+
...interceptorOptions.request,
|
|
306
|
+
headers: decompressedHeaders,
|
|
307
|
+
async resolveBody(hint) {
|
|
308
|
+
const stream = await interceptorOptions.request.resolveBody("octet-stream");
|
|
309
|
+
if (!(stream instanceof ReadableStream)) {
|
|
310
|
+
return stream;
|
|
311
|
+
}
|
|
312
|
+
let decompressedStream = stream;
|
|
313
|
+
for (let i = encodings.length - 1; i >= 0; i--) {
|
|
314
|
+
decompressedStream = decompressedStream.pipeThrough(
|
|
315
|
+
new DecompressionStream(encodings[i])
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
const response = new Response(decompressedStream, {
|
|
319
|
+
headers: toFetchHeaders(decompressedHeaders)
|
|
320
|
+
});
|
|
321
|
+
return toStandardBody(response, { hint });
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
};
|
|
326
|
+
return {
|
|
327
|
+
...options,
|
|
328
|
+
routingInterceptors: [
|
|
329
|
+
routingInterceptor,
|
|
330
|
+
...toArray(options.routingInterceptors)
|
|
331
|
+
]
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const SUPPORTED_ENCODINGS = ["gzip", "deflate", "deflate-raw"];
|
|
336
|
+
function isSupportedEncoding(encoding) {
|
|
337
|
+
return SUPPORTED_ENCODINGS.includes(encoding);
|
|
338
|
+
}
|
|
339
|
+
function parseContentEncodings(header) {
|
|
340
|
+
if (header === void 0) {
|
|
341
|
+
return [];
|
|
342
|
+
}
|
|
343
|
+
return header.split(",").map((part) => part.trim().toLowerCase());
|
|
344
|
+
}
|
|
345
|
+
|
|
247
346
|
class RequestHeadersHandlerPlugin {
|
|
248
347
|
name = "~request-headers";
|
|
249
348
|
init(options) {
|
|
@@ -266,6 +365,243 @@ class RequestHeadersHandlerPlugin {
|
|
|
266
365
|
}
|
|
267
366
|
}
|
|
268
367
|
|
|
368
|
+
class RequestLimitHandlerPlugin {
|
|
369
|
+
name = "~request-limit";
|
|
370
|
+
/**
|
|
371
|
+
* Should limit the original batch request body instead of sub-requests.
|
|
372
|
+
*/
|
|
373
|
+
after = ["~batch"];
|
|
374
|
+
/**
|
|
375
|
+
* Should limit the final body size instead of the compressed one.
|
|
376
|
+
*/
|
|
377
|
+
before = ["~request-compression"];
|
|
378
|
+
maxBodySize;
|
|
379
|
+
constructor(options) {
|
|
380
|
+
this.maxBodySize = options.maxBodySize;
|
|
381
|
+
}
|
|
382
|
+
init(options) {
|
|
383
|
+
const maxBodySize = this.maxBodySize;
|
|
384
|
+
const routingInterceptor = async ({ next, ...interceptorOptions }) => {
|
|
385
|
+
return next({
|
|
386
|
+
...interceptorOptions,
|
|
387
|
+
request: {
|
|
388
|
+
...interceptorOptions.request,
|
|
389
|
+
async resolveBody(hint) {
|
|
390
|
+
const contentLength = Number(
|
|
391
|
+
flattenStandardHeader(interceptorOptions.request.headers["content-length"])
|
|
392
|
+
);
|
|
393
|
+
if (Number.isFinite(contentLength) && contentLength > maxBodySize) {
|
|
394
|
+
throw new ORPCError("PAYLOAD_TOO_LARGE");
|
|
395
|
+
}
|
|
396
|
+
const stream = await interceptorOptions.request.resolveBody("octet-stream");
|
|
397
|
+
if (!(stream instanceof ReadableStream)) {
|
|
398
|
+
return stream;
|
|
399
|
+
}
|
|
400
|
+
let currentBodySize = 0;
|
|
401
|
+
const limitedStream = stream.pipeThrough(
|
|
402
|
+
new TransformStream({
|
|
403
|
+
transform(chunk, controller) {
|
|
404
|
+
currentBodySize += chunk.byteLength;
|
|
405
|
+
if (currentBodySize > maxBodySize) {
|
|
406
|
+
controller.error(new ORPCError("PAYLOAD_TOO_LARGE"));
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
controller.enqueue(chunk);
|
|
410
|
+
}
|
|
411
|
+
})
|
|
412
|
+
);
|
|
413
|
+
const response = new Response(limitedStream, {
|
|
414
|
+
headers: toFetchHeaders(interceptorOptions.request.headers)
|
|
415
|
+
});
|
|
416
|
+
return toStandardBody(response, { hint });
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
};
|
|
421
|
+
return {
|
|
422
|
+
...options,
|
|
423
|
+
routingInterceptors: [
|
|
424
|
+
routingInterceptor,
|
|
425
|
+
...toArray(options.routingInterceptors)
|
|
426
|
+
]
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
const AVG_BYTES_PER_CHAR = 1.2;
|
|
432
|
+
class ResponseCompressionHandlerPlugin {
|
|
433
|
+
name = "~response-compression";
|
|
434
|
+
/**
|
|
435
|
+
* Compression should be done after batching, to compress the final response.
|
|
436
|
+
* Compression should also be done after response headers are set, to access final headers like Content-Type and Cache-Control.
|
|
437
|
+
*/
|
|
438
|
+
after = ["~batch", "~response-headers"];
|
|
439
|
+
encodings;
|
|
440
|
+
threshold;
|
|
441
|
+
constructor(options = {}) {
|
|
442
|
+
this.encodings = options.encodings ?? ["gzip", "deflate"];
|
|
443
|
+
this.threshold = options.threshold ?? 1024;
|
|
444
|
+
}
|
|
445
|
+
init(options) {
|
|
446
|
+
const routingInterceptor = async ({ next, ...interceptorOptions }) => {
|
|
447
|
+
const result = await next();
|
|
448
|
+
if (!result.matched) {
|
|
449
|
+
return result;
|
|
450
|
+
}
|
|
451
|
+
const response = result.response;
|
|
452
|
+
const contentEncoding = flattenStandardHeader(response.headers["content-encoding"])?.trim()?.toLowerCase();
|
|
453
|
+
if (contentEncoding !== void 0) {
|
|
454
|
+
return result;
|
|
455
|
+
}
|
|
456
|
+
if (isNoTransformCacheControl(flattenStandardHeader(response.headers["cache-control"]))) {
|
|
457
|
+
return result;
|
|
458
|
+
}
|
|
459
|
+
const acceptEncodings = parseAcceptEncodings(
|
|
460
|
+
flattenStandardHeader(interceptorOptions.request.headers["accept-encoding"])
|
|
461
|
+
);
|
|
462
|
+
const encoding = this.encodings.find((enc) => acceptEncodings.includes(enc));
|
|
463
|
+
if (encoding === void 0) {
|
|
464
|
+
return result;
|
|
465
|
+
}
|
|
466
|
+
const body = response.body;
|
|
467
|
+
const headers = response.headers;
|
|
468
|
+
if (body instanceof ReadableStream) {
|
|
469
|
+
const contentLength = Number(flattenStandardHeader(headers["content-length"]));
|
|
470
|
+
if ((!Number.isFinite(contentLength) || contentLength >= this.threshold) && isCompressibleContentType(flattenStandardHeader(headers["content-type"]))) {
|
|
471
|
+
return {
|
|
472
|
+
...result,
|
|
473
|
+
response: {
|
|
474
|
+
...response,
|
|
475
|
+
body: body.pipeThrough(new CompressionStream(encoding)),
|
|
476
|
+
headers: {
|
|
477
|
+
...headers,
|
|
478
|
+
"standard-server": "octet-stream",
|
|
479
|
+
"content-length": [],
|
|
480
|
+
"content-encoding": encoding
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
} else if (body instanceof Blob) {
|
|
486
|
+
if ((!Number.isFinite(body.size) || body.size >= this.threshold) && isCompressibleContentType(body.type)) {
|
|
487
|
+
const contentDisposition = headers["content-disposition"] ?? generateContentDisposition(
|
|
488
|
+
body instanceof File ? body.name : "blob"
|
|
489
|
+
);
|
|
490
|
+
return {
|
|
491
|
+
...result,
|
|
492
|
+
response: {
|
|
493
|
+
...response,
|
|
494
|
+
body: body.stream().pipeThrough(new CompressionStream(encoding)),
|
|
495
|
+
headers: {
|
|
496
|
+
...headers,
|
|
497
|
+
"standard-server": "file",
|
|
498
|
+
"content-type": body.type,
|
|
499
|
+
"content-length": [],
|
|
500
|
+
"content-disposition": contentDisposition,
|
|
501
|
+
"content-encoding": encoding
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
} else if (body instanceof FormData) {
|
|
507
|
+
const PART_OVERHEAD = 64;
|
|
508
|
+
let contentLength = 0;
|
|
509
|
+
for (const [key, value] of body) {
|
|
510
|
+
contentLength += PART_OVERHEAD + key.length;
|
|
511
|
+
if (value instanceof Blob) {
|
|
512
|
+
if (!Number.isFinite(value.size)) {
|
|
513
|
+
if (!isCompressibleContentType(value.type)) {
|
|
514
|
+
contentLength = -Infinity;
|
|
515
|
+
break;
|
|
516
|
+
}
|
|
517
|
+
contentLength = Infinity;
|
|
518
|
+
} else {
|
|
519
|
+
contentLength += isCompressibleContentType(value.type) ? value.size : -value.size;
|
|
520
|
+
}
|
|
521
|
+
} else {
|
|
522
|
+
contentLength += value.length * AVG_BYTES_PER_CHAR;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
if (contentLength >= this.threshold) {
|
|
526
|
+
const res = new Response(body);
|
|
527
|
+
const compressedStream = res.body.pipeThrough(new CompressionStream(encoding));
|
|
528
|
+
return {
|
|
529
|
+
...result,
|
|
530
|
+
response: {
|
|
531
|
+
...response,
|
|
532
|
+
body: compressedStream,
|
|
533
|
+
headers: {
|
|
534
|
+
...headers,
|
|
535
|
+
"standard-server": [],
|
|
536
|
+
"content-type": res.headers.get("content-type"),
|
|
537
|
+
"content-length": [],
|
|
538
|
+
"content-encoding": encoding
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
} else if (body instanceof URLSearchParams) {
|
|
544
|
+
const string = body.toString();
|
|
545
|
+
if (string.length * AVG_BYTES_PER_CHAR >= this.threshold) {
|
|
546
|
+
return {
|
|
547
|
+
...result,
|
|
548
|
+
response: {
|
|
549
|
+
...response,
|
|
550
|
+
body: new Blob([string]).stream().pipeThrough(new CompressionStream(encoding)),
|
|
551
|
+
headers: {
|
|
552
|
+
...headers,
|
|
553
|
+
"standard-server": [],
|
|
554
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
555
|
+
"content-length": [],
|
|
556
|
+
"content-encoding": encoding
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
} else if (body !== void 0 && !isAsyncIteratorObject(body)) {
|
|
562
|
+
const string = stringifyJSON(body);
|
|
563
|
+
if (string.length * AVG_BYTES_PER_CHAR >= this.threshold) {
|
|
564
|
+
return {
|
|
565
|
+
...result,
|
|
566
|
+
response: {
|
|
567
|
+
...response,
|
|
568
|
+
body: new Blob([string]).stream().pipeThrough(new CompressionStream(encoding)),
|
|
569
|
+
headers: {
|
|
570
|
+
...headers,
|
|
571
|
+
"standard-server": [],
|
|
572
|
+
"content-type": "application/json",
|
|
573
|
+
"content-length": [],
|
|
574
|
+
"content-encoding": encoding
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
return result;
|
|
581
|
+
};
|
|
582
|
+
return {
|
|
583
|
+
...options,
|
|
584
|
+
routingInterceptors: [
|
|
585
|
+
routingInterceptor,
|
|
586
|
+
...toArray(options.routingInterceptors)
|
|
587
|
+
]
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
function parseAcceptEncodings(header) {
|
|
592
|
+
if (header === void 0) {
|
|
593
|
+
return [];
|
|
594
|
+
}
|
|
595
|
+
return header.split(",").map((part) => part.trim().split(";")[0].trim().toLowerCase()).filter(Boolean);
|
|
596
|
+
}
|
|
597
|
+
const CACHE_CONTROL_NO_TRANSFORM_REGEX = /(?:^|,)\s*no-transform\s*(?:,|$)/i;
|
|
598
|
+
function isNoTransformCacheControl(cacheControl) {
|
|
599
|
+
if (cacheControl === void 0) {
|
|
600
|
+
return false;
|
|
601
|
+
}
|
|
602
|
+
return CACHE_CONTROL_NO_TRANSFORM_REGEX.test(cacheControl);
|
|
603
|
+
}
|
|
604
|
+
|
|
269
605
|
class ResponseHeadersHandlerPlugin {
|
|
270
606
|
name = "~response-headers";
|
|
271
607
|
/**
|
|
@@ -302,4 +638,56 @@ class ResponseHeadersHandlerPlugin {
|
|
|
302
638
|
}
|
|
303
639
|
}
|
|
304
640
|
|
|
305
|
-
|
|
641
|
+
class RethrowHandlerPlugin {
|
|
642
|
+
name = "~rethrow";
|
|
643
|
+
filter;
|
|
644
|
+
CONTEXT_SYMBOL = Symbol("ORPC_RETHROW_HANDLER_PLUGIN_CONTEXT");
|
|
645
|
+
constructor(options) {
|
|
646
|
+
this.filter = options.filter;
|
|
647
|
+
}
|
|
648
|
+
init(options) {
|
|
649
|
+
const routingInterceptor = async (options2) => {
|
|
650
|
+
const pluginContext = {};
|
|
651
|
+
const result = await options2.next({
|
|
652
|
+
...options2,
|
|
653
|
+
context: {
|
|
654
|
+
...options2.context,
|
|
655
|
+
[this.CONTEXT_SYMBOL]: pluginContext
|
|
656
|
+
}
|
|
657
|
+
});
|
|
658
|
+
if (pluginContext.error) {
|
|
659
|
+
throw pluginContext.error.value;
|
|
660
|
+
}
|
|
661
|
+
return result;
|
|
662
|
+
};
|
|
663
|
+
const interceptor = async (options2) => {
|
|
664
|
+
const pluginContext = options2.context[this.CONTEXT_SYMBOL];
|
|
665
|
+
if (!pluginContext) {
|
|
666
|
+
throw new TypeError("[RethrowHandlerPlugin] Rethrow handler context has been corrupted or modified by another plugin or interceptor");
|
|
667
|
+
}
|
|
668
|
+
try {
|
|
669
|
+
return await options2.next();
|
|
670
|
+
} catch (error) {
|
|
671
|
+
if (this.filter(error, options2)) {
|
|
672
|
+
pluginContext.error = { value: error };
|
|
673
|
+
}
|
|
674
|
+
throw error;
|
|
675
|
+
}
|
|
676
|
+
};
|
|
677
|
+
return {
|
|
678
|
+
...options,
|
|
679
|
+
routingInterceptors: [
|
|
680
|
+
...toArray(options.routingInterceptors),
|
|
681
|
+
routingInterceptor
|
|
682
|
+
// rethrow as early as possible and keep it close to `interceptor` to avoid a corrupted or modified context
|
|
683
|
+
],
|
|
684
|
+
interceptors: [
|
|
685
|
+
interceptor,
|
|
686
|
+
// catch as many errors as possible
|
|
687
|
+
...toArray(options.interceptors)
|
|
688
|
+
]
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
export { BatchHandlerPlugin, CORSHandlerPlugin, RequestCompressionHandlerPlugin, RequestHeadersHandlerPlugin, RequestLimitHandlerPlugin, ResponseCompressionHandlerPlugin, ResponseHeadersHandlerPlugin, RethrowHandlerPlugin };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RouterContract, ProcedureContract, ORPCErrorFromErrorMap, ThrowableError, InferSchemaInput, InferSchemaOutput } from '@orpc/contract';
|
|
2
|
-
import { C as Context, a as Procedure, L as Lazyable, M as MergedContext } from './server.
|
|
2
|
+
import { C as Context, a as Procedure, L as Lazyable, M as MergedContext } from './server.CcR4kgje.mjs';
|
|
3
3
|
|
|
4
4
|
type Router<TInitialContext extends Context> = Procedure<TInitialContext, any, any, any, any, any> | {
|
|
5
5
|
[k: string]: Lazyable<Router<TInitialContext>>;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { RPCSerializer, AnyORPCError } from '@orpc/client';
|
|
2
2
|
import { Value, Promisable } from '@orpc/shared';
|
|
3
3
|
import { StandardMethod, StandardLazyRequest, StandardResponse } from '@standardserver/core';
|
|
4
|
-
import { A as AnyProcedure, C as Context } from './server.
|
|
5
|
-
import { A as AnyRouter } from './server.
|
|
4
|
+
import { A as AnyProcedure, C as Context } from './server.CcR4kgje.mjs';
|
|
5
|
+
import { A as AnyRouter } from './server.15O7oC1p.mjs';
|
|
6
6
|
import { AnyProcedureContract } from '@orpc/contract';
|
|
7
|
-
import { b as StandardHandlerHandleOptions, c as StandardHandlerCodec, d as StandardHandlerCodecResolvedProcedure } from './server.
|
|
7
|
+
import { b as StandardHandlerHandleOptions, c as StandardHandlerCodec, d as StandardHandlerCodecResolvedProcedure } from './server.DDFizwfU.mjs';
|
|
8
8
|
|
|
9
9
|
interface RPCMatcherOptions {
|
|
10
10
|
/**
|
|
@@ -38,14 +38,15 @@ interface RPCHandlerCodecOptions<T extends Context> extends RPCMatcherOptions {
|
|
|
38
38
|
/**
|
|
39
39
|
* Resolve HTTP status for encoded successful outputs.
|
|
40
40
|
*
|
|
41
|
-
* Value should be in range `
|
|
41
|
+
* Value should be in the `2xx` range and must be less than `400`.
|
|
42
42
|
* Return `undefined` or `null` to fallback to default
|
|
43
43
|
*
|
|
44
|
-
* @default
|
|
44
|
+
* @default DEFAULT_SUCCESS_STATUS (200)
|
|
45
45
|
*/
|
|
46
46
|
outputStatus?: Value<number | undefined | null, [output: unknown, procedure: AnyProcedure, path: string[], options: StandardHandlerHandleOptions<T>]>;
|
|
47
47
|
/**
|
|
48
48
|
* Mapping ORPCError Code -> HTTP Status Code
|
|
49
|
+
* The status code should be in the `4xx` or `5xx` range (must be greater than or equal to `400`).
|
|
49
50
|
*
|
|
50
51
|
* @default COMMON_ERROR_STATUS_MAP
|
|
51
52
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AnyORPCError } from '@orpc/client';
|
|
2
2
|
import { OrderablePlugin, Interceptor, Promisable } from '@orpc/shared';
|
|
3
3
|
import { StandardLazyRequest, StandardResponse } from '@standardserver/core';
|
|
4
|
-
import { C as Context, c as ProcedureClientInterceptor, A as AnyProcedure } from './server.
|
|
4
|
+
import { C as Context, c as ProcedureClientInterceptor, A as AnyProcedure } from './server.CcR4kgje.js';
|
|
5
5
|
import { Schema, ErrorMap } from '@orpc/contract';
|
|
6
6
|
|
|
7
7
|
interface StandardHandlerPlugin<T extends Context> extends OrderablePlugin {
|
|
@@ -101,4 +101,4 @@ interface StandardHandlerCodec<T extends Context> {
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
export { CompositeStandardHandlerPlugin as C, OtelHandlerPlugin as O, StandardHandler as S };
|
|
104
|
-
export type { StandardHandlerOptions as a, StandardHandlerHandleOptions as b, StandardHandlerCodec as c, StandardHandlerCodecResolvedProcedure as d, StandardHandlerPlugin as e, StandardHandlerRoutingInterceptorOptions as f,
|
|
104
|
+
export type { StandardHandlerOptions as a, StandardHandlerHandleOptions as b, StandardHandlerCodec as c, StandardHandlerCodecResolvedProcedure as d, StandardHandlerPlugin as e, StandardHandlerRoutingInterceptorOptions as f, StandardHandlerInterceptorOptions as g, StandardHandlerHandleResult as h, StandardHandlerInterceptor as i, StandardHandlerRoutingInterceptor as j };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { c as createProcedureClient, P as Procedure, L as Lazy, u as unlazy } from './server.
|
|
1
|
+
import { c as createProcedureClient, P as Procedure, L as Lazy, u as unlazy } from './server.DofEOwf-.mjs';
|
|
2
2
|
import { resolveMetaPlugins, mergeErrorMap, ProcedureContract } from '@orpc/contract';
|
|
3
|
-
import { getOrBind, isTypescriptObject } from '@orpc/shared';
|
|
3
|
+
import { getOrBind, omit, isTypescriptObject } from '@orpc/shared';
|
|
4
4
|
|
|
5
5
|
const DEFAULT_SUCCESS_STATUS = 200;
|
|
6
6
|
const DEFAULT_ERROR_STATUS = 500;
|
|
@@ -77,6 +77,7 @@ function augmentRouter(router, options) {
|
|
|
77
77
|
router["~orpc"].metaPlugins
|
|
78
78
|
);
|
|
79
79
|
const enhanced2 = new Procedure({
|
|
80
|
+
...omit(options, ["middlewares", "errorMap", "meta", "metaPlugins"]),
|
|
80
81
|
...router["~orpc"],
|
|
81
82
|
meta,
|
|
82
83
|
metaPlugins,
|
|
@@ -111,6 +112,7 @@ function augmentImplementedRouter(router, options) {
|
|
|
111
112
|
}
|
|
112
113
|
if (router instanceof Procedure) {
|
|
113
114
|
const enhanced2 = new Procedure({
|
|
115
|
+
...omit(options, ["middlewares"]),
|
|
114
116
|
...router["~orpc"],
|
|
115
117
|
orderedMiddlewares: [
|
|
116
118
|
...options.middlewares.map((middleware) => ({ middleware, inputSchemasLengthAtUse: 0, outputSchemasLengthAtUse: 0 })),
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ORPCError, toORPCError, RPCSerializer, COMMON_ERROR_STATUS_MAP } from '@orpc/client';
|
|
2
2
|
import { sortPlugins, getOpenTelemetryConfig, runWithSpan, toArray, matchesHttpPathPrefix, intercept, ORPC_NAME, isAsyncIteratorObject, override, traceAsyncIterator, recordSpanError, pathToHttpPath, normalizeHttpPath, value, parseEmptyableJSON } from '@orpc/shared';
|
|
3
3
|
import { flattenStandardHeader, parseStandardUrl } from '@standardserver/core';
|
|
4
|
-
import { c as createProcedureClient, u as unlazy, P as Procedure } from './server.
|
|
5
|
-
import { w as walkProcedureContractsSync, g as getRouter, c as createContractProcedure, D as DEFAULT_SUCCESS_STATUS, a as DEFAULT_ERROR_STATUS } from './server.
|
|
4
|
+
import { c as createProcedureClient, u as unlazy, P as Procedure } from './server.DofEOwf-.mjs';
|
|
5
|
+
import { w as walkProcedureContractsSync, g as getRouter, c as createContractProcedure, D as DEFAULT_SUCCESS_STATUS, a as DEFAULT_ERROR_STATUS } from './server.BoiFpNT7.mjs';
|
|
6
6
|
|
|
7
7
|
class CompositeStandardHandlerPlugin {
|
|
8
8
|
name = "~composite";
|
|
@@ -64,7 +64,7 @@ class StandardHandler {
|
|
|
64
64
|
let input = await runWithSpan("decode_input", decodeInput2);
|
|
65
65
|
step = void 0;
|
|
66
66
|
if (isAsyncIteratorObject(input)) {
|
|
67
|
-
input = override(input, traceAsyncIterator("
|
|
67
|
+
input = override(input, traceAsyncIterator("consume_async_iterator_object_input", input));
|
|
68
68
|
}
|
|
69
69
|
const client = createProcedureClient(procedure2, {
|
|
70
70
|
context: context3,
|
|
@@ -119,7 +119,29 @@ interface OrderedMiddleware {
|
|
|
119
119
|
outputSchemasLengthAtUse?: number | undefined;
|
|
120
120
|
middleware: AnyMiddleware;
|
|
121
121
|
}
|
|
122
|
-
interface
|
|
122
|
+
interface ProcedureConfig {
|
|
123
|
+
/**
|
|
124
|
+
* When enabled, input schemas are not validated at runtime.
|
|
125
|
+
* Schemas are still used for type inference and OpenAPI generation.
|
|
126
|
+
*
|
|
127
|
+
* @warning Do not disable validation for schemas that transform values.
|
|
128
|
+
*
|
|
129
|
+
* @default false
|
|
130
|
+
*/
|
|
131
|
+
disableInputValidation?: boolean | undefined;
|
|
132
|
+
/**
|
|
133
|
+
* When enabled, output schemas are not validated at runtime.
|
|
134
|
+
* Schemas are still used for type inference and OpenAPI generation.
|
|
135
|
+
*
|
|
136
|
+
* Useful when output schemas exist only for specification generation.
|
|
137
|
+
*
|
|
138
|
+
* @warning Do not disable validation for schemas that transform values.
|
|
139
|
+
*
|
|
140
|
+
* @default false
|
|
141
|
+
*/
|
|
142
|
+
disableOutputValidation?: boolean | undefined;
|
|
143
|
+
}
|
|
144
|
+
interface ProcedureDefinition<TInitialContext extends Context, TInjectedContext extends Context, TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap, TReturnedError extends AnyORPCError> extends ProcedureContractDefinition<TInputSchema, TOutputSchema, TErrorMap>, ProcedureConfig {
|
|
123
145
|
__TInitialContext?: (type: TInitialContext) => unknown;
|
|
124
146
|
__TInjectedContext?: (type: TInjectedContext) => unknown;
|
|
125
147
|
__TReturnedError?: () => TReturnedError;
|
|
@@ -180,5 +202,5 @@ type ProcedureClientOptions<TInitialContext extends Context, TOutputSchema exten
|
|
|
180
202
|
});
|
|
181
203
|
declare function createProcedureClient<TInitialContext extends Context, TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap, TReturnedError extends AnyORPCError, TClientContext extends ClientContext = object>(lazyableProcedure: Lazyable<Procedure<TInitialContext, any, TInputSchema, TOutputSchema, TErrorMap, TReturnedError>>, ...rest: MaybeOptionalOptions<ProcedureClientOptions<TInitialContext, TOutputSchema, TErrorMap, TReturnedError, TClientContext>>): ProcedureClient<TClientContext, TInputSchema, TOutputSchema, TErrorMap, TReturnedError>;
|
|
182
204
|
|
|
183
|
-
export { Procedure as a, Lazy as
|
|
184
|
-
export type { AnyProcedure as A, Context as C, Lazyable as L, MergedContext as M, ORPCErrorConstructorMap as O, ProcedureClientOptions as P, ProcedureClient as b, ProcedureClientInterceptor as c, Middleware as d, MergedInitialContext as e,
|
|
205
|
+
export { Procedure as a, Lazy as h, createORPCErrorConstructorMap as x, createProcedureClient as y, unlazy as z };
|
|
206
|
+
export type { AnyProcedure as A, Context as C, Lazyable as L, MergedContext as M, ORPCErrorConstructorMap as O, ProcedureClientOptions as P, ProcedureClient as b, ProcedureClientInterceptor as c, Middleware as d, MergedInitialContext as e, ProcedureConfig as f, AnyMiddleware as g, ProcedureHandler as i, OrderedMiddleware as j, LazyDefinition as k, MiddlewareDefinition as l, MiddlewareDone as m, MiddlewareDoneOptions as n, MiddlewareNext as o, MiddlewareNextOptions as p, MiddlewareOptions as q, MiddlewareResult as r, ORPCErrorConstructorMapItem as s, ORPCErrorConstructorMapItemOptions as t, ProcedureClientInterceptorOptions as u, ProcedureDefinition as v, ProcedureHandlerOptions as w };
|
|
@@ -119,7 +119,29 @@ interface OrderedMiddleware {
|
|
|
119
119
|
outputSchemasLengthAtUse?: number | undefined;
|
|
120
120
|
middleware: AnyMiddleware;
|
|
121
121
|
}
|
|
122
|
-
interface
|
|
122
|
+
interface ProcedureConfig {
|
|
123
|
+
/**
|
|
124
|
+
* When enabled, input schemas are not validated at runtime.
|
|
125
|
+
* Schemas are still used for type inference and OpenAPI generation.
|
|
126
|
+
*
|
|
127
|
+
* @warning Do not disable validation for schemas that transform values.
|
|
128
|
+
*
|
|
129
|
+
* @default false
|
|
130
|
+
*/
|
|
131
|
+
disableInputValidation?: boolean | undefined;
|
|
132
|
+
/**
|
|
133
|
+
* When enabled, output schemas are not validated at runtime.
|
|
134
|
+
* Schemas are still used for type inference and OpenAPI generation.
|
|
135
|
+
*
|
|
136
|
+
* Useful when output schemas exist only for specification generation.
|
|
137
|
+
*
|
|
138
|
+
* @warning Do not disable validation for schemas that transform values.
|
|
139
|
+
*
|
|
140
|
+
* @default false
|
|
141
|
+
*/
|
|
142
|
+
disableOutputValidation?: boolean | undefined;
|
|
143
|
+
}
|
|
144
|
+
interface ProcedureDefinition<TInitialContext extends Context, TInjectedContext extends Context, TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap, TReturnedError extends AnyORPCError> extends ProcedureContractDefinition<TInputSchema, TOutputSchema, TErrorMap>, ProcedureConfig {
|
|
123
145
|
__TInitialContext?: (type: TInitialContext) => unknown;
|
|
124
146
|
__TInjectedContext?: (type: TInjectedContext) => unknown;
|
|
125
147
|
__TReturnedError?: () => TReturnedError;
|
|
@@ -180,5 +202,5 @@ type ProcedureClientOptions<TInitialContext extends Context, TOutputSchema exten
|
|
|
180
202
|
});
|
|
181
203
|
declare function createProcedureClient<TInitialContext extends Context, TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap, TReturnedError extends AnyORPCError, TClientContext extends ClientContext = object>(lazyableProcedure: Lazyable<Procedure<TInitialContext, any, TInputSchema, TOutputSchema, TErrorMap, TReturnedError>>, ...rest: MaybeOptionalOptions<ProcedureClientOptions<TInitialContext, TOutputSchema, TErrorMap, TReturnedError, TClientContext>>): ProcedureClient<TClientContext, TInputSchema, TOutputSchema, TErrorMap, TReturnedError>;
|
|
182
204
|
|
|
183
|
-
export { Procedure as a, Lazy as
|
|
184
|
-
export type { AnyProcedure as A, Context as C, Lazyable as L, MergedContext as M, ORPCErrorConstructorMap as O, ProcedureClientOptions as P, ProcedureClient as b, ProcedureClientInterceptor as c, Middleware as d, MergedInitialContext as e,
|
|
205
|
+
export { Procedure as a, Lazy as h, createORPCErrorConstructorMap as x, createProcedureClient as y, unlazy as z };
|
|
206
|
+
export type { AnyProcedure as A, Context as C, Lazyable as L, MergedContext as M, ORPCErrorConstructorMap as O, ProcedureClientOptions as P, ProcedureClient as b, ProcedureClientInterceptor as c, Middleware as d, MergedInitialContext as e, ProcedureConfig as f, AnyMiddleware as g, ProcedureHandler as i, OrderedMiddleware as j, LazyDefinition as k, MiddlewareDefinition as l, MiddlewareDone as m, MiddlewareDoneOptions as n, MiddlewareNext as o, MiddlewareNextOptions as p, MiddlewareOptions as q, MiddlewareResult as r, ORPCErrorConstructorMapItem as s, ORPCErrorConstructorMapItemOptions as t, ProcedureClientInterceptorOptions as u, ProcedureDefinition as v, ProcedureHandlerOptions as w };
|