te.js 2.1.0 → 2.1.2

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 (70) hide show
  1. package/README.md +197 -196
  2. package/auto-docs/analysis/handler-analyzer.js +58 -58
  3. package/auto-docs/analysis/source-resolver.js +101 -101
  4. package/auto-docs/constants.js +37 -37
  5. package/auto-docs/docs-llm/index.js +7 -7
  6. package/auto-docs/docs-llm/prompts.js +222 -222
  7. package/auto-docs/docs-llm/provider.js +132 -132
  8. package/auto-docs/index.js +146 -146
  9. package/auto-docs/openapi/endpoint-processor.js +277 -277
  10. package/auto-docs/openapi/generator.js +107 -107
  11. package/auto-docs/openapi/level3.js +131 -131
  12. package/auto-docs/openapi/spec-builders.js +244 -244
  13. package/auto-docs/ui/docs-ui.js +186 -186
  14. package/auto-docs/utils/logger.js +17 -17
  15. package/auto-docs/utils/strip-usage.js +10 -10
  16. package/cli/docs-command.js +315 -315
  17. package/cli/fly-command.js +71 -71
  18. package/cli/index.js +56 -56
  19. package/cors/index.js +71 -0
  20. package/database/index.js +165 -165
  21. package/database/mongodb.js +146 -146
  22. package/database/redis.js +201 -201
  23. package/docs/README.md +36 -36
  24. package/docs/ammo.md +362 -362
  25. package/docs/api-reference.md +490 -490
  26. package/docs/auto-docs.md +216 -216
  27. package/docs/cli.md +152 -152
  28. package/docs/configuration.md +275 -275
  29. package/docs/database.md +390 -390
  30. package/docs/error-handling.md +438 -438
  31. package/docs/file-uploads.md +333 -333
  32. package/docs/getting-started.md +214 -214
  33. package/docs/middleware.md +355 -355
  34. package/docs/rate-limiting.md +393 -393
  35. package/docs/routing.md +302 -302
  36. package/lib/llm/client.js +73 -0
  37. package/lib/llm/index.js +7 -0
  38. package/lib/llm/parse.js +89 -0
  39. package/package.json +64 -62
  40. package/rate-limit/algorithms/fixed-window.js +141 -141
  41. package/rate-limit/algorithms/sliding-window.js +147 -147
  42. package/rate-limit/algorithms/token-bucket.js +115 -115
  43. package/rate-limit/base.js +165 -165
  44. package/rate-limit/index.js +147 -147
  45. package/rate-limit/storage/base.js +104 -104
  46. package/rate-limit/storage/memory.js +101 -101
  47. package/rate-limit/storage/redis.js +88 -88
  48. package/server/ammo/body-parser.js +220 -220
  49. package/server/ammo/dispatch-helper.js +103 -103
  50. package/server/ammo/enhancer.js +57 -57
  51. package/server/ammo.js +454 -415
  52. package/server/endpoint.js +97 -74
  53. package/server/error.js +9 -9
  54. package/server/errors/code-context.js +125 -125
  55. package/server/errors/llm-error-service.js +140 -140
  56. package/server/files/helper.js +33 -33
  57. package/server/files/uploader.js +143 -143
  58. package/server/handler.js +158 -119
  59. package/server/target.js +185 -175
  60. package/server/targets/middleware-validator.js +22 -22
  61. package/server/targets/path-validator.js +21 -21
  62. package/server/targets/registry.js +160 -160
  63. package/server/targets/shoot-validator.js +21 -21
  64. package/te.js +428 -402
  65. package/utils/auto-register.js +17 -17
  66. package/utils/configuration.js +64 -64
  67. package/utils/errors-llm-config.js +84 -84
  68. package/utils/request-logger.js +43 -43
  69. package/utils/status-codes.js +82 -82
  70. package/utils/tejas-entrypoint-html.js +18 -18
