import { Module, NestModule, MiddlewareConsumer, RequestMethod } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { TypeOrmModule } from '@nestjs/typeorm'; import { ScheduleModule } from '@nestjs/schedule'; import { TenantContextService, TenantContextMiddleware, DEFAULT_TENANT_ID, } from '@iconsulting/shared'; import { EvolutionModule } from './evolution/evolution.module'; import { AdminModule } from './admin/admin.module'; import { HealthModule } from './health/health.module'; import { AnalyticsModule } from './analytics/analytics.module'; import { TenantModule } from './infrastructure/tenant/tenant.module'; import { TenantFinderService } from './infrastructure/tenant/tenant-finder.service'; @Module({ imports: [ // 配置模块 ConfigModule.forRoot({ isGlobal: true, envFilePath: ['.env.local', '.env'], }), // 定时任务模块 ScheduleModule.forRoot(), // 数据库连接 TypeOrmModule.forRootAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: (config: ConfigService) => ({ type: 'postgres', host: config.get('POSTGRES_HOST', 'localhost'), port: config.get('POSTGRES_PORT', 5432), username: config.get('POSTGRES_USER', 'postgres'), password: config.get('POSTGRES_PASSWORD'), database: config.get('POSTGRES_DB', 'iconsulting'), autoLoadEntities: true, // 禁用synchronize,使用init-db.sql初始化schema synchronize: false, logging: config.get('NODE_ENV') === 'development', }), }), // 租户模块 TenantModule, // Health check HealthModule, // 功能模块 EvolutionModule, AdminModule, AnalyticsModule, ], providers: [TenantContextService], }) export class AppModule implements NestModule { constructor( private readonly tenantContext: TenantContextService, private readonly tenantFinder: TenantFinderService, ) {} configure(consumer: MiddlewareConsumer) { // 创建租户中间件 const tenantMiddleware = new TenantContextMiddleware( this.tenantContext, this.tenantFinder, { allowDefaultTenant: true, defaultTenantId: DEFAULT_TENANT_ID, excludePaths: ['/health', '/health/*', '/super-admin/*'], }, ); consumer .apply((req: any, res: any, next: any) => tenantMiddleware.use(req, res, next)) .exclude( { path: 'health', method: RequestMethod.GET }, { path: 'health/(.*)', method: RequestMethod.ALL }, { path: 'super-admin', method: RequestMethod.ALL }, { path: 'super-admin/(.*)', method: RequestMethod.ALL }, ) .forRoutes('*'); } }