83 lines
2.6 KiB
TypeScript
83 lines
2.6 KiB
TypeScript
import { Module, NestModule, MiddlewareConsumer, RequestMethod } from '@nestjs/common';
|
||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||
import {
|
||
TenantContextModule,
|
||
TenantContextMiddleware,
|
||
SimpleTenantFinder,
|
||
DEFAULT_TENANT_ID,
|
||
} from '@iconsulting/shared';
|
||
import { ConversationModule } from './conversation/conversation.module';
|
||
import { ClaudeModule } from './infrastructure/claude/claude.module';
|
||
import { HealthModule } from './health/health.module';
|
||
|
||
@Module({
|
||
imports: [
|
||
// Configuration
|
||
ConfigModule.forRoot({
|
||
isGlobal: true,
|
||
envFilePath: ['.env.local', '.env'],
|
||
}),
|
||
|
||
// Tenant context module (global)
|
||
TenantContextModule.forRoot({
|
||
tenantFinder: SimpleTenantFinder,
|
||
middlewareOptions: {
|
||
allowDefaultTenant: true,
|
||
defaultTenantId: DEFAULT_TENANT_ID,
|
||
excludePaths: ['/health', '/health/*'],
|
||
},
|
||
isGlobal: true,
|
||
}),
|
||
|
||
// Database
|
||
TypeOrmModule.forRootAsync({
|
||
imports: [ConfigModule],
|
||
inject: [ConfigService],
|
||
useFactory: (configService: ConfigService) => ({
|
||
type: 'postgres',
|
||
host: configService.get('POSTGRES_HOST', 'localhost'),
|
||
port: configService.get<number>('POSTGRES_PORT', 5432),
|
||
username: configService.get('POSTGRES_USER', 'iconsulting'),
|
||
password: configService.get('POSTGRES_PASSWORD'),
|
||
database: configService.get('POSTGRES_DB', 'iconsulting'),
|
||
entities: [__dirname + '/**/*.orm{.ts,.js}'],
|
||
// 生产环境禁用synchronize,使用init-db.sql初始化schema
|
||
synchronize: false,
|
||
// 连接池配置 - 优化并发性能
|
||
extra: {
|
||
max: configService.get<number>('DB_POOL_SIZE', 20),
|
||
min: 2,
|
||
idleTimeoutMillis: 30000,
|
||
connectionTimeoutMillis: 5000,
|
||
},
|
||
logging: configService.get('NODE_ENV') === 'development' ? ['query', 'error'] : ['error'],
|
||
retryAttempts: 3,
|
||
retryDelay: 1000,
|
||
}),
|
||
}),
|
||
|
||
// Health check (excluded from global prefix)
|
||
HealthModule,
|
||
|
||
// Feature modules
|
||
ConversationModule,
|
||
ClaudeModule,
|
||
],
|
||
})
|
||
export class AppModule implements NestModule {
|
||
constructor(
|
||
private readonly tenantMiddleware: TenantContextMiddleware,
|
||
) {}
|
||
|
||
configure(consumer: MiddlewareConsumer) {
|
||
consumer
|
||
.apply((req: any, res: any, next: any) => this.tenantMiddleware.use(req, res, next))
|
||
.exclude(
|
||
{ path: 'health', method: RequestMethod.GET },
|
||
{ path: 'health/(.*)', method: RequestMethod.ALL },
|
||
)
|
||
.forRoutes('*');
|
||
}
|
||
}
|