diff --git a/.eslintrc.js b/.eslintrc.js index 44474b80..a241d9ec 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -36,7 +36,6 @@ module.exports = { '@typescript-eslint/no-namespace': 'off', // Allow @ts-nocheck / @ts-ignore where needed (tracked separately) '@typescript-eslint/ban-ts-comment': 'off', - // Disallow console.log in production code - 'no-console': 'off', + 'no-console': 'error', }, }; diff --git a/src/auth/rate-limit.service.ts b/src/auth/rate-limit.service.ts index e4be5c8d..d6b48522 100644 --- a/src/auth/rate-limit.service.ts +++ b/src/auth/rate-limit.service.ts @@ -1,6 +1,6 @@ // @ts-nocheck -import { Injectable, Inject } from '@nestjs/common'; +import { Injectable, Inject, Logger } from '@nestjs/common'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { Cache } from 'cache-manager'; import { @@ -26,6 +26,8 @@ export interface RateLimitRecord { @Injectable() export class RateLimitService { + private readonly logger = new Logger(RateLimitService.name); + constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {} /** @@ -127,7 +129,7 @@ export class RateLimitService { }; } catch (error) { // If cache is unavailable, allow the request - console.error('Rate limit check failed:', error); + this.logger.error('Rate limit check failed:', error instanceof Error ? error.stack : error); return { limit, remaining: limit - 1, diff --git a/src/config/swagger.config.ts b/src/config/swagger.config.ts index 35b215e9..76346c73 100644 --- a/src/config/swagger.config.ts +++ b/src/config/swagger.config.ts @@ -6,7 +6,9 @@ */ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; -import { INestApplication } from '@nestjs/common'; +import { INestApplication, Logger } from '@nestjs/common'; + +const logger = new Logger('SwaggerConfig'); export function setupSwagger(app: INestApplication): void { const config = new DocumentBuilder() @@ -120,7 +122,7 @@ export function setupSwagger(app: INestApplication): void { ], }); - console.log('✅ Swagger UI available at http://localhost:3000/api/docs'); + logger.log('Swagger UI available at http://localhost:3000/api/docs'); } /** diff --git a/src/notifications/notifications.service.ts b/src/notifications/notifications.service.ts index 73db87f9..bb25ea7d 100644 --- a/src/notifications/notifications.service.ts +++ b/src/notifications/notifications.service.ts @@ -1,6 +1,6 @@ // @ts-nocheck -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { PrismaService } from '../database/prisma.service'; import { NotificationsGateway } from './notifications.gateway'; import { EmailService } from '../email/email.service'; @@ -35,6 +35,8 @@ const NOTIFICATION_PREFERENCES_DEFAULTS = { @Injectable() export class NotificationsService { + private readonly logger = new Logger(NotificationsService.name); + constructor( private prisma: PrismaService, private gateway: NotificationsGateway, @@ -133,7 +135,7 @@ export class NotificationsService { select: { fcmToken: true }, }); if (user?.fcmToken) { - console.log(`Sending FCM notification to token: ${user.fcmToken}`); + this.logger.log(`Sending FCM notification to token: ${user.fcmToken}`); // In production, use admin.messaging().send() here } const delivered = this.gateway.sendToUser(userId, 'notification', notification); diff --git a/src/users/email-verification.service.ts b/src/users/email-verification.service.ts index 104bdcf9..e4e41da2 100644 --- a/src/users/email-verification.service.ts +++ b/src/users/email-verification.service.ts @@ -1,6 +1,6 @@ // @ts-nocheck -import { Injectable, BadRequestException, NotFoundException } from '@nestjs/common'; +import { Injectable, BadRequestException, NotFoundException, Logger } from '@nestjs/common'; import { PrismaService } from '../database/prisma.service'; import { ChangeEmailDto } from './dto/email-change.dto'; import { randomBytes } from 'crypto'; @@ -10,6 +10,8 @@ import { RateLimitService } from '../auth/rate-limit.service'; @Injectable() export class EmailVerificationService { + private readonly logger = new Logger(EmailVerificationService.name); + constructor( private prisma: PrismaService, private emailService: EmailService, @@ -65,7 +67,7 @@ export class EmailVerificationService { }) .catch((err) => { // Fail quietly but log - console.error('Failed to queue verification email:', err?.message || err); + this.logger.error('Failed to queue verification email:', err?.message || err); }); return { @@ -113,7 +115,7 @@ export class EmailVerificationService { emailType: 'email_verification', }) .catch((err) => { - console.error('Failed to queue verification email:', err?.message || err); + this.logger.error('Failed to queue verification email:', err?.message || err); }); return { message: 'Verification email resent' }; diff --git a/src/utils/validate-env.ts b/src/utils/validate-env.ts index ec479418..95fe6353 100644 --- a/src/utils/validate-env.ts +++ b/src/utils/validate-env.ts @@ -1,3 +1,7 @@ +import { Logger } from '@nestjs/common'; + +const logger = new Logger('EnvValidation'); + const REQUIRED_ENV_VARS = ['DATABASE_URL', 'JWT_SECRET', 'JWT_REFRESH_SECRET'] as const; const JWT_SECRET_VARS = ['JWT_SECRET', 'JWT_REFRESH_SECRET'] as const; const MIN_JWT_SECRET_LENGTH = 32; @@ -32,7 +36,7 @@ export function validateEnvironment(): void { WEAK.map((k) => ` - ${k}`).join('\n'), ); } - console.error( + logger.error( `\n Fatal:\n ` + sections.join('\n\n ') + `\n\n Please set them in .env or .env.local before starting the application.\n`, diff --git a/src/versioning/examples.controller.ts b/src/versioning/examples.controller.ts index 6c1deae3..5118d967 100644 --- a/src/versioning/examples.controller.ts +++ b/src/versioning/examples.controller.ts @@ -5,8 +5,7 @@ * This demonstrates how to implement versioning in controllers */ -// eslint-disable-next-line @typescript-eslint/no-unused-vars -import { Controller, Get, Post, Body, Param, Put, Delete, UseGuards, Query } from '@nestjs/common'; +import { Controller, Get, Post, Body, Param, Put, Delete, Logger } from '@nestjs/common'; import { ApiVersion } from '../versioning/api-version.decorator'; import { GetVersion } from '../versioning/get-version.decorator'; import { ApiVersionEnum } from '../versioning/api-version.constants'; @@ -20,6 +19,8 @@ import { ApiVersionEnum } from '../versioning/api-version.constants'; */ @Controller('users') export class UsersControllerExample { + private readonly logger = new Logger(UsersControllerExample.name); + /** * V1 & V2: List all users * Both versions support this endpoint with same response format @@ -28,7 +29,7 @@ export class UsersControllerExample { @ApiVersion([ApiVersionEnum.V1, ApiVersionEnum.V2]) findAll(@GetVersion() version: ApiVersionEnum) { // Can branch logic based on version if needed - console.log(`Getting users for version: ${version}`); + this.logger.log(`Getting users for version: ${version}`); return { users: [], version,