@asenajs/hono-adapter 1.1.0 → 1.2.0

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.
@@ -0,0 +1,169 @@
1
+ /**
2
+ * CORS Middleware for Hono Adapter
3
+ *
4
+ * Handles Cross-Origin Resource Sharing (CORS) by:
5
+ * - Setting appropriate CORS headers on responses
6
+ * - Handling preflight OPTIONS requests
7
+ * - Supporting origin validation
8
+ * - Uses Hono's native header system
9
+ *
10
+ * @module defaults/CorsMiddleware
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { Middleware } from '@asenajs/asena/server';
15
+ * import { CorsMiddleware } from '@asenajs/hono-adapter';
16
+ *
17
+ * @Middleware()
18
+ * export class MyCorsMiddleware extends CorsMiddleware {
19
+ * constructor() {
20
+ * super({
21
+ * origin: '*', // or ['https://example.com']
22
+ * methods: ['GET', 'POST', 'PUT', 'DELETE'],
23
+ * credentials: true
24
+ * });
25
+ * }
26
+ * }
27
+ * ```
28
+ */
29
+ import { MiddlewareService } from '../defaults';
30
+ /**
31
+ * CORS Middleware
32
+ *
33
+ * Implements CORS (Cross-Origin Resource Sharing) for Hono adapter.
34
+ * Extend this class and configure it via constructor to customize CORS behavior.
35
+ *
36
+ * **Performance Optimizations:**
37
+ * - Lazy header allocation (only when needed)
38
+ * - Pre-joined header strings for common cases
39
+ * - Fast origin validation
40
+ * - Minimal string allocations
41
+ *
42
+ * **CORS Flow:**
43
+ * 1. Check if request has Origin header (if not, skip CORS)
44
+ * 2. Validate origin against allowed origins
45
+ * 3. Handle preflight OPTIONS request → return 204 immediately
46
+ * 4. For other requests → set CORS headers and call next()
47
+ */
48
+ export class CorsMiddleware extends MiddlewareService {
49
+ origin;
50
+ methods;
51
+ allowedHeaders;
52
+ exposedHeaders;
53
+ credentials;
54
+ maxAge;
55
+ /**
56
+ * Creates a new CORS middleware instance
57
+ *
58
+ * @param options - CORS configuration options
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * @Middleware()
63
+ * export class CustomCors extends CorsMiddleware {
64
+ * constructor() {
65
+ * super({
66
+ * origin: ['https://example.com', 'https://app.example.com'],
67
+ * methods: ['GET', 'POST'],
68
+ * credentials: true,
69
+ * maxAge: 3600
70
+ * });
71
+ * }
72
+ * }
73
+ * ```
74
+ */
75
+ constructor(options = {}) {
76
+ super();
77
+ // Pre-process and store configuration (avoid runtime processing)
78
+ this.origin = options.origin ?? '*';
79
+ this.methods = (options.methods ?? ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']).join(', ');
80
+ this.allowedHeaders = (options.allowedHeaders ?? ['Content-Type', 'Authorization']).join(', ');
81
+ this.exposedHeaders = (options.exposedHeaders ?? []).join(', ');
82
+ this.credentials = options.credentials ?? false;
83
+ this.maxAge = String(options.maxAge ?? 86400); // 24 hours default
84
+ }
85
+ /**
86
+ * CORS middleware handler
87
+ *
88
+ * Execution flow:
89
+ * 1. Check if Origin header present (if not, skip CORS)
90
+ * 2. Validate origin
91
+ * 3. Handle preflight OPTIONS → return 204 No Content
92
+ * 4. Set CORS headers for actual request → call next()
93
+ *
94
+ * @param context - Hono context wrapper
95
+ * @param next - Function to call next middleware or handler
96
+ * @returns Response for preflight, or result of next() for actual requests
97
+ */
98
+ async handle(context, next) {
99
+ const origin = context.req.header('Origin');
100
+ // If no Origin header, this is not a CORS request → skip
101
+ if (!origin) {
102
+ return await next();
103
+ }
104
+ // Validate origin
105
+ const allowedOrigin = this.getAllowedOrigin(origin);
106
+ if (!allowedOrigin) {
107
+ // Origin not allowed → block request
108
+ return new Response('CORS: Origin not allowed', { status: 403 });
109
+ }
110
+ // Set CORS headers using Hono's context (access via context.context for HonoContextWrapper)
111
+ const honoContext = context.context;
112
+ honoContext.header('Access-Control-Allow-Origin', allowedOrigin);
113
+ if (this.credentials) {
114
+ honoContext.header('Access-Control-Allow-Credentials', 'true');
115
+ }
116
+ if (this.exposedHeaders) {
117
+ honoContext.header('Access-Control-Expose-Headers', this.exposedHeaders);
118
+ }
119
+ // Handle preflight OPTIONS request
120
+ if (context.req.method === 'OPTIONS') {
121
+ // Build headers object for preflight response
122
+ const headers = {
123
+ 'Access-Control-Allow-Origin': allowedOrigin,
124
+ 'Access-Control-Allow-Methods': this.methods,
125
+ 'Access-Control-Allow-Headers': this.allowedHeaders,
126
+ 'Access-Control-Max-Age': this.maxAge,
127
+ };
128
+ if (this.credentials) {
129
+ headers['Access-Control-Allow-Credentials'] = 'true';
130
+ }
131
+ // Return 204 No Content for preflight
132
+ return new Response(null, { status: 204, headers });
133
+ }
134
+ // For actual requests, continue to handler
135
+ return await next();
136
+ }
137
+ /**
138
+ * Determines the allowed origin value for the response
139
+ *
140
+ * Performance:
141
+ * - Fast path for '*' (most common case)
142
+ * - String comparison for single origin
143
+ * - Array.includes() for string array (O(n) but n is typically small)
144
+ * - Function call for dynamic validation
145
+ *
146
+ * @param requestOrigin - Origin from request header
147
+ * @returns Allowed origin string or null if not allowed
148
+ */
149
+ getAllowedOrigin(requestOrigin) {
150
+ // Fast path: Allow all origins
151
+ if (this.origin === '*') {
152
+ return '*';
153
+ }
154
+ // Single origin string
155
+ if (typeof this.origin === 'string') {
156
+ return this.origin === requestOrigin ? requestOrigin : null;
157
+ }
158
+ // Array of specific origins
159
+ if (Array.isArray(this.origin)) {
160
+ return this.origin.includes(requestOrigin) ? requestOrigin : null;
161
+ }
162
+ // Function-based validation
163
+ if (typeof this.origin === 'function') {
164
+ return this.origin(requestOrigin) ? requestOrigin : null;
165
+ }
166
+ return null;
167
+ }
168
+ }
169
+ //# sourceMappingURL=CorsMiddleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CorsMiddleware.js","sourceRoot":"","sources":["../../../lib/middlewares/CorsMiddleware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,329 @@
1
+ /**
2
+ * Rate Limiter Middleware for Hono Adapter
3
+ *
4
+ * Implements Token Bucket algorithm for rate limiting:
5
+ * - Token bucket per client (identified by IP or custom key)
6
+ * - Configurable capacity and refill rate
7
+ * - Instance-based storage (each middleware instance has its own buckets)
8
+ * - Zero external dependencies (uses Bun's native APIs)
9
+ * - Asena DI container compatible
10
+ *
11
+ * @module defaults/RateLimiterMiddleware
12
+ *
13
+ * **Usage in Asena Application:**
14
+ * ```typescript
15
+ * import { Middleware } from '@asenajs/asena/server';
16
+ * import { RateLimiterMiddleware } from '@asenajs/hono-adapter';
17
+ *
18
+ * // Create custom rate limiter for your needs
19
+ * @Middleware()
20
+ * export class ApiRateLimiter extends RateLimiterMiddleware {
21
+ * constructor() {
22
+ * super({
23
+ * capacity: 100,
24
+ * refillRate: 100 / 60, // 100 requests per minute
25
+ * });
26
+ * }
27
+ * }
28
+ *
29
+ * // Use in controller (class reference, not instance)
30
+ * @Controller({ middlewares: [ApiRateLimiter] })
31
+ * export class ApiController { ... }
32
+ *
33
+ * // Or use on specific route
34
+ * @Middleware()
35
+ * export class StrictRateLimiter extends RateLimiterMiddleware {
36
+ * constructor() {
37
+ * super({
38
+ * capacity: 5,
39
+ * refillRate: 5 / 60, // 5 requests per minute
40
+ * message: 'Too many login attempts. Please try again later.',
41
+ * });
42
+ * }
43
+ * }
44
+ *
45
+ * @Post({ path: '/login', middlewares: [StrictRateLimiter] })
46
+ * public login() { ... }
47
+ * ```
48
+ */
49
+ import { type Context, MiddlewareService } from '../defaults';
50
+ /**
51
+ * Token bucket for a single client
52
+ */
53
+ interface Bucket {
54
+ /**
55
+ * Current number of tokens available
56
+ */
57
+ tokens: number;
58
+ /**
59
+ * Last refill timestamp (milliseconds)
60
+ */
61
+ lastRefill: number;
62
+ }
63
+ /**
64
+ * Rate limiter configuration options
65
+ */
66
+ export interface RateLimiterOptions {
67
+ /**
68
+ * Maximum token capacity (burst size)
69
+ *
70
+ * This defines how many requests can be made in a burst.
71
+ * Example: capacity = 100 means 100 requests can be made instantly if bucket is full.
72
+ *
73
+ * @default 100
74
+ */
75
+ capacity?: number;
76
+ /**
77
+ * Token refill rate (tokens per second)
78
+ *
79
+ * This defines the sustained request rate.
80
+ * Example: refillRate = 10 means 10 requests per second sustained rate.
81
+ *
82
+ * Common patterns:
83
+ * - 10 req/s → refillRate: 10
84
+ * - 100 req/min → refillRate: 100/60 ≈ 1.67
85
+ * - 1000 req/hour → refillRate: 1000/3600 ≈ 0.28
86
+ *
87
+ * @default 10
88
+ */
89
+ refillRate?: number;
90
+ /**
91
+ * Custom key generator function
92
+ *
93
+ * By default, uses IP address from X-Forwarded-For header or CF-Connecting-IP.
94
+ * You can customize this to use user ID, API key, or any other identifier.
95
+ *
96
+ * @default (ctx) => ctx.req.headers.get('x-forwarded-for') || ctx.req.headers.get('cf-connecting-ip') || 'unknown'
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * // Rate limit by user ID
101
+ * keyGenerator: (ctx) => ctx.getValue('user')?.id || 'anonymous'
102
+ *
103
+ * // Rate limit by API key
104
+ * keyGenerator: (ctx) => ctx.req.headers.get('x-api-key') || 'unknown'
105
+ * ```
106
+ */
107
+ keyGenerator?: (context: Context) => string;
108
+ /**
109
+ * Custom message for rate limit exceeded response
110
+ *
111
+ * @default 'Rate limit exceeded. Please try again later.'
112
+ */
113
+ message?: string;
114
+ /**
115
+ * HTTP status code for rate limit exceeded response
116
+ *
117
+ * @default 429
118
+ */
119
+ statusCode?: number;
120
+ /**
121
+ * Token cost per request
122
+ *
123
+ * Advanced feature: Different endpoints can cost different amounts of tokens.
124
+ *
125
+ * @default 1
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * // Expensive operations cost more tokens
130
+ * cost: (ctx) => ctx.req.url.includes('/search') ? 5 : 1
131
+ * ```
132
+ */
133
+ cost?: number | ((context: Context) => number);
134
+ /**
135
+ * Skip rate limiting based on context
136
+ *
137
+ * Useful for whitelisting certain IPs, paths, or authenticated users.
138
+ *
139
+ * @default undefined
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * // Skip rate limiting for health check
144
+ * skip: (ctx) => ctx.req.url === '/health'
145
+ *
146
+ * // Skip for admin users
147
+ * skip: (ctx) => ctx.getValue('user')?.role === 'admin'
148
+ * ```
149
+ */
150
+ skip?: (context: Context) => boolean;
151
+ /**
152
+ * Bucket cleanup interval in milliseconds
153
+ *
154
+ * Periodically removes inactive buckets to prevent memory leaks.
155
+ * Set to 0 to disable automatic cleanup.
156
+ *
157
+ * @default 60000 (1 minute)
158
+ */
159
+ cleanupInterval?: number;
160
+ /**
161
+ * Bucket TTL (time to live) in milliseconds
162
+ *
163
+ * Buckets that haven't been accessed for this duration will be removed during cleanup.
164
+ *
165
+ * @default 600000 (10 minutes)
166
+ */
167
+ bucketTTL?: number;
168
+ }
169
+ /**
170
+ * Rate Limiter Middleware
171
+ *
172
+ * Implements Token Bucket algorithm for controlling request rate.
173
+ * Each middleware instance maintains its own bucket storage (instance-based strategy).
174
+ *
175
+ * **Token Bucket Algorithm:**
176
+ * 1. Each client has a bucket with a maximum capacity of tokens
177
+ * 2. Tokens refill at a constant rate (refillRate per second)
178
+ * 3. Each request consumes tokens (default: 1 token)
179
+ * 4. If bucket has insufficient tokens → 429 Too Many Requests
180
+ * 5. Bucket capacity never exceeds maximum (tokens don't accumulate indefinitely)
181
+ *
182
+ * **Performance Optimizations:**
183
+ * - O(1) bucket lookup (Map)
184
+ * - O(1) token calculation (pure math, no arrays)
185
+ * - Lazy token refill (calculated on-demand, not via setInterval)
186
+ * - Memory-efficient bucket structure (2 numbers per client)
187
+ * - Automatic cleanup of inactive buckets
188
+ *
189
+ * **Instance-based Strategy:**
190
+ * Each RateLimiterMiddleware instance has its own bucket Map.
191
+ * This enables route-specific rate limiting:
192
+ * - GlobalRateLimiter → 1000 req/min for all routes
193
+ * - ApiRateLimiter → 100 req/min for /api/* routes
194
+ * - StrictRateLimiter → 5 req/min for /login route
195
+ *
196
+ * @example
197
+ * ```typescript
198
+ * // Global rate limiter (1000 req/min)
199
+ * @Middleware()
200
+ * export class GlobalRateLimiter extends RateLimiterMiddleware {
201
+ * constructor() {
202
+ * super({ capacity: 1000, refillRate: 1000/60 });
203
+ * }
204
+ * }
205
+ *
206
+ * // Strict rate limiter for auth endpoints (5 req/min)
207
+ * @Middleware()
208
+ * export class StrictRateLimiter extends RateLimiterMiddleware {
209
+ * constructor() {
210
+ * super({ capacity: 5, refillRate: 5/60 });
211
+ * }
212
+ * }
213
+ * ```
214
+ */
215
+ export declare class RateLimiterMiddleware extends MiddlewareService {
216
+ /**
217
+ * Instance-specific bucket storage
218
+ * Key: Client identifier (IP, user ID, etc.)
219
+ * Value: Token bucket state
220
+ */
221
+ private readonly buckets;
222
+ /**
223
+ * Maximum token capacity
224
+ */
225
+ private readonly capacity;
226
+ /**
227
+ * Token refill rate (tokens per second)
228
+ */
229
+ private readonly refillRate;
230
+ /**
231
+ * Client key generator function
232
+ */
233
+ private readonly keyGenerator;
234
+ /**
235
+ * Rate limit exceeded message
236
+ */
237
+ private readonly message;
238
+ /**
239
+ * Rate limit exceeded status code
240
+ */
241
+ private readonly statusCode;
242
+ /**
243
+ * Token cost per request
244
+ */
245
+ private readonly cost;
246
+ /**
247
+ * Skip predicate function
248
+ */
249
+ private readonly skip?;
250
+ /**
251
+ * Cleanup interval timer ID
252
+ */
253
+ private cleanupTimer?;
254
+ /**
255
+ * Bucket TTL in milliseconds
256
+ */
257
+ private readonly bucketTTL;
258
+ /**
259
+ * Creates a new rate limiter middleware instance
260
+ *
261
+ * @param options - Rate limiter configuration options
262
+ *
263
+ * @example
264
+ * ```typescript
265
+ * @Middleware()
266
+ * export class CustomRateLimiter extends RateLimiterMiddleware {
267
+ * constructor() {
268
+ * super({
269
+ * capacity: 100,
270
+ * refillRate: 10,
271
+ * keyGenerator: (ctx) => ctx.getValue('user')?.id || 'anonymous',
272
+ * message: 'Çok fazla istek gönderdiniz. Lütfen bekleyin.',
273
+ * skip: (ctx) => ctx.req.url === '/health'
274
+ * });
275
+ * }
276
+ * }
277
+ * ```
278
+ */
279
+ constructor(options?: RateLimiterOptions);
280
+ /**
281
+ * Rate limiter middleware handler
282
+ *
283
+ * Execution flow:
284
+ * 1. Check if request should be skipped
285
+ * 2. Generate client key (IP, user ID, etc.)
286
+ * 3. Get or create bucket for client
287
+ * 4. Refill tokens based on elapsed time
288
+ * 5. Check if sufficient tokens available
289
+ * 6. Consume tokens and continue, or return 429
290
+ *
291
+ * @param context - Hono context wrapper
292
+ * @param next - Function to call next middleware or handler
293
+ * @returns Response for rate limited requests, or result of next() for allowed requests
294
+ */
295
+ handle(context: Context, next: () => Promise<void>): Promise<any>;
296
+ /**
297
+ * Cleanup resources (stop cleanup timer)
298
+ *
299
+ * Call this when shutting down the application.
300
+ */
301
+ destroy(): void;
302
+ /**
303
+ * Get current bucket state for a client (for testing/debugging)
304
+ *
305
+ * @param key - Client identifier
306
+ * @returns Bucket state or undefined
307
+ */
308
+ getBucketState(key: string): Bucket | undefined;
309
+ /**
310
+ * Clear all buckets (for testing)
311
+ */
312
+ clearBuckets(): void;
313
+ /**
314
+ * Default key generator - uses X-Forwarded-For or CF-Connecting-IP or falls back to 'unknown'
315
+ *
316
+ * @param context - Hono context
317
+ * @returns Client identifier
318
+ */
319
+ private defaultKeyGenerator;
320
+ /**
321
+ * Setup automatic cleanup of inactive buckets
322
+ *
323
+ * Prevents memory leaks by removing buckets that haven't been accessed recently.
324
+ *
325
+ * @param interval - Cleanup interval in milliseconds
326
+ */
327
+ private setupCleanup;
328
+ }
329
+ export {};