@bepalo/spine 2.6.18 → 2.7.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/generator.d.ts.map +1 -1
- package/dist/cjs/generator.js +1 -1
- package/dist/cjs/generator.js.map +1 -1
- package/dist/cjs/middlewares.d.ts +167 -21
- package/dist/cjs/middlewares.d.ts.map +1 -1
- package/dist/cjs/middlewares.js +578 -28
- package/dist/cjs/middlewares.js.map +1 -1
- package/dist/cjs/parsers.d.ts +32 -10
- package/dist/cjs/parsers.d.ts.map +1 -1
- package/dist/cjs/parsers.js +83 -46
- package/dist/cjs/parsers.js.map +1 -1
- package/dist/cjs/router.d.ts.map +1 -1
- package/dist/cjs/router.js +1 -1
- package/dist/cjs/router.js.map +1 -1
- package/dist/cjs/utils.d.ts +1 -0
- package/dist/cjs/utils.d.ts.map +1 -1
- package/dist/cjs/utils.js.map +1 -1
- package/dist/cjs/utils.node.d.ts +1 -1
- package/dist/cjs/utils.node.d.ts.map +1 -1
- package/dist/cjs/utils.node.js +30 -7
- package/dist/cjs/utils.node.js.map +1 -1
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +1 -1
- package/dist/generator.js.map +1 -1
- package/dist/middlewares.d.ts +167 -21
- package/dist/middlewares.d.ts.map +1 -1
- package/dist/middlewares.js +578 -28
- package/dist/middlewares.js.map +1 -1
- package/dist/parsers.d.ts +32 -10
- package/dist/parsers.d.ts.map +1 -1
- package/dist/parsers.js +83 -46
- package/dist/parsers.js.map +1 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +1 -1
- package/dist/router.js.map +1 -1
- package/dist/utils.d.ts +1 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js.map +1 -1
- package/dist/utils.node.d.ts +1 -1
- package/dist/utils.node.d.ts.map +1 -1
- package/dist/utils.node.js +30 -7
- package/dist/utils.node.js.map +1 -1
- package/package.json +6 -2
package/dist/cjs/middlewares.js
CHANGED
|
@@ -10,8 +10,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
});
|
|
11
11
|
};
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.cors = exports.limitRate = exports.securityHeaders = exports.forceHttps = void 0;
|
|
13
|
+
exports.validate = exports.cors = exports.limitRate = exports.securityHeaders = exports.forceHttps = void 0;
|
|
14
14
|
const helpers_ts_1 = require("./helpers.js");
|
|
15
|
+
const parsers_ts_1 = require("./parsers.js");
|
|
16
|
+
const status_ts_1 = require("./status.js");
|
|
15
17
|
const types_ts_1 = require("./types.js");
|
|
16
18
|
/**
|
|
17
19
|
* Force http into https
|
|
@@ -113,16 +115,17 @@ exports.securityHeaders = securityHeaders;
|
|
|
113
115
|
* Creates a rate limiting middleware using token bucket algorithm.
|
|
114
116
|
* Supports both fixed interval refill and continuous rate-based refill.
|
|
115
117
|
*
|
|
116
|
-
* @template {Record<string, unknown>} ExtendContext
|
|
117
|
-
* @
|
|
118
|
-
* @
|
|
119
|
-
* @
|
|
120
|
-
* @
|
|
121
|
-
* @
|
|
122
|
-
* @
|
|
123
|
-
* @
|
|
124
|
-
* @
|
|
125
|
-
* @
|
|
118
|
+
* @template {Record<string, unknown>} ExtendContext Extend Router Context
|
|
119
|
+
* @property {Object} config Rate limiting configuration
|
|
120
|
+
* @property {Function} [config.key] Function to generate cache key from request and context
|
|
121
|
+
* @property {number} [config.maxTokens] Maximum number of tokens in the bucket
|
|
122
|
+
* @property {number} [config.refillInterval] Fixed interval in seconds for token refill
|
|
123
|
+
* @property {number} [config.refillRate] Continuous refill rate in tokens per second
|
|
124
|
+
* @property {number} [config.cleanUpInterval] Interval in seconds for cleanup timer
|
|
125
|
+
* @property {number} [config.cleanUpIdleDelay] Time in seconds to delay cleanup of filled token buckets
|
|
126
|
+
* @property {boolean} [config.setXRateLimitHeaders=false] Whether to set X-RateLimit headers in response
|
|
127
|
+
* @property {boolean} [config.breakPipeline=false] If true, returns Break_Pipeline
|
|
128
|
+
* @property {"status"|"text"|"json"} [config.responseType="text"] Response type
|
|
126
129
|
* @returns {Handler<ExtendContext>} Middleware function that enforces rate limits
|
|
127
130
|
*
|
|
128
131
|
* @example
|
|
@@ -147,7 +150,12 @@ exports.securityHeaders = securityHeaders;
|
|
|
147
150
|
*/
|
|
148
151
|
const limitRate = (config) => {
|
|
149
152
|
var _a;
|
|
150
|
-
const { key, maxTokens, refillInterval, refillRate, cleanUpInterval, setXRateLimitHeaders = false, breakPipeline = false, } = config;
|
|
153
|
+
const { key, maxTokens, refillInterval, refillRate, cleanUpInterval, setXRateLimitHeaders = false, breakPipeline = false, responseType = "text", } = config;
|
|
154
|
+
const respond = responseType === "json"
|
|
155
|
+
? (code, content, key, tag, init) => (0, helpers_ts_1.json)({ [key]: `${tag}: ${content}`, tag }, Object.assign(Object.assign({}, init), { status: code }))
|
|
156
|
+
: responseType === "text"
|
|
157
|
+
? (code, content, key, tag, init) => (0, helpers_ts_1.text)(`[${key}] ${tag}: ${content}`, Object.assign(Object.assign({}, init), { status: code }))
|
|
158
|
+
: (code, _content, _key, _tag, init) => (0, helpers_ts_1.status)(code, null, init);
|
|
151
159
|
const cleanUpIdleDelay = -((_a = config.cleanUpIdleDelay) !== null && _a !== void 0 ? _a : 0);
|
|
152
160
|
const rateLimits = new Map();
|
|
153
161
|
const now = () => performance.now() / 1000;
|
|
@@ -215,7 +223,7 @@ const limitRate = (config) => {
|
|
|
215
223
|
}
|
|
216
224
|
if (entry.tokens <= 0) {
|
|
217
225
|
ctx.headers.set("Retry-After", Math.ceil(refillInterval - timeElapsed).toFixed());
|
|
218
|
-
return (
|
|
226
|
+
return respond(status_ts_1.Status._429_TooManyRequests, "Rate Limited", "message", "rate-limit");
|
|
219
227
|
}
|
|
220
228
|
else {
|
|
221
229
|
entry.tokens--;
|
|
@@ -241,7 +249,7 @@ const limitRate = (config) => {
|
|
|
241
249
|
entry.lastRefill = now();
|
|
242
250
|
if (entry.tokens <= 0) {
|
|
243
251
|
ctx.headers.set("Retry-After", Math.ceil(1 / refillRate).toFixed());
|
|
244
|
-
return (
|
|
252
|
+
return respond(status_ts_1.Status._429_TooManyRequests, "Rate Limited", "message", "rate-limit");
|
|
245
253
|
}
|
|
246
254
|
else {
|
|
247
255
|
entry.tokens--;
|
|
@@ -263,16 +271,17 @@ exports.limitRate = limitRate;
|
|
|
263
271
|
* Creates a CORS (Cross-Origin Resource Sharing) middleware.
|
|
264
272
|
* Supports preflight requests and configurable CORS headers.
|
|
265
273
|
*
|
|
266
|
-
* @template {Record<string, unknown>} ExtendContext
|
|
267
|
-
* @param {Object} [config]
|
|
268
|
-
* @param {string|string[]|"*"} [config.origins="*"]
|
|
269
|
-
* @param {(HttpMethod|HttpMethodUpper|HttpMethodLower)[]} [config.methods=["Get","Head","Put","Patch","Post","Delete"]]
|
|
270
|
-
* @param {string[]} [config.allowedHeaders=["Content-Type","Authorization"]]
|
|
271
|
-
* @param {string[]} [config.exposedHeaders]
|
|
272
|
-
* @param {boolean} [config.credentials=false]
|
|
273
|
-
* @param {number} [config.maxAge=86400]
|
|
274
|
-
* @param {boolean} [config.varyOrigin=true]
|
|
275
|
-
* @param {boolean} [config.breakPipeline=false]
|
|
274
|
+
* @template {Record<string, unknown>} ExtendContext Extend Router Context
|
|
275
|
+
* @param {Object} [config] CORS configuration
|
|
276
|
+
* @param {string|string[]|"*"} [config.origins="*"] Allowed origins (wildcard "*", single origin, or array)
|
|
277
|
+
* @param {(HttpMethod|HttpMethodUpper|HttpMethodLower)[]} [config.methods=["Get","Head","Put","Patch","Post","Delete"]] Allowed HTTP methods
|
|
278
|
+
* @param {string[]} [config.allowedHeaders=["Content-Type","Authorization"]] Allowed request headers
|
|
279
|
+
* @param {string[]} [config.exposedHeaders] Headers exposed to the browser
|
|
280
|
+
* @param {boolean} [config.credentials=false] Allow credentials (cookies, authorization headers)
|
|
281
|
+
* @param {number} [config.maxAge=86400] Maximum age for preflight cache in seconds
|
|
282
|
+
* @param {boolean} [config.varyOrigin=true] Add Vary: Origin header for caching
|
|
283
|
+
* @param {boolean} [config.breakPipeline=false] If true, returns Break_Pipeline
|
|
284
|
+
* @param {"status"|"text"|"json"} [config.responseType="text"] Response type
|
|
276
285
|
* @returns {Handler<ExtendContext>} Middleware function that handles CORS headers
|
|
277
286
|
*
|
|
278
287
|
* @throws {HttpError} If credentials is enabled with wildcard origin ("*")
|
|
@@ -292,7 +301,12 @@ exports.limitRate = limitRate;
|
|
|
292
301
|
*
|
|
293
302
|
*/
|
|
294
303
|
const cors = (config) => {
|
|
295
|
-
const { origins = "*", methods: methods_ = ["Get", "Head", "Put", "Patch", "Post", "Delete"], allowedHeaders = ["Content-Type", "Authorization"], exposedHeaders, credentials = false, maxAge = 86400, varyOrigin = true, breakPipeline = false, } = config !== null && config !== void 0 ? config : {};
|
|
304
|
+
const { origins = "*", methods: methods_ = ["Get", "Head", "Put", "Patch", "Post", "Delete"], allowedHeaders = ["Content-Type", "Authorization"], exposedHeaders, credentials = false, maxAge = 86400, varyOrigin = true, breakPipeline = false, responseType = "text", } = config !== null && config !== void 0 ? config : {};
|
|
305
|
+
const respond = responseType === "json"
|
|
306
|
+
? (code, content, key, tag, init) => (0, helpers_ts_1.json)({ [key]: `${tag}: ${content}`, tag }, Object.assign(Object.assign({}, init), { status: code }))
|
|
307
|
+
: responseType === "text"
|
|
308
|
+
? (code, content, key, tag, init) => (0, helpers_ts_1.text)(`[${key}] ${tag}: ${content}`, Object.assign(Object.assign({}, init), { status: code }))
|
|
309
|
+
: (code, _content, _key, _tag, init) => (0, helpers_ts_1.status)(code, null, init);
|
|
296
310
|
const globOrigin = origins === "*" ? "*" : null;
|
|
297
311
|
const originsSet = new Set(origins === "*" ? [] : typeof origins === "string" ? [origins] : origins);
|
|
298
312
|
const methods = methods_ === null || methods_ === void 0 ? void 0 : methods_.map((m) => m.toUpperCase());
|
|
@@ -324,7 +338,7 @@ const cors = (config) => {
|
|
|
324
338
|
headers.set("Access-Control-Allow-Origin", corsOrigin);
|
|
325
339
|
if (credentials) {
|
|
326
340
|
if (corsOrigin === "*")
|
|
327
|
-
throw new types_ts_1.HttpError(
|
|
341
|
+
throw new types_ts_1.HttpError(status_ts_1.Status._403_Forbidden, "CORS: Cannot use credentials with wildcard origin");
|
|
328
342
|
headers.set("Access-Control-Allow-Credentials", "true");
|
|
329
343
|
}
|
|
330
344
|
if (exposedHeaders && exposedHeaders.length > 0) {
|
|
@@ -338,7 +352,7 @@ const cors = (config) => {
|
|
|
338
352
|
const requestMethod = request.headers.get("Access-Control-Request-Method");
|
|
339
353
|
if (requestMethod &&
|
|
340
354
|
!methods.includes(requestMethod)) {
|
|
341
|
-
return (
|
|
355
|
+
return respond(status_ts_1.Status._405_MethodNotAllowed, `Method ${requestMethod} not allowed`, "error", "CORS");
|
|
342
356
|
}
|
|
343
357
|
headers.set("Access-Control-Allow-Methods", methods.join(", "));
|
|
344
358
|
}
|
|
@@ -348,7 +362,7 @@ const cors = (config) => {
|
|
|
348
362
|
if (maxAge != null) {
|
|
349
363
|
headers.set("Access-Control-Max-Age", maxAge.toString());
|
|
350
364
|
}
|
|
351
|
-
return (0, helpers_ts_1.status)(
|
|
365
|
+
return (0, helpers_ts_1.status)(status_ts_1.Status._204_NoContent, null);
|
|
352
366
|
}
|
|
353
367
|
if (breakPipeline) {
|
|
354
368
|
return types_ts_1.Break_Pipeline;
|
|
@@ -356,4 +370,540 @@ const cors = (config) => {
|
|
|
356
370
|
};
|
|
357
371
|
};
|
|
358
372
|
exports.cors = cors;
|
|
373
|
+
/**
|
|
374
|
+
* Creates a request params, query and body validator middleware function
|
|
375
|
+
*
|
|
376
|
+
* @param {Validator<Record<string, string>,ExtendContext>} [config.params] Parameters validator
|
|
377
|
+
* @param {CustomErrorType} [config.paramsErrors] Parameters validator's expected error instance types other than Error derivatives
|
|
378
|
+
* @param {boolean|ValidateQueryParser<ExtendContext>} [config.queryParse] Parse query before validation. 'true' for default parser or provide a custom parser
|
|
379
|
+
* @param {Validator<Record<string, string>,ExtendContext>} [config.query] Query validator
|
|
380
|
+
* @param {CustomErrorType} [config.queryErrors] Query validator's expected error instance types other than Error derivatives
|
|
381
|
+
* @param {boolean|ValidateCookieParser<ExtendContext>} [config.cookieParse] Parse cookie before validation. 'true' for default parser or provide a custom parser
|
|
382
|
+
* @param {Validator<Record<string, string>,ExtendContext>} [config.cookie] Cookie validator
|
|
383
|
+
* @param {CustomErrorType} [config.cookieErrors] Cookie validator's expected error instance types other than Error derivatives
|
|
384
|
+
* @param {ParseBodyOptions} [config.bodyParseOptions] Body parser options
|
|
385
|
+
* @param {boolean|ValidateBodyParser<ExtendContext>} [config.bodyParse] Parse body before validation. 'true' for default parser or provide a custom parser
|
|
386
|
+
* @param {ValidatorFnIt<ParsedBody,ExtendContext>|Array<ValidatorIt<ParsedBody,ExtendContext>>} [config.body] Body validator
|
|
387
|
+
* @param {CustomErrorType} [config.bodyErrors] Body validator's expected error instance types other than Error derivatives
|
|
388
|
+
* @param {Array<CustomErrorType>} [config.errors] All validator's expected error instance types other than Error derivatives. Can be overridden.
|
|
389
|
+
* @param {boolean} [config.paramsReassign] Reassign validated return value of the params validator function
|
|
390
|
+
* @param {boolean} [config.queryReassign] Reassign validated return value of the query validator function
|
|
391
|
+
* @param {boolean} [config.cookieReassign] Reassign validated return value of the cookie validator function
|
|
392
|
+
* @param {boolean} [config.bodyReassign] Reassign validated return value of the body validator function
|
|
393
|
+
* @param {boolean|{<Target extends Record<string, unknown>>(target: Target,key: string,):void|any;}} [config.strangeParams] Handle strange or unexpected properties
|
|
394
|
+
* @param {boolean|{<Target extends Record<string, unknown>>(target: Target,key: string,):void|any;}} [config.strangeQuery] Handle strange or unexpected properties
|
|
395
|
+
* @param {boolean|{<Target extends Record<string, unknown>>(target: Target,key: string,):void|any;}} [config.strangeCookie] Handle strange or unexpected properties
|
|
396
|
+
* @param {boolean|{<Target extends Record<string, unknown>>(target: Target,key: string,):void|any;}} [config.strangeBody] Handle strange or unexpected properties
|
|
397
|
+
* @param {boolean|{<Target extends Record<string, unknown>>(target: Target,key: string,):void|any;}} [config.strange] A default common option to handle strange or unexpected properties
|
|
398
|
+
* @param {"status"|"text"|"json"} [config.responseType="text"] Response type.
|
|
399
|
+
* - Note: 'status' type will omit content
|
|
400
|
+
* @param {boolean} [config.breakPipeline=false] If true, returns Break_Pipeline
|
|
401
|
+
* @returns {HandlerReturn}
|
|
402
|
+
*/
|
|
403
|
+
const validate = ({ responseType = "text", errors, paramsReassign = false, params: paramsValidator, paramsErrors, strangeParams, queryParse, queryReassign = false, query: queryValidator, queryErrors, strangeQuery, cookieParse, cookieReassign = false, cookie: cookieValidator, cookieErrors, strangeCookie, bodyParse, bodyParseOptions, bodyReassign = false, body: bodyValidator, bodyErrors, strangeBody, strange, breakPipeline = false, }) => {
|
|
404
|
+
paramsErrors = paramsErrors !== null && paramsErrors !== void 0 ? paramsErrors : errors;
|
|
405
|
+
queryErrors = queryErrors !== null && queryErrors !== void 0 ? queryErrors : errors;
|
|
406
|
+
cookieErrors = cookieErrors !== null && cookieErrors !== void 0 ? cookieErrors : errors;
|
|
407
|
+
bodyErrors = bodyErrors !== null && bodyErrors !== void 0 ? bodyErrors : errors;
|
|
408
|
+
const errorMatches = (target, errors) => {
|
|
409
|
+
for (const error of errors) {
|
|
410
|
+
if (target instanceof error) {
|
|
411
|
+
return true;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return false;
|
|
415
|
+
};
|
|
416
|
+
// Validate error instance types
|
|
417
|
+
if (errors) {
|
|
418
|
+
for (let i = 0; i < errors.length; i++) {
|
|
419
|
+
const error = errors[i];
|
|
420
|
+
if (!(typeof error === "function")) {
|
|
421
|
+
throw new TypeError(`Validator errors type at index ${i} is invalid`);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
if (paramsErrors) {
|
|
426
|
+
for (let i = 0; i < paramsErrors.length; i++) {
|
|
427
|
+
const error = paramsErrors[i];
|
|
428
|
+
if (!(typeof error === "function")) {
|
|
429
|
+
throw new TypeError(`Validator paramsErrors type at index ${i} is invalid`);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
if (queryErrors) {
|
|
434
|
+
for (let i = 0; i < queryErrors.length; i++) {
|
|
435
|
+
const error = queryErrors[i];
|
|
436
|
+
if (!(typeof error === "function")) {
|
|
437
|
+
throw new TypeError(`Validator queryErrors type at index ${i} is invalid`);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
if (cookieErrors) {
|
|
442
|
+
for (let i = 0; i < cookieErrors.length; i++) {
|
|
443
|
+
const error = cookieErrors[i];
|
|
444
|
+
if (!(typeof error === "function")) {
|
|
445
|
+
throw new TypeError(`Validator cookieErrors type at index ${i} is invalid`);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
if (bodyErrors) {
|
|
450
|
+
for (let i = 0; i < bodyErrors.length; i++) {
|
|
451
|
+
const error = bodyErrors[i];
|
|
452
|
+
if (!(typeof error === "function")) {
|
|
453
|
+
throw new TypeError(`Validator bodyErrors type at index ${i} is invalid`);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
//
|
|
458
|
+
strangeParams = strangeParams !== null && strangeParams !== void 0 ? strangeParams : strange;
|
|
459
|
+
strangeQuery = strangeQuery !== null && strangeQuery !== void 0 ? strangeQuery : strange;
|
|
460
|
+
strangeCookie = strangeCookie !== null && strangeCookie !== void 0 ? strangeCookie : strange;
|
|
461
|
+
strangeBody = strangeBody !== null && strangeBody !== void 0 ? strangeBody : strange;
|
|
462
|
+
// Validate strangeParams
|
|
463
|
+
if (strangeParams != undefined &&
|
|
464
|
+
typeof strangeParams !== "boolean" &&
|
|
465
|
+
typeof strangeParams !== "function") {
|
|
466
|
+
throw new TypeError("Validator strangeParams type must be either boolean, undefined or a function");
|
|
467
|
+
}
|
|
468
|
+
// Validate strangeQuery
|
|
469
|
+
if (strangeQuery != undefined &&
|
|
470
|
+
typeof strangeQuery !== "boolean" &&
|
|
471
|
+
typeof strangeQuery !== "function") {
|
|
472
|
+
throw new TypeError("Validator strangeQuery type must be either boolean, undefined or a function");
|
|
473
|
+
}
|
|
474
|
+
// Validate strangeCookie
|
|
475
|
+
if (strangeCookie != undefined &&
|
|
476
|
+
typeof strangeCookie !== "boolean" &&
|
|
477
|
+
typeof strangeCookie !== "function") {
|
|
478
|
+
throw new TypeError("Validator strangeCookie type must be either boolean, undefined or a function");
|
|
479
|
+
}
|
|
480
|
+
// Validate strangeBody
|
|
481
|
+
if (strangeBody != undefined &&
|
|
482
|
+
typeof strangeBody !== "boolean" &&
|
|
483
|
+
typeof strangeBody !== "function") {
|
|
484
|
+
throw new TypeError("Validator strangeBody type must be either boolean, undefined or a function");
|
|
485
|
+
}
|
|
486
|
+
// Validate query parser
|
|
487
|
+
if (queryParse != undefined &&
|
|
488
|
+
typeof queryParse !== "boolean" &&
|
|
489
|
+
typeof queryParse !== "function") {
|
|
490
|
+
throw new TypeError("Validator queryParse type must be either boolean, undefined or a function");
|
|
491
|
+
}
|
|
492
|
+
// Validate cookie parser
|
|
493
|
+
if (cookieParse != undefined &&
|
|
494
|
+
typeof cookieParse !== "boolean" &&
|
|
495
|
+
typeof cookieParse !== "function") {
|
|
496
|
+
throw new TypeError("Validator cookieParse type must be either boolean, undefined or a function");
|
|
497
|
+
}
|
|
498
|
+
// Validate body parser
|
|
499
|
+
if (parsers_ts_1.parseBody != undefined &&
|
|
500
|
+
typeof parsers_ts_1.parseBody !== "boolean" &&
|
|
501
|
+
typeof parsers_ts_1.parseBody !== "function") {
|
|
502
|
+
throw new TypeError("Validator parseBody type must be either boolean, undefined or a function");
|
|
503
|
+
}
|
|
504
|
+
const respond = responseType === "json"
|
|
505
|
+
? (code, content, key, tag, init) => (0, helpers_ts_1.json)({ [key]: `${tag}: ${content}`, tag }, Object.assign(Object.assign({}, init), { status: code }))
|
|
506
|
+
: responseType === "text"
|
|
507
|
+
? (code, content, key, tag, init) => (0, helpers_ts_1.text)(`[${key}] ${tag}: ${content}`, Object.assign(Object.assign({}, init), { status: code }))
|
|
508
|
+
: (code, _content, _key, _tag, init) => (0, helpers_ts_1.status)(code, null, init);
|
|
509
|
+
//
|
|
510
|
+
// Prepare parsers
|
|
511
|
+
//
|
|
512
|
+
const queryParser = queryParse === true
|
|
513
|
+
? ((ctx) => {
|
|
514
|
+
if (ctx.query == null) {
|
|
515
|
+
ctx.query = {};
|
|
516
|
+
}
|
|
517
|
+
const searchParams = ctx.url.searchParams;
|
|
518
|
+
for (const key of searchParams.keys()) {
|
|
519
|
+
const values = searchParams.getAll(key);
|
|
520
|
+
ctx.query[key] =
|
|
521
|
+
values.length > 1 ? values[values.length - 1] : values[0];
|
|
522
|
+
}
|
|
523
|
+
})
|
|
524
|
+
: queryParse || undefined;
|
|
525
|
+
const cookieParser = cookieParse === true
|
|
526
|
+
? ((ctx) => {
|
|
527
|
+
if (ctx.cookie == null) {
|
|
528
|
+
ctx.cookie = {};
|
|
529
|
+
}
|
|
530
|
+
(0, parsers_ts_1.parseCookieFromRequest)(ctx.request, ctx.cookie);
|
|
531
|
+
})
|
|
532
|
+
: cookieParse || undefined;
|
|
533
|
+
const bodyParser = bodyParse === true
|
|
534
|
+
? (0, parsers_ts_1.parseBody)(bodyParseOptions)
|
|
535
|
+
: bodyParse || undefined;
|
|
536
|
+
///////////////////////////////////////////////////////////////////////////
|
|
537
|
+
// Validate params validators
|
|
538
|
+
const paramsValidatorIsFunction = typeof paramsValidator === "function";
|
|
539
|
+
const paramsValidatorIsObject = typeof paramsValidator === "object" && !Array.isArray(paramsValidator);
|
|
540
|
+
if (paramsValidator) {
|
|
541
|
+
if (!paramsValidatorIsFunction && !paramsValidatorIsObject) {
|
|
542
|
+
throw new TypeError("Params validator type must be function or object");
|
|
543
|
+
}
|
|
544
|
+
else if (paramsValidatorIsObject) {
|
|
545
|
+
for (const key of Object.keys(paramsValidator)) {
|
|
546
|
+
if (typeof paramsValidator[key] !== "function") {
|
|
547
|
+
throw new TypeError(`Params validator property type must be function at '${key}'`);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
// Validate query validators
|
|
553
|
+
const queryValidatorIsFunction = typeof queryValidator === "function";
|
|
554
|
+
const queryValidatorIsObject = typeof queryValidator === "object" && !Array.isArray(queryValidator);
|
|
555
|
+
if (queryValidator) {
|
|
556
|
+
if (!queryValidatorIsFunction && !queryValidatorIsObject) {
|
|
557
|
+
throw new TypeError("Query validator type must be function or object");
|
|
558
|
+
}
|
|
559
|
+
else if (queryValidatorIsObject) {
|
|
560
|
+
for (const key of Object.keys(queryValidator)) {
|
|
561
|
+
if (typeof queryValidator[key] !== "function") {
|
|
562
|
+
throw new TypeError(`Query validator property type must be function at '${key}'`);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
// Validate cookie validators
|
|
568
|
+
const cookieValidatorIsFunction = typeof cookieValidator === "function";
|
|
569
|
+
const cookieValidatorIsObject = typeof cookieValidator === "object" && !Array.isArray(cookieValidator);
|
|
570
|
+
if (cookieValidator) {
|
|
571
|
+
if (!cookieValidatorIsFunction && !cookieValidatorIsObject) {
|
|
572
|
+
throw new TypeError("Cookie validator type must be function or object");
|
|
573
|
+
}
|
|
574
|
+
else if (cookieValidatorIsObject) {
|
|
575
|
+
for (const key of Object.keys(cookieValidator)) {
|
|
576
|
+
if (typeof cookieValidator[key] !== "function") {
|
|
577
|
+
throw new TypeError(`Cookie validator property type must be function at '${key}'`);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
// Validate body validators
|
|
583
|
+
const bodyValidatorIsFunction = typeof bodyValidator === "function";
|
|
584
|
+
const bodyValidatorIsArray = Array.isArray(bodyValidator);
|
|
585
|
+
const bodyValidatorIsObject = typeof bodyValidator === "object" && !bodyValidatorIsArray;
|
|
586
|
+
const bodyValidators = bodyValidator
|
|
587
|
+
? Array.isArray(bodyValidator)
|
|
588
|
+
? bodyValidator
|
|
589
|
+
: [bodyValidator]
|
|
590
|
+
: undefined;
|
|
591
|
+
if (bodyValidators) {
|
|
592
|
+
if (!bodyValidatorIsFunction &&
|
|
593
|
+
!bodyValidatorIsObject &&
|
|
594
|
+
!bodyValidatorIsArray) {
|
|
595
|
+
throw new TypeError("Body validator type must be function or object or array of objects");
|
|
596
|
+
}
|
|
597
|
+
else if (bodyValidatorIsArray && bodyValidators.length === 0) {
|
|
598
|
+
throw new TypeError("Body validator must not be an empty array");
|
|
599
|
+
}
|
|
600
|
+
for (let i = 0; i < bodyValidators.length; i++) {
|
|
601
|
+
const validator = bodyValidators[i];
|
|
602
|
+
const bodyValidatorIsFunction = typeof validator === "function";
|
|
603
|
+
const validatorIsObject = typeof validator === "object" && !Array.isArray(validator);
|
|
604
|
+
if (!bodyValidatorIsFunction && !validatorIsObject) {
|
|
605
|
+
throw new TypeError(bodyValidators.length > 0
|
|
606
|
+
? `Body validator must be a valid function or object at ${i}`
|
|
607
|
+
: "Body validator must be a valid function or object");
|
|
608
|
+
}
|
|
609
|
+
else if (validatorIsObject) {
|
|
610
|
+
for (const key of Object.keys(validator)) {
|
|
611
|
+
if (typeof validator[key] !== "function") {
|
|
612
|
+
throw new TypeError(bodyValidatorIsArray
|
|
613
|
+
? `Body validator property type must be function at index ${i} '${key}'`
|
|
614
|
+
: `Body validator property type must be function at '${key}'`);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
////////////////////////////////////////////////////////////////////////
|
|
621
|
+
return (ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
622
|
+
const params = ctx.params;
|
|
623
|
+
// Validate Params
|
|
624
|
+
if (paramsValidatorIsFunction) {
|
|
625
|
+
const result = paramsValidator.apply
|
|
626
|
+
? paramsValidator.apply(ctx, params)
|
|
627
|
+
: paramsValidator(params);
|
|
628
|
+
if (result instanceof Error) {
|
|
629
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, result.message, "params", "error");
|
|
630
|
+
}
|
|
631
|
+
else if (paramsErrors && errorMatches(result, paramsErrors)) {
|
|
632
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, String(result), "error", "params");
|
|
633
|
+
}
|
|
634
|
+
else if (result instanceof Response ||
|
|
635
|
+
result === types_ts_1.Break_Pipe ||
|
|
636
|
+
result === types_ts_1.Break_Pipeline) {
|
|
637
|
+
return result;
|
|
638
|
+
}
|
|
639
|
+
else if (paramsReassign) {
|
|
640
|
+
ctx.params = result;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
else if (paramsValidatorIsObject) {
|
|
644
|
+
for (const key of Object.keys(params)) {
|
|
645
|
+
const validator = paramsValidator[key];
|
|
646
|
+
if (validator == null && !strangeParams) {
|
|
647
|
+
continue;
|
|
648
|
+
}
|
|
649
|
+
const result = validator == null
|
|
650
|
+
? typeof strangeParams === "function"
|
|
651
|
+
? strangeParams(params, key)
|
|
652
|
+
: params[key]
|
|
653
|
+
: validator.apply
|
|
654
|
+
? validator.apply(ctx, params[key])
|
|
655
|
+
: validator(params[key]);
|
|
656
|
+
if (result instanceof Error) {
|
|
657
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, result.message, "error", "params");
|
|
658
|
+
}
|
|
659
|
+
else if (paramsErrors && errorMatches(result, paramsErrors)) {
|
|
660
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, String(result), "error", "params");
|
|
661
|
+
}
|
|
662
|
+
else if (result instanceof Response ||
|
|
663
|
+
result === types_ts_1.Break_Pipe ||
|
|
664
|
+
result === types_ts_1.Break_Pipeline) {
|
|
665
|
+
return result;
|
|
666
|
+
}
|
|
667
|
+
else if (paramsReassign) {
|
|
668
|
+
params[key] = result;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
// Parse query
|
|
673
|
+
if (queryParser) {
|
|
674
|
+
yield queryParser(ctx);
|
|
675
|
+
}
|
|
676
|
+
const query = ctx.query;
|
|
677
|
+
// Validate Query
|
|
678
|
+
if (queryValidatorIsFunction) {
|
|
679
|
+
const result = queryValidator.apply
|
|
680
|
+
? queryValidator.apply(ctx, query)
|
|
681
|
+
: queryValidator(query);
|
|
682
|
+
if (result instanceof Error) {
|
|
683
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, result.message, "error", "query");
|
|
684
|
+
}
|
|
685
|
+
else if (queryErrors && errorMatches(result, queryErrors)) {
|
|
686
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, String(result), "error", "query");
|
|
687
|
+
}
|
|
688
|
+
else if (result instanceof Response ||
|
|
689
|
+
result === types_ts_1.Break_Pipe ||
|
|
690
|
+
result === types_ts_1.Break_Pipeline) {
|
|
691
|
+
return result;
|
|
692
|
+
}
|
|
693
|
+
else if (queryReassign) {
|
|
694
|
+
ctx.query = result;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
else if (queryValidatorIsObject) {
|
|
698
|
+
for (const key of Object.keys(query)) {
|
|
699
|
+
const validator = queryValidator[key];
|
|
700
|
+
if (validator == null && !strangeQuery) {
|
|
701
|
+
continue;
|
|
702
|
+
}
|
|
703
|
+
const result = validator == null
|
|
704
|
+
? typeof strangeQuery === "function"
|
|
705
|
+
? strangeQuery(query, key)
|
|
706
|
+
: query[key]
|
|
707
|
+
: validator.apply
|
|
708
|
+
? validator.apply(ctx, query[key])
|
|
709
|
+
: validator(query[key]);
|
|
710
|
+
if (result instanceof Error) {
|
|
711
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, result.message, "error", "query");
|
|
712
|
+
}
|
|
713
|
+
else if (queryErrors && errorMatches(result, queryErrors)) {
|
|
714
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, String(result), "error", "query");
|
|
715
|
+
}
|
|
716
|
+
else if (result instanceof Response ||
|
|
717
|
+
result === types_ts_1.Break_Pipe ||
|
|
718
|
+
result === types_ts_1.Break_Pipeline) {
|
|
719
|
+
return result;
|
|
720
|
+
}
|
|
721
|
+
else if (queryReassign) {
|
|
722
|
+
query[key] = result;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
// Parse cookie
|
|
727
|
+
if (cookieParser) {
|
|
728
|
+
yield cookieParser(ctx);
|
|
729
|
+
}
|
|
730
|
+
const cookie = ctx.cookie;
|
|
731
|
+
// Validate Cookie
|
|
732
|
+
if (cookieValidatorIsFunction) {
|
|
733
|
+
const result = cookieValidator.apply
|
|
734
|
+
? cookieValidator.apply(ctx, cookie)
|
|
735
|
+
: cookieValidator(cookie);
|
|
736
|
+
if (result instanceof Error) {
|
|
737
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, result.message, "error", "cookie");
|
|
738
|
+
}
|
|
739
|
+
else if (cookieErrors && errorMatches(result, cookieErrors)) {
|
|
740
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, String(result), "error", "cookie");
|
|
741
|
+
}
|
|
742
|
+
else if (result instanceof Response ||
|
|
743
|
+
result === types_ts_1.Break_Pipe ||
|
|
744
|
+
result === types_ts_1.Break_Pipeline) {
|
|
745
|
+
return result;
|
|
746
|
+
}
|
|
747
|
+
else if (cookieReassign) {
|
|
748
|
+
ctx.cookie = result;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
else if (cookieValidatorIsObject) {
|
|
752
|
+
for (const key of Object.keys(cookie)) {
|
|
753
|
+
const validator = cookieValidator[key];
|
|
754
|
+
if (validator == null && !strangeCookie) {
|
|
755
|
+
continue;
|
|
756
|
+
}
|
|
757
|
+
const result = validator == null
|
|
758
|
+
? typeof strangeCookie === "function"
|
|
759
|
+
? strangeCookie(cookie, key)
|
|
760
|
+
: cookie[key]
|
|
761
|
+
: validator.apply
|
|
762
|
+
? validator.apply(ctx, cookie[key])
|
|
763
|
+
: validator(cookie[key]);
|
|
764
|
+
if (result instanceof Error) {
|
|
765
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, result.message, "error", "cookie");
|
|
766
|
+
}
|
|
767
|
+
else if (cookieErrors && errorMatches(result, cookieErrors)) {
|
|
768
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, String(result), "error", "cookie");
|
|
769
|
+
}
|
|
770
|
+
else if (result instanceof Response ||
|
|
771
|
+
result === types_ts_1.Break_Pipe ||
|
|
772
|
+
result === types_ts_1.Break_Pipeline) {
|
|
773
|
+
return result;
|
|
774
|
+
}
|
|
775
|
+
else if (cookieReassign) {
|
|
776
|
+
cookie[key] = result;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
// Parse body
|
|
781
|
+
if (bodyParser) {
|
|
782
|
+
yield bodyParser(ctx);
|
|
783
|
+
}
|
|
784
|
+
const body = ctx.body;
|
|
785
|
+
// Validate Body
|
|
786
|
+
if (bodyValidators) {
|
|
787
|
+
if (Array.isArray(body)) {
|
|
788
|
+
for (let i = 0; i < body.length; i++) {
|
|
789
|
+
const validator = bodyValidators[i % bodyValidators.length];
|
|
790
|
+
const activeBody = body[i];
|
|
791
|
+
if (typeof validator === "function") {
|
|
792
|
+
const result = validator.apply(ctx, activeBody);
|
|
793
|
+
if (result instanceof Error) {
|
|
794
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, result.message, "error", "body");
|
|
795
|
+
}
|
|
796
|
+
else if (bodyErrors && errorMatches(result, bodyErrors)) {
|
|
797
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, String(result), "error", "body");
|
|
798
|
+
}
|
|
799
|
+
else if (result instanceof Response ||
|
|
800
|
+
result === types_ts_1.Break_Pipe ||
|
|
801
|
+
result === types_ts_1.Break_Pipeline) {
|
|
802
|
+
return result;
|
|
803
|
+
}
|
|
804
|
+
else if (bodyReassign) {
|
|
805
|
+
body[i] = result;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
else if (validator) {
|
|
809
|
+
if (activeBody &&
|
|
810
|
+
typeof activeBody === "object" &&
|
|
811
|
+
!Array.isArray(activeBody)) {
|
|
812
|
+
for (const key of Object.keys(activeBody)) {
|
|
813
|
+
const propValidator = validator[key];
|
|
814
|
+
if (propValidator == null && !strangeBody) {
|
|
815
|
+
continue;
|
|
816
|
+
}
|
|
817
|
+
const result = propValidator == null
|
|
818
|
+
? typeof strangeBody === "function"
|
|
819
|
+
? strangeBody(activeBody, key)
|
|
820
|
+
: activeBody[key]
|
|
821
|
+
: propValidator.apply
|
|
822
|
+
? propValidator.apply(ctx, activeBody[key])
|
|
823
|
+
: propValidator(activeBody[key]);
|
|
824
|
+
if (result instanceof Error) {
|
|
825
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, result.message, "error", "body");
|
|
826
|
+
}
|
|
827
|
+
else if (bodyErrors && errorMatches(result, bodyErrors)) {
|
|
828
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, String(result), "error", "body");
|
|
829
|
+
}
|
|
830
|
+
else if (result instanceof Response ||
|
|
831
|
+
result === types_ts_1.Break_Pipe ||
|
|
832
|
+
result === types_ts_1.Break_Pipeline) {
|
|
833
|
+
return result;
|
|
834
|
+
}
|
|
835
|
+
else if (bodyReassign) {
|
|
836
|
+
activeBody[key] = result;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
else {
|
|
841
|
+
return respond(status_ts_1.Status._400_BadRequest, `Invalid body type at index ${i}`, "error", "body");
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
else {
|
|
847
|
+
const validator = bodyValidators[0];
|
|
848
|
+
if (typeof validator === "function") {
|
|
849
|
+
const result = validator.apply
|
|
850
|
+
? validator.apply(ctx, body)
|
|
851
|
+
: validator(body);
|
|
852
|
+
if (result instanceof Error) {
|
|
853
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, result.message, "error", "body");
|
|
854
|
+
}
|
|
855
|
+
else if (bodyErrors && errorMatches(result, bodyErrors)) {
|
|
856
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, String(result), "error", "body");
|
|
857
|
+
}
|
|
858
|
+
else if (result instanceof Response ||
|
|
859
|
+
result === types_ts_1.Break_Pipe ||
|
|
860
|
+
result === types_ts_1.Break_Pipeline) {
|
|
861
|
+
return result;
|
|
862
|
+
}
|
|
863
|
+
else if (bodyReassign) {
|
|
864
|
+
ctx.body = result;
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
else if (validator) {
|
|
868
|
+
if (body && typeof body === "object" && !Array.isArray(body)) {
|
|
869
|
+
for (const key of Object.keys(body)) {
|
|
870
|
+
const propValidator = validator[key];
|
|
871
|
+
if (propValidator == null && !strangeBody) {
|
|
872
|
+
continue;
|
|
873
|
+
}
|
|
874
|
+
const result = propValidator == null
|
|
875
|
+
? typeof strangeBody === "function"
|
|
876
|
+
? strangeBody(body, key)
|
|
877
|
+
: body
|
|
878
|
+
: propValidator.apply
|
|
879
|
+
? propValidator.apply(ctx, body[key])
|
|
880
|
+
: propValidator(body[key]);
|
|
881
|
+
if (result instanceof Error) {
|
|
882
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, result.message, "error", "body");
|
|
883
|
+
}
|
|
884
|
+
else if (bodyErrors && errorMatches(result, bodyErrors)) {
|
|
885
|
+
return respond(result.status || status_ts_1.Status._400_BadRequest, String(result), "error", "body");
|
|
886
|
+
}
|
|
887
|
+
else if (result instanceof Response ||
|
|
888
|
+
result === types_ts_1.Break_Pipe ||
|
|
889
|
+
result === types_ts_1.Break_Pipeline) {
|
|
890
|
+
return result;
|
|
891
|
+
}
|
|
892
|
+
else if (bodyReassign) {
|
|
893
|
+
body[key] = result;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
else {
|
|
898
|
+
return respond(status_ts_1.Status._400_BadRequest, "Invalid body type", "error", "body");
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
if (breakPipeline) {
|
|
904
|
+
return types_ts_1.Break_Pipeline;
|
|
905
|
+
}
|
|
906
|
+
});
|
|
907
|
+
};
|
|
908
|
+
exports.validate = validate;
|
|
359
909
|
//# sourceMappingURL=middlewares.js.map
|