@noony-serverless/core 0.1.1 → 0.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.
Files changed (62) hide show
  1. package/build/core/core.d.ts +16 -48
  2. package/build/core/core.js +2 -61
  3. package/build/core/handler.d.ts +37 -16
  4. package/build/core/handler.js +131 -42
  5. package/build/core/index.d.ts +0 -1
  6. package/build/core/index.js +0 -1
  7. package/build/middlewares/ConsolidatedValidationMiddleware.d.ts +126 -0
  8. package/build/middlewares/ConsolidatedValidationMiddleware.js +330 -0
  9. package/build/middlewares/ProcessingMiddleware.d.ts +138 -0
  10. package/build/middlewares/ProcessingMiddleware.js +425 -0
  11. package/build/middlewares/SecurityMiddleware.d.ts +157 -0
  12. package/build/middlewares/SecurityMiddleware.js +307 -0
  13. package/build/middlewares/authenticationMiddleware.d.ts +379 -0
  14. package/build/middlewares/authenticationMiddleware.js +216 -0
  15. package/build/middlewares/bodyParserMiddleware.d.ts +99 -0
  16. package/build/middlewares/bodyParserMiddleware.js +99 -0
  17. package/build/middlewares/bodyValidationMiddleware.d.ts +69 -3
  18. package/build/middlewares/bodyValidationMiddleware.js +68 -2
  19. package/build/middlewares/dependencyInjectionMiddleware.d.ts +238 -0
  20. package/build/middlewares/dependencyInjectionMiddleware.js +238 -0
  21. package/build/middlewares/errorHandlerMiddleware.d.ts +94 -0
  22. package/build/middlewares/errorHandlerMiddleware.js +105 -0
  23. package/build/middlewares/guards/RouteGuards.d.ts +476 -21
  24. package/build/middlewares/guards/RouteGuards.js +418 -21
  25. package/build/middlewares/guards/adapters/CustomTokenVerificationPortAdapter.d.ts +271 -0
  26. package/build/middlewares/guards/adapters/CustomTokenVerificationPortAdapter.js +301 -0
  27. package/build/middlewares/guards/cache/CacheAdapter.d.ts +369 -28
  28. package/build/middlewares/guards/cache/CacheAdapter.js +124 -5
  29. package/build/middlewares/guards/cache/MemoryCacheAdapter.d.ts +113 -4
  30. package/build/middlewares/guards/cache/MemoryCacheAdapter.js +113 -4
  31. package/build/middlewares/guards/config/GuardConfiguration.d.ts +568 -18
  32. package/build/middlewares/guards/config/GuardConfiguration.js +266 -10
  33. package/build/middlewares/guards/guards/FastAuthGuard.d.ts +5 -5
  34. package/build/middlewares/guards/guards/PermissionGuardFactory.d.ts +5 -13
  35. package/build/middlewares/guards/guards/PermissionGuardFactory.js +4 -4
  36. package/build/middlewares/guards/index.d.ts +43 -1
  37. package/build/middlewares/guards/index.js +46 -1
  38. package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.d.ts +1 -1
  39. package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.js +1 -1
  40. package/build/middlewares/guards/resolvers/PermissionResolver.d.ts +1 -1
  41. package/build/middlewares/guards/resolvers/PlainPermissionResolver.d.ts +1 -1
  42. package/build/middlewares/guards/resolvers/WildcardPermissionResolver.d.ts +1 -1
  43. package/build/middlewares/guards/services/FastUserContextService.d.ts +20 -33
  44. package/build/middlewares/guards/services/FastUserContextService.js +19 -5
  45. package/build/middlewares/headerVariablesMiddleware.d.ts +118 -0
  46. package/build/middlewares/headerVariablesMiddleware.js +118 -0
  47. package/build/middlewares/httpAttributesMiddleware.d.ts +235 -0
  48. package/build/middlewares/httpAttributesMiddleware.js +236 -1
  49. package/build/middlewares/index.d.ts +3 -1
  50. package/build/middlewares/index.js +6 -1
  51. package/build/middlewares/queryParametersMiddleware.d.ts +105 -0
  52. package/build/middlewares/queryParametersMiddleware.js +105 -0
  53. package/build/middlewares/rateLimitingMiddleware.d.ts +601 -9
  54. package/build/middlewares/rateLimitingMiddleware.js +623 -11
  55. package/build/middlewares/responseWrapperMiddleware.d.ts +170 -1
  56. package/build/middlewares/responseWrapperMiddleware.js +170 -1
  57. package/build/middlewares/securityAuditMiddleware.js +5 -5
  58. package/package.json +11 -9
  59. package/build/core/containerPool.d.ts +0 -44
  60. package/build/core/containerPool.js +0 -103
  61. package/build/middlewares/validationMiddleware.d.ts +0 -9
  62. package/build/middlewares/validationMiddleware.js +0 -40
