@orpc/server 2.0.0-beta.25 → 2.0.0-beta.27
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 +37 -76
- package/dist/adapters/aws-lambda/index.mjs +3 -3
- package/dist/adapters/crossws/index.mjs +3 -3
- package/dist/adapters/fastify/index.mjs +3 -3
- package/dist/adapters/fetch/index.mjs +3 -3
- package/dist/adapters/message-port/index.mjs +3 -3
- package/dist/adapters/node/index.mjs +3 -3
- package/dist/adapters/standard/index.d.mts +1 -1
- package/dist/adapters/standard/index.d.ts +1 -1
- package/dist/adapters/standard/index.mjs +3 -3
- package/dist/adapters/websocket/index.mjs +3 -3
- package/dist/extensions/callable.mjs +2 -2
- package/dist/index.d.mts +261 -1
- package/dist/index.d.ts +261 -1
- package/dist/index.mjs +78 -5
- package/dist/plugins/index.d.mts +64 -23
- package/dist/plugins/index.d.ts +64 -23
- package/dist/plugins/index.mjs +116 -46
- package/dist/shared/{server.7T18Khvf.mjs → server.CkButhNT.mjs} +7 -2
- package/dist/shared/{server.Cbv46U7N.mjs → server.D9VprDph.mjs} +2 -2
- package/dist/shared/{server.DgunZU0v.mjs → server.Dh77P3ii.mjs} +1 -1
- package/dist/shared/{server.B2pXdfpL.mjs → server.eCTV8Vpp.mjs} +1 -1
- package/package.json +6 -5
package/dist/plugins/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Value, Promisable, ThrowableError } from '@orpc/shared';
|
|
2
|
-
import { StandardLazyRequest, StandardHeaders } from '@standardserver/core';
|
|
2
|
+
import { StandardLazyRequest, StandardHeaders, StandardMethod } from '@standardserver/core';
|
|
3
3
|
import { C as Context } from '../shared/server.CwrYlF72.js';
|
|
4
4
|
import { S as StandardHandlerPlugin, f as StandardHandlerRoutingInterceptorOptions, a as StandardHandlerOptions, g as StandardHandlerInterceptorOptions } from '../shared/server.DrN1Pj1-.js';
|
|
5
5
|
export { R as RequestLimitHandlerPlugin, a as RequestLimitHandlerPluginOptions } from '../shared/server.BhHrioCw.js';
|
|
@@ -96,18 +96,18 @@ interface CORSHandlerPluginOptions<T extends Context> {
|
|
|
96
96
|
*
|
|
97
97
|
* @default (origin) => origin
|
|
98
98
|
*/
|
|
99
|
-
origin?: Value<
|
|
99
|
+
origin?: Value<string | readonly string[] | null | undefined, [origin: string | undefined, options: StandardHandlerRoutingInterceptorOptions<T>]>;
|
|
100
100
|
/**
|
|
101
101
|
* Configures the `Timing-Allow-Origin` header.
|
|
102
102
|
* Can be a string, an array of allowed origins, or a function that returns the allowed origin(s).
|
|
103
103
|
*
|
|
104
104
|
* @default undefined
|
|
105
105
|
*/
|
|
106
|
-
timingOrigin?: Value<
|
|
106
|
+
timingOrigin?: Value<string | readonly string[] | null | undefined, [origin: string | undefined, options: StandardHandlerRoutingInterceptorOptions<T>]>;
|
|
107
107
|
/**
|
|
108
108
|
* Configures the `Access-Control-Allow-Methods` header for preflight requests.
|
|
109
109
|
*
|
|
110
|
-
* @default ['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH']
|
|
110
|
+
* @default ['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH', 'QUERY']
|
|
111
111
|
*/
|
|
112
112
|
allowMethods?: readonly string[];
|
|
113
113
|
/**
|
|
@@ -155,6 +155,64 @@ declare class CORSHandlerPlugin<T extends Context> implements StandardHandlerPlu
|
|
|
155
155
|
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
/**
|
|
159
|
+
* Adds Cross-Site Request Forgery (CSRF) protection that makes the safe `GET` method as
|
|
160
|
+
* secure as unsafe ones such as `POST`. It rejects `GET` requests arriving as top-level
|
|
161
|
+
* navigations initiated cross-site or from outside the browser, the only context where
|
|
162
|
+
* another site can make a browser attach `SameSite=Lax` cookies to a safe-method request.
|
|
163
|
+
*
|
|
164
|
+
* @remarks
|
|
165
|
+
* **Note**: Requests browsers send without `SameSite=Lax` cookies, such as cross-site `fetch`
|
|
166
|
+
* and `<img>`, pass through, so procedures stay reachable from other sites. This safeguard
|
|
167
|
+
* requires authentication cookies explicitly marked `SameSite=Lax` or `SameSite=Strict`,
|
|
168
|
+
* since browsers may attach other cookies to the requests that pass.
|
|
169
|
+
*
|
|
170
|
+
* @see {@link https://orpc.dev/docs/plugins/get-method-csrf-protection | GET Method CSRF Protection Plugin}
|
|
171
|
+
*/
|
|
172
|
+
declare class GetMethodCsrfProtectionHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
173
|
+
name: string;
|
|
174
|
+
/** Judge the real request, before batch splits it into client-authored sub-requests. */
|
|
175
|
+
after: string[];
|
|
176
|
+
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
177
|
+
private isAllowed;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
interface MethodOverrideHandlerPluginOptions {
|
|
181
|
+
/**
|
|
182
|
+
* The query parameter carrying the override method.
|
|
183
|
+
*
|
|
184
|
+
* @default 'method'
|
|
185
|
+
*/
|
|
186
|
+
param?: string;
|
|
187
|
+
/**
|
|
188
|
+
* The methods a POST request may be overridden to.
|
|
189
|
+
*
|
|
190
|
+
* GET and HEAD are excluded by default because they switch input decoding
|
|
191
|
+
* from the request body to the query string and widen the CSRF surface.
|
|
192
|
+
*
|
|
193
|
+
* @default ['PUT', 'PATCH', 'DELETE']
|
|
194
|
+
*/
|
|
195
|
+
methods?: readonly StandardMethod[];
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Overrides the HTTP method of a POST request based on a query parameter,
|
|
199
|
+
* so HTML forms (which only support GET and POST) can invoke procedures
|
|
200
|
+
* routed as PUT, PATCH, or DELETE.
|
|
201
|
+
*
|
|
202
|
+
* @see {@link https://orpc.dev/docs/plugins/method-override | Method Override Plugin}
|
|
203
|
+
*/
|
|
204
|
+
declare class MethodOverrideHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
205
|
+
name: string;
|
|
206
|
+
/**
|
|
207
|
+
* Should override batch sub-request methods, not the original batch request.
|
|
208
|
+
*/
|
|
209
|
+
before: string[];
|
|
210
|
+
private readonly param;
|
|
211
|
+
private readonly methods;
|
|
212
|
+
constructor(options?: MethodOverrideHandlerPluginOptions);
|
|
213
|
+
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
214
|
+
}
|
|
215
|
+
|
|
158
216
|
/**
|
|
159
217
|
* Decompresses incoming request bodies based on the Content-Encoding header,
|
|
160
218
|
* supporting gzip, deflate, and deflate-raw.
|
|
@@ -287,22 +345,5 @@ declare class RethrowHandlerPlugin<T extends Context> implements StandardHandler
|
|
|
287
345
|
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
288
346
|
}
|
|
289
347
|
|
|
290
|
-
|
|
291
|
-
|
|
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 };
|
|
348
|
+
export { BATCH_CONTENT_TYPE, BatchHandlerPlugin, CORSHandlerPlugin, CORSHandlerPlugin as CORSPlugin, GetMethodCsrfProtectionHandlerPlugin, MethodOverrideHandlerPlugin, RequestCompressionHandlerPlugin, RequestHeadersHandlerPlugin, RequestHeadersHandlerPlugin as RequestHeadersPlugin, ResponseCompressionHandlerPlugin, ResponseHeadersHandlerPlugin, ResponseHeadersHandlerPlugin as ResponseHeadersPlugin, RethrowHandlerPlugin };
|
|
349
|
+
export type { BatchHandlerPluginOptions, CORSHandlerPluginOptions, MethodOverrideHandlerPluginOptions, RequestHeadersHandlerPluginContext, RequestHeadersHandlerPluginContext as RequestHeadersPluginContext, ResponseCompressionHandlerPluginOptions, ResponseHeadersHandlerPluginContext, ResponseHeadersHandlerPluginContext as ResponseHeadersPluginContext, RethrowHandlerPluginOptions };
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { toArray, value, isCompressibleContentType, isAsyncIteratorObject, stringifyJSON } from '@orpc/shared';
|
|
1
|
+
import { toArray, value, parseAcceptEncodingQualities, 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
4
|
import { toFetchHeaders, toStandardBody, toStandardHeaders } from '@standardserver/fetch';
|
|
5
5
|
export { R as RequestLimitHandlerPlugin } from '../shared/server.Cd4Z1hpV.mjs';
|
|
6
|
-
import
|
|
6
|
+
import '@orpc/client';
|
|
7
7
|
|
|
8
8
|
const BATCH_CONTENT_TYPE = "application/vnd.orpc.batch";
|
|
9
9
|
class BatchHandlerPlugin {
|
|
@@ -64,7 +64,7 @@ class BatchHandlerPlugin {
|
|
|
64
64
|
messages = mightBeMessages;
|
|
65
65
|
} else {
|
|
66
66
|
const mightBeMessages = await interceptorOptions.request.resolveBody();
|
|
67
|
-
if (!Array.isArray(mightBeMessages)) {
|
|
67
|
+
if (!Array.isArray(mightBeMessages) || mightBeMessages.some((m) => !isClientPeerSendMessage(m))) {
|
|
68
68
|
return {
|
|
69
69
|
matched: true,
|
|
70
70
|
response: { status: 400, headers: {}, body: "Invalid batch request body" }
|
|
@@ -78,6 +78,13 @@ class BatchHandlerPlugin {
|
|
|
78
78
|
response: { status: 400, headers: {}, body: "Invalid batch request" }
|
|
79
79
|
};
|
|
80
80
|
}
|
|
81
|
+
const outerMethod = interceptorOptions.request.method;
|
|
82
|
+
if ((outerMethod === "GET" || outerMethod === "QUERY") && messages.some((message) => message.kind === "request" && message.json.method !== outerMethod)) {
|
|
83
|
+
return {
|
|
84
|
+
matched: true,
|
|
85
|
+
response: { status: 400, headers: {}, body: `${outerMethod} batch requests only accept ${outerMethod} sub-requests` }
|
|
86
|
+
};
|
|
87
|
+
}
|
|
81
88
|
const maxSize = await value(this.maxSize, interceptorOptions);
|
|
82
89
|
if (messages.length > maxSize) {
|
|
83
90
|
return {
|
|
@@ -209,7 +216,7 @@ class CORSHandlerPlugin {
|
|
|
209
216
|
constructor(options = {}) {
|
|
210
217
|
const defaults = {
|
|
211
218
|
origin: (origin) => origin,
|
|
212
|
-
allowMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH"]
|
|
219
|
+
allowMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH", "QUERY"]
|
|
213
220
|
};
|
|
214
221
|
this.options = {
|
|
215
222
|
...defaults,
|
|
@@ -223,12 +230,12 @@ class CORSHandlerPlugin {
|
|
|
223
230
|
return result;
|
|
224
231
|
}
|
|
225
232
|
const resHeaders = { ...result.response.headers };
|
|
226
|
-
const origin = flattenStandardHeader(interceptorOptions.request.headers.origin)
|
|
227
|
-
const allowedOrigins = toArray(
|
|
233
|
+
const origin = flattenStandardHeader(interceptorOptions.request.headers.origin);
|
|
234
|
+
const allowedOrigins = toArray(value(this.options.origin, origin, interceptorOptions));
|
|
228
235
|
if (allowedOrigins.includes("*")) {
|
|
229
236
|
resHeaders["access-control-allow-origin"] = "*";
|
|
230
237
|
} else {
|
|
231
|
-
if (allowedOrigins.includes(origin)) {
|
|
238
|
+
if (origin !== void 0 && allowedOrigins.includes(origin)) {
|
|
232
239
|
resHeaders["access-control-allow-origin"] = origin;
|
|
233
240
|
}
|
|
234
241
|
const existingVary = flattenStandardHeader(resHeaders.vary);
|
|
@@ -236,10 +243,10 @@ class CORSHandlerPlugin {
|
|
|
236
243
|
resHeaders.vary = existingVary ? `${existingVary}, Origin` : "Origin";
|
|
237
244
|
}
|
|
238
245
|
}
|
|
239
|
-
const allowedTimingOrigins = toArray(
|
|
246
|
+
const allowedTimingOrigins = toArray(value(this.options.timingOrigin, origin, interceptorOptions));
|
|
240
247
|
if (allowedTimingOrigins.includes("*")) {
|
|
241
248
|
resHeaders["timing-allow-origin"] = "*";
|
|
242
|
-
} else if (allowedTimingOrigins.includes(origin)) {
|
|
249
|
+
} else if (origin !== void 0 && allowedTimingOrigins.includes(origin)) {
|
|
243
250
|
resHeaders["timing-allow-origin"] = origin;
|
|
244
251
|
}
|
|
245
252
|
if (this.options.credentials) {
|
|
@@ -285,6 +292,84 @@ class CORSHandlerPlugin {
|
|
|
285
292
|
}
|
|
286
293
|
}
|
|
287
294
|
|
|
295
|
+
class GetMethodCsrfProtectionHandlerPlugin {
|
|
296
|
+
name = "~get-method-csrf-protection";
|
|
297
|
+
/** Judge the real request, before batch splits it into client-authored sub-requests. */
|
|
298
|
+
after = ["~batch"];
|
|
299
|
+
init(options) {
|
|
300
|
+
const routingInterceptor = (interceptorOptions) => {
|
|
301
|
+
if (this.isAllowed(interceptorOptions)) {
|
|
302
|
+
return interceptorOptions.next();
|
|
303
|
+
}
|
|
304
|
+
return Promise.resolve({
|
|
305
|
+
matched: true,
|
|
306
|
+
response: { status: 403, headers: {}, body: "Request blocked by CSRF protection." }
|
|
307
|
+
});
|
|
308
|
+
};
|
|
309
|
+
return {
|
|
310
|
+
...options,
|
|
311
|
+
routingInterceptors: [routingInterceptor, ...toArray(options.routingInterceptors)]
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
isAllowed({ request }) {
|
|
315
|
+
if (request.method !== "GET") {
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
const site = flattenStandardHeader(request.headers["sec-fetch-site"])?.toLowerCase();
|
|
319
|
+
if (site === void 0 || site === "same-origin" || site === "same-site") {
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
const mode = flattenStandardHeader(request.headers["sec-fetch-mode"])?.toLowerCase();
|
|
323
|
+
const dest = flattenStandardHeader(request.headers["sec-fetch-dest"])?.toLowerCase();
|
|
324
|
+
if (mode === void 0 || dest === void 0) {
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
327
|
+
return mode !== "navigate" || dest !== "document";
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
class MethodOverrideHandlerPlugin {
|
|
332
|
+
name = "~method-override";
|
|
333
|
+
/**
|
|
334
|
+
* Should override batch sub-request methods, not the original batch request.
|
|
335
|
+
*/
|
|
336
|
+
before = ["~batch"];
|
|
337
|
+
param;
|
|
338
|
+
methods;
|
|
339
|
+
constructor(options = {}) {
|
|
340
|
+
this.param = options.param ?? "method";
|
|
341
|
+
this.methods = new Set((options.methods ?? ["PUT", "PATCH", "DELETE"]).map((method) => method.toUpperCase()));
|
|
342
|
+
}
|
|
343
|
+
init(options) {
|
|
344
|
+
const routingInterceptor = async ({ next, ...interceptorOptions }) => {
|
|
345
|
+
const { request } = interceptorOptions;
|
|
346
|
+
if (request.method !== "POST") {
|
|
347
|
+
return next();
|
|
348
|
+
}
|
|
349
|
+
const [pathname, search, hash] = parseStandardUrl(request.url);
|
|
350
|
+
const params = new URLSearchParams(search);
|
|
351
|
+
const raw = params.getAll(this.param).at(-1);
|
|
352
|
+
if (raw === void 0) {
|
|
353
|
+
return next();
|
|
354
|
+
}
|
|
355
|
+
const method = raw.toUpperCase();
|
|
356
|
+
if (!this.methods.has(method)) {
|
|
357
|
+
return next();
|
|
358
|
+
}
|
|
359
|
+
params.delete(this.param);
|
|
360
|
+
const url = `${pathname}${params.size ? `?${params}` : ""}${hash ?? ""}`;
|
|
361
|
+
return next({
|
|
362
|
+
...interceptorOptions,
|
|
363
|
+
request: { ...request, method, url }
|
|
364
|
+
});
|
|
365
|
+
};
|
|
366
|
+
return {
|
|
367
|
+
...options,
|
|
368
|
+
routingInterceptors: [routingInterceptor, ...toArray(options.routingInterceptors)]
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
288
373
|
class RequestCompressionHandlerPlugin {
|
|
289
374
|
name = "~request-compression";
|
|
290
375
|
/**
|
|
@@ -395,13 +480,16 @@ class ResponseCompressionHandlerPlugin {
|
|
|
395
480
|
if (contentEncoding !== void 0) {
|
|
396
481
|
return result;
|
|
397
482
|
}
|
|
483
|
+
if (response.status === 206 || response.headers["content-range"] !== void 0) {
|
|
484
|
+
return result;
|
|
485
|
+
}
|
|
398
486
|
if (isNoTransformCacheControl(flattenStandardHeader(response.headers["cache-control"]))) {
|
|
399
487
|
return result;
|
|
400
488
|
}
|
|
401
|
-
const acceptEncodings =
|
|
489
|
+
const acceptEncodings = parseAcceptEncodingQualities(
|
|
402
490
|
flattenStandardHeader(interceptorOptions.request.headers["accept-encoding"])
|
|
403
491
|
);
|
|
404
|
-
const encoding = this.encodings.find((enc) => acceptEncodings.
|
|
492
|
+
const encoding = this.encodings.find((enc) => (acceptEncodings.get(enc) ?? 0) > 0);
|
|
405
493
|
if (encoding === void 0) {
|
|
406
494
|
return result;
|
|
407
495
|
}
|
|
@@ -419,7 +507,8 @@ class ResponseCompressionHandlerPlugin {
|
|
|
419
507
|
...headers,
|
|
420
508
|
"standard-server": "octet-stream",
|
|
421
509
|
"content-length": [],
|
|
422
|
-
"content-encoding": encoding
|
|
510
|
+
"content-encoding": encoding,
|
|
511
|
+
"vary": varyByAcceptEncoding(headers.vary)
|
|
423
512
|
}
|
|
424
513
|
}
|
|
425
514
|
};
|
|
@@ -440,7 +529,8 @@ class ResponseCompressionHandlerPlugin {
|
|
|
440
529
|
"content-type": body.type,
|
|
441
530
|
"content-length": [],
|
|
442
531
|
"content-disposition": contentDisposition,
|
|
443
|
-
"content-encoding": encoding
|
|
532
|
+
"content-encoding": encoding,
|
|
533
|
+
"vary": varyByAcceptEncoding(headers.vary)
|
|
444
534
|
}
|
|
445
535
|
}
|
|
446
536
|
};
|
|
@@ -477,7 +567,8 @@ class ResponseCompressionHandlerPlugin {
|
|
|
477
567
|
"standard-server": [],
|
|
478
568
|
"content-type": res.headers.get("content-type"),
|
|
479
569
|
"content-length": [],
|
|
480
|
-
"content-encoding": encoding
|
|
570
|
+
"content-encoding": encoding,
|
|
571
|
+
"vary": varyByAcceptEncoding(headers.vary)
|
|
481
572
|
}
|
|
482
573
|
}
|
|
483
574
|
};
|
|
@@ -495,7 +586,8 @@ class ResponseCompressionHandlerPlugin {
|
|
|
495
586
|
"standard-server": [],
|
|
496
587
|
"content-type": "application/x-www-form-urlencoded",
|
|
497
588
|
"content-length": [],
|
|
498
|
-
"content-encoding": encoding
|
|
589
|
+
"content-encoding": encoding,
|
|
590
|
+
"vary": varyByAcceptEncoding(headers.vary)
|
|
499
591
|
}
|
|
500
592
|
}
|
|
501
593
|
};
|
|
@@ -513,7 +605,8 @@ class ResponseCompressionHandlerPlugin {
|
|
|
513
605
|
"standard-server": [],
|
|
514
606
|
"content-type": "application/json",
|
|
515
607
|
"content-length": [],
|
|
516
|
-
"content-encoding": encoding
|
|
608
|
+
"content-encoding": encoding,
|
|
609
|
+
"vary": varyByAcceptEncoding(headers.vary)
|
|
517
610
|
}
|
|
518
611
|
}
|
|
519
612
|
};
|
|
@@ -530,11 +623,13 @@ class ResponseCompressionHandlerPlugin {
|
|
|
530
623
|
};
|
|
531
624
|
}
|
|
532
625
|
}
|
|
533
|
-
function
|
|
534
|
-
|
|
535
|
-
|
|
626
|
+
function varyByAcceptEncoding(vary) {
|
|
627
|
+
const current = flattenStandardHeader(vary);
|
|
628
|
+
if (current === void 0) {
|
|
629
|
+
return "accept-encoding";
|
|
536
630
|
}
|
|
537
|
-
|
|
631
|
+
const fields = current.split(",").map((field) => field.trim().toLowerCase());
|
|
632
|
+
return fields.includes("accept-encoding") || fields.includes("*") ? current : `${current}, accept-encoding`;
|
|
538
633
|
}
|
|
539
634
|
const CACHE_CONTROL_NO_TRANSFORM_REGEX = /(?:^|,)\s*no-transform\s*(?:,|$)/i;
|
|
540
635
|
function isNoTransformCacheControl(cacheControl) {
|
|
@@ -632,29 +727,4 @@ class RethrowHandlerPlugin {
|
|
|
632
727
|
}
|
|
633
728
|
}
|
|
634
729
|
|
|
635
|
-
|
|
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 };
|
|
730
|
+
export { BATCH_CONTENT_TYPE, BatchHandlerPlugin, CORSHandlerPlugin, CORSHandlerPlugin as CORSPlugin, GetMethodCsrfProtectionHandlerPlugin, MethodOverrideHandlerPlugin, RequestCompressionHandlerPlugin, RequestHeadersHandlerPlugin, RequestHeadersHandlerPlugin as RequestHeadersPlugin, ResponseCompressionHandlerPlugin, ResponseHeadersHandlerPlugin, ResponseHeadersHandlerPlugin as ResponseHeadersPlugin, RethrowHandlerPlugin };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { wrapAsyncIteratorPreservingEventMeta, ORPCError, cloneORPCError } from '@orpc/client';
|
|
2
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';
|
|
3
|
+
import { getConstructor, isTypescriptObject, resolveMaybeOptionalOptions, toArray, value, runWithSpan, intercept, isAsyncIteratorObject, override, traceAsyncIterator, traceReadableStream, isPlainObject, mergeTwoLevels } from '@orpc/shared';
|
|
4
4
|
|
|
5
5
|
class Lazy {
|
|
6
6
|
"~orpc";
|
|
@@ -127,7 +127,12 @@ async function executeProcedureInternal(procedure, options) {
|
|
|
127
127
|
const endInputIndex = midIndex === orderedMiddlewares.length ? inputSchemas.length : orderedMiddlewares[midIndex].inputSchemasLengthAtUse ?? 0;
|
|
128
128
|
if (!procedure["~orpc"].disableInputValidation) {
|
|
129
129
|
for (let i = startInputIndex; i < endInputIndex; i++) {
|
|
130
|
-
|
|
130
|
+
const validated = await validateInput(
|
|
131
|
+
i,
|
|
132
|
+
inputSchemas[i],
|
|
133
|
+
inputSchemas.length > 1 && isPlainObject(currentInput) ? options.input : currentInput
|
|
134
|
+
);
|
|
135
|
+
currentInput = i !== 0 ? mergeTwoLevels(currentInput, validated) : validated;
|
|
131
136
|
}
|
|
132
137
|
}
|
|
133
138
|
let currentOutput;
|
|
@@ -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.CkButhNT.mjs';
|
|
5
|
+
import { w as walkProcedureContractsSync, g as getRouter, c as createContractProcedure, D as DEFAULT_SUCCESS_STATUS, a as DEFAULT_ERROR_STATUS } from './server.Dh77P3ii.mjs';
|
|
6
6
|
|
|
7
7
|
class CompositeStandardHandlerPlugin {
|
|
8
8
|
name = "~composite";
|
|
@@ -1,4 +1,4 @@
|
|
|
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.CkButhNT.mjs';
|
|
2
2
|
import { resolveMetaPlugins, mergeErrorMap, ProcedureContract } from '@orpc/contract';
|
|
3
3
|
import { omit, isTypescriptObject } from '@orpc/shared';
|
|
4
4
|
|
|
@@ -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.CkButhNT.mjs';
|
|
3
3
|
|
|
4
4
|
class DecoratedProcedure extends Procedure {
|
|
5
5
|
meta(...plugins) {
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orpc/server",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.0.0-beta.
|
|
4
|
+
"version": "2.0.0-beta.27",
|
|
5
5
|
"license": "MIT",
|
|
6
|
+
"funding": "https://github.com/sponsors/dinwwwh",
|
|
6
7
|
"homepage": "https://orpc.dev",
|
|
7
8
|
"repository": {
|
|
8
9
|
"type": "git",
|
|
@@ -106,13 +107,13 @@
|
|
|
106
107
|
"@standardserver/node": "^0.7.1",
|
|
107
108
|
"@standardserver/peer": "^0.7.1",
|
|
108
109
|
"cookie": "^2.0.1",
|
|
109
|
-
"@orpc/client": "2.0.0-beta.
|
|
110
|
-
"@orpc/contract": "2.0.0-beta.
|
|
111
|
-
"@orpc/shared": "2.0.0-beta.
|
|
110
|
+
"@orpc/client": "2.0.0-beta.27",
|
|
111
|
+
"@orpc/contract": "2.0.0-beta.27",
|
|
112
|
+
"@orpc/shared": "2.0.0-beta.27"
|
|
112
113
|
},
|
|
113
114
|
"devDependencies": {
|
|
114
115
|
"crossws": "^0.4.6",
|
|
115
|
-
"fastify": "^5.11.
|
|
116
|
+
"fastify": "^5.11.3",
|
|
116
117
|
"supertest": "^7.2.2",
|
|
117
118
|
"zod": "^4.4.3"
|
|
118
119
|
},
|