Files
whale-town-end/src/main.ts
moyin 9e0e07b07c docs:更新主应用OpenAPI配置
- 更新WebSocket连接地址为/game路径
- 添加开发和生产环境的WebSocket服务器配置
- 完善WebSocket连接说明文档
- 统一API文档中的WebSocket信息
2026-01-09 17:46:32 +08:00

187 lines
5.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { WsAdapter } from '@nestjs/platform-ws';
/**
* 检查数据库配置是否完整 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() {
// 打印启动横幅
printBanner();
const app = await NestFactory.create(AppModule, {
logger: ['error', 'warn', 'log'],
});
// 配置原生 WebSocket 适配器
app.useWebSocketAdapter(new WsAdapter(app));
// 允许前端后台如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文档 - 包含用户认证、聊天系统、Zulip集成等功能
## 主要功能模块
### 🔐 用户认证 (auth)
- 用户注册、登录
- JWT Token 管理
- 邮箱验证和密码重置
- 验证码登录
### 💬 聊天系统 (chat)
- WebSocket 实时聊天
- 聊天历史记录
- 系统状态监控
- Zulip 集成状态
### 🔌 WebSocket 接口 (websocket)
- 实时消息传输
- 位置同步
- 地图房间管理
- 连接状态监控
### 👑 管理员后台 (admin)
- 用户管理
- 系统监控
- 日志查看
## WebSocket 连接
游戏聊天功能主要通过 WebSocket 实现:
**连接地址**: \`wss://whaletownend.xinghangee.icu/game\` (原生WebSocket)
**重要变更**: 已从Socket.IO迁移到原生WebSocket提升性能和稳定性
**连接路径**: \`/game\` - 统一的WebSocket入口
**支持的事件**:
- \`login\`: 用户登录(需要 JWT Token
- \`chat\`: 发送聊天消息
- \`position\`: 位置更新
**JWT Token 要求**:
- issuer: \`whale-town\`
- audience: \`whale-town-users\`
- type: \`access\`
- 必需字段: \`sub\`, \`username\`, \`email\`, \`role\`
## Zulip 集成
系统集成了 Zulip 聊天服务,实现游戏内聊天与 Zulip 社群的双向同步。
**支持的地图**:
- Whale Port (鲸鱼港)
- Pumpkin Valley (南瓜谷)
- Novice Village (新手村)
## 最近更新 (v2.1.0)
### 🚀 WebSocket 架构升级
- ✅ 移除Socket.IO依赖使用原生WebSocket
- ✅ 实现地图房间分组管理
- ✅ 支持本地和全局消息广播
- ✅ 新增实时连接监控
### 📚 文档完善
- ✅ 新增WebSocket专用API文档
- ✅ 提供交互式消息格式展示
- ✅ 包含测试工具和示例代码
- ✅ 完整的开发者指南
### 🔧 性能优化
- ✅ 更高效的消息路由机制
- ✅ 优化连接池管理
- ✅ 增强错误处理和日志记录
`)
.setVersion('2.1.0')
.addTag('auth', '🔐 用户认证相关接口')
.addTag('chat', '💬 聊天系统相关接口')
.addTag('websocket', '🔌 WebSocket接口文档和测试')
.addTag('admin', '👑 管理员后台相关接口')
.addBearerAuth(
{
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT',
name: 'JWT',
description: '请输入JWT token',
in: 'header',
},
'JWT-auth',
)
.addServer('http://localhost:3000', '开发环境 - REST API')
.addServer('https://whaletownend.xinghangee.icu', '生产环境 - REST API')
.addServer('wss://whaletownend.xinghangee.icu/game', '生产环境 - WebSocket')
.addServer('ws://localhost:3001/game', '开发环境 - WebSocket')
.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();