@@ -6,47 +6,12 @@ import * as express from 'express';
66import * as rateLimit from 'express-rate-limit' ;
77import * as helmet from 'helmet' ;
88import { join } from 'path' ;
9+ import { SwaggerTheme , SwaggerThemeNameEnum } from 'swagger-themes' ;
910
1011import { AppModule } from './app.module' ;
1112import { HttpExceptionFilter } from './filters/http-exception.filter' ;
1213import { TransformInterceptor } from './interceptors/transform.interceptor' ;
1314
14- // 端口检测函数
15- const checkPortAvailability = ( port : number ) : Promise < boolean > => {
16- return new Promise ( ( resolve ) => {
17- const net = require ( 'net' ) ;
18- const tester = net . createServer ( )
19- . once ( 'error' , ( ) => resolve ( false ) )
20- . once ( 'listening' , ( ) => tester . once ( 'close' , ( ) => resolve ( true ) ) . close ( ) )
21- . listen ( port ) ;
22- } ) ;
23- } ;
24-
25- // 查找可用端口
26- const findAvailableApplicationPort = async ( startPort : number , maxAttempts = 10 ) : Promise < number > => {
27- for ( let i = 0 ; i < maxAttempts ; i ++ ) {
28- const portToTry = startPort + i ;
29- if ( await checkPortAvailability ( portToTry ) ) {
30- return portToTry ;
31- }
32- }
33- throw new Error ( `No available ports found in range ${ startPort } -${ startPort + maxAttempts - 1 } ` ) ;
34- } ;
35-
36- // 等待端口可用
37- const waitForPort = async ( port : number , timeout = 30000 ) : Promise < boolean > => {
38- const startTime = Date . now ( ) ;
39-
40- while ( Date . now ( ) - startTime < timeout ) {
41- if ( await checkPortAvailability ( port ) ) {
42- return true ;
43- }
44- await new Promise ( resolve => setTimeout ( resolve , 500 ) ) ;
45- }
46-
47- return false ;
48- } ;
49-
5015export async function bootstrap ( ) {
5116 try {
5217 const app = await NestFactory . create ( AppModule ) ;
@@ -72,38 +37,52 @@ export async function bootstrap() {
7237 app . use ( bodyParser . json ( { limit : '10mb' } ) ) ;
7338 app . use ( bodyParser . urlencoded ( { limit : '10mb' , extended : true } ) ) ;
7439
40+ // 增强版 Swagger 配置
7541 const swaggerConfig = new DocumentBuilder ( )
76- . setTitle ( 'ReactPress Open Api' )
77- . setDescription ( 'ReactPress Open Api Document' )
78- . setVersion ( '1.0' )
42+ . setTitle ( 'ReactPress API Documentation' )
43+ . setDescription ( 'Comprehensive API documentation for ReactPress - A modern content management system built with NestJS' )
44+ . setVersion ( '2.0' )
45+ . setContact ( 'ReactPress Team' , 'https://github.com/fecommunity/reactpress' , '[email protected] ' ) 46+ . setLicense ( 'MIT' , 'https://github.com/fecommunity/reactpress/blob/main/LICENSE' )
47+ . addServer ( configService . get ( 'SERVER_SITE_URL' , 'http://localhost:3002' ) , 'API Server' )
7948 . build ( ) ;
49+
8050 const document = SwaggerModule . createDocument ( app , swaggerConfig ) ;
81- SwaggerModule . setup ( 'api' , app , document ) ;
51+
52+ // 使用 swagger-themes 提供专业主题
53+ const theme = new SwaggerTheme ( ) ;
54+
55+ // 自定义 Swagger 设置
56+ const options = {
57+ customCss : theme . getBuffer ( SwaggerThemeNameEnum . MATERIAL ) , // 应用主题
58+ customSiteTitle : 'ReactPress API Documentation' ,
59+ customfavIcon : '/public/favicon.png' ,
60+ swaggerOptions : {
61+ docExpansion : 'list' ,
62+ filter : true ,
63+ showRequestDuration : true ,
64+ persistAuthorization : true , // 保持授权数据
65+ displayOperationId : true ,
66+ operationsSorter : 'method' , // 按方法排序
67+ tagsSorter : 'alpha' , // 按字母顺序排序标签
68+ } ,
69+ customCssUrl : '/public/swagger/custom.css' , // 额外的自定义CSS
70+ } ;
71+
72+ // 设置 Swagger UI
73+ SwaggerModule . setup ( 'api' , app , document , options ) ;
8274
8375 const configuredPort = configService . get ( 'SERVER_PORT' , 3002 ) ;
8476
85- // 确保端口可用
86- const isPortAvailable = await checkPortAvailability ( configuredPort ) ;
87- if ( ! isPortAvailable ) {
88- console . warn ( `[ReactPress] Port ${ configuredPort } is not available, waiting for it to be released...` ) ;
89- const portReleased = await waitForPort ( configuredPort ) ;
90-
91- if ( ! portReleased ) {
92- console . error ( `[ReactPress] Port ${ configuredPort } is still occupied after waiting` ) ;
93- process . exit ( 1 ) ;
94- }
95- }
96-
9777 await app . listen ( configuredPort ) ;
9878 console . log ( `[ReactPress] Application started on http://localhost:${ configuredPort } ` ) ;
99- console . log ( `[ReactPress] Please visit http://localhost:${ configuredPort } /api manually ` ) ;
79+ console . log ( `[ReactPress] API Documentation available at http://localhost:${ configuredPort } /api/docs ` ) ;
10080
10181 return app ;
10282
10383 } catch ( error ) {
10484 console . error ( '[ReactPress] Failed to start application:' , error ) ;
10585
106- // 提供友好的错误信息
10786 if ( error . code === 'EADDRINUSE' ) {
10887 console . error ( '[ReactPress] Port is already in use. Please check for other running instances.' ) ;
10988 console . error ( '[ReactPress] You can change the port in your .env file or terminate the conflicting process.' ) ;
@@ -113,7 +92,6 @@ export async function bootstrap() {
11392 }
11493}
11594
116- // 添加进程信号处理
11795process . on ( 'SIGINT' , ( ) => {
11896 console . log ( '\n[ReactPress] Application shutting down gracefully...' ) ;
11997 process . exit ( 0 ) ;
0 commit comments