UNPKG

express-rate-limiter-ts

Version:

A powerful, flexible and modern rate limiter middleware for Express.js written in TypeScript.

107 lines (106 loc) 3.96 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MongoStore = void 0; const mongodb_1 = require("mongodb"); // MongoStore: Production için tam çalışan, asenkron, TTL ve ban destekli bir store. class MongoStore { constructor(options) { this.windowMs = options.windowMs; this.client = new mongodb_1.MongoClient(options.uri); } // Start connection (should be called on first use) async connect() { if (!this.db) { await this.client.connect(); this.db = this.client.db(); this.counters = this.db.collection('rateLimiter_counters'); this.bans = this.db.collection('rateLimiter_bans'); this.stats = this.db.collection('rateLimiter_stats'); // Create TTL indexes (one time only) await this.counters.createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 }); await this.bans.createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 }); } } // Increment counter and check limit async incr(key) { var _a, _b; await this.connect(); const now = new Date(); const expiresAt = new Date(now.getTime() + this.windowMs); const result = await this.counters.findOneAndUpdate({ key }, { $inc: { count: 1 }, $setOnInsert: { createdAt: now }, $set: { expiresAt }, }, { upsert: true, returnDocument: 'after' }); return { current: (_b = (_a = result === null || result === void 0 ? void 0 : result.value) === null || _a === void 0 ? void 0 : _a.count) !== null && _b !== void 0 ? _b : 1, remaining: 0, // Remaining limit will be calculated in middleware resetTime: expiresAt, exceeded: false, }; } // Read counter async get(key) { await this.connect(); const doc = await this.counters.findOne({ key }); if (!doc) return { count: 0, resetTime: Date.now() + this.windowMs }; return { count: doc.count, resetTime: doc.expiresAt.getTime() }; } // Reset counter async reset(key) { await this.connect(); await this.counters.deleteOne({ key }); } // Record statistics async recordStat(route) { await this.connect(); await this.stats.updateOne({ route }, { $inc: { count: 1 }, $set: { lastTriggered: new Date() } }, { upsert: true }); } // Get statistics async getStats() { await this.connect(); const docs = await this.stats.find().toArray(); const stats = {}; for (const doc of docs) { stats[doc.route] = { count: doc.count, lastTriggered: doc.lastTriggered, }; } return stats; } // Apply ban async ban(key, seconds, reason) { await this.connect(); const expiresAt = new Date(Date.now() + seconds * 1000); await this.bans.updateOne({ key }, { $set: { reason, expiresAt } }, { upsert: true }); } // Check ban async isBanned(key) { await this.connect(); const doc = await this.bans.findOne({ key }); if (doc && doc.expiresAt > new Date()) { return { banned: true, banExpiresAt: doc.expiresAt, reason: doc.reason }; } return { banned: false }; } // Get banned keys async getBanned() { await this.connect(); const now = new Date(); const docs = await this.bans.find({ expiresAt: { $gt: now } }).toArray(); const result = {}; for (const doc of docs) { result[doc.key] = { banExpiresAt: doc.expiresAt, reason: doc.reason }; } return result; } // Remove ban async unban(key) { await this.connect(); await this.bans.deleteOne({ key }); await this.counters.deleteOne({ key }); } } exports.MongoStore = MongoStore;