import helmet from '@fastify/helmet'; import { API_PREFIX } from '@lingxi/shared'; import { NestFactory } from '@nestjs/core'; import { FastifyAdapter, type NestFastifyApplication } from '@nestjs/platform-fastify'; import { Logger } from 'nestjs-pino'; import { AppModule } from './app.module'; import { AllExceptionsFilter } from './common/filters/all-exceptions.filter'; import { APP_CONFIG } from './config/config.module'; import type { AppConfig } from './config/env'; import { buildOpenApiDocument, setupOpenApi } from './openapi/document'; export interface CreatedApiApp { app: NestFastifyApplication; config: AppConfig; } /** 创建并配置 API 应用(测试与 OpenAPI 导出复用,不负责监听端口) */ export async function createApp(): Promise { const app = await NestFactory.create( AppModule, new FastifyAdapter({ trustProxy: true, bodyLimit: 1024 * 1024 }), { bufferLogs: true }, ); const config = app.get(APP_CONFIG); app.useLogger(app.get(Logger)); app.setGlobalPrefix(API_PREFIX, { exclude: ['health'] }); app.useGlobalFilters(new AllExceptionsFilter()); app.enableCors({ origin: config.webOrigins, credentials: true, methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], }); // 安全响应头;Swagger UI 需要内联脚本,CSP 在关闭文档页后再开启 await app.register(helmet, { contentSecurityPolicy: false }); app.enableShutdownHooks(); return { app, config }; } export { buildOpenApiDocument, setupOpenApi };