import { Injectable, ExecutionContext, Inject } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { ThrottlerGuard, ThrottlerStorage, getOptionsToken, getStorageToken } from '@nestjs/throttler'; import { SystemConfigService, CONFIG_KEYS } from '../modules/system-config/system-config.service'; // Route-prefix → throttler tier mapping. // Evaluated in order; first match wins. const ROUTE_TIERS: Array<{ prefix: string; tier: 'auth' | 'strict' | 'default' }> = [ { prefix: '/auth', tier: 'auth' }, { prefix: '/fayda/verification',tier: 'auth' }, { prefix: '/bookings', tier: 'strict' }, { prefix: '/passengers', tier: 'strict' }, { prefix: '/payments', tier: 'strict' }, { prefix: '/wallet', tier: 'strict' }, ]; @Injectable() export class DynamicThrottlerGuard extends ThrottlerGuard { constructor( @Inject(getOptionsToken()) options: any, @Inject(getStorageToken()) storageService: ThrottlerStorage, reflector: Reflector, private readonly systemConfig: SystemConfigService, ) { super(options, storageService, reflector); } async canActivate(context: ExecutionContext): Promise { if (context.getType() !== 'http') { return true; } const [authLimit, authTtl, strictLimit, strictTtl, defaultLimit, defaultTtl] = await Promise.all([ this.systemConfig.getNumber(CONFIG_KEYS.THROTTLE_AUTH_LIMIT), this.systemConfig.getNumber(CONFIG_KEYS.THROTTLE_AUTH_TTL_MS), this.systemConfig.getNumber(CONFIG_KEYS.THROTTLE_STRICT_LIMIT), this.systemConfig.getNumber(CONFIG_KEYS.THROTTLE_STRICT_TTL_MS), this.systemConfig.getNumber(CONFIG_KEYS.THROTTLE_DEFAULT_LIMIT), this.systemConfig.getNumber(CONFIG_KEYS.THROTTLE_DEFAULT_TTL_MS), ]); const url: string = context.switchToHttp().getRequest<{ url: string }>().url ?? ''; const matched = ROUTE_TIERS.find(({ prefix }) => url.startsWith(prefix)); const tier = matched?.tier ?? 'default'; if (tier === 'auth') { this.throttlers = [{ name: 'auth', ttl: authTtl, limit: authLimit }]; } else if (tier === 'strict') { this.throttlers = [{ name: 'strict', ttl: strictTtl, limit: strictLimit }]; } else { this.throttlers = [{ name: 'default', ttl: defaultTtl, limit: defaultLimit }]; } return super.canActivate(context); } }