@bepalo/router 1.0.3

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.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +557 -0
  3. package/dist/cjs/helpers.d.ts +290 -0
  4. package/dist/cjs/helpers.d.ts.map +1 -0
  5. package/dist/cjs/helpers.js +691 -0
  6. package/dist/cjs/helpers.js.map +1 -0
  7. package/dist/cjs/index.d.ts +5 -0
  8. package/dist/cjs/index.d.ts.map +1 -0
  9. package/dist/cjs/index.js +21 -0
  10. package/dist/cjs/index.js.map +1 -0
  11. package/dist/cjs/list.d.ts +166 -0
  12. package/dist/cjs/list.d.ts.map +1 -0
  13. package/dist/cjs/list.js +483 -0
  14. package/dist/cjs/list.js.map +1 -0
  15. package/dist/cjs/middlewares.d.ts +251 -0
  16. package/dist/cjs/middlewares.d.ts.map +1 -0
  17. package/dist/cjs/middlewares.js +359 -0
  18. package/dist/cjs/middlewares.js.map +1 -0
  19. package/dist/cjs/router.d.ts +333 -0
  20. package/dist/cjs/router.d.ts.map +1 -0
  21. package/dist/cjs/router.js +659 -0
  22. package/dist/cjs/router.js.map +1 -0
  23. package/dist/cjs/tree.d.ts +18 -0
  24. package/dist/cjs/tree.d.ts.map +1 -0
  25. package/dist/cjs/tree.js +162 -0
  26. package/dist/cjs/tree.js.map +1 -0
  27. package/dist/cjs/types.d.ts +127 -0
  28. package/dist/cjs/types.d.ts.map +1 -0
  29. package/dist/cjs/types.js +3 -0
  30. package/dist/cjs/types.js.map +1 -0
  31. package/dist/cjs/upload-stream.d.ts +105 -0
  32. package/dist/cjs/upload-stream.d.ts.map +1 -0
  33. package/dist/cjs/upload-stream.js +417 -0
  34. package/dist/cjs/upload-stream.js.map +1 -0
  35. package/dist/helpers.d.ts +290 -0
  36. package/dist/helpers.d.ts.map +1 -0
  37. package/dist/helpers.js +691 -0
  38. package/dist/helpers.js.map +1 -0
  39. package/dist/index.d.ts +5 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +21 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/list.d.ts +166 -0
  44. package/dist/list.d.ts.map +1 -0
  45. package/dist/list.js +483 -0
  46. package/dist/list.js.map +1 -0
  47. package/dist/middlewares.d.ts +251 -0
  48. package/dist/middlewares.d.ts.map +1 -0
  49. package/dist/middlewares.js +359 -0
  50. package/dist/middlewares.js.map +1 -0
  51. package/dist/router.d.ts +333 -0
  52. package/dist/router.d.ts.map +1 -0
  53. package/dist/router.js +659 -0
  54. package/dist/router.js.map +1 -0
  55. package/dist/tree.d.ts +18 -0
  56. package/dist/tree.d.ts.map +1 -0
  57. package/dist/tree.js +162 -0
  58. package/dist/tree.js.map +1 -0
  59. package/dist/types.d.ts +127 -0
  60. package/dist/types.d.ts.map +1 -0
  61. package/dist/types.js +3 -0
  62. package/dist/types.js.map +1 -0
  63. package/dist/upload-stream.d.ts +105 -0
  64. package/dist/upload-stream.d.ts.map +1 -0
  65. package/dist/upload-stream.js +417 -0
  66. package/dist/upload-stream.js.map +1 -0
  67. package/package.json +51 -0