@@ -104,8 +104,193 @@ const getRateLimit = (context, options) => {
104
104
  };
105
105
  };
106
106
  /**
107
- * Rate Limiting Middleware
108
- * Implements sliding window rate limiting with comprehensive features
107
+ * Rate Limiting Middleware with sliding window implementation.
108
+ * Implements comprehensive rate limiting with dynamic limits, custom storage, and security features.
109
+ *
110
+ * ## When to Use RateLimitingMiddleware
111
+ *
112
+ * ### ✅ Recommended Use Cases:
113
+ * - **Business Logic Rate Limiting**: User-specific quotas, subscription-based limits
114
+ * - **Authentication & Security**: Login attempts, password resets, token refresh
115
+ * - **Content Creation**: Post creation, comment submission, profile updates
116
+ * - **Resource-Intensive Operations**: File uploads, data processing, complex queries
117
+ * - **Advanced Scenarios**: A/B testing limits, geographic restrictions, time-based rules
118
+ *
119
+ * ### ❌ Not Recommended Use Cases:
120
+ * - **Basic DDoS Protection**: Use WAF/CloudFlare instead
121
+ * - **Static Asset Protection**: Use CDN rate limiting
122
+ * - **Simple Volumetric Attacks**: Network-level solutions more effective
123
+ *
124
+ * ## Architecture Integration
125
+ *
126
+ * ### With WAF (Web Application Firewall):
127
+ * - WAF handles: IP blocking, DDoS protection, bot detection
128
+ * - Application handles: Business logic, user-aware limits, complex rules
129
+ * - Focus on complementary functionality, not duplication
130
+ *
131
+ * ### With API Gateway:
132
+ * - Gateway handles: Service-level limits, routing quotas, load balancing
133
+ * - Application handles: User context, subscription limits, feature-specific rules
134
+ * - Different layers for different concerns
135
+ *
136
+ * ### Direct Exposure (No WAF/Gateway):
137
+ * - Application must handle comprehensive protection
138
+ * - Implement multiple protection layers within middleware
139
+ * - Critical for security in simple deployments
140
+ *
141
+ * @implements {BaseMiddleware}
142
+ *
143
+ * @example
144
+ * Basic API rate limiting:
145
+ * ```typescript
146
+ * import { Handler, RateLimitingMiddleware } from '@noony-serverless/core';
147
+ *
148
+ * const apiHandler = new Handler()
149
+ * .use(new RateLimitingMiddleware({
150
+ * maxRequests: 100,
151
+ * windowMs: 60000, // 1 minute
152
+ * message: 'Too many API requests'
153
+ * }))
154
+ * .handle(async (context) => {
155
+ * const data = await getApiData();
156
+ * return { success: true, data };
157
+ * });
158
+ * ```
159
+ *
160
+ * @example
161
+ * Authentication endpoint with strict limits:
162
+ * ```typescript
163
+ * const loginHandler = new Handler()
164
+ * .use(new RateLimitingMiddleware({
165
+ * maxRequests: 5,
166
+ * windowMs: 60000, // 1 minute
167
+ * message: 'Too many login attempts',
168
+ * statusCode: 429
169
+ * }))
170
+ * .handle(async (context) => {
171
+ * const { email, password } = context.req.parsedBody;
172
+ * const token = await authenticate(email, password);
173
+ * return { success: true, token };
174
+ * });
175
+ * ```
176
+ *
177
+ * @example
178
+ * Dynamic limits based on user authentication:
179
+ * ```typescript
180
+ * const smartApiHandler = new Handler()
181
+ * .use(new RateLimitingMiddleware({
182
+ * maxRequests: 50, // Default for unauthenticated
183
+ * windowMs: 60000,
184
+ * dynamicLimits: {
185
+ * authenticated: {
186
+ * maxRequests: 1000,
187
+ * windowMs: 60000,
188
+ * matcher: (context) => !!context.user
189
+ * },
190
+ * premium: {
191
+ * maxRequests: 5000,
192
+ * windowMs: 60000,
193
+ * matcher: (context) => context.user?.plan === 'premium'
194
+ * }
195
+ * }
196
+ * }))
197
+ * .handle(async (context) => {
198
+ * return { success: true, limit: 'applied dynamically' };
199
+ * });
200
+ * ```
201
+ *
202
+ * @example
203
+ * Multi-layer defense (with WAF):
204
+ * ```typescript
205
+ * // WAF handles basic IP limits (10,000/min), DDoS protection
206
+ * // Application refines with business logic
207
+ * const wafAwareHandler = new Handler()
208
+ * .use(new RateLimitingMiddleware({
209
+ * maxRequests: 100, // Refined limit after WAF filtering
210
+ * windowMs: 60000,
211
+ * dynamicLimits: {
212
+ * premium: {
213
+ * maxRequests: 500,
214
+ * windowMs: 60000,
215
+ * matcher: (context) => context.user?.plan === 'premium'
216
+ * }
217
+ * },
218
+ * keyGenerator: (context) => `user:${context.user?.id || context.req.ip}`
219
+ * }))
220
+ * .handle(async (context) => {
221
+ * // Business logic with user-aware limits
222
+ * return await processUserRequest(context);
223
+ * });
224
+ * ```
225
+ *
226
+ * @example
227
+ * API Gateway integration:
228
+ * ```typescript
229
+ * // Gateway: 10,000 req/hour per service, 1,000 req/min per endpoint
230
+ * // Application: User-specific limits within gateway envelope
231
+ * const gatewayAwareHandler = new Handler()
232
+ * .use(new RateLimitingMiddleware({
233
+ * maxRequests: 100, // Per user within gateway limits
234
+ * windowMs: 60000,
235
+ * dynamicLimits: {
236
+ * freeTrial: {
237
+ * maxRequests: 10,
238
+ * windowMs: 60000,
239
+ * matcher: (context) => context.user?.trialExpired === false
240
+ * },
241
+ * enterprise: {
242
+ * maxRequests: 5000,
243
+ * windowMs: 60000,
244
+ * matcher: (context) => context.user?.plan === 'enterprise'
245
+ * }
246
+ * },
247
+ * keyGenerator: (context) => `user:${context.user?.id}`
248
+ * }))
249
+ * .handle(async (context) => {
250
+ * // Refined business logic limits
251
+ * return await handleApiRequest(context);
252
+ * });
253
+ * ```
254
+ *
255
+ * @example
256
+ * Comprehensive protection (no WAF/Gateway):
257
+ * ```typescript
258
+ * // Application must handle all protection layers
259
+ * const comprehensiveHandler = new Handler()
260
+ * .use(new RateLimitingMiddleware({
261
+ * maxRequests: 100,
262
+ * windowMs: 60000,
263
+ * dynamicLimits: {
264
+ * // IP-based protection (WAF-like)
265
+ * suspicious_ip: {
266
+ * maxRequests: 10,
267
+ * windowMs: 60000,
268
+ * matcher: (context) => detectSuspiciousIP(context.req.ip)
269
+ * },
270
+ * // Endpoint-specific (Gateway-like)
271
+ * auth_endpoint: {
272
+ * maxRequests: 5,
273
+ * windowMs: 60000,
274
+ * matcher: (context) => context.req.path?.includes('/auth/')
275
+ * },
276
+ * // Business logic (Application-specific)
277
+ * user_specific: {
278
+ * maxRequests: 1000,
279
+ * windowMs: 60000,
280
+ * matcher: (context) => !!context.user
281
+ * }
282
+ * },
283
+ * keyGenerator: (context) => {
284
+ * const user = context.user?.id;
285
+ * const ip = context.req.ip;
286
+ * const endpoint = context.req.path;
287
+ * return user ? `user:${user}` : `ip:${ip}:${endpoint}`;
288
+ * }
289
+ * }))
290
+ * .handle(async (context) => {
291
+ * return await processRequest(context);
292
+ * });
293
+ * ```
109
294
  */
