secure-kit
Version:
Production-grade security + performance toolkit for backend frameworks with OWASP Top 10 compliance
105 lines • 3.11 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.AdvancedRateLimiter = void 0;
class AdvancedRateLimiter {
constructor(config) {
this.store = new Map();
this.config = {
windowMs: 15 * 60 * 1000, // 15 minutes default
max: 100,
maxRequests: 100,
...config,
};
// Cleanup expired entries every minute
this.cleanupInterval = setInterval(() => {
this.cleanup();
}, 60000);
}
/**
* Check if a request should be rate limited
*/
isAllowed(identifier) {
const now = Date.now();
const limits = {
windowMs: this.config.windowMs || 15 * 60 * 1000,
maxRequests: this.config.maxRequests || this.config.max || 100,
};
let entry = this.store.get(identifier);
if (!entry || now > entry.resetTime) {
// Create new entry or reset expired one
entry = {
count: 0,
resetTime: now + limits.windowMs,
violations: entry?.violations || 0,
};
}
// Check if limit exceeded
if (entry.count >= limits.maxRequests) {
entry.violations++;
this.store.set(identifier, entry);
return {
allowed: false,
remaining: 0,
resetTime: entry.resetTime,
retryAfter: Math.ceil((entry.resetTime - now) / 1000),
};
}
// Increment count and store
entry.count++;
this.store.set(identifier, entry);
return {
allowed: true,
remaining: limits.maxRequests - entry.count,
resetTime: entry.resetTime,
};
}
/**
* Clean up expired entries from store
*/
cleanup() {
const now = Date.now();
const toDelete = [];
for (const [key, entry] of this.store.entries()) {
if (now > entry.resetTime && entry.violations === 0) {
toDelete.push(key);
}
}
toDelete.forEach(key => this.store.delete(key));
}
/**
* Get current statistics
*/
getStats() {
const now = Date.now();
let activeEntries = 0;
let totalViolations = 0;
for (const entry of this.store.values()) {
if (now <= entry.resetTime) {
activeEntries++;
}
totalViolations += entry.violations;
}
return {
totalEntries: this.store.size,
activeEntries,
totalViolations,
};
}
/**
* Reset rate limit for a specific identifier
*/
reset(identifier) {
this.store.delete(identifier);
}
/**
* Destroy the rate limiter and cleanup
*/
destroy() {
if (this.cleanupInterval) {
clearInterval(this.cleanupInterval);
}
this.store.clear();
}
}
exports.AdvancedRateLimiter = AdvancedRateLimiter;
//# sourceMappingURL=advanced-rate-limiter.js.map
;