nextlimiter 1.0.0 → 1.0.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.
package/types/index.d.ts CHANGED
@@ -1,246 +1,277 @@
1
- // NexLimit — TypeScript type definitions
2
- // Compatible with @types/node and @types/express
3
-
4
- import { Request, Response, NextFunction } from 'express';
5
-
6
- // ── Store interface ──────────────────────────────────────────────────────────
7
-
8
- export interface Store {
9
- get(key: string): any;
10
- set(key: string, value: any, ttlMs: number): void;
11
- increment(key: string, ttlMs: number): number;
12
- delete(key: string): void;
13
- keys(): string[];
14
- clear(): void;
15
- }
16
-
17
- // ── Plan definitions ─────────────────────────────────────────────────────────
18
-
19
- export interface PlanDefinition {
20
- windowMs: number;
21
- max: number;
22
- burstMax?: number;
23
- description?: string;
24
- }
25
-
26
- export type BuiltInPlan = 'free' | 'pro' | 'enterprise';
27
- export type BuiltInPreset = 'strict' | 'relaxed' | 'api' | 'auth';
28
- export type Strategy = 'fixed-window' | 'sliding-window' | 'token-bucket';
29
- export type KeyBy = 'ip' | 'user-id' | 'api-key';
30
-
31
- // ── Configuration ────────────────────────────────────────────────────────────
32
-
33
- export interface LimiterOptions {
34
- /** Time window in milliseconds. Default: 60000 (1 minute) */
35
- windowMs?: number;
36
-
37
- /** Maximum number of requests per window. Default: 100 */
38
- max?: number;
39
-
40
- /** Rate limiting algorithm. Default: 'sliding-window' */
41
- strategy?: Strategy;
42
-
43
- /** How to generate the rate limit key. Default: 'ip' */
44
- keyBy?: KeyBy | ((req: Request) => string);
45
-
46
- /** Redis key prefix. Default: 'nexlimit:' */
47
- keyPrefix?: string;
48
-
49
- /** SaaS plan name — overrides windowMs and max */
50
- plan?: BuiltInPlan | string;
51
-
52
- /** Named preset to use as base configuration */
53
- preset?: BuiltInPreset;
54
-
55
- /** Custom plan definitions (extend or replace built-in plans) */
56
- plans?: Record<string, PlanDefinition>;
57
-
58
- /** Enable behavior-based smart rate limiting. Default: false */
59
- smart?: boolean;
60
-
61
- /** Burst threshold multiplier that triggers smart penalty. Default: 2.0 */
62
- smartThreshold?: number;
63
-
64
- /** How long smart penalty lasts in ms. Default: 60000 */
65
- smartCooldownMs?: number;
66
-
67
- /** Reduce limit to this fraction when penalized. Default: 0.5 */
68
- smartPenaltyFactor?: number;
69
-
70
- /** Enable request logging. Default: false */
71
- logging?: boolean;
72
-
73
- /** Log prefix string. Default: '[NexLimit]' */
74
- logPrefix?: string;
75
-
76
- /** Send X-RateLimit-* headers. Default: true */
77
- headers?: boolean;
78
-
79
- /** HTTP status code for blocked requests. Default: 429 */
80
- statusCode?: number;
81
-
82
- /** Message body for blocked requests */
83
- message?: string;
84
-
85
- /** Custom storage backend */
86
- store?: Store;
87
-
88
- /**
89
- * Return true to skip rate limiting for this request.
90
- * Useful for whitelisting internal services or health checks.
91
- */
92
- skip?: (req: Request) => boolean;
93
-
94
- /** Called when a request is blocked. Replaces the default 429 response. */
95
- onLimitReached?: (req: Request, res: Response, info: RateLimitResult) => void;
96
-
97
- /** Fully custom key generator function */
98
- keyGenerator?: (req: Request) => string;
99
- }
100
-
101
- // ── Rate limit result ────────────────────────────────────────────────────────
102
-
103
- export interface RateLimitResult {
104
- /** Whether this request is allowed to proceed */
105
- allowed: boolean;
106
-
107
- /** Maximum requests per window */
108
- limit: number;
109
-
110
- /** Remaining requests in current window */
111
- remaining: number;
112
-
113
- /** Unix timestamp (ms) when the window resets */
114
- resetAt: number;
115
-
116
- /** Seconds to wait before retrying (0 if allowed) */
117
- retryAfter: number;
118
-
119
- /** The resolved rate limit key */
120
- key: string;
121
-
122
- /** Strategy used for this check */
123
- strategy: Strategy;
124
-
125
- /** True if blocked specifically by smart limiting */
126
- smartBlocked: boolean;
127
-
128
- /** Seconds until resetAt */
129
- readonly retryAfterSeconds: number;
130
-
131
- toJSON(): Omit<RateLimitResult, 'key' | 'strategy' | 'smartBlocked' | 'retryAfterSeconds' | 'toJSON'>;
132
- }
133
-
134
- // ── Analytics ────────────────────────────────────────────────────────────────
135
-
136
- export interface KeyCount {
137
- key: string;
138
- count: number;
139
- }
140
-
141
- export interface SmartPenalizedKey {
142
- key: string;
143
- expiresAt: number;
144
- remainingMs: number;
145
- }
146
-
147
- export interface LimiterStats {
148
- totalRequests: number;
149
- blockedRequests: number;
150
- allowedRequests: number;
151
- blockRate: number;
152
- topKeys: KeyCount[];
153
- topBlocked: KeyCount[];
154
- trackedSince: string;
155
- uptimeMs: number;
156
- smartLimiting?: {
157
- enabled: boolean;
158
- penalizedKeys: SmartPenalizedKey[];
159
- };
160
- config: {
161
- strategy: Strategy;
162
- windowMs: number;
163
- max: number;
164
- keyBy: string;
165
- plan: string;
166
- smart: boolean;
167
- };
168
- }
169
-
170
- // ── Limiter class ────────────────────────────────────────────────────────────
171
-
172
- export declare class Limiter {
173
- constructor(options?: LimiterOptions);
174
-
175
- /** Returns an Express-compatible middleware function */
176
- middleware(): (req: Request, res: Response, next: NextFunction) => Promise<void>;
177
-
178
- /** Programmatic rate limit check by key string */
179
- check(key: string): Promise<RateLimitResult>;
180
-
181
- /** Reset rate limit state for a specific key */
182
- reset(key: string): Promise<void>;
183
-
184
- /** Get analytics snapshot */
185
- getStats(): LimiterStats;
186
-
187
- /** Reset analytics counters */
188
- resetStats(): void;
189
-
190
- /** Read-only resolved configuration */
191
- readonly config: Readonly<Required<LimiterOptions>>;
192
- }
193
-
194
- // ── Factory functions ────────────────────────────────────────────────────────
195
-
196
- /**
197
- * Create a fully configured Limiter instance.
198
- *
199
- * @example
200
- * const limiter = createLimiter({ windowMs: 60_000, max: 100 });
201
- * app.use(limiter.middleware());
202
- */
203
- export declare function createLimiter(options?: LimiterOptions): Limiter;
204
-
205
- /**
206
- * Zero-config middleware. Returns an Express handler directly.
207
- *
208
- * @example
209
- * app.use(autoLimit());
210
- */
211
- export declare function autoLimit(options?: LimiterOptions): ReturnType<Limiter['middleware']>;
212
-
213
- /**
214
- * Create a limiter pre-configured for a SaaS plan tier.
215
- *
216
- * @example
217
- * const limiter = createPlanLimiter('pro', { keyBy: 'api-key' });
218
- */
219
- export declare function createPlanLimiter(plan: BuiltInPlan | string, options?: LimiterOptions): Limiter;
220
-
221
- /**
222
- * Create a limiter from a named preset.
223
- *
224
- * @example
225
- * app.post('/login', createPresetLimiter('auth').middleware());
226
- */
227
- export declare function createPresetLimiter(preset: BuiltInPreset, options?: LimiterOptions): Limiter;
228
-
229
- // ── Storage ──────────────────────────────────────────────────────────────────
230
-
231
- export declare class MemoryStore implements Store {
232
- constructor();
233
- get(key: string): any;
234
- set(key: string, value: any, ttlMs: number): void;
235
- increment(key: string, ttlMs: number): number;
236
- delete(key: string): void;
237
- keys(): string[];
238
- clear(): void;
239
- destroy(): void;
240
- readonly size: number;
241
- }
242
-
243
- // ── Constants ────────────────────────────────────────────────────────────────
244
-
245
- export declare const PRESETS: Record<BuiltInPreset, LimiterOptions>;
246
- export declare const DEFAULT_PLANS: Record<BuiltInPlan, PlanDefinition>;
1
+ // NextLimiter — TypeScript type definitions
2
+ // Compatible with @types/node and @types/express
3
+
4
+ import { Request, Response, NextFunction } from 'express';
5
+
6
+ // ── Store interface ──────────────────────────────────────────────────────────
7
+
8
+ export interface Store {
9
+ get(key: string): any;
10
+ set(key: string, value: any, ttlMs: number): void;
11
+ increment(key: string, ttlMs: number): number;
12
+ delete(key: string): void;
13
+ keys(): string[];
14
+ clear(): void;
15
+ }
16
+
17
+ // ── Plan definitions ─────────────────────────────────────────────────────────
18
+
19
+ export interface PlanDefinition {
20
+ windowMs: number;
21
+ max: number;
22
+ burstMax?: number;
23
+ description?: string;
24
+ }
25
+
26
+ export type BuiltInPlan = 'free' | 'pro' | 'enterprise';
27
+ export type BuiltInPreset = 'strict' | 'relaxed' | 'api' | 'auth';
28
+ export type Strategy = 'fixed-window' | 'sliding-window' | 'token-bucket';
29
+ export type KeyBy = 'ip' | 'user-id' | 'api-key';
30
+
31
+ // ── Configuration ────────────────────────────────────────────────────────────
32
+
33
+ export interface LimiterOptions {
34
+ /** Time window in milliseconds. Default: 60000 (1 minute) */
35
+ windowMs?: number;
36
+
37
+ /** Maximum number of requests per window. Default: 100 */
38
+ max?: number;
39
+
40
+ /** Rate limiting algorithm. Default: 'sliding-window' */
41
+ strategy?: Strategy;
42
+
43
+ /** How to generate the rate limit key. Default: 'ip' */
44
+ keyBy?: KeyBy | ((req: Request) => string);
45
+
46
+ /** Redis key prefix. Default: 'nextlimiter:' */
47
+ keyPrefix?: string;
48
+
49
+ /** SaaS plan name — overrides windowMs and max */
50
+ plan?: BuiltInPlan | string;
51
+
52
+ /** Named preset to use as base configuration */
53
+ preset?: BuiltInPreset;
54
+
55
+ /** Custom plan definitions (extend or replace built-in plans) */
56
+ plans?: Record<string, PlanDefinition>;
57
+
58
+ /** Enable behavior-based smart rate limiting. Default: false */
59
+ smart?: boolean;
60
+
61
+ /** Burst threshold multiplier that triggers smart penalty. Default: 2.0 */
62
+ smartThreshold?: number;
63
+
64
+ /** How long smart penalty lasts in ms. Default: 60000 */
65
+ smartCooldownMs?: number;
66
+
67
+ /** Reduce limit to this fraction when penalized. Default: 0.5 */
68
+ smartPenaltyFactor?: number;
69
+
70
+ /** Enable request logging. Default: false */
71
+ logging?: boolean;
72
+
73
+ /** Log prefix string. Default: '[NextLimiter]' */
74
+ logPrefix?: string;
75
+
76
+ /** Send X-RateLimit-* headers. Default: true */
77
+ headers?: boolean;
78
+
79
+ /** HTTP status code for blocked requests. Default: 429 */
80
+ statusCode?: number;
81
+
82
+ /** Message body for blocked requests */
83
+ message?: string;
84
+
85
+ /** Custom storage backend */
86
+ store?: Store;
87
+
88
+ /**
89
+ * Return true to skip rate limiting for this request.
90
+ * Useful for whitelisting internal services or health checks.
91
+ */
92
+ skip?: (req: Request) => boolean;
93
+
94
+ /** Called when a request is blocked. Replaces the default 429 response. */
95
+ onLimitReached?: (req: Request, res: Response, info: RateLimitResult) => void;
96
+
97
+ /** Fully custom key generator function */
98
+ keyGenerator?: (req: Request) => string;
99
+ }
100
+
101
+ // ── Rate limit result ────────────────────────────────────────────────────────
102
+
103
+ export interface RateLimitResult {
104
+ /** Whether this request is allowed to proceed */
105
+ allowed: boolean;
106
+
107
+ /** Maximum requests per window */
108
+ limit: number;
109
+
110
+ /** Remaining requests in current window */
111
+ remaining: number;
112
+
113
+ /** Unix timestamp (ms) when the window resets */
114
+ resetAt: number;
115
+
116
+ /** Seconds to wait before retrying (0 if allowed) */
117
+ retryAfter: number;
118
+
119
+ /** The resolved rate limit key */
120
+ key: string;
121
+
122
+ /** Strategy used for this check */
123
+ strategy: Strategy;
124
+
125
+ /** True if blocked specifically by smart limiting */
126
+ smartBlocked: boolean;
127
+
128
+ /** Seconds until resetAt */
129
+ readonly retryAfterSeconds: number;
130
+
131
+ toJSON(): Omit<RateLimitResult, 'key' | 'strategy' | 'smartBlocked' | 'retryAfterSeconds' | 'toJSON'>;
132
+ }
133
+
134
+ // ── Analytics ────────────────────────────────────────────────────────────────
135
+
136
+ export interface KeyCount {
137
+ key: string;
138
+ count: number;
139
+ }
140
+
141
+ export interface SmartPenalizedKey {
142
+ key: string;
143
+ expiresAt: number;
144
+ remainingMs: number;
145
+ }
146
+
147
+ export interface LimiterStats {
148
+ totalRequests: number;
149
+ blockedRequests: number;
150
+ allowedRequests: number;
151
+ blockRate: number;
152
+ topKeys: KeyCount[];
153
+ topBlocked: KeyCount[];
154
+ trackedSince: string;
155
+ uptimeMs: number;
156
+ smartLimiting?: {
157
+ enabled: boolean;
158
+ penalizedKeys: SmartPenalizedKey[];
159
+ };
160
+ config: {
161
+ strategy: Strategy;
162
+ windowMs: number;
163
+ max: number;
164
+ keyBy: string;
165
+ plan: string;
166
+ smart: boolean;
167
+ };
168
+ }
169
+
170
+ // ── Limiter class ────────────────────────────────────────────────────────────
171
+
172
+ export declare class Limiter {
173
+ constructor(options?: LimiterOptions);
174
+
175
+ /** Returns an Express-compatible middleware function */
176
+ middleware(): (req: Request, res: Response, next: NextFunction) => Promise<void>;
177
+
178
+ /** Programmatic rate limit check by key string */
179
+ check(key: string): Promise<RateLimitResult>;
180
+
181
+ /** Reset rate limit state for a specific key */
182
+ reset(key: string): Promise<void>;
183
+
184
+ /** Get analytics snapshot */
185
+ getStats(): LimiterStats;
186
+
187
+ /** Reset analytics counters */
188
+ resetStats(): void;
189
+
190
+ /** Read-only resolved configuration */
191
+ readonly config: Readonly<Required<LimiterOptions>>;
192
+ }
193
+
194
+ // ── Factory functions ────────────────────────────────────────────────────────
195
+
196
+ /**
197
+ * Create a fully configured Limiter instance.
198
+ *
199
+ * @example
200
+ * const limiter = createLimiter({ windowMs: 60_000, max: 100 });
201
+ * app.use(limiter.middleware());
202
+ */
203
+ export declare function createLimiter(options?: LimiterOptions): Limiter;
204
+
205
+ /**
206
+ * Zero-config middleware. Returns an Express handler directly.
207
+ *
208
+ * @example
209
+ * app.use(autoLimit());
210
+ */
211
+ export declare function autoLimit(options?: LimiterOptions): ReturnType<Limiter['middleware']>;
212
+
213
+ /**
214
+ * Create a limiter pre-configured for a SaaS plan tier.
215
+ *
216
+ * @example
217
+ * const limiter = createPlanLimiter('pro', { keyBy: 'api-key' });
218
+ */
219
+ export declare function createPlanLimiter(plan: BuiltInPlan | string, options?: LimiterOptions): Limiter;
220
+
221
+ /**
222
+ * Create a limiter from a named preset.
223
+ *
224
+ * @example
225
+ * app.post('/login', createPresetLimiter('auth').middleware());
226
+ */
227
+ export declare function createPresetLimiter(preset: BuiltInPreset, options?: LimiterOptions): Limiter;
228
+
229
+ // ── Storage ──────────────────────────────────────────────────────────────────
230
+
231
+ export declare class MemoryStore implements Store {
232
+ constructor();
233
+ get(key: string): any;
234
+ set(key: string, value: any, ttlMs: number): void;
235
+ increment(key: string, ttlMs: number): number;
236
+ delete(key: string): void;
237
+ keys(): string[];
238
+ clear(): void;
239
+ destroy(): void;
240
+ readonly size: number;
241
+ }
242
+
243
+ /**
244
+ * RedisStore — Redis-backed storage backend for NextLimiter.
245
+ *
246
+ * Requires ioredis to be installed separately:
247
+ * npm install ioredis
248
+ *
249
+ * Uses an atomic Lua script for increment — race-condition safe across
250
+ * multiple Node.js processes behind a load balancer.
251
+ *
252
+ * @example
253
+ * import Redis from 'ioredis';
254
+ * import { createLimiter, RedisStore } from 'nextlimiter';
255
+ *
256
+ * const redis = new Redis();
257
+ * const limiter = createLimiter({ store: new RedisStore(redis), max: 100 });
258
+ * app.use('/api', limiter.middleware());
259
+ */
260
+ export declare class RedisStore implements Store {
261
+ /**
262
+ * @param client - A connected ioredis client instance
263
+ */
264
+ constructor(client: any);
265
+ get(key: string): Promise<any>;
266
+ set(key: string, value: any, ttlMs: number): Promise<void>;
267
+ /** Atomically increments the counter using a Lua script. */
268
+ increment(key: string, ttlMs: number): Promise<number>;
269
+ delete(key: string): Promise<void>;
270
+ keys(): string[];
271
+ clear(): void;
272
+ }
273
+
274
+ // ── Constants ────────────────────────────────────────────────────────────────
275
+
276
+ export declare const PRESETS: Record<BuiltInPreset, LimiterOptions>;
277
+ export declare const DEFAULT_PLANS: Record<BuiltInPlan, PlanDefinition>;