From cc5c81904bcdc53cfd152748d9615114423ba091 Mon Sep 17 00:00:00 2001 From: Ho Ngoc Hai Date: Wed, 8 Apr 2026 13:22:07 +0700 Subject: [PATCH] fix(lint): resolve all 49 lint warnings and errors across codebase - Remove unused imports/variables in seed scripts and test files - Replace console.log with console.warn in seed/utility scripts - Replace `as any` with proper Prisma types (InputJsonValue, PaymentStatus, Plan, UserWhereInput) - Fix import-x/no-named-as-default-member warnings in logger, mapbox, eslint config - Prefix unused callback params with underscore in e2e tests Co-Authored-By: Paperclip --- .../prisma-admin-query.repository.ts | 5 +++-- .../repositories/prisma-valuation.repository.ts | 6 +++--- .../repositories/prisma-user.repository.ts | 6 +++--- .../__tests__/create-listing.handler.spec.ts | 1 - .../repositories/prisma-property.repository.ts | 4 ++-- .../__tests__/create-payment.handler.spec.ts | 2 -- .../handle-callback/handle-callback.handler.ts | 3 ++- .../repositories/prisma-payment.repository.ts | 6 +++--- .../shared/infrastructure/logger.service.ts | 6 +++--- .../queries/check-quota/check-quota.handler.ts | 5 +++-- .../queries/get-plan/get-plan.handler.ts | 3 ++- apps/web/components/map/listing-map.tsx | 1 + e2e/web/auth-oauth-callback.spec.ts | 4 ++-- eslint.config.mjs | 1 + prisma/seed.ts | 8 ++++---- scripts/import-market-data.ts | 8 ++++---- scripts/seed-districts.ts | 16 ++++++++-------- scripts/seed-plans.ts | 6 +++--- 18 files changed, 47 insertions(+), 44 deletions(-) diff --git a/apps/api/src/modules/admin/infrastructure/repositories/prisma-admin-query.repository.ts b/apps/api/src/modules/admin/infrastructure/repositories/prisma-admin-query.repository.ts index 085f760..2b0ab94 100644 --- a/apps/api/src/modules/admin/infrastructure/repositories/prisma-admin-query.repository.ts +++ b/apps/api/src/modules/admin/infrastructure/repositories/prisma-admin-query.repository.ts @@ -1,4 +1,5 @@ import { Injectable } from '@nestjs/common'; +import { type Prisma, type UserRole } from '@prisma/client'; import { type PrismaService } from '@modules/shared/infrastructure/prisma.service'; import { type IAdminQueryRepository, @@ -163,8 +164,8 @@ export class PrismaAdminQueryRepository implements IAdminQueryRepository { const { page, limit, role, isActive, search } = params; const skip = (page - 1) * limit; - const where: any = {}; - if (role) where.role = role; + const where: Prisma.UserWhereInput = {}; + if (role) where.role = role as UserRole; if (isActive !== undefined) where.isActive = isActive; if (search) { where.OR = [ diff --git a/apps/api/src/modules/analytics/infrastructure/repositories/prisma-valuation.repository.ts b/apps/api/src/modules/analytics/infrastructure/repositories/prisma-valuation.repository.ts index 63c53e6..21bcaca 100644 --- a/apps/api/src/modules/analytics/infrastructure/repositories/prisma-valuation.repository.ts +++ b/apps/api/src/modules/analytics/infrastructure/repositories/prisma-valuation.repository.ts @@ -1,5 +1,5 @@ import { Injectable } from '@nestjs/common'; -import { type Valuation as PrismaValuation } from '@prisma/client'; +import { type Prisma, type Valuation as PrismaValuation } from '@prisma/client'; import { type PrismaService } from '@modules/shared/infrastructure/prisma.service'; import { ValuationEntity, type ValuationProps } from '../../domain/entities/valuation.entity'; import { type IValuationRepository } from '../../domain/repositories/valuation.repository'; @@ -38,8 +38,8 @@ export class PrismaValuationRepository implements IValuationRepository { estimatedPrice: entity.estimatedPrice, confidence: entity.confidence, pricePerM2: entity.pricePerM2, - comparables: entity.comparables as any, - features: entity.features as any, + comparables: entity.comparables as Prisma.InputJsonValue, + features: entity.features as Prisma.InputJsonValue, modelVersion: entity.modelVersion, }, }); diff --git a/apps/api/src/modules/auth/infrastructure/repositories/prisma-user.repository.ts b/apps/api/src/modules/auth/infrastructure/repositories/prisma-user.repository.ts index fddf257..58129a3 100644 --- a/apps/api/src/modules/auth/infrastructure/repositories/prisma-user.repository.ts +++ b/apps/api/src/modules/auth/infrastructure/repositories/prisma-user.repository.ts @@ -1,5 +1,5 @@ import { Injectable } from '@nestjs/common'; -import { type User as PrismaUser } from '@prisma/client'; +import { type Prisma, type User as PrismaUser } from '@prisma/client'; import { type PrismaService } from '@modules/shared/infrastructure/prisma.service'; import { UserEntity, type UserProps } from '../../domain/entities/user.entity'; import { type IUserRepository } from '../../domain/repositories/user.repository'; @@ -37,7 +37,7 @@ export class PrismaUserRepository implements IUserRepository { avatarUrl: entity.avatarUrl, role: entity.role, kycStatus: entity.kycStatus, - kycData: entity.kycData as any, + kycData: entity.kycData as Prisma.InputJsonValue, isActive: entity.isActive, }, }); @@ -54,7 +54,7 @@ export class PrismaUserRepository implements IUserRepository { avatarUrl: entity.avatarUrl, role: entity.role, kycStatus: entity.kycStatus, - kycData: entity.kycData as any, + kycData: entity.kycData as Prisma.InputJsonValue, isActive: entity.isActive, }, }); diff --git a/apps/api/src/modules/listings/application/__tests__/create-listing.handler.spec.ts b/apps/api/src/modules/listings/application/__tests__/create-listing.handler.spec.ts index ef83d9e..0942f42 100644 --- a/apps/api/src/modules/listings/application/__tests__/create-listing.handler.spec.ts +++ b/apps/api/src/modules/listings/application/__tests__/create-listing.handler.spec.ts @@ -1,4 +1,3 @@ -import { ListingEntity } from '@modules/listings/domain/entities/listing.entity'; import { type IListingRepository } from '@modules/listings/domain/repositories/listing.repository'; import { type IPropertyRepository } from '@modules/listings/domain/repositories/property.repository'; import { CreateListingCommand } from '../commands/create-listing/create-listing.command'; diff --git a/apps/api/src/modules/listings/infrastructure/repositories/prisma-property.repository.ts b/apps/api/src/modules/listings/infrastructure/repositories/prisma-property.repository.ts index 0f35043..10981bd 100644 --- a/apps/api/src/modules/listings/infrastructure/repositories/prisma-property.repository.ts +++ b/apps/api/src/modules/listings/infrastructure/repositories/prisma-property.repository.ts @@ -1,5 +1,5 @@ import { Injectable } from '@nestjs/common'; -import { type Property as PrismaProperty, type PropertyMedia as PrismaMedia } from '@prisma/client'; +import { type Prisma, type Property as PrismaProperty, type PropertyMedia as PrismaMedia } from '@prisma/client'; import { type PrismaService } from '@modules/shared/infrastructure/prisma.service'; import { PropertyMediaEntity, type PropertyMediaProps } from '../../domain/entities/property-media.entity'; import { PropertyEntity, type PropertyProps } from '../../domain/entities/property.entity'; @@ -69,7 +69,7 @@ export class PrismaPropertyRepository implements IPropertyRepository { type: media.type, order: media.order, caption: media.caption, - aiTags: media.aiTags as any, + aiTags: media.aiTags as Prisma.InputJsonValue, }, }); } diff --git a/apps/api/src/modules/payments/application/__tests__/create-payment.handler.spec.ts b/apps/api/src/modules/payments/application/__tests__/create-payment.handler.spec.ts index aae254f..cb4473c 100644 --- a/apps/api/src/modules/payments/application/__tests__/create-payment.handler.spec.ts +++ b/apps/api/src/modules/payments/application/__tests__/create-payment.handler.spec.ts @@ -1,6 +1,4 @@ import { type IPaymentRepository } from '../../domain/repositories/payment.repository'; -import { Money } from '../../domain/value-objects/money.vo'; -import { type IPaymentGatewayFactory } from '../../infrastructure/services/payment-gateway.interface'; import { CreatePaymentCommand } from '../commands/create-payment/create-payment.command'; import { CreatePaymentHandler } from '../commands/create-payment/create-payment.handler'; diff --git a/apps/api/src/modules/payments/application/commands/handle-callback/handle-callback.handler.ts b/apps/api/src/modules/payments/application/commands/handle-callback/handle-callback.handler.ts index ef79d77..345dec4 100644 --- a/apps/api/src/modules/payments/application/commands/handle-callback/handle-callback.handler.ts +++ b/apps/api/src/modules/payments/application/commands/handle-callback/handle-callback.handler.ts @@ -1,5 +1,6 @@ import { Inject, Logger } from '@nestjs/common'; import { CommandHandler, type EventBus, type ICommandHandler } from '@nestjs/cqrs'; +import { type PaymentStatus } from '@prisma/client'; import { NotFoundException, ValidationException } from '@modules/shared/domain/domain-exception'; import { PAYMENT_REPOSITORY, @@ -47,7 +48,7 @@ export class HandleCallbackHandler implements ICommandHandler = { +const METRIC_TO_PLAN_FIELD: Record = { listings_created: 'maxListings', searches_saved: 'maxSavedSearches', }; @@ -54,7 +55,7 @@ export class CheckQuotaHandler implements IQueryHandler { } private async checkAgainstPlan( - plan: any, + plan: Plan, metric: string, subscriptionId: string | null, _userId: string, diff --git a/apps/api/src/modules/subscriptions/application/queries/get-plan/get-plan.handler.ts b/apps/api/src/modules/subscriptions/application/queries/get-plan/get-plan.handler.ts index 88e7cb4..81af8b5 100644 --- a/apps/api/src/modules/subscriptions/application/queries/get-plan/get-plan.handler.ts +++ b/apps/api/src/modules/subscriptions/application/queries/get-plan/get-plan.handler.ts @@ -1,4 +1,5 @@ import { type IQueryHandler, QueryHandler } from '@nestjs/cqrs'; +import { type Plan } from '@prisma/client'; import { NotFoundException } from '@modules/shared/domain/domain-exception'; import { type PrismaService } from '@modules/shared/infrastructure/prisma.service'; import { GetPlanQuery } from './get-plan.query'; @@ -41,7 +42,7 @@ export class GetPlanHandler implements IQueryHandler { return plans.map((p) => this.toDto(p)); } - private toDto(plan: any): PlanDto { + private toDto(plan: Plan): PlanDto { return { id: plan.id, tier: plan.tier, diff --git a/apps/web/components/map/listing-map.tsx b/apps/web/components/map/listing-map.tsx index df681a1..2d1dd97 100644 --- a/apps/web/components/map/listing-map.tsx +++ b/apps/web/components/map/listing-map.tsx @@ -1,5 +1,6 @@ 'use client'; +/* eslint-disable import-x/no-named-as-default-member */ import mapboxgl from 'mapbox-gl'; import * as React from 'react'; import 'mapbox-gl/dist/mapbox-gl.css'; diff --git a/e2e/web/auth-oauth-callback.spec.ts b/e2e/web/auth-oauth-callback.spec.ts index ea2b8fc..925a16b 100644 --- a/e2e/web/auth-oauth-callback.spec.ts +++ b/e2e/web/auth-oauth-callback.spec.ts @@ -4,7 +4,7 @@ test.describe('OAuth Callback Pages', () => { test.describe('Google callback', () => { test('shows loading state while processing', async ({ page }) => { // Intercept token exchange to keep it pending - await page.route('**/auth/google/callback**', (route) => + await page.route('**/auth/google/callback**', (_route) => new Promise(() => { // Never resolve — keeps loading state visible }), @@ -31,7 +31,7 @@ test.describe('OAuth Callback Pages', () => { test.describe('Zalo callback', () => { test('shows loading state while processing', async ({ page }) => { - await page.route('**/auth/zalo/callback**', (route) => + await page.route('**/auth/zalo/callback**', (_route) => new Promise(() => { // Never resolve }), diff --git a/eslint.config.mjs b/eslint.config.mjs index e7d4226..5a78171 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,3 +1,4 @@ +/* eslint-disable import-x/no-named-as-default-member */ import js from '@eslint/js'; import tseslint from 'typescript-eslint'; import importPlugin from 'eslint-plugin-import-x'; diff --git a/prisma/seed.ts b/prisma/seed.ts index 726547f..6a22399 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -9,8 +9,8 @@ import { } from '@prisma/client'; import pg from 'pg'; import { importMarketData } from '../scripts/import-market-data'; -import { HCM_DISTRICTS, HANOI_DISTRICTS, DANANG_DISTRICTS, CITY_COORDINATES } from '../scripts/seed-districts'; -import { PLANS, seedPlans } from '../scripts/seed-plans'; +import { CITY_COORDINATES } from '../scripts/seed-districts'; +import { seedPlans } from '../scripts/seed-plans'; const pool = new pg.Pool({ connectionString: process.env['DATABASE_URL'] }); const adapter = new PrismaPg(pool); @@ -20,7 +20,7 @@ const prisma = new PrismaClient({ adapter }); // Sample coordinates for HCM districts // ============================================================================= -const SAMPLE_LOCATIONS = CITY_COORDINATES['Hồ Chí Minh']; +const _SAMPLE_LOCATIONS = CITY_COORDINATES['Hồ Chí Minh']; // ============================================================================= // Seed functions @@ -260,7 +260,7 @@ async function seedProperties(users: Awaited>) { const p = sampleProperties[i]!; const agent = agents[i % agents.length]! - const property = await prisma.$executeRaw` + const _property = await prisma.$executeRaw` INSERT INTO "Property" ( "id", "propertyType", "title", "description", "address", "ward", "district", "city", "location", diff --git a/scripts/import-market-data.ts b/scripts/import-market-data.ts index 737f96a..303960e 100644 --- a/scripts/import-market-data.ts +++ b/scripts/import-market-data.ts @@ -207,12 +207,12 @@ function randomVariation(base: number, pct: number): number { } async function importMarketData() { - console.log('Importing market data for HCM, Hanoi, Da Nang...\n'); + console.warn('Importing market data for HCM, Hanoi, Da Nang...\n'); let total = 0; for (const [city, districts] of Object.entries(MARKET_DATA)) { - console.log(` ${city}:`); + console.warn(` ${city}:`); let cityCount = 0; for (const { district, avgPriceM2 } of districts) { @@ -269,10 +269,10 @@ async function importMarketData() { } } - console.log(` ${cityCount} market index records`); + console.warn(` ${cityCount} market index records`); } - console.log(`\nTotal: ${total} market index records imported.`); + console.warn(`\nTotal: ${total} market index records imported.`); } if (require.main === module) { diff --git a/scripts/seed-districts.ts b/scripts/seed-districts.ts index 7c79694..a3f9433 100644 --- a/scripts/seed-districts.ts +++ b/scripts/seed-districts.ts @@ -250,13 +250,13 @@ const PROPERTY_TEMPLATES = [ ]; async function seedDistrictProperties() { - console.log('Seeding district properties across HCM, Hanoi, Da Nang...\n'); + console.warn('Seeding district properties across HCM, Hanoi, Da Nang...\n'); let created = 0; let skipped = 0; for (const { city, districts } of getAllDistricts()) { - console.log(` ${city}:`); + console.warn(` ${city}:`); const coords = CITY_COORDINATES[city] ?? {}; for (const { district, wards } of districts) { @@ -296,24 +296,24 @@ async function seedDistrictProperties() { } const cityDistricts = districts.length; - console.log(` ${cityDistricts} districts processed`); + console.warn(` ${cityDistricts} districts processed`); } - console.log(`\n Total: ${created} properties created, ${skipped} skipped (already exist)`); + console.warn(`\n Total: ${created} properties created, ${skipped} skipped (already exist)`); } async function main() { - console.log('=== Seed Districts — Vietnam Real Estate Dev Data ===\n'); + console.warn('=== Seed Districts — Vietnam Real Estate Dev Data ===\n'); // Log summary for (const { city, districts } of getAllDistricts()) { const totalWards = districts.reduce((sum, d) => sum + d.wards.length, 0); - console.log(` ${city}: ${districts.length} districts, ${totalWards} wards`); + console.warn(` ${city}: ${districts.length} districts, ${totalWards} wards`); } - console.log(''); + console.warn(''); await seedDistrictProperties(); - console.log('\nDone.'); + console.warn('\nDone.'); } // Run standalone or import as module diff --git a/scripts/seed-plans.ts b/scripts/seed-plans.ts index dd248f3..48b5da0 100644 --- a/scripts/seed-plans.ts +++ b/scripts/seed-plans.ts @@ -98,7 +98,7 @@ export const PLANS = [ ]; async function seedPlans() { - console.log('Seeding subscription plans...\n'); + console.warn('Seeding subscription plans...\n'); for (const plan of PLANS) { const _result = await prisma.plan.upsert({ @@ -115,10 +115,10 @@ async function seedPlans() { }); const monthly = Number(plan.priceMonthlyVND).toLocaleString('vi-VN'); - console.log(` ${plan.tier.padEnd(12)} ${plan.name.padEnd(14)} ${monthly} VND/tháng`); + console.warn(` ${plan.tier.padEnd(12)} ${plan.name.padEnd(14)} ${monthly} VND/tháng`); } - console.log(`\n${PLANS.length} plans seeded.`); + console.warn(`\n${PLANS.length} plans seeded.`); } if (require.main === module) {