import { Logger, ValidationPipe } from '@nestjs/common'; import { NestFactory } from '@nestjs/core'; import { NestExpressApplication } from '@nestjs/platform-express'; import { existsSync, mkdirSync } from 'node:fs'; import { resolve } from 'node:path'; import { AppModule } from './app.module'; import { AppConfig, configuration, validateEnv } from './config/configuration'; async function bootstrap(): Promise { const logger = new Logger('Bootstrap'); // 启动前校验环境变量(生产环境禁止 DB_SYNCHRONIZE=true 等) const problems = validateEnv(configuration()); if (problems.length > 0) { for (const problem of problems) logger.warn(`环境变量问题:${problem}`); if ((process.env.NODE_ENV ?? 'development') === 'production') { logger.error('生产环境配置校验失败,启动中止'); process.exit(1); } } const app = await NestFactory.create(AppModule, { logger: ['error', 'warn', 'log'], }); const config = app.get(AppConfig); app.useGlobalPipes( new ValidationPipe({ transform: true, whitelist: true, forbidNonWhitelisted: false, transformOptions: { enableImplicitConversion: false }, }), ); // Windows 客户端与管理端跨源访问 app.enableCors({ origin: true, credentials: false, exposedHeaders: ['Content-Disposition'], }); // 上传文件静态访问:/static////. const storageDir = resolve(config.storageDir); if (!existsSync(storageDir)) mkdirSync(storageDir, { recursive: true }); app.useStaticAssets(storageDir, { prefix: '/static/', index: false, fallthrough: true }); // 契约快照静态访问(若存在):/contracts/rest-api.yaml 等 if (config.contractsDir && existsSync(config.contractsDir)) { app.useStaticAssets(resolve(config.contractsDir), { prefix: '/contracts/', index: false }); } app.enableShutdownHooks(); const db = config.db; await app.listen(config.port, config.bindHost); logger.log(`OpenDance Studio Web 服务端已启动:http://${config.bindHost}:${config.port}`); logger.log(`健康检查:http://${config.bindHost}:${config.port}/health`); logger.log(`数据库:${db.host}:${db.port}/${db.name}(现有实例,本服务不管理 MySQL)`); logger.log(`文件存储:${storageDir}`); logger.log(`契约版本:${JSON.stringify(config.contractVersions)}`); } void bootstrap().catch((error) => { // eslint-disable-next-line no-console console.error('服务启动失败:', error); process.exit(1); });