UNPKG

@canmertinyo/rate-limiter-mongo

Version:

A simple rate-limiting middleware for Express.js with support for in-memory, Redis, and MongoDB storage

84 lines (65 loc) 2.03 kB
import { RateLimiter, RateLimitRecord } from "@canmertinyo/rate-limiter-core"; import mongoose from "mongoose"; import { RateLimitModel } from "./schemas/rate-limit.schema"; export class MongoStorage implements RateLimiter { private model: mongoose.Model<RateLimitRecord> = RateLimitModel; constructor( private readonly uri: string = "mongodb://localhost:27017/rate-limits", private readonly options?: mongoose.ConnectOptions ) {} public async initialize(): Promise<RateLimiter> { await mongoose.connect(this.uri, this.options); return this; } public async getRateLimitRecord( key: string ): Promise<RateLimitRecord | undefined> { const record = await this.model.findOne({ key }); if (!record) return; var { _id, ...object } = record.toObject(); return record ? object : undefined; } public async createRateLimitRecord( record: RateLimitRecord ): Promise<RateLimitRecord> { const newRecord = await this.model.create(record); newRecord.save(); var { _id, ...object } = newRecord.toObject(); return object as RateLimitRecord; } public async updateRateLimitRecord( key: string, timestamp: number, count: number ): Promise<RateLimitRecord> { const record = await this.model.findOneAndUpdate( { key }, { timestamp, count, }, { new: true, } ); if (!record) { throw new Error("No record found."); } var { _id, ...object } = record.toObject(); return object as RateLimitRecord; } public async increment(key: string): Promise<RateLimitRecord> { const record = await this.model.findOneAndUpdate( { key }, { $inc: { count: 1 } }, { new: true, } ); if (!record) { throw new Error("No record found to increment."); } var { _id, ...object } = record.toObject(); return object as RateLimitRecord; } }