110
295
  class RateLimitingMiddleware {
111
296
  store;
@@ -179,18 +364,224 @@ class RateLimitingMiddleware {
179
364
  }
180
365
  exports.RateLimitingMiddleware = RateLimitingMiddleware;
181
366
  /**
182
- * Rate Limiting Middleware Factory
183
- * @param options Rate limiting configuration
184
- * @returns BaseMiddleware
367
+ * Factory function that creates a rate limiting middleware.
368
+ * Provides flexible rate limiting with configurable options and presets.
369
+ *
370
+ * ## Architecture Decision Matrix
371
+ *
372
+ * | Infrastructure | WAF Rate Limiting | Gateway Rate Limiting | Application Rate Limiting |
373
+ * |----------------|------------------|---------------------|-------------------------|
374
+ * | **WAF + Gateway + App** | ✅ Basic DDoS protection | ✅ Service-level limits | ✅ Business logic |
375
+ * | **Gateway + App** | ❌ Not available | ✅ Service + IP limits | ✅ User context + business |
376
+ * | **WAF + App** | ✅ Network protection | ❌ Not available | ✅ All business logic |
377
+ * | **App Only** | ❌ Must implement | ❌ Must implement | ✅ Everything |
378
+ *
379
+ * ## Implementation Strategy by Architecture
380
+ *
381
+ * ### Multi-Layer Defense (Recommended for Enterprise)
382
+ * ```typescript
383
+ * // WAF Layer: 10,000 req/min per IP (CloudFlare/AWS WAF)
384
+ * // Gateway Layer: 1,000 req/min per API key (Kong/AWS API Gateway)
385
+ * // Application Layer: User-specific business rules (This middleware)
386
+ *
387
+ * const enterprise = rateLimiting({
388
+ * maxRequests: 100, // Refined after other layers
389
+ * dynamicLimits: {
390
+ * premium: { maxRequests: 500, matcher: (ctx) => ctx.user?.plan === 'premium' }
391
+ * }
392
+ * });
393
+ * ```
394
+ *
395
+ * ### Gateway + Application (Good for Most Applications)
396
+ * ```typescript
397
+ * // Gateway: Service capacity protection
398
+ * // Application: Business logic enforcement
399
+ *
400
+ * const standard = rateLimiting({
401
+ * maxRequests: 200, // Higher since Gateway pre-filters
402
+ * dynamicLimits: {
403
+ * authenticated: { maxRequests: 1000, matcher: (ctx) => !!ctx.user }
404
+ * }
405
+ * });
406
+ * ```
407
+ *
408
+ * ### Application Only (Comprehensive Protection Required)
409
+ * ```typescript
410
+ * // Must handle all layers of protection
411
+ *
412
+ * const comprehensive = rateLimiting({
413
+ * maxRequests: 50, // Conservative default
414
+ * dynamicLimits: {
415
+ * // WAF-like: IP protection
416
+ * suspicious: { maxRequests: 5, matcher: (ctx) => detectSuspicious(ctx.req.ip) },
417
+ * // Gateway-like: Endpoint protection
418
+ * auth: { maxRequests: 10, matcher: (ctx) => ctx.req.path?.includes('/auth/') },
419
+ * // Business: User-specific
420
+ * premium: { maxRequests: 1000, matcher: (ctx) => ctx.user?.plan === 'premium' }
421
+ * }
422
+ * });
423
+ * ```
424
+ *
425
+ * ## Cost-Benefit Analysis
426
+ *
427
+ * | Architecture | Setup Complexity | Runtime Cost | Protection Level | Maintenance |
428
+ * |-------------|-----------------|-------------|-----------------|-------------|
429
+ * | **WAF + Gateway + App** | High | High | Maximum | Medium |
430
+ * | **Gateway + App** | Medium | Medium | Good | Low |
431
+ * | **WAF + App** | Medium | Medium | Good | Medium |
432
+ * | **App Only** | Low | Low | Variable | High |
433
+ *
434
+ * @param options - Rate limiting configuration options
435
+ * @returns BaseMiddleware instance
436
+ *
437
+ * @example
438
+ * Using preset configurations:
439
+ * ```typescript
440
+ * import { Handler, rateLimiting, RateLimitPresets } from '@noony-serverless/core';
441
+ *
442
+ * // Strict limits for sensitive endpoints
443
+ * const authHandler = new Handler()
444
+ * .use(rateLimiting(RateLimitPresets.AUTH))
445
+ * .handle(async (context) => {
446
+ * return await handleAuthentication(context.req.parsedBody);
447
+ * });
448
+ *
449
+ * // Standard API limits
450
+ * const apiHandler = new Handler()
451
+ * .use(rateLimiting(RateLimitPresets.API))
452
+ * .handle(async (context) => {
453
+ * return await handleApiRequest(context);
454
+ * });
455
+ * ```
456
+ *
457
+ * @example
458
+ * Custom rate limiting with skip conditions:
459
+ * ```typescript
460
+ * const conditionalHandler = new Handler()
461
+ * .use(rateLimiting({
462
+ * maxRequests: 100,
463
+ * windowMs: 60000,
464
+ * skip: (context) => {
465
+ * // Skip rate limiting for admin users
466
+ * return context.user?.role === 'admin';
467
+ * },
468
+ * keyGenerator: (context) => {
469
+ * // Rate limit per user instead of IP
470
+ * return context.user?.id || context.req.ip || 'anonymous';
471
+ * }
472
+ * }))
473
+ * .handle(async (context) => {
474
+ * return { success: true, message: 'Request processed' };
475
+ * });
476
+ * ```
477
+ *
478
+ * @example
479
+ * Production Redis store integration:
480
+ * ```typescript
481
+ * import Redis from 'ioredis';
482
+ *
483
+ * class RedisRateLimitStore implements RateLimitStore {
484
+ * constructor(private redis: Redis) {}
485
+ *
486
+ * async increment(key: string, windowMs: number) {
487
+ * const multi = this.redis.multi();
488
+ * multi.incr(key);
489
+ * multi.expire(key, Math.ceil(windowMs / 1000));
490
+ * const results = await multi.exec();
491
+ * return { count: results![0][1] as number, resetTime: Date.now() + windowMs };
492
+ * }
493
+ * }
494
+ *
495
+ * const productionHandler = new Handler()
496
+ * .use(rateLimiting({
497
+ * store: new RedisRateLimitStore(redisClient),
498
+ * maxRequests: 1000,
499
+ * windowMs: 60000
500
+ * }))
501
+ * .handle(async (context) => {
502
+ * return await handleHighVolumeAPI(context);
503
+ * });
504
+ * ```
505
+ *
506
+ * @example
507
+ * Multi-dimensional rate limiting:
508
+ * ```typescript
509
+ * const advancedHandler = new Handler()
510
+ * .use(rateLimiting({
511
+ * maxRequests: 100,
512
+ * windowMs: 60000,
513
+ * dynamicLimits: {
514
+ * // Different limits by operation type
515
+ * read_operations: {
516
+ * maxRequests: 1000,
517
+ * windowMs: 60000,
518
+ * matcher: (context) => context.req.method === 'GET'
519
+ * },
520
+ * write_operations: {
521
+ * maxRequests: 50,
522
+ * windowMs: 60000,
523
+ * matcher: (context) => ['POST', 'PUT', 'DELETE'].includes(context.req.method || '')
524
+ * },
525
+ * // Different limits by user tier
526
+ * enterprise_users: {
527
+ * maxRequests: 5000,
528
+ * windowMs: 60000,
529
+ * matcher: (context) => context.user?.tier === 'enterprise'
530
+ * }
531
+ * },
532
+ * keyGenerator: (context) => {
533
+ * // Multi-dimensional key: user + operation type
534
+ * const userId = context.user?.id || context.req.ip;
535
+ * const operation = context.req.method === 'GET' ? 'read' : 'write';
536
+ * return `${operation}:${userId}`;
537
+ * }
538
+ * }))
539
+ * .handle(async (context) => {
540
+ * return await processAdvancedRequest(context);
541
+ * });
542
+ * ```
185
543
  */
186
544
  const rateLimiting = (options = {}) => new RateLimitingMiddleware(options);
187
545
  exports.rateLimiting = rateLimiting;
188
546
  /**
189
- * Predefined rate limit configurations
547
+ * Predefined rate limit configurations for common use cases.
548
+ *
549
+ * These presets are designed to work well in different infrastructure scenarios:
550
+ * - WAF + Application: Higher limits since WAF pre-filters traffic
551
+ * - Gateway + Application: Moderate limits complementing gateway quotas
552
+ * - Application Only: Conservative limits for comprehensive protection
553
+ *
554
+ * ## Preset Selection Guide
555
+ *
556
+ * | Preset | Use Case | Infrastructure | Requests/Min |
557
+ * |--------|----------|---------------|-------------|
558
+ * | `STRICT` | Sensitive operations | Any | 5 |
559
+ * | `AUTH` | Authentication endpoints | Any | 10 |
560
+ * | `PUBLIC` | Public/unauthenticated | App Only | 50 |
561
+ * | `API` | Standard API endpoints | WAF/Gateway + App | 100-1000 |
562
+ * | `DEVELOPMENT` | Development/testing | Development | 10,000 |
563
+ *
564
+ * @example
565
+ * Choosing the right preset:
566
+ * ```typescript
567
+ * // High-security endpoint (password reset)
568
+ * .use(rateLimiting(RateLimitPresets.STRICT))
569
+ *
570
+ * // Login/registration
571
+ * .use(rateLimiting(RateLimitPresets.AUTH))
572
+ *
573
+ * // Public API with WAF protection
574
+ * .use(rateLimiting(RateLimitPresets.API))
575
+ *
576
+ * // Public API without WAF (direct exposure)
577
+ * .use(rateLimiting(RateLimitPresets.PUBLIC))
578
+ * ```
190
579
  */
191
580
  exports.RateLimitPresets = {
192
581
  /**
193
582
  * Very strict limits for sensitive endpoints
583
+ * Use for: Password resets, account changes, payment operations
584
+ * Infrastructure: Any (universal protection)
194
585
  */
195
586
  STRICT: {
196
587
  maxRequests: 5,
@@ -198,14 +589,16 @@ exports.RateLimitPresets = {
198
589
  message: 'Too many requests to sensitive endpoint',
199
590
  },
200
591
  /**
201
- * Standard API limits
592
+ * Standard API limits with dynamic scaling for authenticated users
593
+ * Use for: Main API endpoints, data retrieval, business operations
594
+ * Infrastructure: Best with WAF or Gateway (higher baseline limits)
202
595
  */
203
596
  API: {
204
- maxRequests: 100,
597
+ maxRequests: 100, // Baseline for unauthenticated/free users
205
598
  windowMs: 60000, // 1 minute
206
599
  dynamicLimits: {
207
600
  authenticated: {
208
- maxRequests: 1000,
601
+ maxRequests: 1000, // 10x increase for authenticated users
209
602
  windowMs: 60000,
210
603
  matcher: (context) => !!context.user,
211
604
  },
@@ -213,25 +606,244 @@ exports.RateLimitPresets = {
213
606
  },
214
607
  /**
215
608
  * Authentication endpoint limits
609
+ * Use for: Login, registration, token refresh, password operations
610
+ * Infrastructure: Any (essential security protection)
216
611
  */
217
612
  AUTH: {
218
613
  maxRequests: 10,
219
614
  windowMs: 60000, // 1 minute
220
615
  message: 'Too many authentication attempts',
616
+ keyGenerator: (context) => {
617
+ // Rate limit per IP + email combination for better security
618
+ const ip = context.req.ip || 'unknown';
619
+ const email = context.req.parsedBody?.email;
620
+ return email ? `auth:${email}:${ip}` : `auth:${ip}`;
621
+ },
221
622
  },
222
623
  /**
223
- * Public endpoint limits
624
+ * Public endpoint limits for direct application exposure
625
+ * Use for: Public APIs, webhooks, health checks
626
+ * Infrastructure: Application only (no WAF/Gateway protection)
224
627
  */
225
628
  PUBLIC: {
226
629
  maxRequests: 50,
227
630
  windowMs: 60000, // 1 minute
631
+ dynamicLimits: {
632
+ // Be more restrictive with suspicious traffic patterns
633
+ suspicious: {
634
+ maxRequests: 10,
635
+ windowMs: 60000,
636
+ matcher: (context) => {
637
+ const userAgent = context.req.headers?.['user-agent'] || '';
638
+ return (!userAgent || userAgent.includes('bot') || userAgent.length < 10);
639
+ },
640
+ },
641
+ },
228
642
  },
229
643
  /**
230
- * Development mode - very permissive
644
+ * Development mode - very permissive limits
645
+ * Use for: Development, testing, debugging
646
+ * Infrastructure: Development environment only
231
647
  */
232
648
  DEVELOPMENT: {
233
649
  maxRequests: 10000,
234
650
  windowMs: 60000, // 1 minute
651
+ skip: (context) => {
652
+ // Skip rate limiting for localhost and development IPs
653
+ const ip = context.req.ip || '';
654
+ return (ip.startsWith('127.') ||
655
+ ip.startsWith('::1') ||
656
+ ip.startsWith('192.168.'));
657
+ },
658
+ },
659
+ /**
660
+ * Enterprise-grade configuration with multi-tier support
661
+ * Use for: Production SaaS applications, enterprise APIs
662
+ * Infrastructure: WAF + Gateway + Application (full stack protection)
663
+ */
664
+ ENTERPRISE: {
665
+ maxRequests: 200, // Higher baseline with multiple protection layers
666
+ windowMs: 60000,
667
+ dynamicLimits: {
668
+ free: {
669
+ maxRequests: 100,
670
+ windowMs: 60000,
671
+ matcher: (context) => !context.user || context.user?.plan === 'free',
672
+ },
673
+ premium: {
674
+ maxRequests: 1000,
675
+ windowMs: 60000,
676
+ matcher: (context) => context.user?.plan === 'premium',
677
+ },
678
+ enterprise: {
679
+ maxRequests: 5000,
680
+ windowMs: 60000,
681
+ matcher: (context) => context.user?.plan === 'enterprise',
682
+ },
683
+ admin: {
684
+ maxRequests: 10000,
685
+ windowMs: 60000,
686
+ matcher: (context) => context.user?.role === 'admin',
687
+ },
688
+ },
689
+ keyGenerator: (context) => {
690
+ // Use user ID for authenticated, IP for anonymous
691
+ return context.user?.id
692
+ ? `user:${context.user.id}`
693
+ : `ip:${context.req.ip}`;
694
+ },
235
695
  },
236
696
  };
697
+ /**
698
+ * Configuration helpers and utilities for rate limiting setup
699
+ *
700
+ * ## Best Practices for Production
701
+ *
702
+ * ### 1. Store Selection
703
+ * - **Development**: Use default `MemoryStore` (built-in)
704
+ * - **Production Single Instance**: Use `MemoryStore` with cleanup
705
+ * - **Production Multi-Instance**: Use Redis-based store
706
+ * - **Serverless**: Use external store (Redis/DynamoDB) for state persistence
707
+ *
708
+ * ### 2. Key Generation Strategy
709
+ * ```typescript
710
+ * // Bad: Too generic, easy to abuse
711
+ * keyGenerator: () => 'global'
712
+ *
713
+ * // Good: Multi-dimensional keys
714
+ * keyGenerator: (context) => {
715
+ * const user = context.user?.id;
716
+ * const endpoint = context.req.path?.split('/')[2]; // /api/users -> users
717
+ * const method = context.req.method;
718
+ * return user ? `${user}:${endpoint}:${method}` : `${context.req.ip}:${endpoint}`;
719
+ * }
720
+ * ```
721
+ *
722
+ * ### 3. Dynamic Limits Best Practices
723
+ * ```typescript
724
+ * // Order matchers from most specific to least specific
725
+ * dynamicLimits: {
726
+ * admin: { maxRequests: 10000, matcher: (ctx) => ctx.user?.role === 'admin' },
727
+ * enterprise: { maxRequests: 5000, matcher: (ctx) => ctx.user?.plan === 'enterprise' },
728
+ * premium: { maxRequests: 1000, matcher: (ctx) => ctx.user?.plan === 'premium' },
729
+ * authenticated: { maxRequests: 500, matcher: (ctx) => !!ctx.user },
730
+ * // Default fallback handled by maxRequests
731
+ * }
732
+ * ```
733
+ *
734
+ * ### 4. Error Handling and Fallback
735
+ * ```typescript
736
+ * const resilientRateLimit = rateLimiting({
737
+ * maxRequests: 100,
738
+ * windowMs: 60000,
739
+ *
740
+ * // Custom store with fallback
741
+ * store: new ResilientStore({
742
+ * primary: redisStore,
743
+ * fallback: new MemoryStore(),
744
+ * timeout: 500 // ms
745
+ * }),
746
+ *
747
+ * // Graceful degradation on errors
748
+ * onError: (error, context) => {
749
+ * logger.warn('Rate limiting error, allowing request', { error, ip: context.req.ip });
750
+ * return false; // Don't block request on store errors
751
+ * }
752
+ * });
753
+ * ```
754
+ *
755
+ * ### 5. Monitoring and Alerting
756
+ * ```typescript
757
+ * // Monitor rate limit effectiveness
758
+ * const monitoredRateLimit = rateLimiting({
759
+ * maxRequests: 100,
760
+ * windowMs: 60000,
761
+ *
762
+ * onRateLimit: (context, info) => {
763
+ * // Alert on high rate limit hits
764
+ * metrics.increment('rate_limit.exceeded', {
765
+ * endpoint: context.req.path,
766
+ * user: context.user?.id || 'anonymous'
767
+ * });
768
+ *
769
+ * // Log suspicious patterns
770
+ * if (info.current > info.limit * 2) {
771
+ * logger.warn('Potential abuse detected', {
772
+ * ip: context.req.ip,
773
+ * userAgent: context.req.headers?.['user-agent'],
774
+ * attempts: info.current
775
+ * });
776
+ * }
777
+ * }
778
+ * });
779
+ * ```
780
+ *
781
+ * ### 6. Testing Rate Limits
782
+ * ```typescript
783
+ * // Test helper for rate limit validation
784
+ * export const testRateLimit = async (
785
+ * handler: Handler,
786
+ * requests: number,
787
+ * shouldSucceed: number
788
+ * ) => {
789
+ * const results = await Promise.all(
790
+ * Array(requests).fill(0).map(() => handler.execute(mockRequest, mockResponse))
791
+ * );
792
+ *
793
+ * const successful = results.filter(r => r.statusCode !== 429).length;
794
+ * expect(successful).toBe(shouldSucceed);
795
+ * };
796
+ * ```
797
+ *
798
+ * ## Troubleshooting Common Issues
799
+ *
800
+ * ### Issue: Rate limits not working
801
+ * **Solution**: Check key generation and store connection
802
+ * ```typescript
803
+ * // Debug key generation
804
+ * keyGenerator: (context) => {
805
+ * const key = generateKey(context);
806
+ * console.log('Rate limit key:', key); // Remove in production
807
+ * return key;
808
+ * }
809
+ * ```
810
+ *
811
+ * ### Issue: Too many false positives
812
+ * **Solution**: Refine dynamic limits and key generation
813
+ * ```typescript
814
+ * // More granular limits
815
+ * dynamicLimits: {
816
+ * read: { maxRequests: 1000, matcher: (ctx) => ctx.req.method === 'GET' },
817
+ * write: { maxRequests: 100, matcher: (ctx) => ctx.req.method !== 'GET' }
818
+ * }
819
+ * ```
820
+ *
821
+ * ### Issue: Memory leaks in MemoryStore
822
+ * **Solution**: Ensure proper cleanup interval and limits
823
+ * ```typescript
824
+ * // Monitor store size
825
+ * setInterval(() => {
826
+ * const storeSize = memoryStore.size();
827
+ * if (storeSize > 10000) {
828
+ * logger.warn('Rate limit store size growing', { size: storeSize });
829
+ * }
830
+ * }, 60000);
831
+ * ```
832
+ *
833
+ * ### Issue: Rate limits too restrictive
834
+ * **Solution**: Implement gradual enforcement
835
+ * ```typescript
836
+ * const gradualLimit = rateLimiting({
837
+ * maxRequests: 100,
838
+ * windowMs: 60000,
839
+ *
840
+ * // Warn before blocking
841
+ * onApproachingLimit: (context, info) => {
842
+ * if (info.remaining < 10) {
843
+ * context.res.header('X-Rate-Limit-Warning', 'Approaching limit');
844
+ * }
845
+ * }
846
+ * });
847
+ * ```
848
+ */
237
849
  //# sourceMappingURL=rateLimitingMiddleware.js.map