RateLimitService implements fixed-window counters as one atomic
PostgreSQL upsert (race-safe under concurrency, proven by test), with
opportunistic sweeping of expired windows and an explicit reset for
successful-login scenarios. The global RateLimitGuard applies
@RateLimit({scope, limit, windowSeconds}) per client IP and answers
429 with Retry-After; main.ts trusts the single Caddy hop so req.ip
is the real client.
Closes #11
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
18 lines
551 B
TypeScript
18 lines
551 B
TypeScript
import { Global, Module } from '@nestjs/common';
|
|
import { APP_GUARD } from '@nestjs/core';
|
|
|
|
import { RateLimitGuard } from './rate-limit.guard';
|
|
import { RateLimitService } from './rate-limit.service';
|
|
|
|
/**
|
|
* Global: the guard runs for every route but only acts where a handler
|
|
* carries @RateLimit metadata; the service is injectable everywhere for
|
|
* account-scoped limits.
|
|
*/
|
|
@Global()
|
|
@Module({
|
|
providers: [RateLimitService, { provide: APP_GUARD, useClass: RateLimitGuard }],
|
|
exports: [RateLimitService],
|
|
})
|
|
export class RateLimitModule {}
|