nextlimiter 1.0.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,246 @@
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>;