@bepalo/spine 1.5.17 → 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/README.md +532 -1
- package/dist/auth-middlewares.d.ts.map +1 -1
- package/dist/auth-middlewares.js +1 -0
- package/dist/auth-middlewares.js.map +1 -1
- package/dist/cache.d.ts +72 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +387 -0
- package/dist/cache.js.map +1 -0
- package/dist/cjs/auth-middlewares.d.ts.map +1 -1
- package/dist/cjs/auth-middlewares.js +1 -0
- package/dist/cjs/auth-middlewares.js.map +1 -1
- package/dist/cjs/cache.d.ts +72 -0
- package/dist/cjs/cache.d.ts.map +1 -0
- package/dist/cjs/cache.js +387 -0
- package/dist/cjs/cache.js.map +1 -0
- package/dist/cjs/exp-cache.d.ts +101 -0
- package/dist/cjs/exp-cache.d.ts.map +1 -0
- package/dist/cjs/exp-cache.js +551 -0
- package/dist/cjs/exp-cache.js.map +1 -0
- package/dist/cjs/generator.d.ts +142 -19
- package/dist/cjs/generator.d.ts.map +1 -1
- package/dist/cjs/generator.js +416 -36
- package/dist/cjs/generator.js.map +1 -1
- package/dist/cjs/helpers.d.ts +49 -2
- package/dist/cjs/helpers.d.ts.map +1 -1
- package/dist/cjs/helpers.js +169 -14
- package/dist/cjs/helpers.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +3 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/linked-list.d.ts +35 -0
- package/dist/cjs/linked-list.d.ts.map +1 -0
- package/dist/cjs/linked-list.js +300 -0
- package/dist/cjs/linked-list.js.map +1 -0
- package/dist/cjs/middlewares.d.ts +264 -28
- package/dist/cjs/middlewares.d.ts.map +1 -1
- package/dist/cjs/middlewares.js +691 -44
- 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 +84 -46
- package/dist/cjs/parsers.js.map +1 -1
- package/dist/cjs/router.d.ts +5 -6
- package/dist/cjs/router.d.ts.map +1 -1
- package/dist/cjs/router.js +272 -149
- package/dist/cjs/router.js.map +1 -1
- package/dist/cjs/status.d.ts.map +1 -1
- package/dist/cjs/status.js +80 -79
- package/dist/cjs/status.js.map +1 -1
- package/dist/cjs/types.d.ts +74 -2
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/types.js +15 -2
- package/dist/cjs/types.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 +1 -0
- 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 +31 -7
- package/dist/cjs/utils.node.js.map +1 -1
- package/dist/exp-cache.d.ts +101 -0
- package/dist/exp-cache.d.ts.map +1 -0
- package/dist/exp-cache.js +551 -0
- package/dist/exp-cache.js.map +1 -0
- package/dist/generator.d.ts +142 -19
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +416 -36
- package/dist/generator.js.map +1 -1
- package/dist/helpers.d.ts +49 -2
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +169 -14
- package/dist/helpers.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/linked-list.d.ts +35 -0
- package/dist/linked-list.d.ts.map +1 -0
- package/dist/linked-list.js +300 -0
- package/dist/linked-list.js.map +1 -0
- package/dist/middlewares.d.ts +264 -28
- package/dist/middlewares.d.ts.map +1 -1
- package/dist/middlewares.js +691 -44
- 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 +84 -46
- package/dist/parsers.js.map +1 -1
- package/dist/router.d.ts +5 -6
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +272 -149
- package/dist/router.js.map +1 -1
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +80 -79
- package/dist/status.js.map +1 -1
- package/dist/types.d.ts +74 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +15 -2
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +1 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +1 -0
- 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 +31 -7
- package/dist/utils.node.js.map +1 -1
- package/package.json +6 -2
package/dist/cjs/middlewares.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
// src/middlewares.ts
|
|
2
3
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
4
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
5
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -9,23 +10,123 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
10
|
});
|
|
10
11
|
};
|
|
11
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.cors = exports.limitRate = void 0;
|
|
13
|
+
exports.validate = exports.cors = exports.limitRate = exports.securityHeaders = exports.forceHttps = void 0;
|
|
13
14
|
const helpers_ts_1 = require("./helpers.js");
|
|
15
|
+
const parsers_ts_1 = require("./parsers.js");
|
|
16
|
+
const status_ts_1 = require("./status.js");
|
|
14
17
|
const types_ts_1 = require("./types.js");
|
|
18
|
+
/**
|
|
19
|
+
* Force http into https
|
|
20
|
+
*
|
|
21
|
+
* @returns {Handler<ExtendContext>} Middleware function
|
|
22
|
+
*
|
|
23
|
+
*/
|
|
24
|
+
const forceHttps = (config) => {
|
|
25
|
+
var _a;
|
|
26
|
+
const toPort = (_a = config === null || config === void 0 ? void 0 : config.toPort) !== null && _a !== void 0 ? _a : 443;
|
|
27
|
+
return function ({ url }) {
|
|
28
|
+
if (url.protocol === "http:") {
|
|
29
|
+
const newUrl = new URL(url);
|
|
30
|
+
newUrl.protocol = "https:";
|
|
31
|
+
newUrl.port = toPort === 443 ? "" : String(toPort);
|
|
32
|
+
return (0, helpers_ts_1.redirectPermanentPreserve)(newUrl.toString());
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
exports.forceHttps = forceHttps;
|
|
37
|
+
/**
|
|
38
|
+
* Set security headers.
|
|
39
|
+
* - "X-Content-Type-Options": always "nosniff"
|
|
40
|
+
* - "X-Frame-Options": default "DENY"
|
|
41
|
+
* - "Referrer-Policy": from parameters
|
|
42
|
+
* - "Strict-Transport-Security": from parameters
|
|
43
|
+
* - "Content-Security-Policy": from parameters
|
|
44
|
+
*
|
|
45
|
+
* @returns {Handler<ExtendContext>} Middleware function
|
|
46
|
+
*
|
|
47
|
+
*/
|
|
48
|
+
const securityHeaders = (config) => {
|
|
49
|
+
const { crossOriginOpenerPolicy, crossOriginEmbedderPolicy, crossOriginResourcePolicy, referrerPolicy, xFrameOptions = "DENY", strictTransportSecurity: hsts_, contentSecurityPolicy: csp_, headers, } = config !== null && config !== void 0 ? config : {};
|
|
50
|
+
const hsts = hsts_ == null
|
|
51
|
+
? undefined
|
|
52
|
+
: typeof hsts_ === "string"
|
|
53
|
+
? hsts_
|
|
54
|
+
: typeof hsts_ === "boolean"
|
|
55
|
+
? hsts_
|
|
56
|
+
? (0, helpers_ts_1.buildStrictTransportSecurity)({})
|
|
57
|
+
: undefined
|
|
58
|
+
: (0, helpers_ts_1.buildStrictTransportSecurity)(hsts_);
|
|
59
|
+
const contentSecurityPolicy = csp_ == null ? undefined : (0, helpers_ts_1.buildContentSecurityPolicy)(csp_);
|
|
60
|
+
/////////////////////////////////////////////
|
|
61
|
+
const preparedHeaders = [];
|
|
62
|
+
if (headers != null) {
|
|
63
|
+
if (Array.isArray(headers)) {
|
|
64
|
+
for (const [key, value] of headers) {
|
|
65
|
+
preparedHeaders.push([key, value]);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
for (const key of Object.keys(headers)) {
|
|
70
|
+
preparedHeaders.push([key, headers[key]]);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/////////////////////////////////////////////
|
|
75
|
+
preparedHeaders.push(["X-Content-Type-Options", "nosniff"]);
|
|
76
|
+
if (xFrameOptions != null) {
|
|
77
|
+
preparedHeaders.push(["X-Frame-Options", xFrameOptions]);
|
|
78
|
+
}
|
|
79
|
+
if (referrerPolicy != undefined) {
|
|
80
|
+
preparedHeaders.push(["Referrer-Policy", referrerPolicy]);
|
|
81
|
+
}
|
|
82
|
+
if (hsts != null) {
|
|
83
|
+
preparedHeaders.push(["Strict-Transport-Security", hsts]);
|
|
84
|
+
}
|
|
85
|
+
if (contentSecurityPolicy != null) {
|
|
86
|
+
preparedHeaders.push(["Content-Security-Policy", contentSecurityPolicy]);
|
|
87
|
+
}
|
|
88
|
+
if (crossOriginOpenerPolicy != null) {
|
|
89
|
+
preparedHeaders.push([
|
|
90
|
+
"Cross-Origin-Opener-Policy",
|
|
91
|
+
crossOriginOpenerPolicy,
|
|
92
|
+
]);
|
|
93
|
+
}
|
|
94
|
+
if (crossOriginEmbedderPolicy != null) {
|
|
95
|
+
preparedHeaders.push([
|
|
96
|
+
"Cross-Origin-Embedder-Policy",
|
|
97
|
+
crossOriginEmbedderPolicy,
|
|
98
|
+
]);
|
|
99
|
+
}
|
|
100
|
+
if (crossOriginResourcePolicy != null) {
|
|
101
|
+
preparedHeaders.push([
|
|
102
|
+
"Cross-Origin-Resource-Policy",
|
|
103
|
+
crossOriginResourcePolicy,
|
|
104
|
+
]);
|
|
105
|
+
}
|
|
106
|
+
/////////////////////////////////////////////
|
|
107
|
+
return function ({ headers }) {
|
|
108
|
+
for (const [key, value] of preparedHeaders) {
|
|
109
|
+
headers.set(key, value);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
exports.securityHeaders = securityHeaders;
|
|
15
114
|
/**
|
|
16
115
|
* Creates a rate limiting middleware using token bucket algorithm.
|
|
17
116
|
* Supports both fixed interval refill and continuous rate-based refill.
|
|
18
117
|
*
|
|
19
|
-
* @template {Record<string, unknown>} ExtendContext
|
|
20
|
-
* @
|
|
21
|
-
* @
|
|
22
|
-
* @
|
|
23
|
-
* @
|
|
24
|
-
* @
|
|
25
|
-
* @
|
|
26
|
-
* @
|
|
27
|
-
* @
|
|
28
|
-
* @
|
|
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
|
|
129
|
+
* @returns {Handler<ExtendContext>} Middleware function that enforces rate limits
|
|
29
130
|
*
|
|
30
131
|
* @example
|
|
31
132
|
* // Fixed interval rate limiting (10 requests per minute)
|
|
@@ -45,11 +146,16 @@ const types_ts_1 = require("./types.js");
|
|
|
45
146
|
* maxTokens: 100,
|
|
46
147
|
* });
|
|
47
148
|
*
|
|
48
|
-
* @throws {
|
|
149
|
+
* @throws {Error} If neither refillInterval nor refillRate is provided
|
|
49
150
|
*/
|
|
50
151
|
const limitRate = (config) => {
|
|
51
152
|
var _a;
|
|
52
|
-
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);
|
|
53
159
|
const cleanUpIdleDelay = -((_a = config.cleanUpIdleDelay) !== null && _a !== void 0 ? _a : 0);
|
|
54
160
|
const rateLimits = new Map();
|
|
55
161
|
const now = () => performance.now() / 1000;
|
|
@@ -117,7 +223,7 @@ const limitRate = (config) => {
|
|
|
117
223
|
}
|
|
118
224
|
if (entry.tokens <= 0) {
|
|
119
225
|
ctx.headers.set("Retry-After", Math.ceil(refillInterval - timeElapsed).toFixed());
|
|
120
|
-
return (
|
|
226
|
+
return respond(status_ts_1.Status._429_TooManyRequests, "Rate Limited", "message", "rate-limit");
|
|
121
227
|
}
|
|
122
228
|
else {
|
|
123
229
|
entry.tokens--;
|
|
@@ -143,7 +249,7 @@ const limitRate = (config) => {
|
|
|
143
249
|
entry.lastRefill = now();
|
|
144
250
|
if (entry.tokens <= 0) {
|
|
145
251
|
ctx.headers.set("Retry-After", Math.ceil(1 / refillRate).toFixed());
|
|
146
|
-
return (
|
|
252
|
+
return respond(status_ts_1.Status._429_TooManyRequests, "Rate Limited", "message", "rate-limit");
|
|
147
253
|
}
|
|
148
254
|
else {
|
|
149
255
|
entry.tokens--;
|
|
@@ -158,24 +264,27 @@ const limitRate = (config) => {
|
|
|
158
264
|
});
|
|
159
265
|
};
|
|
160
266
|
}
|
|
161
|
-
throw new
|
|
267
|
+
throw new Error("LIMIT-RATE: `refillInterval` or `refillRate` or both should be set");
|
|
162
268
|
};
|
|
163
269
|
exports.limitRate = limitRate;
|
|
164
270
|
/**
|
|
165
271
|
* Creates a CORS (Cross-Origin Resource Sharing) middleware.
|
|
166
272
|
* Supports preflight requests and configurable CORS headers.
|
|
167
273
|
*
|
|
168
|
-
* @template {Record<string, unknown>} ExtendContext
|
|
169
|
-
* @param {Object} [config]
|
|
170
|
-
* @param {string|string[]|"*"} [config.origins="*"]
|
|
171
|
-
* @param {HttpMethod[]} [config.methods=["
|
|
172
|
-
* @param {string[]} [config.allowedHeaders=["Content-Type","Authorization"]]
|
|
173
|
-
* @param {string[]} [config.exposedHeaders]
|
|
174
|
-
* @param {boolean} [config.credentials=false]
|
|
175
|
-
* @param {number} [config.maxAge=86400]
|
|
176
|
-
* @param {boolean} [config.varyOrigin=
|
|
177
|
-
* @param {boolean} [
|
|
178
|
-
* @
|
|
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
|
|
285
|
+
* @returns {Handler<ExtendContext>} Middleware function that handles CORS headers
|
|
286
|
+
*
|
|
287
|
+
* @throws {HttpError} If credentials is enabled with wildcard origin ("*")
|
|
179
288
|
*
|
|
180
289
|
* @example
|
|
181
290
|
* // Basic CORS with all defaults
|
|
@@ -186,21 +295,21 @@ exports.limitRate = limitRate;
|
|
|
186
295
|
* const corsMiddleware = cors({
|
|
187
296
|
* origins: ["https://example.com", "https://api.example.com"],
|
|
188
297
|
* credentials: true,
|
|
189
|
-
* methods: ["
|
|
298
|
+
* methods: ["Get", "Post", "Put", "Delete"],
|
|
190
299
|
* allowedHeaders: ["Content-Type", "Authorization", "X-Custom-Header"]
|
|
191
300
|
* });
|
|
192
301
|
*
|
|
193
|
-
* @throws {HttpError} If credentials is true with wildcard origin ("*")
|
|
194
302
|
*/
|
|
195
303
|
const cors = (config) => {
|
|
196
|
-
const { origins = "*", methods = ["Get", "Head", "Put", "Patch", "Post", "Delete"], allowedHeaders = ["Content-Type", "Authorization"], exposedHeaders, credentials = false, maxAge = 86400, varyOrigin =
|
|
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);
|
|
197
310
|
const globOrigin = origins === "*" ? "*" : null;
|
|
198
|
-
const originsSet = new Set(
|
|
199
|
-
|
|
200
|
-
for (let i = 0; i < methods.length; i++) {
|
|
201
|
-
methods[i] = methods[i].toUpperCase();
|
|
202
|
-
}
|
|
203
|
-
}
|
|
311
|
+
const originsSet = new Set(origins === "*" ? [] : typeof origins === "string" ? [origins] : origins);
|
|
312
|
+
const methods = methods_ === null || methods_ === void 0 ? void 0 : methods_.map((m) => m.toUpperCase());
|
|
204
313
|
return function (ctx) {
|
|
205
314
|
const { request, headers } = ctx;
|
|
206
315
|
const origin = request.headers.get("origin");
|
|
@@ -218,8 +327,9 @@ const cors = (config) => {
|
|
|
218
327
|
corsOrigin = originsSet.has(origin) ? origin : null;
|
|
219
328
|
}
|
|
220
329
|
if (!corsOrigin) {
|
|
221
|
-
if (varyOrigin)
|
|
222
|
-
|
|
330
|
+
if (varyOrigin) {
|
|
331
|
+
headers.append("Vary", "Origin");
|
|
332
|
+
}
|
|
223
333
|
if (breakPipeline) {
|
|
224
334
|
return types_ts_1.Break_Pipeline;
|
|
225
335
|
}
|
|
@@ -228,30 +338,31 @@ const cors = (config) => {
|
|
|
228
338
|
headers.set("Access-Control-Allow-Origin", corsOrigin);
|
|
229
339
|
if (credentials) {
|
|
230
340
|
if (corsOrigin === "*")
|
|
231
|
-
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");
|
|
232
342
|
headers.set("Access-Control-Allow-Credentials", "true");
|
|
233
343
|
}
|
|
234
344
|
if (exposedHeaders && exposedHeaders.length > 0) {
|
|
235
345
|
headers.set("Access-Control-Expose-Headers", exposedHeaders.join(", "));
|
|
236
346
|
}
|
|
237
|
-
if (varyOrigin) {
|
|
347
|
+
if (varyOrigin && origins !== "*") {
|
|
238
348
|
headers.append("Vary", "Origin");
|
|
239
349
|
}
|
|
240
350
|
if (request.method === "OPTIONS") {
|
|
241
351
|
if (methods && methods.length > 0) {
|
|
242
352
|
const requestMethod = request.headers.get("Access-Control-Request-Method");
|
|
243
|
-
if (requestMethod &&
|
|
244
|
-
|
|
353
|
+
if (requestMethod &&
|
|
354
|
+
!methods.includes(requestMethod)) {
|
|
355
|
+
return respond(status_ts_1.Status._405_MethodNotAllowed, `Method ${requestMethod} not allowed`, "error", "CORS");
|
|
245
356
|
}
|
|
246
357
|
headers.set("Access-Control-Allow-Methods", methods.join(", "));
|
|
247
358
|
}
|
|
248
359
|
if (allowedHeaders && allowedHeaders.length > 0) {
|
|
249
360
|
headers.set("Access-Control-Allow-Headers", allowedHeaders.join(", "));
|
|
250
361
|
}
|
|
251
|
-
if (maxAge) {
|
|
362
|
+
if (maxAge != null) {
|
|
252
363
|
headers.set("Access-Control-Max-Age", maxAge.toString());
|
|
253
364
|
}
|
|
254
|
-
return (0, helpers_ts_1.status)(
|
|
365
|
+
return (0, helpers_ts_1.status)(status_ts_1.Status._204_NoContent, null);
|
|
255
366
|
}
|
|
256
367
|
if (breakPipeline) {
|
|
257
368
|
return types_ts_1.Break_Pipeline;
|
|
@@ -259,4 +370,540 @@ const cors = (config) => {
|
|
|
259
370
|
};
|
|
260
371
|
};
|
|
261
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;
|
|
262
909
|
//# sourceMappingURL=middlewares.js.map
|