- 明确指定允许的域名列表,包括生产环境域名 - 添加Vite开发服务器端口支持 - 完善CORS方法和头部配置,确保WebSocket握手正常 - 支持xinghangee.icu子域名的通配符匹配 修复远程域名WebSocket连接问题的核心配置
98 lines
3.2 KiB
TypeScript
98 lines
3.2 KiB
TypeScript
import { NestFactory } from '@nestjs/core';
|
||
import { AppModule } from './app.module';
|
||
import { ValidationPipe } from '@nestjs/common';
|
||
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
||
|
||
/**
|
||
* 检查数据库配置是否完整 by angjustinl 2025-12-17
|
||
*
|
||
* @returns 是否配置了数据库
|
||
*/
|
||
function isDatabaseConfigured(): boolean {
|
||
const requiredEnvVars = ['DB_HOST', 'DB_PORT', 'DB_USERNAME', 'DB_PASSWORD', 'DB_NAME'];
|
||
return requiredEnvVars.every(varName => process.env[varName]);
|
||
}
|
||
|
||
/**
|
||
* 打印启动横幅
|
||
*/
|
||
function printBanner() {
|
||
const isDatabaseMode = isDatabaseConfigured();
|
||
|
||
console.log('\n' + '='.repeat(70));
|
||
console.log('🎮 Pixel Game Server');
|
||
console.log('='.repeat(70));
|
||
console.log(`📦 存储模式: ${isDatabaseMode ? '数据库模式 (MySQL)' : '内存模式 (Memory)'}`);
|
||
|
||
if (!isDatabaseMode) {
|
||
console.log('⚠️ 警告: 未检测到数据库配置,使用内存存储');
|
||
console.log('💡 提示: 数据将在服务重启后丢失');
|
||
console.log('📝 配置: 请在 .env 文件中配置数据库连接信息');
|
||
} else {
|
||
console.log('✅ 数据库: 已连接到 MySQL 数据库');
|
||
}
|
||
|
||
console.log('='.repeat(70) + '\n');
|
||
}
|
||
|
||
async function bootstrap() {
|
||
const app = await NestFactory.create(AppModule, {
|
||
logger: ['error', 'warn', 'log'],
|
||
});
|
||
|
||
// 允许前端后台(如Vite/React)跨域访问,包括WebSocket
|
||
app.enableCors({
|
||
origin: [
|
||
'http://localhost:3000',
|
||
'http://localhost:5173', // Vite默认端口
|
||
'https://whaletownend.xinghangee.icu',
|
||
/^https:\/\/.*\.xinghangee\.icu$/
|
||
],
|
||
credentials: true,
|
||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
||
allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],
|
||
});
|
||
|
||
// 全局启用校验管道(核心配置)
|
||
app.useGlobalPipes(
|
||
new ValidationPipe({
|
||
whitelist: true, // 过滤掉 DTO 中未定义的字段(比如传了个 `age` 但 DTO 里没有,会自动忽略)
|
||
forbidNonWhitelisted: true, // 若传了未定义的字段,直接报错(防止传多余参数)
|
||
transform: true, // 自动把入参转为 DTO 对应的类型(比如前端传的字符串数字 `'1'` 转为数字 `1`)
|
||
}),
|
||
);
|
||
|
||
// 配置Swagger文档
|
||
const config = new DocumentBuilder()
|
||
.setTitle('Pixel Game Server API')
|
||
.setDescription('像素游戏服务器API文档 - 包含用户认证、登录注册、验证码登录、邮箱冲突检测等功能')
|
||
.setVersion('1.1.1')
|
||
.addTag('auth', '用户认证相关接口')
|
||
.addTag('admin', '管理员后台相关接口')
|
||
.addBearerAuth(
|
||
{
|
||
type: 'http',
|
||
scheme: 'bearer',
|
||
bearerFormat: 'JWT',
|
||
name: 'JWT',
|
||
description: '请输入JWT token',
|
||
in: 'header',
|
||
},
|
||
'JWT-auth',
|
||
)
|
||
.build();
|
||
|
||
const document = SwaggerModule.createDocument(app, config);
|
||
SwaggerModule.setup('api-docs', app, document, {
|
||
swaggerOptions: {
|
||
persistAuthorization: true,
|
||
},
|
||
});
|
||
|
||
await app.listen(3000);
|
||
console.log('Pixel Game Server is running on http://localhost:3000');
|
||
console.log('API Documentation is available at http://localhost:3000/api-docs');
|
||
}
|
||
|
||
bootstrap();
|