import 'reflect-metadata'; import { ValidationPipe } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { NestFactory } from '@nestjs/core'; import { FastifyAdapter, NestFastifyApplication, } from '@nestjs/platform-fastify'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { Logger } from 'nestjs-pino'; import multipart from '@fastify/multipart'; import { AppModule } from './app.module'; // @ts-expect-error: allow JSON.stringify(BigInt) BigInt.prototype.toJSON = function () { const value = this as bigint; if (value > BigInt(Number.MAX_SAFE_INTEGER)) { return this.toString(); } return Number(this); }; async function bootstrap() { const fastifyAdapter = new FastifyAdapter() as FastifyAdapter; // multipart for file upload (e.g. OSS, S3) await fastifyAdapter.register(multipart as any, { limits: { fileSize: 30 * 1024 * 1024, // 30 MB }, }); const app = await NestFactory.create( AppModule, fastifyAdapter, { bufferLogs: true, snapshot: true, }, ); // nestjs-pino logger app.useLogger(app.get(Logger)); // Global API prefix; mgnt routes stay under /api/v1/mgnt/* app.setGlobalPrefix('api/v1'); app.useGlobalPipes( new ValidationPipe({ transform: true, whitelist: true, forbidNonWhitelisted: false, }), ); const configService = app.get(ConfigService); const host = configService.get('APP_HOST') ?? configService.get('HOST') ?? '0.0.0.0'; const port = configService.get('APP_PORT') ?? Number(process.env.PORT ?? 3300); const crossOrigin = configService.get('APP_CROSS_ORIGIN') ?? configService.get('CROSS_ORIGIN') ?? '*'; app.enableCors({ origin: crossOrigin === '*' ? true : crossOrigin.split(',').map((o) => o.trim()), methods: 'GET,PUT,PATCH,POST,DELETE', }); if (process.env.NODE_ENV !== 'production') { const config = new DocumentBuilder() .setTitle('盒子管理系统管理后台 API 文档') .setDescription('盒子管理系统管理后台接口 (api/v1/mgnt/*)') .setVersion('1.0') .addBearerAuth() .addServer(`http://${host}:${port}`, '本地开发环境') .addTag('系统 - 授权', '管理后台授权相关接口 (mgnt/auth)') .addTag('系统 - 用户', '管理后台用户管理接口 (mgnt/users)') .addTag('系统 - 角色', '管理后台角色管理接口 (mgnt/roles)') .addTag('系统 - 菜单', '管理后台菜单管理接口 (mgnt/menus)') .build(); const document = SwaggerModule.createDocument(app, config); SwaggerModule.setup('api-docs', app, document, { swaggerOptions: { docExpansion: 'none', tagsSorter: 'alpha', operationsSorter: 'alpha', }, }); } await app.listen(port, host); const url = `http://${host}:${port}`; console.log(`🚀 box-mgnt-api is running at: ${url}`); console.log(`📚 API Documentation: ${url}/api-docs`); console.log(`🔧 Management APIs: ${url}/api/v1/mgnt/*`); } bootstrap();