feat(server): add tsoa to generate api swaggers
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -27,3 +27,4 @@ build
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
/packages/server/src/routes/routes.ts
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "tsc && tsc-alias",
|
||||
"build": "tsoa spec-and-routes && tsc && tsc-alias",
|
||||
"serve": "node ./build/index.js",
|
||||
"start": "nodemon"
|
||||
},
|
||||
@@ -16,10 +16,11 @@
|
||||
"compression": "^1.7.5",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.21.2",
|
||||
"express-oas-generator": "^1.0.48",
|
||||
"nocache": "^4.0.0",
|
||||
"sequelize": "^6.37.7",
|
||||
"sqlite3": "^5.1.7"
|
||||
"sqlite3": "^5.1.7",
|
||||
"tsoa": "^5.0.0",
|
||||
"swagger-ui-express": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/axios": "^0.9.36",
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import { Express } from "express";
|
||||
import {userInfoMiddleware, groupInfoMiddleware} from "@/middleware/auth";
|
||||
|
||||
export const createApis = (app: Express) => {
|
||||
app.get("/api/test", async (req, res) => {
|
||||
res.status(200).json({
|
||||
message: "success",
|
||||
data: null,
|
||||
});
|
||||
});
|
||||
|
||||
// 同时使用用户信息和群组信息中间件
|
||||
app.get("/api/user-group/info", userInfoMiddleware, groupInfoMiddleware, async (req, res) => {
|
||||
res.status(200).json({
|
||||
message: "success",
|
||||
data: {
|
||||
user: req.userInfo,
|
||||
group: req.groupInfo
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/** add apis here */
|
||||
};
|
||||
20
packages/server/src/controllers/TestController.ts
Normal file
20
packages/server/src/controllers/TestController.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Controller, Get, Route, Response, Tags } from 'tsoa';
|
||||
import { ApiResponse } from '../types/api';
|
||||
|
||||
@Route('api')
|
||||
@Tags('Test')
|
||||
export class TestController extends Controller {
|
||||
/**
|
||||
* 测试接口
|
||||
* @summary 测试接口
|
||||
* @description 用于测试API连通性的基础接口
|
||||
*/
|
||||
@Get('/test')
|
||||
@Response<ApiResponse>(200, 'Success')
|
||||
public async getTest(): Promise<ApiResponse> {
|
||||
return {
|
||||
message: 'success',
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
30
packages/server/src/controllers/UserGroupController.ts
Normal file
30
packages/server/src/controllers/UserGroupController.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { Controller, Get, Route, Response, Tags, Middlewares, Request } from 'tsoa';
|
||||
import { ApiResponse, UserGroupInfo } from '../types/api';
|
||||
import { userInfoMiddleware, groupInfoMiddleware } from '../middleware/auth';
|
||||
import type { Request as ExpressRequest } from 'express';
|
||||
|
||||
@Route('api')
|
||||
@Tags('User Group')
|
||||
export class UserGroupController extends Controller {
|
||||
/**
|
||||
* 获取用户群组信息
|
||||
* @summary 获取用户群组信息
|
||||
* @description 获取当前用户的个人信息和所在群组的所有用户信息
|
||||
*/
|
||||
@Get('/user-group/info')
|
||||
@Middlewares([userInfoMiddleware, groupInfoMiddleware])
|
||||
@Response<ApiResponse<UserGroupInfo>>(200, 'Success')
|
||||
@Response(401, 'Unauthorized')
|
||||
public async getUserGroupInfo(@Request() req: ExpressRequest): Promise<ApiResponse<UserGroupInfo>> {
|
||||
const userInfo = req.userInfo;
|
||||
const groupInfo = req.groupInfo;
|
||||
|
||||
return {
|
||||
message: 'success',
|
||||
data: {
|
||||
user: userInfo || null,
|
||||
group: groupInfo || null
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -4,16 +4,12 @@ import cors from "cors";
|
||||
import compression from "compression";
|
||||
import nocache from "nocache";
|
||||
import path from "path";
|
||||
import expressOasGenerator, {
|
||||
OpenAPIV3,
|
||||
SPEC_OUTPUT_FILE_BEHAVIOR,
|
||||
} from "express-oas-generator";
|
||||
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../../.env") });
|
||||
|
||||
import "./database";
|
||||
import { sequelize } from "@/database/instance";
|
||||
import { createApis } from "./api";
|
||||
import { RegisterTsoaRoutes } from "./middleware/tsoa.middleware";
|
||||
|
||||
const port = process.env.PORT || 3005;
|
||||
|
||||
@@ -26,29 +22,9 @@ app.use(compression());
|
||||
|
||||
app.use(express.static(path.resolve(__dirname, "client")));
|
||||
|
||||
createApis(app);
|
||||
// Register tsoa routes
|
||||
RegisterTsoaRoutes(app);
|
||||
|
||||
expressOasGenerator.handleResponses(app, {
|
||||
specOutputFileBehavior: SPEC_OUTPUT_FILE_BEHAVIOR.RECREATE,
|
||||
swaggerDocumentOptions: {},
|
||||
predefinedSpec: (spec: OpenAPIV3.Document) => {
|
||||
if (spec.info) {
|
||||
spec.info.description = "Egret App Server";
|
||||
}
|
||||
if (spec.paths) {
|
||||
delete spec.paths["/v3/api-docs"];
|
||||
}
|
||||
return spec;
|
||||
},
|
||||
});
|
||||
|
||||
expressOasGenerator.handleRequests();
|
||||
|
||||
app.get("/v3/api-docs", async (req, res) => {
|
||||
expressOasGenerator.getSpecV3((err, doc) => {
|
||||
res.status(200).json(doc);
|
||||
});
|
||||
});
|
||||
|
||||
const host = "0.0.0.0";
|
||||
app.listen(Number(port), host, async () => {
|
||||
|
||||
12
packages/server/src/middleware/tsoa.middleware.ts
Normal file
12
packages/server/src/middleware/tsoa.middleware.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import swaggerUi from 'swagger-ui-express';
|
||||
import path from 'path';
|
||||
|
||||
export function RegisterTsoaRoutes(app: any) {
|
||||
// Register tsoa routes - 动态导入以避免编译时错误
|
||||
const { RegisterRoutes } = require('../routes/routes');
|
||||
RegisterRoutes(app);
|
||||
|
||||
// Serve swagger documentation - 动态导入swagger文档
|
||||
const swaggerDocument = require(path.join(__dirname, '../swagger.json'));
|
||||
app.use('/v3/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
|
||||
}
|
||||
14
packages/server/src/types/api.ts
Normal file
14
packages/server/src/types/api.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { UserInfo } from '../middleware/auth';
|
||||
|
||||
export interface ApiResponse<T = any> {
|
||||
message: string;
|
||||
data: T | null;
|
||||
}
|
||||
|
||||
export interface UserGroupInfo {
|
||||
user: UserInfo | null;
|
||||
group: {
|
||||
groupId: number;
|
||||
users: UserInfo[];
|
||||
} | null;
|
||||
}
|
||||
@@ -9,7 +9,10 @@
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
},
|
||||
"outDir": "./build"
|
||||
"outDir": "./build",
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"useDefineForClassFields": false
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "build"],
|
||||
|
||||
18
packages/server/tsoa.json
Normal file
18
packages/server/tsoa.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"entryFile": "src/index.ts",
|
||||
"noImplicitAdditionalProperties": "throw-on-extras",
|
||||
"controllerPathGlobs": ["src/controllers/**/*Controller.ts"],
|
||||
"spec": {
|
||||
"outputDirectory": "build",
|
||||
"specVersion": 3,
|
||||
"name": "Egret App Server",
|
||||
"description": "Egret App Server API Documentation",
|
||||
"version": "1.0.0",
|
||||
"basePath": "/",
|
||||
"schemes": ["http", "https"],
|
||||
"host": "localhost:3005"
|
||||
},
|
||||
"routes": {
|
||||
"routesDir": "src/routes"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user