@orpc/server 2.0.0-beta.23 → 2.0.0-beta.25
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 +4 -1
- package/dist/adapters/aws-lambda/index.d.mts +93 -0
- package/dist/adapters/aws-lambda/index.d.ts +93 -0
- package/dist/adapters/aws-lambda/index.mjs +66 -0
- package/dist/adapters/crossws/index.d.mts +10 -4
- package/dist/adapters/crossws/index.d.ts +10 -4
- package/dist/adapters/crossws/index.mjs +3 -3
- package/dist/adapters/fastify/index.d.mts +85 -0
- package/dist/adapters/fastify/index.d.ts +85 -0
- package/dist/adapters/fastify/index.mjs +66 -0
- package/dist/adapters/fetch/index.d.mts +13 -16
- package/dist/adapters/fetch/index.d.ts +13 -16
- package/dist/adapters/fetch/index.mjs +6 -12
- package/dist/adapters/message-port/index.d.mts +12 -7
- package/dist/adapters/message-port/index.d.ts +12 -7
- package/dist/adapters/message-port/index.mjs +3 -3
- package/dist/adapters/node/index.d.mts +12 -16
- package/dist/adapters/node/index.d.ts +12 -16
- package/dist/adapters/node/index.mjs +7 -12
- package/dist/adapters/standard/index.d.mts +5 -5
- package/dist/adapters/standard/index.d.ts +5 -5
- 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 +10 -4
- package/dist/adapters/websocket/index.d.ts +10 -4
- package/dist/adapters/websocket/index.mjs +3 -3
- 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 +20 -3
- package/dist/helpers/index.d.ts +20 -3
- package/dist/index.d.mts +39 -7
- package/dist/index.d.ts +39 -7
- package/dist/index.mjs +23 -18
- package/dist/plugins/index.d.mts +59 -48
- package/dist/plugins/index.d.ts +59 -48
- package/dist/plugins/index.mjs +34 -67
- package/dist/shared/{server.DofEOwf-.mjs → server.7T18Khvf.mjs} +6 -32
- package/dist/shared/{server.DBs0rrf9.mjs → server.B2pXdfpL.mjs} +1 -1
- package/dist/shared/server.BhHrioCw.d.ts +34 -0
- package/dist/shared/{server.DG9aQpJK.d.ts → server.C2n16pp0.d.ts} +27 -5
- package/dist/shared/{server.A8J9H8OE.mjs → server.Cbv46U7N.mjs} +21 -5
- package/dist/shared/server.Cd4Z1hpV.mjs +69 -0
- package/dist/shared/{server.omY4cUs0.d.mts → server.CkNnZ5F-.d.mts} +27 -5
- package/dist/shared/{server.CcR4kgje.d.ts → server.CwrYlF72.d.mts} +10 -42
- package/dist/shared/{server.CcR4kgje.d.mts → server.CwrYlF72.d.ts} +10 -42
- package/dist/shared/server.D0Ipbmdv.d.mts +34 -0
- package/dist/shared/{server.D4cnq66J.mjs → server.DgunZU0v.mjs} +3 -3
- package/dist/shared/{server.m3szVJGU.d.ts → server.Dm0os-OP.d.mts} +24 -12
- package/dist/shared/{server.BhsVw7m7.d.ts → server.DrN1Pj1-.d.ts} +3 -3
- package/dist/shared/{server.15O7oC1p.d.mts → server.DtfwuV6U.d.ts} +24 -12
- package/dist/shared/{server.DDFizwfU.d.mts → server.JbCIPL4P.d.mts} +3 -3
- package/package.json +26 -9
- package/dist/shared/server.D_QauotT.mjs +0 -30
package/dist/plugins/index.d.ts
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { Value, Promisable, ThrowableError } from '@orpc/shared';
|
|
2
2
|
import { StandardLazyRequest, StandardHeaders } from '@standardserver/core';
|
|
3
|
-
import { C as Context } from '../shared/server.
|
|
4
|
-
import {
|
|
3
|
+
import { C as Context } from '../shared/server.CwrYlF72.js';
|
|
4
|
+
import { S as StandardHandlerPlugin, f as StandardHandlerRoutingInterceptorOptions, a as StandardHandlerOptions, g as StandardHandlerInterceptorOptions } from '../shared/server.DrN1Pj1-.js';
|
|
5
|
+
export { R as RequestLimitHandlerPlugin, a as RequestLimitHandlerPluginOptions } from '../shared/server.BhHrioCw.js';
|
|
5
6
|
import '@orpc/client';
|
|
6
7
|
import '@orpc/contract';
|
|
7
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Content type for batch responses that use the length-prefixed binary framing
|
|
11
|
+
* (streaming mode, and buffered mode when any sub-response contains binary).
|
|
12
|
+
*
|
|
13
|
+
* Decoding is driven by the `standard-server` body hint, not this header,
|
|
14
|
+
* so it only serves to describe the payload to logs, proxies, and dev tools.
|
|
15
|
+
*/
|
|
16
|
+
declare const BATCH_CONTENT_TYPE = "application/vnd.orpc.batch";
|
|
8
17
|
interface BatchHandlerPluginOptions<T extends Context> {
|
|
9
18
|
/**
|
|
10
19
|
* The max size of the batch allowed.
|
|
@@ -54,6 +63,15 @@ interface BatchHandlerPluginOptions<T extends Context> {
|
|
|
54
63
|
interval?: number;
|
|
55
64
|
};
|
|
56
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Handles batch requests sent by the client Batch Link Plugin, splitting each
|
|
68
|
+
* batch into sub-requests and streaming their responses back together.
|
|
69
|
+
*
|
|
70
|
+
* @remarks
|
|
71
|
+
* **Note**: HTTP/2 and later already multiplex requests over a single connection, which often makes this plugin unnecessary.
|
|
72
|
+
*
|
|
73
|
+
* @see {@link https://orpc.dev/docs/plugins/batch | Batch Plugin}
|
|
74
|
+
*/
|
|
57
75
|
declare class BatchHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
58
76
|
name: string;
|
|
59
77
|
/**
|
|
@@ -119,9 +137,10 @@ interface CORSHandlerPluginOptions<T extends Context> {
|
|
|
119
137
|
exposeHeaders?: readonly string[];
|
|
120
138
|
}
|
|
121
139
|
/**
|
|
122
|
-
*
|
|
140
|
+
* Configures the [CORS Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)
|
|
141
|
+
* for your API, including preflight requests.
|
|
123
142
|
*
|
|
124
|
-
* @see {@link https://orpc.dev/docs/plugins/cors CORS Plugin
|
|
143
|
+
* @see {@link https://orpc.dev/docs/plugins/cors | CORS Handler Plugin}
|
|
125
144
|
*/
|
|
126
145
|
declare class CORSHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
127
146
|
private readonly options;
|
|
@@ -137,17 +156,11 @@ declare class CORSHandlerPlugin<T extends Context> implements StandardHandlerPlu
|
|
|
137
156
|
}
|
|
138
157
|
|
|
139
158
|
/**
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
* (for example, fetch/XHR) rather than from standard HTML forms or direct browser navigation.
|
|
159
|
+
* Decompresses incoming request bodies based on the Content-Encoding header,
|
|
160
|
+
* supporting gzip, deflate, and deflate-raw.
|
|
143
161
|
*
|
|
144
|
-
* @
|
|
162
|
+
* @see {@link https://orpc.dev/docs/plugins/request-compression | Request Compression Plugin}
|
|
145
163
|
*/
|
|
146
|
-
declare class CSRFGuardHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
147
|
-
name: string;
|
|
148
|
-
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
164
|
declare class RequestCompressionHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
152
165
|
name: string;
|
|
153
166
|
/**
|
|
@@ -157,6 +170,11 @@ declare class RequestCompressionHandlerPlugin<T extends Context> implements Stan
|
|
|
157
170
|
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
158
171
|
}
|
|
159
172
|
|
|
173
|
+
/**
|
|
174
|
+
* The context shape into which the Request Headers Plugin injects `reqHeaders`.
|
|
175
|
+
*
|
|
176
|
+
* @see {@link https://orpc.dev/docs/plugins/request-headers | Request Headers Plugin}
|
|
177
|
+
*/
|
|
160
178
|
interface RequestHeadersHandlerPluginContext {
|
|
161
179
|
/**
|
|
162
180
|
* Request headers as a Headers instance. This is injected by the Request Headers Plugin.
|
|
@@ -167,42 +185,13 @@ interface RequestHeadersHandlerPluginContext {
|
|
|
167
185
|
* The Request Headers Plugin injects a `reqHeaders` instance into the context,
|
|
168
186
|
* allowing access to request headers in oRPC.
|
|
169
187
|
*
|
|
170
|
-
* @see {@link https://orpc.dev/docs/plugins/request-headers Request Headers Plugin
|
|
188
|
+
* @see {@link https://orpc.dev/docs/plugins/request-headers | Request Headers Plugin}
|
|
171
189
|
*/
|
|
172
190
|
declare class RequestHeadersHandlerPlugin<T extends RequestHeadersHandlerPluginContext> implements StandardHandlerPlugin<T> {
|
|
173
191
|
name: string;
|
|
174
192
|
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
175
193
|
}
|
|
176
194
|
|
|
177
|
-
interface RequestLimitHandlerPluginOptions {
|
|
178
|
-
/**
|
|
179
|
-
* The maximum allowed request body size in bytes.
|
|
180
|
-
*/
|
|
181
|
-
maxBodySize: number;
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Rejects requests whose body exceeds `maxBodySize`.
|
|
185
|
-
*
|
|
186
|
-
* When used with the request compression plugin, the limit applies to the
|
|
187
|
-
* decompressed payload rather than the compressed wire size.
|
|
188
|
-
*
|
|
189
|
-
* @see {@link https://orpc.dev/docs/plugins/request-limit Request Limit Plugin Docs}
|
|
190
|
-
*/
|
|
191
|
-
declare class RequestLimitHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
192
|
-
name: string;
|
|
193
|
-
/**
|
|
194
|
-
* Should limit the original batch request body instead of sub-requests.
|
|
195
|
-
*/
|
|
196
|
-
after: string[];
|
|
197
|
-
/**
|
|
198
|
-
* Should limit the final body size instead of the compressed one.
|
|
199
|
-
*/
|
|
200
|
-
before: string[];
|
|
201
|
-
private readonly maxBodySize;
|
|
202
|
-
constructor(options: RequestLimitHandlerPluginOptions);
|
|
203
|
-
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
195
|
interface ResponseCompressionHandlerPluginOptions<_T extends Context> {
|
|
207
196
|
/**
|
|
208
197
|
* The compression schemes to use for response compression.
|
|
@@ -225,7 +214,7 @@ interface ResponseCompressionHandlerPluginOptions<_T extends Context> {
|
|
|
225
214
|
* Compresses response bodies based on the client's Accept-Encoding header.
|
|
226
215
|
* Works at the standard handler level, so it supports all adapters.
|
|
227
216
|
*
|
|
228
|
-
* @see {@link https://orpc.dev/docs/plugins/response-compression Response Compression Plugin
|
|
217
|
+
* @see {@link https://orpc.dev/docs/plugins/response-compression | Response Compression Plugin}
|
|
229
218
|
*/
|
|
230
219
|
declare class ResponseCompressionHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
231
220
|
name: string;
|
|
@@ -240,6 +229,11 @@ declare class ResponseCompressionHandlerPlugin<T extends Context> implements Sta
|
|
|
240
229
|
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
241
230
|
}
|
|
242
231
|
|
|
232
|
+
/**
|
|
233
|
+
* The context shape into which the Response Headers Plugin injects `resHeaders`.
|
|
234
|
+
*
|
|
235
|
+
* @see {@link https://orpc.dev/docs/plugins/response-headers | Response Headers Plugin}
|
|
236
|
+
*/
|
|
243
237
|
interface ResponseHeadersHandlerPluginContext {
|
|
244
238
|
/**
|
|
245
239
|
* Response headers as a Headers instance. This is injected by the Response Headers Plugin.
|
|
@@ -251,7 +245,7 @@ interface ResponseHeadersHandlerPluginContext {
|
|
|
251
245
|
* The Response Headers Plugin allows you to set response headers in oRPC.
|
|
252
246
|
* It injects a resHeaders instance into the context, enabling you to modify response headers easily.
|
|
253
247
|
*
|
|
254
|
-
* @see {@link https://orpc.dev/docs/plugins/response-headers Response Headers Plugin
|
|
248
|
+
* @see {@link https://orpc.dev/docs/plugins/response-headers | Response Headers Plugin}
|
|
255
249
|
*/
|
|
256
250
|
declare class ResponseHeadersHandlerPlugin<T extends ResponseHeadersHandlerPluginContext> implements StandardHandlerPlugin<T> {
|
|
257
251
|
name: string;
|
|
@@ -283,7 +277,7 @@ interface RethrowHandlerPluginOptions<T extends Context> {
|
|
|
283
277
|
* and rethrow matching errors directly to your framework's error handling mechanism
|
|
284
278
|
* (e.g., NestJS exception filters, Express error middleware).
|
|
285
279
|
*
|
|
286
|
-
* @see {@link https://orpc.dev/docs/plugins/rethrow Rethrow Plugin
|
|
280
|
+
* @see {@link https://orpc.dev/docs/plugins/rethrow | Rethrow Handler Plugin}
|
|
287
281
|
*/
|
|
288
282
|
declare class RethrowHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
289
283
|
name: string;
|
|
@@ -293,5 +287,22 @@ declare class RethrowHandlerPlugin<T extends Context> implements StandardHandler
|
|
|
293
287
|
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
294
288
|
}
|
|
295
289
|
|
|
296
|
-
|
|
297
|
-
|
|
290
|
+
/**
|
|
291
|
+
* Adds basic Cross-Site Request Forgery (CSRF) protection to your oRPC application.
|
|
292
|
+
* When a request includes cookies, it helps ensure the request originates from JavaScript
|
|
293
|
+
* (for example, fetch/XHR) rather than from standard HTML forms or direct browser navigation.
|
|
294
|
+
*
|
|
295
|
+
* @remarks
|
|
296
|
+
* Unlike `SameSite` cookies, this protection also covers cross-site requests that
|
|
297
|
+
* still carry cookies, so it is the recommended safeguard when you enable the `GET`
|
|
298
|
+
* method on RPC handlers or rely on cookie-based authentication.
|
|
299
|
+
*
|
|
300
|
+
* @see {@link https://orpc.dev/docs/plugins/simple-csrf-protection | Simple CSRF Protection Plugin}
|
|
301
|
+
*/
|
|
302
|
+
declare class SimpleCsrfProtectionHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
303
|
+
name: string;
|
|
304
|
+
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export { BATCH_CONTENT_TYPE, BatchHandlerPlugin, CORSHandlerPlugin, CORSHandlerPlugin as CORSPlugin, RequestCompressionHandlerPlugin, RequestHeadersHandlerPlugin, RequestHeadersHandlerPlugin as RequestHeadersPlugin, ResponseCompressionHandlerPlugin, ResponseHeadersHandlerPlugin, ResponseHeadersHandlerPlugin as ResponseHeadersPlugin, RethrowHandlerPlugin, SimpleCsrfProtectionHandlerPlugin };
|
|
308
|
+
export type { BatchHandlerPluginOptions, CORSHandlerPluginOptions, RequestHeadersHandlerPluginContext, RequestHeadersHandlerPluginContext as RequestHeadersPluginContext, ResponseCompressionHandlerPluginOptions, ResponseHeadersHandlerPluginContext, ResponseHeadersHandlerPluginContext as ResponseHeadersPluginContext, RethrowHandlerPluginOptions };
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { toArray, value, isCompressibleContentType, isAsyncIteratorObject, stringifyJSON } from '@orpc/shared';
|
|
2
2
|
import { flattenStandardHeader, parseStandardUrl, generateContentDisposition, mergeStandardHeaders } from '@standardserver/core';
|
|
3
3
|
import { isClientPeerSendMessage, ServerPeer, encodePeerMessage } from '@standardserver/peer';
|
|
4
|
-
export { C as CSRFGuardHandlerPlugin } from '../shared/server.D_QauotT.mjs';
|
|
5
4
|
import { toFetchHeaders, toStandardBody, toStandardHeaders } from '@standardserver/fetch';
|
|
5
|
+
export { R as RequestLimitHandlerPlugin } from '../shared/server.Cd4Z1hpV.mjs';
|
|
6
6
|
import { ORPCError } from '@orpc/client';
|
|
7
7
|
|
|
8
|
+
const BATCH_CONTENT_TYPE = "application/vnd.orpc.batch";
|
|
8
9
|
class BatchHandlerPlugin {
|
|
9
10
|
name = "~batch";
|
|
10
11
|
/**
|
|
@@ -121,7 +122,7 @@ class BatchHandlerPlugin {
|
|
|
121
122
|
response: {
|
|
122
123
|
status,
|
|
123
124
|
headers,
|
|
124
|
-
body: new Blob(chunks, { type:
|
|
125
|
+
body: new Blob(chunks, { type: BATCH_CONTENT_TYPE })
|
|
125
126
|
}
|
|
126
127
|
};
|
|
127
128
|
}
|
|
@@ -182,7 +183,11 @@ class BatchHandlerPlugin {
|
|
|
182
183
|
});
|
|
183
184
|
return {
|
|
184
185
|
matched: true,
|
|
185
|
-
response: {
|
|
186
|
+
response: {
|
|
187
|
+
status,
|
|
188
|
+
headers: { ...headers, "content-type": BATCH_CONTENT_TYPE },
|
|
189
|
+
body: stream
|
|
190
|
+
}
|
|
186
191
|
};
|
|
187
192
|
};
|
|
188
193
|
return {
|
|
@@ -365,69 +370,6 @@ class RequestHeadersHandlerPlugin {
|
|
|
365
370
|
}
|
|
366
371
|
}
|
|
367
372
|
|
|
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
373
|
const AVG_BYTES_PER_CHAR = 1.2;
|
|
432
374
|
class ResponseCompressionHandlerPlugin {
|
|
433
375
|
name = "~response-compression";
|
|
@@ -690,4 +632,29 @@ class RethrowHandlerPlugin {
|
|
|
690
632
|
}
|
|
691
633
|
}
|
|
692
634
|
|
|
693
|
-
|
|
635
|
+
class SimpleCsrfProtectionHandlerPlugin {
|
|
636
|
+
name = "~simple-csrf-protection";
|
|
637
|
+
init(options) {
|
|
638
|
+
const interceptor = async (interceptorOptions) => {
|
|
639
|
+
const mode = flattenStandardHeader(
|
|
640
|
+
interceptorOptions.request.headers["sec-fetch-mode"]
|
|
641
|
+
)?.toLowerCase();
|
|
642
|
+
if (mode === void 0) {
|
|
643
|
+
return interceptorOptions.next();
|
|
644
|
+
}
|
|
645
|
+
if (mode === "cors" || mode === "same-origin") {
|
|
646
|
+
return interceptorOptions.next();
|
|
647
|
+
}
|
|
648
|
+
throw new ORPCError("FORBIDDEN", {
|
|
649
|
+
message: "Request blocked by CSRF protection."
|
|
650
|
+
});
|
|
651
|
+
};
|
|
652
|
+
return {
|
|
653
|
+
...options,
|
|
654
|
+
// appended last so user's interceptors can catch ORPCError
|
|
655
|
+
interceptors: [...toArray(options.interceptors), interceptor]
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
export { BATCH_CONTENT_TYPE, BatchHandlerPlugin, CORSHandlerPlugin, CORSHandlerPlugin as CORSPlugin, RequestCompressionHandlerPlugin, RequestHeadersHandlerPlugin, RequestHeadersHandlerPlugin as RequestHeadersPlugin, ResponseCompressionHandlerPlugin, ResponseHeadersHandlerPlugin, ResponseHeadersHandlerPlugin as ResponseHeadersPlugin, RethrowHandlerPlugin, SimpleCsrfProtectionHandlerPlugin };
|
|
@@ -1,32 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { reconcileORPCError, ValidationError, ProcedureContract } from '@orpc/contract';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
function createORPCErrorConstructorMap(errorMap) {
|
|
6
|
-
const proxy = new Proxy(errorMap, {
|
|
7
|
-
get(target, code) {
|
|
8
|
-
if (typeof code !== "string") {
|
|
9
|
-
return getOrBind(target, code);
|
|
10
|
-
}
|
|
11
|
-
const item = (...rest) => {
|
|
12
|
-
const options = resolveMaybeOptionalOptions(rest);
|
|
13
|
-
const config = errorMap[code];
|
|
14
|
-
const error = new ORPCError(code, {
|
|
15
|
-
message: options.message ?? config?.message,
|
|
16
|
-
data: options.data,
|
|
17
|
-
cause: options.cause
|
|
18
|
-
});
|
|
19
|
-
if (config) {
|
|
20
|
-
error.defined = true;
|
|
21
|
-
error.inferable = true;
|
|
22
|
-
}
|
|
23
|
-
return error;
|
|
24
|
-
};
|
|
25
|
-
return item;
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
return proxy;
|
|
29
|
-
}
|
|
1
|
+
import { wrapAsyncIteratorPreservingEventMeta, ORPCError, cloneORPCError } from '@orpc/client';
|
|
2
|
+
import { createORPCErrorConstructorMap, reconcileORPCError, ValidationError, ProcedureContract } from '@orpc/contract';
|
|
3
|
+
import { getConstructor, isTypescriptObject, resolveMaybeOptionalOptions, toArray, value, runWithSpan, intercept, isAsyncIteratorObject, override, traceAsyncIterator, traceReadableStream } from '@orpc/shared';
|
|
30
4
|
|
|
31
5
|
class Lazy {
|
|
32
6
|
"~orpc";
|
|
@@ -34,7 +8,7 @@ class Lazy {
|
|
|
34
8
|
this["~orpc"] = def;
|
|
35
9
|
}
|
|
36
10
|
/**
|
|
37
|
-
* Checks if the given instance satisfies the {@
|
|
11
|
+
* Checks if the given instance satisfies the {@link Lazy} class/interface.
|
|
38
12
|
*/
|
|
39
13
|
static [Symbol.hasInstance](instance) {
|
|
40
14
|
if (this !== Lazy) {
|
|
@@ -220,7 +194,7 @@ class Procedure {
|
|
|
220
194
|
this["~orpc"] = def;
|
|
221
195
|
}
|
|
222
196
|
/**
|
|
223
|
-
* Checks if the given instance satisfies the {@
|
|
197
|
+
* Checks if the given instance satisfies the {@link Procedure} class/interface.
|
|
224
198
|
*/
|
|
225
199
|
static [Symbol.hasInstance](instance) {
|
|
226
200
|
if (this !== Procedure) {
|
|
@@ -234,4 +208,4 @@ class Procedure {
|
|
|
234
208
|
}
|
|
235
209
|
}
|
|
236
210
|
|
|
237
|
-
export { Lazy as L, Procedure as P,
|
|
211
|
+
export { Lazy as L, Procedure as P, createProcedureClient as c, unlazy as u };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolveMetaPlugins, mergeErrorMap, getHiddenMetaPlugins } from '@orpc/contract';
|
|
2
|
-
import { P as Procedure } from './server.
|
|
2
|
+
import { P as Procedure } from './server.7T18Khvf.mjs';
|
|
3
3
|
|
|
4
4
|
class DecoratedProcedure extends Procedure {
|
|
5
5
|
meta(...plugins) {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { C as Context } from './server.CwrYlF72.js';
|
|
2
|
+
import { S as StandardHandlerPlugin, a as StandardHandlerOptions } from './server.DrN1Pj1-.js';
|
|
3
|
+
|
|
4
|
+
interface RequestLimitHandlerPluginOptions {
|
|
5
|
+
/**
|
|
6
|
+
* The maximum allowed request body size in bytes.
|
|
7
|
+
*/
|
|
8
|
+
maxBodySize: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Rejects requests whose body exceeds `maxBodySize`.
|
|
12
|
+
*
|
|
13
|
+
* When used with the request compression plugin, the limit applies to the
|
|
14
|
+
* decompressed payload rather than the compressed wire size.
|
|
15
|
+
*
|
|
16
|
+
* @see {@link https://orpc.dev/docs/plugins/request-limit | Request Limit Plugin}
|
|
17
|
+
*/
|
|
18
|
+
declare class RequestLimitHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
19
|
+
name: string;
|
|
20
|
+
/**
|
|
21
|
+
* Should limit the original batch request body instead of sub-requests.
|
|
22
|
+
*/
|
|
23
|
+
after: string[];
|
|
24
|
+
/**
|
|
25
|
+
* Should limit the final body size instead of the compressed one.
|
|
26
|
+
*/
|
|
27
|
+
before: string[];
|
|
28
|
+
private readonly maxBodySize;
|
|
29
|
+
constructor(options: RequestLimitHandlerPluginOptions);
|
|
30
|
+
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { RequestLimitHandlerPlugin as R };
|
|
34
|
+
export type { RequestLimitHandlerPluginOptions as a };
|
|
@@ -1,11 +1,21 @@
|
|
|
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.CwrYlF72.js';
|
|
5
|
+
import { A as AnyRouter } from './server.DtfwuV6U.js';
|
|
6
6
|
import { AnyProcedureContract } from '@orpc/contract';
|
|
7
|
-
import {
|
|
7
|
+
import { c as StandardHandlerHandleOptions, d as StandardHandlerCodec, e as StandardHandlerCodecResolvedProcedure } from './server.DrN1Pj1-.js';
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Methods that can invoke procedures by default. Browsers cannot trigger them
|
|
11
|
+
* cross-site without a CORS preflight or an HTML form, unlike `GET`, which a plain
|
|
12
|
+
* `<a>` click or redirect can trigger with `SameSite=Lax` cookies attached. Other
|
|
13
|
+
* methods (`HEAD`, `OPTIONS`, `QUERY`, ...) have safe semantics that should not
|
|
14
|
+
* invoke a procedure that can modify data.
|
|
15
|
+
*
|
|
16
|
+
* @see {@link https://orpc.dev/docs/rpc/handler#supported-http-methods | RPC Handler - Supported HTTP Methods}
|
|
17
|
+
*/
|
|
18
|
+
declare const RPC_DEFAULT_ALLOW_METHODS: readonly StandardMethod[];
|
|
9
19
|
interface RPCMatcherOptions {
|
|
10
20
|
/**
|
|
11
21
|
* Filter which procedures are exposed for matching. Return `false` to exclude.
|
|
@@ -13,15 +23,27 @@ interface RPCMatcherOptions {
|
|
|
13
23
|
* @default true
|
|
14
24
|
*/
|
|
15
25
|
filter?: Value<boolean, [procedure: AnyProcedureContract | AnyProcedure, path: string[]]>;
|
|
26
|
+
/**
|
|
27
|
+
* Restricts which HTTP methods can invoke procedures, either with a list of allowed
|
|
28
|
+
* methods or decided per request via a function. Requests using a disallowed method
|
|
29
|
+
* are treated as unmatched. `GET` is excluded by default because it is exposed to
|
|
30
|
+
* Cross-Site Request Forgery (CSRF) attacks.
|
|
31
|
+
*
|
|
32
|
+
* @default RPC_DEFAULT_ALLOW_METHODS (['POST', 'PUT', 'PATCH', 'DELETE'])
|
|
33
|
+
* @see {@link https://orpc.dev/docs/rpc/handler#supported-http-methods | RPC Handler - Supported HTTP Methods}
|
|
34
|
+
*/
|
|
35
|
+
allowMethods?: readonly StandardMethod[] | ((method: StandardMethod, procedure: AnyProcedure, path: string[]) => boolean);
|
|
16
36
|
}
|
|
17
37
|
declare class RPCMatcher {
|
|
18
38
|
private readonly filter;
|
|
39
|
+
private readonly allowMethodsSet;
|
|
40
|
+
private readonly allowMethodsFn;
|
|
19
41
|
private readonly rootRouter;
|
|
20
42
|
private readonly tree;
|
|
21
43
|
private readonly pendingLazyRouters;
|
|
22
44
|
constructor(router: AnyRouter, options?: RPCMatcherOptions);
|
|
23
45
|
private index;
|
|
24
|
-
match(
|
|
46
|
+
match(method: StandardMethod, pathname: `/${string}`, prefix: `/${string}` | undefined): Promise<{
|
|
25
47
|
path: string[];
|
|
26
48
|
procedure: AnyProcedure;
|
|
27
49
|
} | undefined>;
|
|
@@ -65,5 +87,5 @@ declare class RPCHandlerCodec<T extends Context> implements StandardHandlerCodec
|
|
|
65
87
|
encodeError(error: AnyORPCError, _procedure: AnyProcedure, _path: string[], _options: StandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
|
|
66
88
|
}
|
|
67
89
|
|
|
68
|
-
export { RPCHandlerCodec as a, RPCMatcher as b };
|
|
90
|
+
export { RPCHandlerCodec as a, RPCMatcher as b, RPC_DEFAULT_ALLOW_METHODS as d };
|
|
69
91
|
export type { RPCHandlerCodecOptions as R, RPCMatcherOptions as c };
|
|
@@ -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.7T18Khvf.mjs';
|
|
5
|
+
import { w as walkProcedureContractsSync, g as getRouter, c as createContractProcedure, D as DEFAULT_SUCCESS_STATUS, a as DEFAULT_ERROR_STATUS } from './server.DgunZU0v.mjs';
|
|
6
6
|
|
|
7
7
|
class CompositeStandardHandlerPlugin {
|
|
8
8
|
name = "~composite";
|
|
@@ -121,13 +121,22 @@ class OtelHandlerPlugin {
|
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
const RPC_DEFAULT_ALLOW_METHODS = ["POST", "PUT", "PATCH", "DELETE"];
|
|
124
125
|
class RPCMatcher {
|
|
125
126
|
filter;
|
|
127
|
+
allowMethodsSet;
|
|
128
|
+
allowMethodsFn;
|
|
126
129
|
rootRouter;
|
|
127
130
|
tree = /* @__PURE__ */ new Map();
|
|
128
131
|
pendingLazyRouters = /* @__PURE__ */ new Map();
|
|
129
132
|
constructor(router, options = {}) {
|
|
130
133
|
this.filter = options.filter ?? true;
|
|
134
|
+
const allowMethods = options.allowMethods ?? RPC_DEFAULT_ALLOW_METHODS;
|
|
135
|
+
if (typeof allowMethods !== "function") {
|
|
136
|
+
this.allowMethodsSet = new Set(allowMethods);
|
|
137
|
+
} else {
|
|
138
|
+
this.allowMethodsFn = allowMethods;
|
|
139
|
+
}
|
|
131
140
|
this.rootRouter = router;
|
|
132
141
|
this.index(router);
|
|
133
142
|
}
|
|
@@ -147,7 +156,10 @@ class RPCMatcher {
|
|
|
147
156
|
this.pendingLazyRouters.set(pathToHttpPath(result.path), result);
|
|
148
157
|
}
|
|
149
158
|
}
|
|
150
|
-
async match(
|
|
159
|
+
async match(method, pathname, prefix) {
|
|
160
|
+
if (this.allowMethodsSet && !this.allowMethodsSet.has(method)) {
|
|
161
|
+
return void 0;
|
|
162
|
+
}
|
|
151
163
|
if (pathname.length > 1 && pathname.endsWith("/")) {
|
|
152
164
|
pathname = pathname.slice(0, -1);
|
|
153
165
|
}
|
|
@@ -182,9 +194,13 @@ class RPCMatcher {
|
|
|
182
194
|
if (entry === void 0) {
|
|
183
195
|
return void 0;
|
|
184
196
|
}
|
|
197
|
+
const procedure = entry.procedure ?? await this.resolveProcedure(entry);
|
|
198
|
+
if (this.allowMethodsFn && !this.allowMethodsFn(method, procedure, entry.path)) {
|
|
199
|
+
return void 0;
|
|
200
|
+
}
|
|
185
201
|
return {
|
|
186
202
|
path: entry.path,
|
|
187
|
-
procedure
|
|
203
|
+
procedure
|
|
188
204
|
};
|
|
189
205
|
}
|
|
190
206
|
resolvePendingLazyRouters(pathname) {
|
|
@@ -285,4 +301,4 @@ class RPCHandlerCodec {
|
|
|
285
301
|
}
|
|
286
302
|
}
|
|
287
303
|
|
|
288
|
-
export { CompositeStandardHandlerPlugin as C, OtelHandlerPlugin as O, RPCHandlerCodec as R, StandardHandler as S, RPCMatcher as a };
|
|
304
|
+
export { CompositeStandardHandlerPlugin as C, OtelHandlerPlugin as O, RPCHandlerCodec as R, StandardHandler as S, RPCMatcher as a, RPC_DEFAULT_ALLOW_METHODS as b };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { ORPCError } from '@orpc/client';
|
|
2
|
+
import { toArray } from '@orpc/shared';
|
|
3
|
+
import { flattenStandardHeader } from '@standardserver/core';
|
|
4
|
+
import { toFetchHeaders, toStandardBody } from '@standardserver/fetch';
|
|
5
|
+
|
|
6
|
+
class RequestLimitHandlerPlugin {
|
|
7
|
+
name = "~request-limit";
|
|
8
|
+
/**
|
|
9
|
+
* Should limit the original batch request body instead of sub-requests.
|
|
10
|
+
*/
|
|
11
|
+
after = ["~batch"];
|
|
12
|
+
/**
|
|
13
|
+
* Should limit the final body size instead of the compressed one.
|
|
14
|
+
*/
|
|
15
|
+
before = ["~request-compression"];
|
|
16
|
+
maxBodySize;
|
|
17
|
+
constructor(options) {
|
|
18
|
+
this.maxBodySize = options.maxBodySize;
|
|
19
|
+
}
|
|
20
|
+
init(options) {
|
|
21
|
+
const maxBodySize = this.maxBodySize;
|
|
22
|
+
const routingInterceptor = async ({ next, ...interceptorOptions }) => {
|
|
23
|
+
return next({
|
|
24
|
+
...interceptorOptions,
|
|
25
|
+
request: {
|
|
26
|
+
...interceptorOptions.request,
|
|
27
|
+
async resolveBody(hint) {
|
|
28
|
+
const contentLength = Number(
|
|
29
|
+
flattenStandardHeader(interceptorOptions.request.headers["content-length"])
|
|
30
|
+
);
|
|
31
|
+
if (Number.isFinite(contentLength) && contentLength > maxBodySize) {
|
|
32
|
+
throw new ORPCError("PAYLOAD_TOO_LARGE");
|
|
33
|
+
}
|
|
34
|
+
const stream = await interceptorOptions.request.resolveBody("octet-stream");
|
|
35
|
+
if (!(stream instanceof ReadableStream)) {
|
|
36
|
+
return stream;
|
|
37
|
+
}
|
|
38
|
+
let currentBodySize = 0;
|
|
39
|
+
const limitedStream = stream.pipeThrough(
|
|
40
|
+
new TransformStream({
|
|
41
|
+
transform(chunk, controller) {
|
|
42
|
+
currentBodySize += chunk.byteLength;
|
|
43
|
+
if (currentBodySize > maxBodySize) {
|
|
44
|
+
controller.error(new ORPCError("PAYLOAD_TOO_LARGE"));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
controller.enqueue(chunk);
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
);
|
|
51
|
+
const response = new Response(limitedStream, {
|
|
52
|
+
headers: toFetchHeaders(interceptorOptions.request.headers)
|
|
53
|
+
});
|
|
54
|
+
return toStandardBody(response, { hint });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
return {
|
|
60
|
+
...options,
|
|
61
|
+
routingInterceptors: [
|
|
62
|
+
routingInterceptor,
|
|
63
|
+
...toArray(options.routingInterceptors)
|
|
64
|
+
]
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { RequestLimitHandlerPlugin as R };
|