@@ -1,393 +1,393 @@
1
- # Rate Limiting
2
-
3
- Tejas includes a powerful rate limiting system to protect your API from abuse. It supports multiple algorithms and storage backends.
4
-
5
- ## Quick Start
6
-
7
- ```javascript
8
- import Tejas from 'te.js';
9
-
10
- const app = new Tejas();
11
-
12
- app
13
- .withRedis({ url: 'redis://localhost:6379' })
14
- .withRateLimit({
15
- maxRequests: 100,
16
- timeWindowSeconds: 60
17
- })
18
- .takeoff();
19
- ```
20
-
21
- This limits all endpoints to 100 requests per minute per IP address.
22
-
23
- ## Configuration Options
24
-
25
- ```javascript
26
- app.withRateLimit({
27
- // Core settings
28
- maxRequests: 100, // Maximum requests in time window
29
- timeWindowSeconds: 60, // Time window in seconds
30
-
31
- // Algorithm selection
32
- algorithm: 'sliding-window', // 'sliding-window' | 'token-bucket' | 'fixed-window'
33
-
34
- // Storage backend
35
- store: 'redis', // 'redis' | 'memory'
36
-
37
- // Custom key generator (defaults to IP-based)
38
- keyGenerator: (ammo) => ammo.ip,
39
-
40
- // Algorithm-specific options
41
- algorithmOptions: {},
42
-
43
- // Key prefix for storage keys (useful for namespacing)
44
- keyPrefix: 'rl:',
45
-
46
- // Header format
47
- headerFormat: {
48
- type: 'standard', // 'standard' | 'legacy' | 'both'
49
- draft7: false, // Include RateLimit-Policy header (e.g. "100;w=60")
50
- draft8: false // Use delta-seconds for RateLimit-Reset instead of Unix timestamp
51
- },
52
-
53
- // Custom handler when rate limited
54
- onRateLimited: (ammo) => {
55
- ammo.fire(429, { error: 'Slow down!' });
56
- }
57
- });
58
- ```
59
-
60
- ## Algorithms
61
-
62
- ### Sliding Window (Default)
63
-
64
- Best for smooth, accurate rate limiting. Prevents the "burst at window boundary" problem.
65
-
66
- ```javascript
67
- app.withRateLimit({
68
- maxRequests: 100,
69
- timeWindowSeconds: 60,
70
- algorithm: 'sliding-window'
71
- });
72
- ```
73
-
74
- **How it works:** Calculates the request rate using a weighted combination of the current and previous time windows.
75
-
76
- ### Token Bucket
77
-
78
- Best for APIs that allow occasional bursts while maintaining a long-term average rate.
79
-
80
- ```javascript
81
- app.withRateLimit({
82
- maxRequests: 100,
83
- timeWindowSeconds: 60,
84
- algorithm: 'token-bucket',
85
- algorithmOptions: {
86
- refillRate: 1.67, // Tokens per second (100/60)
87
- burstSize: 150 // Maximum tokens (allows 50% burst)
88
- }
89
- });
90
- ```
91
-
92
- **How it works:** Tokens are added at a steady rate. Each request consumes a token. Allows bursts up to `burstSize`.
93
-
94
- ### Fixed Window
95
-
96
- Simplest algorithm. Good for basic use cases.
97
-
98
- ```javascript
99
- app.withRateLimit({
100
- maxRequests: 100,
101
- timeWindowSeconds: 60,
102
- algorithm: 'fixed-window',
103
- algorithmOptions: {
104
- strictWindow: true // Align to clock boundaries
105
- }
106
- });
107
- ```
108
-
109
- **How it works:** Counts requests in fixed time windows (e.g., every minute). Can allow 2x requests at window boundaries.
110
-
111
- ## Storage Backends
112
-
113
- ### Memory (Default)
114
-
115
- Good for single-server deployments:
116
-
117
- ```javascript
118
- app.withRateLimit({
119
- maxRequests: 100,
120
- timeWindowSeconds: 60,
121
- store: 'memory'
122
- });
123
- ```
124
-
125
- **Pros:** No external dependencies, fast
126
- **Cons:** Not shared between server instances
127
-
128
- ### Redis
129
-
130
- Required for distributed/multi-server deployments:
131
-
132
- ```javascript
133
- app
134
- .withRedis({ url: 'redis://localhost:6379' })
135
- .withRateLimit({
136
- maxRequests: 100,
137
- timeWindowSeconds: 60,
138
- store: 'redis'
139
- });
140
- ```
141
-
142
- **Pros:** Shared across all servers, persistent
143
- **Cons:** Requires Redis server, slightly higher latency
144
-
145
- > **Important:** Initialize Redis with `withRedis()` before using `store: 'redis'`
146
-
147
- ## Custom Key Generation
148
-
149
- By default, rate limiting is based on client IP. Customize this:
150
-
151
- ### By User ID
152
-
153
- ```javascript
154
- app.withRateLimit({
155
- maxRequests: 100,
156
- timeWindowSeconds: 60,
157
- keyGenerator: (ammo) => ammo.user?.id || ammo.ip
158
- });
159
- ```
160
-
161
- ### By API Key
162
-
163
- ```javascript
164
- app.withRateLimit({
165
- maxRequests: 1000,
166
- timeWindowSeconds: 60,
167
- keyGenerator: (ammo) => ammo.headers['x-api-key'] || ammo.ip
168
- });
169
- ```
170
-
171
- ### By Endpoint
172
-
173
- ```javascript
174
- app.withRateLimit({
175
- maxRequests: 100,
176
- timeWindowSeconds: 60,
177
- keyGenerator: (ammo) => `${ammo.ip}:${ammo.endpoint}`
178
- });
179
- ```
180
-
181
- ## Response Headers
182
-
183
- Rate limit headers are automatically added to responses:
184
-
185
- ### Standard Headers (Default)
186
-
187
- ```
188
- RateLimit-Limit: 100
189
- RateLimit-Remaining: 95
190
- RateLimit-Reset: 1706540400
191
- ```
192
-
193
- ### Legacy Headers
194
-
195
- ```javascript
196
- app.withRateLimit({
197
- headerFormat: { type: 'legacy' }
198
- });
199
- ```
200
-
201
- ```
202
- X-RateLimit-Limit: 100
203
- X-RateLimit-Remaining: 95
204
- X-RateLimit-Reset: 1706540400
205
- ```
206
-
207
- ### Both Header Types
208
-
209
- ```javascript
210
- app.withRateLimit({
211
- headerFormat: { type: 'both' }
212
- });
213
- ```
214
-
215
- ### Draft 7 Policy Header
216
-
217
- ```javascript
218
- app.withRateLimit({
219
- headerFormat: { type: 'standard', draft7: true }
220
- });
221
- ```
222
-
223
- Adds: `RateLimit-Policy: 100;w=60`
224
-
225
- ## When Rate Limited
226
-
227
- ### Default Behavior
228
-
229
- Returns `429 Too Many Requests` with a `Retry-After` header (seconds until the rate limit resets).
230
-
231
- ### Custom Handler
232
-
233
- ```javascript
234
- app.withRateLimit({
235
- maxRequests: 100,
236
- timeWindowSeconds: 60,
237
- onRateLimited: (ammo) => {
238
- ammo.fire(429, {
239
- error: 'Rate limit exceeded',
240
- message: 'Please slow down and try again later',
241
- retryAfter: ammo.res.getHeader('Retry-After')
242
- });
243
- }
244
- });
245
- ```
246
-
247
- ## Route-Specific Rate Limiting
248
-
249
- Apply different limits to different routes using middleware:
250
-
251
- ```javascript
252
- import Tejas, { Target } from 'te.js';
253
- import rateLimiter from 'te.js/rate-limit/index.js';
254
-
255
- const app = new Tejas();
256
- const api = new Target('/api');
257
-
258
- // Strict limit for auth endpoints
259
- const authLimiter = rateLimiter({
260
- maxRequests: 5,
261
- timeWindowSeconds: 60,
262
- algorithm: 'fixed-window'
263
- });
264
-
265
- // Relaxed limit for read operations
266
- const readLimiter = rateLimiter({
267
- maxRequests: 1000,
268
- timeWindowSeconds: 60,
269
- algorithm: 'sliding-window'
270
- });
271
-
272
- // Apply to specific routes
273
- api.register('/login', authLimiter, (ammo) => {
274
- // Login logic
275
- });
276
-
277
- api.register('/data', readLimiter, (ammo) => {
278
- // Data retrieval
279
- });
280
- ```
281
-
282
- ## Algorithm Comparison
283
-
284
- | Algorithm | Best For | Burst Handling | Accuracy | Memory |
285
- |-----------|----------|----------------|----------|--------|
286
- | **Sliding Window** | Most APIs | Smooth | High | Medium |
287
- | **Token Bucket** | Burst-tolerant APIs | Allows bursts | Medium | Low |
288
- | **Fixed Window** | Simple cases | Poor at boundaries | Low | Low |
289
-
290
- ## Examples
291
-
292
- ### API with Different Tiers
293
-
294
- ```javascript
295
- const tierLimits = {
296
- free: { maxRequests: 100, timeWindowSeconds: 3600 },
297
- pro: { maxRequests: 1000, timeWindowSeconds: 3600 },
298
- enterprise: { maxRequests: 10000, timeWindowSeconds: 3600 }
299
- };
300
-
301
- app.withRateLimit({
302
- ...tierLimits.free, // Default to free tier
303
- keyGenerator: (ammo) => {
304
- const tier = ammo.user?.tier || 'free';
305
- return `${tier}:${ammo.user?.id || ammo.ip}`;
306
- },
307
- algorithmOptions: {
308
- // Dynamically set limits based on tier
309
- getLimits: (key) => {
310
- const tier = key.split(':')[0];
311
- return tierLimits[tier] || tierLimits.free;
312
- }
313
- }
314
- });
315
- ```
316
-
317
- ### Endpoint-Specific with Global Fallback
318
-
319
- ```javascript
320
- // Global rate limit
321
- app.withRateLimit({
322
- maxRequests: 1000,
323
- timeWindowSeconds: 60
324
- });
325
-
326
- // Stricter limit for expensive endpoints
327
- const expensiveLimiter = rateLimiter({
328
- maxRequests: 10,
329
- timeWindowSeconds: 60,
330
- store: 'redis'
331
- });
332
-
333
- api.register('/search', expensiveLimiter, (ammo) => {
334
- // Search logic
335
- });
336
-
337
- api.register('/export', expensiveLimiter, (ammo) => {
338
- // Export logic
339
- });
340
- ```
341
-
342
- ## Monitoring
343
-
344
- Check rate limit status in your handlers:
345
-
346
- ```javascript
347
- target.register('/status', (ammo) => {
348
- ammo.fire({
349
- limit: ammo.res.getHeader('RateLimit-Limit'),
350
- remaining: ammo.res.getHeader('RateLimit-Remaining'),
351
- reset: ammo.res.getHeader('RateLimit-Reset')
352
- });
353
- });
354
- ```
355
-
356
- ## Custom Storage Backend
357
-
358
- Extend the `RateLimitStorage` base class to create your own storage backend:
359
-
360
- ```javascript
361
- import RateLimitStorage from 'te.js/rate-limit/storage/base.js';
362
-
363
- class PostgresStorage extends RateLimitStorage {
364
- async get(key) {
365
- // Retrieve rate limit data for key
366
- // Return object or null if not found
367
- }
368
-
369
- async set(key, value, ttl) {
370
- // Store rate limit data with TTL (seconds)
371
- }
372
-
373
- async increment(key) {
374
- // Increment counter, return new value or null
375
- }
376
-
377
- async delete(key) {
378
- // Delete rate limit data for key
379
- }
380
- }
381
- ```
382
-
383
- The built-in backends (`MemoryStorage` and `RedisStorage`) both extend this base class.
384
-
385
- ## Best Practices
386
-
387
- 1. **Use Redis in production** — Memory store doesn't scale across instances
388
- 2. **Set appropriate limits** — Too strict frustrates users, too lenient invites abuse
389
- 3. **Different limits for different endpoints** — Auth endpoints need stricter limits
390
- 4. **Include headers** — Help clients self-regulate
391
- 5. **Provide clear error messages** — Tell users when they can retry
392
- 6. **Consider user tiers** — Premium users may need higher limits
393
- 7. **Monitor and adjust** — Track rate limit hits and adjust accordingly
1
+ # Rate Limiting
2
+
3
+ Tejas includes a powerful rate limiting system to protect your API from abuse. It supports multiple algorithms and storage backends.
4
+
5
+ ## Quick Start
6
+
7
+ ```javascript
8
+ import Tejas from 'te.js';
9
+
10
+ const app = new Tejas();
11
+
12
+ app
13
+ .withRedis({ url: 'redis://localhost:6379' })
14
+ .withRateLimit({
15
+ maxRequests: 100,
16
+ timeWindowSeconds: 60
17
+ })
18
+ .takeoff();
19
+ ```
20
+
21
+ This limits all endpoints to 100 requests per minute per IP address.
22
+
23
+ ## Configuration Options
24
+
25
+ ```javascript
26
+ app.withRateLimit({
27
+ // Core settings
28
+ maxRequests: 100, // Maximum requests in time window
29
+ timeWindowSeconds: 60, // Time window in seconds
30
+
31
+ // Algorithm selection
32
+ algorithm: 'sliding-window', // 'sliding-window' | 'token-bucket' | 'fixed-window'
33
+
34
+ // Storage backend
35
+ store: 'redis', // 'redis' | 'memory'
36
+
37
+ // Custom key generator (defaults to IP-based)
38
+ keyGenerator: (ammo) => ammo.ip,
39
+
40
+ // Algorithm-specific options
41
+ algorithmOptions: {},
42
+
43
+ // Key prefix for storage keys (useful for namespacing)
44
+ keyPrefix: 'rl:',
45
+
46
+ // Header format
47
+ headerFormat: {
48
+ type: 'standard', // 'standard' | 'legacy' | 'both'
49
+ draft7: false, // Include RateLimit-Policy header (e.g. "100;w=60")
50
+ draft8: false // Use delta-seconds for RateLimit-Reset instead of Unix timestamp
51
+ },
52
+
53
+ // Custom handler when rate limited
54
+ onRateLimited: (ammo) => {
55
+ ammo.fire(429, { error: 'Slow down!' });
56
+ }
57
+ });
58
+ ```
59
+
60
+ ## Algorithms
61
+
62
+ ### Sliding Window (Default)
63
+
64
+ Best for smooth, accurate rate limiting. Prevents the "burst at window boundary" problem.
65
+
66
+ ```javascript
67
+ app.withRateLimit({
68
+ maxRequests: 100,
69
+ timeWindowSeconds: 60,
70
+ algorithm: 'sliding-window'
71
+ });
72
+ ```
73
+
74
+ **How it works:** Calculates the request rate using a weighted combination of the current and previous time windows.
75
+
76
+ ### Token Bucket
77
+
78
+ Best for APIs that allow occasional bursts while maintaining a long-term average rate.
79
+
80
+ ```javascript
81
+ app.withRateLimit({
82
+ maxRequests: 100,
83
+ timeWindowSeconds: 60,
84
+ algorithm: 'token-bucket',
85
+ algorithmOptions: {
86
+ refillRate: 1.67, // Tokens per second (100/60)
87
+ burstSize: 150 // Maximum tokens (allows 50% burst)
88
+ }
89
+ });
90
+ ```
91
+
92
+ **How it works:** Tokens are added at a steady rate. Each request consumes a token. Allows bursts up to `burstSize`.
93
+
94
+ ### Fixed Window
95
+
96
+ Simplest algorithm. Good for basic use cases.
97
+
98
+ ```javascript
99
+ app.withRateLimit({
100
+ maxRequests: 100,
101
+ timeWindowSeconds: 60,
102
+ algorithm: 'fixed-window',
103
+ algorithmOptions: {
104
+ strictWindow: true // Align to clock boundaries
105
+ }
106
+ });
107
+ ```
108
+
109
+ **How it works:** Counts requests in fixed time windows (e.g., every minute). Can allow 2x requests at window boundaries.
110
+
111
+ ## Storage Backends
112
+
113
+ ### Memory (Default)
114
+
115
+ Good for single-server deployments:
116
+
117
+ ```javascript
118
+ app.withRateLimit({
119
+ maxRequests: 100,
120
+ timeWindowSeconds: 60,
121
+ store: 'memory'
122
+ });
123
+ ```
124
+
125
+ **Pros:** No external dependencies, fast
126
+ **Cons:** Not shared between server instances
127
+
128
+ ### Redis
129
+
130
+ Required for distributed/multi-server deployments:
131
+
132
+ ```javascript
133
+ app
134
+ .withRedis({ url: 'redis://localhost:6379' })
135
+ .withRateLimit({
136
+ maxRequests: 100,
137
+ timeWindowSeconds: 60,
138
+ store: 'redis'
139
+ });
140
+ ```
141
+
142
+ **Pros:** Shared across all servers, persistent
143
+ **Cons:** Requires Redis server, slightly higher latency
144
+
145
+ > **Important:** Initialize Redis with `withRedis()` before using `store: 'redis'`
146
+
147
+ ## Custom Key Generation
148
+
149
+ By default, rate limiting is based on client IP. Customize this:
150
+
151
+ ### By User ID
152
+
153
+ ```javascript
154
+ app.withRateLimit({
155
+ maxRequests: 100,
156
+ timeWindowSeconds: 60,
157
+ keyGenerator: (ammo) => ammo.user?.id || ammo.ip
158
+ });
159
+ ```
160
+
161
+ ### By API Key
162
+
163
+ ```javascript
164
+ app.withRateLimit({
165
+ maxRequests: 1000,
166
+ timeWindowSeconds: 60,
167
+ keyGenerator: (ammo) => ammo.headers['x-api-key'] || ammo.ip
168
+ });
169
+ ```
170
+
171
+ ### By Endpoint
172
+
173
+ ```javascript
174
+ app.withRateLimit({
175
+ maxRequests: 100,
176
+ timeWindowSeconds: 60,
177
+ keyGenerator: (ammo) => `${ammo.ip}:${ammo.endpoint}`
178
+ });
179
+ ```
180
+
181
+ ## Response Headers
182
+
183
+ Rate limit headers are automatically added to responses:
184
+
185
+ ### Standard Headers (Default)
186
+
187
+ ```
188
+ RateLimit-Limit: 100
189
+ RateLimit-Remaining: 95
190
+ RateLimit-Reset: 1706540400
191
+ ```
192
+
193
+ ### Legacy Headers
194
+
195
+ ```javascript
196
+ app.withRateLimit({
197
+ headerFormat: { type: 'legacy' }
198
+ });
199
+ ```
200
+
201
+ ```
202
+ X-RateLimit-Limit: 100
203
+ X-RateLimit-Remaining: 95
204
+ X-RateLimit-Reset: 1706540400
205
+ ```
206
+
207
+ ### Both Header Types
208
+
209
+ ```javascript
210
+ app.withRateLimit({
211
+ headerFormat: { type: 'both' }
212
+ });
213
+ ```
214
+
215
+ ### Draft 7 Policy Header
216
+
217
+ ```javascript
218
+ app.withRateLimit({
219
+ headerFormat: { type: 'standard', draft7: true }
220
+ });
221
+ ```
222
+
223
+ Adds: `RateLimit-Policy: 100;w=60`
224
+
225
+ ## When Rate Limited
226
+
227
+ ### Default Behavior
228
+
229
+ Returns `429 Too Many Requests` with a `Retry-After` header (seconds until the rate limit resets).
230
+
231
+ ### Custom Handler
232
+
233
+ ```javascript
234
+ app.withRateLimit({
235
+ maxRequests: 100,
236
+ timeWindowSeconds: 60,
237
+ onRateLimited: (ammo) => {
238
+ ammo.fire(429, {
239
+ error: 'Rate limit exceeded',
240
+ message: 'Please slow down and try again later',
241
+ retryAfter: ammo.res.getHeader('Retry-After')
242
+ });
243
+ }
244
+ });
245
+ ```
246
+
247
+ ## Route-Specific Rate Limiting
248
+
249
+ Apply different limits to different routes using middleware:
250
+
251
+ ```javascript
252
+ import Tejas, { Target } from 'te.js';
253
+ import rateLimiter from 'te.js/rate-limit/index.js';
254
+
255
+ const app = new Tejas();
256
+ const api = new Target('/api');
257
+
258
+ // Strict limit for auth endpoints
259
+ const authLimiter = rateLimiter({
260
+ maxRequests: 5,
261
+ timeWindowSeconds: 60,
262
+ algorithm: 'fixed-window'
263
+ });
264
+
265
+ // Relaxed limit for read operations
266
+ const readLimiter = rateLimiter({
267
+ maxRequests: 1000,
268
+ timeWindowSeconds: 60,
269
+ algorithm: 'sliding-window'
270
+ });
271
+
272
+ // Apply to specific routes
273
+ api.register('/login', authLimiter, (ammo) => {
274
+ // Login logic
275
+ });
276
+
277
+ api.register('/data', readLimiter, (ammo) => {
278
+ // Data retrieval
279
+ });
280
+ ```
281
+
282
+ ## Algorithm Comparison
283
+
284
+ | Algorithm | Best For | Burst Handling | Accuracy | Memory |
285
+ |-----------|----------|----------------|----------|--------|
286
+ | **Sliding Window** | Most APIs | Smooth | High | Medium |
287
+ | **Token Bucket** | Burst-tolerant APIs | Allows bursts | Medium | Low |
288
+ | **Fixed Window** | Simple cases | Poor at boundaries | Low | Low |
289
+
290
+ ## Examples
291
+
292
+ ### API with Different Tiers
293
+
294
+ ```javascript
295
+ const tierLimits = {
296
+ free: { maxRequests: 100, timeWindowSeconds: 3600 },
297
+ pro: { maxRequests: 1000, timeWindowSeconds: 3600 },
298
+ enterprise: { maxRequests: 10000, timeWindowSeconds: 3600 }
299
+ };
300
+
301
+ app.withRateLimit({
302
+ ...tierLimits.free, // Default to free tier
303
+ keyGenerator: (ammo) => {
304
+ const tier = ammo.user?.tier || 'free';
305
+ return `${tier}:${ammo.user?.id || ammo.ip}`;
306
+ },
307
+ algorithmOptions: {
308
+ // Dynamically set limits based on tier
309
+ getLimits: (key) => {
310
+ const tier = key.split(':')[0];
311
+ return tierLimits[tier] || tierLimits.free;
312
+ }
313
+ }
314
+ });
315
+ ```
316
+
317
+ ### Endpoint-Specific with Global Fallback
318
+
319
+ ```javascript
320
+ // Global rate limit
321
+ app.withRateLimit({
322
+ maxRequests: 1000,
323
+ timeWindowSeconds: 60
324
+ });
325
+
326
+ // Stricter limit for expensive endpoints
327
+ const expensiveLimiter = rateLimiter({
328
+ maxRequests: 10,
329
+ timeWindowSeconds: 60,
330
+ store: 'redis'
331
+ });
332
+
333
+ api.register('/search', expensiveLimiter, (ammo) => {
334
+ // Search logic
335
+ });
336
+
337
+ api.register('/export', expensiveLimiter, (ammo) => {
338
+ // Export logic
339
+ });
340
+ ```
341
+
342
+ ## Monitoring
343
+
344
+ Check rate limit status in your handlers:
345
+
346
+ ```javascript
347
+ target.register('/status', (ammo) => {
348
+ ammo.fire({
349
+ limit: ammo.res.getHeader('RateLimit-Limit'),
350
+ remaining: ammo.res.getHeader('RateLimit-Remaining'),
351
+ reset: ammo.res.getHeader('RateLimit-Reset')
352
+ });
353
+ });
354
+ ```
355
+
356
+ ## Custom Storage Backend
357
+
358
+ Extend the `RateLimitStorage` base class to create your own storage backend:
359
+
360
+ ```javascript
361
+ import RateLimitStorage from 'te.js/rate-limit/storage/base.js';
362
+
363
+ class PostgresStorage extends RateLimitStorage {
364
+ async get(key) {
365
+ // Retrieve rate limit data for key
366
+ // Return object or null if not found
367
+ }
368
+
369
+ async set(key, value, ttl) {
370
+ // Store rate limit data with TTL (seconds)
371
+ }
372
+
373
+ async increment(key) {
374
+ // Increment counter, return new value or null
375
+ }
376
+
377
+ async delete(key) {
378
+ // Delete rate limit data for key
379
+ }
380
+ }
381
+ ```
382
+
383
+ The built-in backends (`MemoryStorage` and `RedisStorage`) both extend this base class.
384
+
385
+ ## Best Practices
386
+
387
+ 1. **Use Redis in production** — Memory store doesn't scale across instances
388
+ 2. **Set appropriate limits** — Too strict frustrates users, too lenient invites abuse
389
+ 3. **Different limits for different endpoints** — Auth endpoints need stricter limits
390
+ 4. **Include headers** — Help clients self-regulate
391
+ 5. **Provide clear error messages** — Tell users when they can retry
392
+ 6. **Consider user tiers** — Premium users may need higher limits
393
+ 7. **Monitor and adjust** — Track rate limit hits and adjust accordingly