@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
text/typescript
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;
}
}