| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- import { NestFactory } from '@nestjs/core';
- import { Logger, ValidationPipe } from '@nestjs/common';
- import { ConfigService } from '@nestjs/config';
- import helmet from 'helmet';
- import compression from 'compression';
- import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
- // import * as path from 'path';
- // import * as express from 'express';
- import { AppModule } from './app.module';
- async function bootstrap() {
- const app = await NestFactory.create(AppModule, {
- bufferLogs: true,
- });
- const logger = new Logger('Bootstrap');
- app.useLogger(logger);
- const configService = app.get(ConfigService);
- const host =
- configService.get<string>('APP_HOST') ??
- configService.get<string>('HOST') ??
- '0.0.0.0';
- const port =
- configService.get<number>('APP_PORT') ??
- Number(process.env.APP_PORT ?? 3301);
- const corsOrigin = configService.get<string>('APP_CORS_ORIGIN') ?? '*';
- const corsOriginOption =
- corsOrigin === '*'
- ? true
- : corsOrigin
- .split(',')
- .map((o) => o.trim())
- .filter(Boolean);
- app.enableCors({
- origin: corsOriginOption,
- methods: ['GET', 'PUT', 'PATCH', 'POST', 'DELETE'],
- credentials: true,
- });
- // const imageRoot = path.resolve(
- // configService.get<string>('IMAGE_ROOT_PATH') || '/data/box-images',
- // );
- // app.use(
- // '/images',
- // express.static(imageRoot, {
- // setHeaders: (res: any) => {
- // res.setHeader('Access-Control-Allow-Origin', corsOrigin);
- // res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
- // res.setHeader(
- // 'Access-Control-Allow-Headers',
- // 'Origin, X-Requested-With, Content-Type, Accept, Authorization',
- // );
- // },
- // }),
- // );
- // 👇 Important: this makes /health become /api/v1/health
- app.setGlobalPrefix('api/v1', {
- exclude: ['/'],
- });
- app.use(helmet());
- app.use(compression());
- app.useGlobalPipes(
- new ValidationPipe({
- whitelist: true,
- transform: true,
- transformOptions: {
- enableImplicitConversion: true,
- },
- forbidNonWhitelisted: false,
- }),
- );
- // Setup Swagger (OpenAPI)
- const swaggerConfig = new DocumentBuilder()
- .setTitle('盒子应用接口文档')
- .setDescription(
- 'box-app-api 的公开接口文档,面向前端应用。包含广告、视频、首页等模块。',
- )
- .setVersion('1.0.0')
- .build();
- const swaggerDocument = SwaggerModule.createDocument(app, swaggerConfig);
- SwaggerModule.setup('api-docs', app, swaggerDocument, {
- jsonDocumentUrl: '/api-docs-json',
- swaggerOptions: {
- persistAuthorization: true,
- docExpansion: 'none',
- },
- });
- // Prevent Swagger UI/JSON from being cached (browser + proxies)
- app.use(['/api-docs', '/api-docs-json'], (req, res, next) => {
- res.setHeader(
- 'Cache-Control',
- 'no-store, no-cache, must-revalidate, proxy-revalidate',
- );
- res.setHeader('Pragma', 'no-cache');
- res.setHeader('Expires', '0');
- next();
- });
- await app.listen(port, host);
- const url = `http://${host}:${port}`;
- logger.log(`🚀 box-app-api listening on ${url} (global prefix: /api/v1)`);
- logger.log(`📖 Swagger 文档: ${url}/api-docs`);
- logger.log(`📄 Swagger JSON: ${url}/api-docs-json`);
- }
- bootstrap().catch((error) => {
- // eslint-disable-next-line no-console
- console.error('❌ Failed to bootstrap box-app-api', error);
- process.exit(1);
- });
|