@@ -0,0 +1,251 @@
1
+ import { CTXAddress } from "./helpers.js";
2
+ import { RouterContext } from "./router.js";
3
+ import { HttpMethod } from "./types.js";
4
+ import { CacheConfig } from "@bepalo/cache";
5
+ import { JWT, JwtPayload, JwtVerifyOptions } from "@bepalo/jwt";
6
+ /**
7
+ * Creates a rate limiting middleware using token bucket algorithm.
8
+ * Supports both fixed interval refill and continuous rate-based refill.
9
+ *
10
+ * @template Context - Must extend RouterContext & CTXAddress
11
+ * @param {Object} config - Rate limiting configuration
12
+ * @param {Function} config.key - Function to generate cache key from request and context
13
+ * @param {number} [config.refillInterval] - Fixed interval in milliseconds for token refill
14
+ * @param {number} [config.refillRate] - Continuous refill rate in tokens per second (or custom denominator)
15
+ * @param {number} config.maxTokens - Maximum number of tokens in the bucket
16
+ * @param {number} [config.refillTimeSecondsDenominator=1000] - Denominator for time calculations (default: 1000 = seconds)
17
+ * @param {Function} [config.now=Date.now] - Function returning current timestamp in milliseconds
18
+ * @param {CacheConfig<string, any>} [config.cacheConfig] - Configuration for the underlying cache
19
+ * @param {boolean} [config.setXRateLimitHeaders=false] - Whether to set X-RateLimit headers in response
20
+ * @returns {Function} Middleware function that enforces rate limits
21
+ *
22
+ * @example
23
+ * // Fixed interval rate limiting (10 requests per minute)
24
+ * const rateLimiter = limitRate({
25
+ * key: (req, ctx) => ctx.address.address, // IP-based limiting
26
+ * refillInterval: 60 * 1000, // 1 minute
27
+ * refillRate: 10, // 10 tokens per interval
28
+ * maxTokens: 10,
29
+ * setXRateLimitHeaders: true
30
+ * });
31
+ *
32
+ * @example
33
+ * // Continuous rate limiting (100 requests per hour)
34
+ * const rateLimiter = limitRate({
35
+ * key: (req, ctx) => req.headers.get('x-user-id') || 'anonymous',
36
+ * refillRate: 100 / (60 * 60), // 100 tokens per hour
37
+ * maxTokens: 100,
38
+ * refillTimeSecondsDenominator: 1 // Use seconds as time unit
39
+ * });
40
+ *
41
+ * @throws {Error} If neither refillInterval nor refillRate is provided
42
+ */
43
+ export declare const limitRate: <Context extends RouterContext & CTXAddress>(config: {
44
+ key: (req: Request, ctx: Context) => string;
45
+ refillInterval?: number;
46
+ refillRate?: number;
47
+ maxTokens: number;
48
+ refillTimeSecondsDenominator?: number;
49
+ now?: () => number;
50
+ cacheConfig?: CacheConfig<string, any>;
51
+ setXRateLimitHeaders?: boolean;
52
+ }) => (req: Request, ctx: Context) => Response | undefined;
53
+ /**
54
+ * Creates a CORS (Cross-Origin Resource Sharing) middleware.
55
+ * Supports preflight requests and configurable CORS headers.
56
+ *
57
+ * @template Context - Must extend RouterContext
58
+ * @param {Object} [config] - CORS configuration
59
+ * @param {string|string[]|"*"} [config.origins="*"] - Allowed origins (wildcard "*", single origin, or array)
60
+ * @param {HttpMethod[]} [config.methods=["GET","HEAD","PUT","PATCH","POST","DELETE"]] - Allowed HTTP methods
61
+ * @param {string[]} [config.allowedHeaders=["Content-Type","Authorization"]] - Allowed request headers
62
+ * @param {string[]} [config.exposedHeaders] - Headers exposed to the browser
63
+ * @param {boolean} [config.credentials=false] - Allow credentials (cookies, authorization headers)
64
+ * @param {number} [config.maxAge=86400] - Maximum age for preflight cache in seconds
65
+ * @param {boolean} [config.varyOrigin=false] - Add Vary: Origin header for caching
66
+ * @returns {Function} Middleware function that handles CORS headers
67
+ *
68
+ * @example
69
+ * // Basic CORS with all defaults
70
+ * const corsMiddleware = cors();
71
+ *
72
+ * @example
73
+ * // Specific origins with credentials
74
+ * const corsMiddleware = cors({
75
+ * origins: ["https://example.com", "https://api.example.com"],
76
+ * credentials: true,
77
+ * methods: ["GET", "POST", "PUT", "DELETE"],
78
+ * allowedHeaders: ["Content-Type", "Authorization", "X-Custom-Header"]
79
+ * });
80
+ *
81
+ * @throws {Error} If credentials is true with wildcard origin ("*")
82
+ */
83
+ export declare const cors: <Context extends RouterContext>(config?: {
84
+ origins: "*" | string | string[];
85
+ methods?: HttpMethod[] | null;
86
+ allowedHeaders?: string[] | null;
87
+ exposedHeaders?: string[] | null;
88
+ credentials?: boolean | null;
89
+ maxAge?: number | null;
90
+ varyOrigin?: boolean;
91
+ }) => (req: Request, ctx: Context) => Response | undefined;
92
+ /**
93
+ * Context type for Basic Authentication middleware.
94
+ * @template {string} [prop="basicAuth"] - Property name to store auth data in context
95
+ * @typedef {RouterContext & {[K in prop]?: {username: string; role: string} & Record<string, any>}} CTXBasicAuth
96
+ */
97
+ export type CTXBasicAuth<prop extends string = "basicAuth"> = RouterContext & {
98
+ [K in prop]?: {
99
+ username: string;
100
+ role: string;
101
+ } & Record<string, any>;
102
+ };
103
+ /**
104
+ * Creates a Basic Authentication middleware.
105
+ * Supports RFC 7617 Basic Authentication scheme.
106
+ *
107
+ * @template Context - Must extend CTXBasicAuth
108
+ * @template {string} prop - Property name to store auth data in context
109
+ * @param {Object} config - Basic Authentication configuration
110
+ * @param {Map<string, {pass: string} & Record<string, any>>} config.credentials - Map of usernames to user data (must include 'pass')
111
+ * @param {"raw"|"base64"} [config.type="raw"] - Credential encoding type
112
+ * @param {":"|" "} [config.separator=":"] - Separator between username and password
113
+ * @param {string} [config.realm="Protected"] - Authentication realm
114
+ * @param {prop} [config.ctxProp="basicAuth"] - Context property name for auth data
115
+ * @returns {Function} Middleware function that validates Basic Authentication
116
+ *
117
+ * @example
118
+ * // Simple username/password authentication
119
+ * const users = new Map();
120
+ * users.set("admin", { pass: "secret123", role: "admin", permissions: ["read", "write"] });
121
+ * users.set("user", { pass: "password", role: "user", permissions: ["read"] });
122
+ *
123
+ * const basicAuth = authBasic({
124
+ * credentials: users,
125
+ * realm: "My API",
126
+ * ctxProp: "user" // Store in ctx.user instead of ctx.basicAuth
127
+ * });
128
+ */
129
+ export declare const authBasic: <Context extends CTXBasicAuth, prop extends string = "basicAuth">({ credentials, type, separator, realm, ctxProp, }: {
130
+ credentials: Map<string, {
131
+ pass: string;
132
+ } & Record<string, any>>;
133
+ type?: "raw" | "base64";
134
+ separator?: ":" | " ";
135
+ realm?: string;
136
+ ctxProp?: prop;
137
+ }) => (req: Request, ctx: Context) => Response | undefined;
138
+ /**
139
+ * Context type for API Key Authentication middleware.
140
+ * @template {string} [prop="apiKeyAuth"] - Property name to store auth data in context
141
+ * @typedef {RouterContext & {[K in prop]?: {apiKey: string} & Record<string, any>}} CTXAPIKeyAuth
142
+ */
143
+ export type CTXAPIKeyAuth<prop extends string = "apiKeyAuth"> = RouterContext & {
144
+ [K in prop]?: {
145
+ apiKey: string;
146
+ } & Record<string, any>;
147
+ };
148
+ /**
149
+ * Creates an API Key Authentication middleware.
150
+ * Validates API keys from X-API-Key header.
151
+ *
152
+ * @template Context - Must extend CTXAPIKeyAuth
153
+ * @template {string} prop - Property name to store auth data in context
154
+ * @param {Object} config - API Key Authentication configuration
155
+ * @param {Function} config.verify - Function to verify API key (returns boolean)
156
+ * @param {prop} [config.ctxProp="apiKeyAuth"] - Context property name for auth data
157
+ * @returns {Function} Middleware function that validates API keys
158
+ *
159
+ * @example
160
+ * // API key validation with database lookup
161
+ * const apiKeys = new Set(["abc123", "def456", "ghi789"]);
162
+ *
163
+ * const apiKeyAuth = authAPIKey({
164
+ * verify: (apiKey) => apiKeys.has(apiKey),
165
+ * ctxProp: "apiClient" // Store in ctx.apiClient
166
+ * });
167
+ *
168
+ * @example
169
+ * // API key with additional validation
170
+ * const apiKeyAuth = authAPIKey({
171
+ * verify: (apiKey) => {
172
+ * // Validate format
173
+ * if (!apiKey.startsWith("sk_")) return false;
174
+ *
175
+ * // Check against database
176
+ * return db.apiKeys.isValid(apiKey);
177
+ * }
178
+ * });
179
+ */
180
+ export declare const authAPIKey: <Context extends CTXAPIKeyAuth, prop extends string = "apiKeyAuth">({ verify, ctxProp, }: {
181
+ verify: (apiKey: string) => boolean;
182
+ ctxProp?: prop;
183
+ }) => (req: Request, ctx: Context) => Response | undefined;
184
+ /**
185
+ * Context type for JWT Authentication middleware.
186
+ * @template {JwtPayload<{}>} Payload - JWT payload type
187
+ * @template {string} [prop="jwtAuth"] - Property name to store auth data in context
188
+ * @typedef {RouterContext & {[K in prop]?: {jwt: JWT<Payload>; token: string; payload: Payload} & Record<string, any>}} CTXJWTAuth
189
+ */
190
+ export type CTXJWTAuth<Payload extends JwtPayload<{}>, prop extends string = "jwtAuth"> = RouterContext & {
191
+ [K in prop]?: {
192
+ jwt: JWT<Payload>;
193
+ token: string;
194
+ payload: Payload;
195
+ } & Record<string, any>;
196
+ };
197
+ /**
198
+ * Creates a JWT (JSON Web Token) Authentication middleware.
199
+ * Validates Bearer tokens from Authorization header.
200
+ *
201
+ * @template {JwtPayload<{}>} Payload - JWT payload type
202
+ * @template Context - Must extend CTXJWTAuth<Payload, prop>
203
+ * @template {string} prop - Property name to store auth data in context
204
+ * @param {Object} config - JWT Authentication configuration
205
+ * @param {JWT<Payload>} config.jwt - JWT instance for verification
206
+ * @param {Function} [config.validate] - Additional payload validation function
207
+ * @param {JwtVerifyOptions} [config.verifyOptions] - JWT verification options
208
+ * @param {prop} [config.ctxProp="jwtAuth"] - Context property name for auth data
209
+ * @returns {Function} Middleware function that validates JWT tokens
210
+ *
211
+ * @example
212
+ * // Simple JWT authentication
213
+ * const jwt = new JWT({ secret: process.env.JWT_SECRET });
214
+ *
215
+ * const jwtAuth = authJWT({
216
+ * jwt,
217
+ * validate: (payload) => payload.exp > Date.now() / 1000, // Check expiration
218
+ * ctxProp: "auth" // Store in ctx.auth
219
+ * });
220
+ *
221
+ * @example
222
+ * // JWT with custom payload validation
223
+ * interface MyPayload extends JwtPayload<{}> {
224
+ * userId: string;
225
+ * role: string;
226
+ * permissions: string[];
227
+ * }
228
+ *
229
+ * const jwt = new JWT<MyPayload>({ secret: process.env.JWT_SECRET });
230
+ *
231
+ * const jwtAuth = authJWT<MyPayload>({
232
+ * jwt,
233
+ * validate: (payload) => {
234
+ * // Custom business logic
235
+ * if (!payload.userId) return false;
236
+ * if (payload.role !== "admin") return false;
237
+ * return true;
238
+ * },
239
+ * verifyOptions: {
240
+ * algorithms: ["HS256"],
241
+ * maxAge: "2h"
242
+ * }
243
+ * });
244
+ */
245
+ export declare const authJWT: <Payload extends JwtPayload<{}>, Context extends CTXJWTAuth<Payload, prop>, prop extends string = "jwtAuth">({ jwt, validate, verifyOptions, ctxProp, }: {
246
+ jwt: JWT<Payload>;
247
+ validate?: (payload: Payload) => boolean;
248
+ verifyOptions?: JwtVerifyOptions;
249
+ ctxProp?: prop;
250
+ }) => (req: Request, ctx: Context) => Response | undefined;
251
+ //# sourceMappingURL=middlewares.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middlewares.d.ts","sourceRoot":"","sources":["../src/middlewares.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,359 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.authJWT = exports.authAPIKey = exports.authBasic = exports.cors = exports.limitRate = void 0;
4
+ const helpers_js_1 = require("./helpers.js");
5
+ const cache_1 = require("@bepalo/cache");
6
+ const time_1 = require("@bepalo/time");
7
+ /**
8
+ * Creates a rate limiting middleware using token bucket algorithm.
9
+ * Supports both fixed interval refill and continuous rate-based refill.
10
+ *
11
+ * @template Context - Must extend RouterContext & CTXAddress
12
+ * @param {Object} config - Rate limiting configuration
13
+ * @param {Function} config.key - Function to generate cache key from request and context
14
+ * @param {number} [config.refillInterval] - Fixed interval in milliseconds for token refill
15
+ * @param {number} [config.refillRate] - Continuous refill rate in tokens per second (or custom denominator)
16
+ * @param {number} config.maxTokens - Maximum number of tokens in the bucket
17
+ * @param {number} [config.refillTimeSecondsDenominator=1000] - Denominator for time calculations (default: 1000 = seconds)
18
+ * @param {Function} [config.now=Date.now] - Function returning current timestamp in milliseconds
19
+ * @param {CacheConfig<string, any>} [config.cacheConfig] - Configuration for the underlying cache
20
+ * @param {boolean} [config.setXRateLimitHeaders=false] - Whether to set X-RateLimit headers in response
21
+ * @returns {Function} Middleware function that enforces rate limits
22
+ *
23
+ * @example
24
+ * // Fixed interval rate limiting (10 requests per minute)
25
+ * const rateLimiter = limitRate({
26
+ * key: (req, ctx) => ctx.address.address, // IP-based limiting
27
+ * refillInterval: 60 * 1000, // 1 minute
28
+ * refillRate: 10, // 10 tokens per interval
29
+ * maxTokens: 10,
30
+ * setXRateLimitHeaders: true
31
+ * });
32
+ *
33
+ * @example
34
+ * // Continuous rate limiting (100 requests per hour)
35
+ * const rateLimiter = limitRate({
36
+ * key: (req, ctx) => req.headers.get('x-user-id') || 'anonymous',
37
+ * refillRate: 100 / (60 * 60), // 100 tokens per hour
38
+ * maxTokens: 100,
39
+ * refillTimeSecondsDenominator: 1 // Use seconds as time unit
40
+ * });
41
+ *
42
+ * @throws {Error} If neither refillInterval nor refillRate is provided
43
+ */
44
+ const limitRate = (config) => {
45
+ const { key, refillInterval, refillRate, maxTokens, refillTimeSecondsDenominator = 1000, now = () => Date.now(), cacheConfig = {
46
+ now: () => Date.now(),
47
+ // defaultMaxAgse: Time.for(10).seconds._ms,
48
+ defaultMaxAge: time_1.Time.for(1).hour._ms,
49
+ cleanupInterval: time_1.Time.every(10).minutes._ms,
50
+ onGetMiss: (cache, key, reason) => {
51
+ cache.set(key, { tokens: maxTokens, lastRefill: now() });
52
+ return true;
53
+ },
54
+ }, setXRateLimitHeaders = false, } = config;
55
+ let rateLimits = new cache_1.Cache(cacheConfig);
56
+ if (refillInterval) {
57
+ return (req, ctx) => {
58
+ var _a;
59
+ const id = key(req, ctx);
60
+ const entry = (_a = rateLimits.get(id)) === null || _a === void 0 ? void 0 : _a.value;
61
+ const timeElapsed = now() - entry.lastRefill;
62
+ if (timeElapsed >= refillInterval) {
63
+ if (refillRate) {
64
+ const newTokens = entry.tokens +
65
+ refillRate * Math.floor(timeElapsed / refillInterval);
66
+ entry.tokens = Math.min(newTokens, maxTokens);
67
+ entry.lastRefill = now();
68
+ }
69
+ else {
70
+ entry.tokens = maxTokens;
71
+ entry.lastRefill = now();
72
+ }
73
+ }
74
+ if (entry.tokens <= 0) {
75
+ ctx.headers.set("Retry-After", Math.ceil((refillInterval - timeElapsed) / refillTimeSecondsDenominator).toFixed());
76
+ return (0, helpers_js_1.status)(429);
77
+ }
78
+ else {
79
+ entry.tokens--;
80
+ }
81
+ if (setXRateLimitHeaders) {
82
+ ctx.headers.set("X-RateLimit-Limit", maxTokens.toFixed());
83
+ ctx.headers.set("X-RateLimit-Remaining", entry.tokens.toFixed());
84
+ }
85
+ };
86
+ }
87
+ else if (refillRate) {
88
+ return (req, ctx) => {
89
+ var _a;
90
+ const id = key(req, ctx);
91
+ const entry = (_a = rateLimits.get(id)) === null || _a === void 0 ? void 0 : _a.value;
92
+ const timeElapsed = now() - entry.lastRefill;
93
+ const newTokens = entry.tokens +
94
+ (refillRate * timeElapsed) / refillTimeSecondsDenominator;
95
+ entry.tokens = Math.min(newTokens, maxTokens);
96
+ entry.lastRefill = now();
97
+ if (entry.tokens <= 0) {
98
+ ctx.headers.set("Retry-After", Math.ceil(1 / refillRate).toFixed());
99
+ return (0, helpers_js_1.status)(429);
100
+ }
101
+ else {
102
+ entry.tokens--;
103
+ }
104
+ if (setXRateLimitHeaders) {
105
+ ctx.headers.set("X-RateLimit-Limit", maxTokens.toFixed());
106
+ ctx.headers.set("X-RateLimit-Remaining", Math.max(0, entry.tokens).toFixed());
107
+ }
108
+ };
109
+ }
110
+ throw new Error("LIMIT-RATE: `refillInterval` or `refillRate` or both should be set");
111
+ };
112
+ exports.limitRate = limitRate;
113
+ /**
114
+ * Creates a CORS (Cross-Origin Resource Sharing) middleware.
115
+ * Supports preflight requests and configurable CORS headers.
116
+ *
117
+ * @template Context - Must extend RouterContext
118
+ * @param {Object} [config] - CORS configuration
119
+ * @param {string|string[]|"*"} [config.origins="*"] - Allowed origins (wildcard "*", single origin, or array)
120
+ * @param {HttpMethod[]} [config.methods=["GET","HEAD","PUT","PATCH","POST","DELETE"]] - Allowed HTTP methods
121
+ * @param {string[]} [config.allowedHeaders=["Content-Type","Authorization"]] - Allowed request headers
122
+ * @param {string[]} [config.exposedHeaders] - Headers exposed to the browser
123
+ * @param {boolean} [config.credentials=false] - Allow credentials (cookies, authorization headers)
124
+ * @param {number} [config.maxAge=86400] - Maximum age for preflight cache in seconds
125
+ * @param {boolean} [config.varyOrigin=false] - Add Vary: Origin header for caching
126
+ * @returns {Function} Middleware function that handles CORS headers
127
+ *
128
+ * @example
129
+ * // Basic CORS with all defaults
130
+ * const corsMiddleware = cors();
131
+ *
132
+ * @example
133
+ * // Specific origins with credentials
134
+ * const corsMiddleware = cors({
135
+ * origins: ["https://example.com", "https://api.example.com"],
136
+ * credentials: true,
137
+ * methods: ["GET", "POST", "PUT", "DELETE"],
138
+ * allowedHeaders: ["Content-Type", "Authorization", "X-Custom-Header"]
139
+ * });
140
+ *
141
+ * @throws {Error} If credentials is true with wildcard origin ("*")
142
+ */
143
+ const cors = (config) => {
144
+ const { origins = "*", methods = ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE"], allowedHeaders = ["Content-Type", "Authorization"], exposedHeaders, credentials = false, maxAge = 86400, varyOrigin = false, } = config !== null && config !== void 0 ? config : {};
145
+ const globOrigin = origins === "*" ? "*" : null;
146
+ const originsSet = new Set(typeof origins !== "string" ? origins : origins !== "*" ? [] : [origins]);
147
+ return (req, ctx) => {
148
+ const origin = req.headers.get("origin");
149
+ let corsOrigin = null;
150
+ if (!origin) {
151
+ return;
152
+ }
153
+ if (globOrigin) {
154
+ corsOrigin = "*";
155
+ }
156
+ else {
157
+ corsOrigin = originsSet.has(origin) ? origin : null;
158
+ }
159
+ if (!corsOrigin) {
160
+ if (varyOrigin)
161
+ ctx.headers.append("Vary", "Origin");
162
+ return;
163
+ }
164
+ ctx.headers.set("Access-Control-Allow-Origin", corsOrigin);
165
+ if (credentials) {
166
+ if (corsOrigin === "*")
167
+ throw new Error("CORS: Cannot use credentials with wildcard origin");
168
+ ctx.headers.set("Access-Control-Allow-Credentials", "true");
169
+ }
170
+ if (exposedHeaders && exposedHeaders.length > 0) {
171
+ ctx.headers.set("Access-Control-Expose-Headers", exposedHeaders.join(", "));
172
+ }
173
+ if (varyOrigin) {
174
+ ctx.headers.append("Vary", "Origin");
175
+ }
176
+ if (req.method === "OPTIONS") {
177
+ if (methods && methods.length > 0) {
178
+ ctx.headers.set("Access-Control-Allow-Methods", methods.join(", "));
179
+ }
180
+ if (allowedHeaders && allowedHeaders.length > 0) {
181
+ ctx.headers.set("Access-Control-Allow-Headers", allowedHeaders.join(", "));
182
+ }
183
+ if (maxAge) {
184
+ ctx.headers.set("Access-Control-Max-Age", maxAge.toString());
185
+ }
186
+ return (0, helpers_js_1.status)(204, null);
187
+ }
188
+ };
189
+ };
190
+ exports.cors = cors;
191
+ /**
192
+ * Creates a Basic Authentication middleware.
193
+ * Supports RFC 7617 Basic Authentication scheme.
194
+ *
195
+ * @template Context - Must extend CTXBasicAuth
196
+ * @template {string} prop - Property name to store auth data in context
197
+ * @param {Object} config - Basic Authentication configuration
198
+ * @param {Map<string, {pass: string} & Record<string, any>>} config.credentials - Map of usernames to user data (must include 'pass')
199
+ * @param {"raw"|"base64"} [config.type="raw"] - Credential encoding type
200
+ * @param {":"|" "} [config.separator=":"] - Separator between username and password
201
+ * @param {string} [config.realm="Protected"] - Authentication realm
202
+ * @param {prop} [config.ctxProp="basicAuth"] - Context property name for auth data
203
+ * @returns {Function} Middleware function that validates Basic Authentication
204
+ *
205
+ * @example
206
+ * // Simple username/password authentication
207
+ * const users = new Map();
208
+ * users.set("admin", { pass: "secret123", role: "admin", permissions: ["read", "write"] });
209
+ * users.set("user", { pass: "password", role: "user", permissions: ["read"] });
210
+ *
211
+ * const basicAuth = authBasic({
212
+ * credentials: users,
213
+ * realm: "My API",
214
+ * ctxProp: "user" // Store in ctx.user instead of ctx.basicAuth
215
+ * });
216
+ */
217
+ const authBasic = ({ credentials, type = "raw", separator = ":", realm = "Protected", ctxProp = "basicAuth", }) => {
218
+ return (req, ctx) => {
219
+ const authorization = req.headers.get("authorization");
220
+ ctx.headers.set("WWW-Authenticate", `Basic realm="${realm}", charset="UTF-8"`);
221
+ if (!authorization)
222
+ return (0, helpers_js_1.status)(401);
223
+ const [scheme, creds] = authorization.split(" ", 2);
224
+ if (scheme.toLowerCase() !== "basic" || !creds)
225
+ return (0, helpers_js_1.status)(401);
226
+ let xcreds;
227
+ try {
228
+ xcreds = type === "base64" ? atob(creds) : creds;
229
+ }
230
+ catch (_a) {
231
+ return (0, helpers_js_1.status)(401);
232
+ }
233
+ const [username, password] = xcreds.split(separator, 2);
234
+ if (!username || !password)
235
+ return (0, helpers_js_1.status)(401);
236
+ const user = credentials.get(username);
237
+ if (!user || password !== user.pass)
238
+ return (0, helpers_js_1.status)(401);
239
+ ctx[ctxProp] = {
240
+ username,
241
+ role: user.role,
242
+ };
243
+ };
244
+ };
245
+ exports.authBasic = authBasic;
246
+ /**
247
+ * Creates an API Key Authentication middleware.
248
+ * Validates API keys from X-API-Key header.
249
+ *
250
+ * @template Context - Must extend CTXAPIKeyAuth
251
+ * @template {string} prop - Property name to store auth data in context
252
+ * @param {Object} config - API Key Authentication configuration
253
+ * @param {Function} config.verify - Function to verify API key (returns boolean)
254
+ * @param {prop} [config.ctxProp="apiKeyAuth"] - Context property name for auth data
255
+ * @returns {Function} Middleware function that validates API keys
256
+ *
257
+ * @example
258
+ * // API key validation with database lookup
259
+ * const apiKeys = new Set(["abc123", "def456", "ghi789"]);
260
+ *
261
+ * const apiKeyAuth = authAPIKey({
262
+ * verify: (apiKey) => apiKeys.has(apiKey),
263
+ * ctxProp: "apiClient" // Store in ctx.apiClient
264
+ * });
265
+ *
266
+ * @example
267
+ * // API key with additional validation
268
+ * const apiKeyAuth = authAPIKey({
269
+ * verify: (apiKey) => {
270
+ * // Validate format
271
+ * if (!apiKey.startsWith("sk_")) return false;
272
+ *
273
+ * // Check against database
274
+ * return db.apiKeys.isValid(apiKey);
275
+ * }
276
+ * });
277
+ */
278
+ const authAPIKey = ({ verify, ctxProp = "apiKeyAuth", }) => {
279
+ return (req, ctx) => {
280
+ const apiKey = req.headers.get("X-API-Key");
281
+ if (!apiKey || !verify(apiKey))
282
+ return (0, helpers_js_1.status)(401);
283
+ ctx[ctxProp] = {
284
+ apiKey,
285
+ };
286
+ };
287
+ };
288
+ exports.authAPIKey = authAPIKey;
289
+ /**
290
+ * Creates a JWT (JSON Web Token) Authentication middleware.
291
+ * Validates Bearer tokens from Authorization header.
292
+ *
293
+ * @template {JwtPayload<{}>} Payload - JWT payload type
294
+ * @template Context - Must extend CTXJWTAuth<Payload, prop>
295
+ * @template {string} prop - Property name to store auth data in context
296
+ * @param {Object} config - JWT Authentication configuration
297
+ * @param {JWT<Payload>} config.jwt - JWT instance for verification
298
+ * @param {Function} [config.validate] - Additional payload validation function
299
+ * @param {JwtVerifyOptions} [config.verifyOptions] - JWT verification options
300
+ * @param {prop} [config.ctxProp="jwtAuth"] - Context property name for auth data
301
+ * @returns {Function} Middleware function that validates JWT tokens
302
+ *
303
+ * @example
304
+ * // Simple JWT authentication
305
+ * const jwt = new JWT({ secret: process.env.JWT_SECRET });
306
+ *
307
+ * const jwtAuth = authJWT({
308
+ * jwt,
309
+ * validate: (payload) => payload.exp > Date.now() / 1000, // Check expiration
310
+ * ctxProp: "auth" // Store in ctx.auth
311
+ * });
312
+ *
313
+ * @example
314
+ * // JWT with custom payload validation
315
+ * interface MyPayload extends JwtPayload<{}> {
316
+ * userId: string;
317
+ * role: string;
318
+ * permissions: string[];
319
+ * }
320
+ *
321
+ * const jwt = new JWT<MyPayload>({ secret: process.env.JWT_SECRET });
322
+ *
323
+ * const jwtAuth = authJWT<MyPayload>({
324
+ * jwt,
325
+ * validate: (payload) => {
326
+ * // Custom business logic
327
+ * if (!payload.userId) return false;
328
+ * if (payload.role !== "admin") return false;
329
+ * return true;
330
+ * },
331
+ * verifyOptions: {
332
+ * algorithms: ["HS256"],
333
+ * maxAge: "2h"
334
+ * }
335
+ * });
336
+ */
337
+ const authJWT = ({ jwt, validate, verifyOptions, ctxProp = "jwtAuth", }) => {
338
+ return (req, ctx) => {
339
+ var _a;
340
+ const authorization = req.headers.get("authorization");
341
+ if (!authorization)
342
+ return (0, helpers_js_1.status)(401);
343
+ const [scheme, token] = authorization.split(" ", 2);
344
+ if (scheme.toLowerCase() !== "bearer" || !token)
345
+ return (0, helpers_js_1.status)(401);
346
+ const result = jwt.verifySync(token, verifyOptions);
347
+ if (!result.payload)
348
+ return (0, helpers_js_1.status)(401, (_a = result.error) === null || _a === void 0 ? void 0 : _a.message);
349
+ if (validate && !validate(result.payload))
350
+ return (0, helpers_js_1.status)(401);
351
+ ctx[ctxProp] = {
352
+ jwt,
353
+ token,
354
+ payload: result.payload,
355
+ };
356
+ };
357
+ };
358
+ exports.authJWT = authJWT;
359
+ //# sourceMappingURL=middlewares.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middlewares.js","sourceRoot":"","sources":["../src/middlewares.ts"],"names":[],"mappings":"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"}