"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var UsageInterceptor_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.UsageInterceptor = void 0; const common_1 = require("@nestjs/common"); const rxjs_1 = require("rxjs"); const usage_service_1 = require("./usage.service"); const tenant_entity_1 = require("../auth/entities/tenant.entity"); let UsageInterceptor = UsageInterceptor_1 = class UsageInterceptor { usageService; logger = new common_1.Logger(UsageInterceptor_1.name); constructor(usageService) { this.usageService = usageService; } async intercept(context, next) { const request = context.switchToHttp().getRequest(); const tenant = request.tenant; const apiKey = request.apiKey; if (tenant && apiKey && !request.url.includes('/auth/management')) { this.logger.debug(`📊 Monitoring request for Tenant: ${tenant.id}`); const plan = tenant.plan || tenant_entity_1.TenantPlan.FREE; const limit = tenant_entity_1.QUOTA_LIMITS[plan]; const { allowed: quotaAllowed, used: monthlyUsed } = await this.usageService.checkQuota(tenant.id, limit); if (!quotaAllowed) { throw new common_1.HttpException({ statusCode: common_1.HttpStatus.TOO_MANY_REQUESTS, error: 'Quota Exceeded', message: 'Monthly API usage quota exceeded', used: monthlyUsed, limit, upgrade_url: 'https://map-dashbord.intaleqapp.com/#billing' }, common_1.HttpStatus.TOO_MANY_REQUESTS); } const rpmLimit = tenant_entity_1.RATE_LIMITS[plan]; const { allowed: rateAllowed, used: currentRpm } = await this.usageService.checkRateLimit(tenant.id, rpmLimit); if (!rateAllowed) { throw new common_1.HttpException({ statusCode: common_1.HttpStatus.TOO_MANY_REQUESTS, error: 'Rate Limit Exceeded', message: `Request rate limit exceeded (${rpmLimit} req/min for ${plan} plan)`, current_rate: currentRpm, limit: rpmLimit, retry_after: '60s' }, common_1.HttpStatus.TOO_MANY_REQUESTS); } } const startTime = Date.now(); return next.handle().pipe((0, rxjs_1.tap)(() => { if (tenant && apiKey) { const response = context.switchToHttp().getResponse(); const responseTimeMs = Date.now() - startTime; this.logger.log(`📈 Usage Recorded: ${request.method} ${request.url.split('?')[0]} for Tenant ${tenant.id}`); this.usageService.recordRequest({ tenantId: tenant.id, apiKeyId: apiKey.id, endpoint: request.url.split('?')[0], method: request.method, statusCode: response.statusCode, responseTimeMs, userAgent: request.headers['user-agent'], ipAddress: request.ip || request.headers['x-forwarded-for'], }); } })); } }; exports.UsageInterceptor = UsageInterceptor; exports.UsageInterceptor = UsageInterceptor = UsageInterceptor_1 = __decorate([ (0, common_1.Injectable)(), __metadata("design:paramtypes", [usage_service_1.UsageService]) ], UsageInterceptor); //# sourceMappingURL=usage.interceptor.js.map