ElderlyCare-MockServer/server.js

153 lines
3.7 KiB
JavaScript

const express = require('express');
const bodyParser = require('body-parser');
const Mock = require('mockjs');
const fs = require('fs-extra');
const dayjs = require('dayjs');
// ✅ 引入 swagger 组件
const swaggerUi = require('swagger-ui-express');
const swaggerJSDoc = require('swagger-jsdoc');
const app = express();
const PORT = 3000;
const CONFIG_PATH = './mock-config.json';
app.use(bodyParser.json());
// 加载配置文件
let mockConfigs = fs.existsSync(CONFIG_PATH) ? fs.readJsonSync(CONFIG_PATH) : [];
// ✅ 统一响应结构
function formatResponse(data, code = 200, message = 'success') {
return {
code,
type: code === 200 ? 'success' : 'error',
message,
result: data,
extras: null,
time: dayjs().format('YYYY-MM-DD HH:mm:ss')
};
}
// ✅ 注册 mock 接口
function registerMockApi(config) {
const { method, path, response } = config;
const methodName = method.toLowerCase();
app[methodName](path, (req, res) => {
try {
const data = Mock.mock(response);
res.json(formatResponse(data));
} catch (err) {
res.json(formatResponse(null, 500, err.message));
}
});
}
// 初始注册全部
mockConfigs.forEach(registerMockApi);
// ✅ 添加新接口
app.post('/mock-api/add', async (req, res) => {
const config = req.body;
if (!config.method || !config.path || !config.response) {
return res.json(formatResponse(null, 400, '参数不完整'));
}
registerMockApi(config);
mockConfigs.push(config);
await fs.writeJson(CONFIG_PATH, mockConfigs, { spaces: 2 });
res.json(formatResponse({ path: config.path }, 200, '接口已添加'));
});
// ✅ 获取全部 mock 定义
app.get('/mock-api/list', (req, res) => {
res.json(formatResponse(mockConfigs));
});
// ✅ 获取所有 URL 路由(简版)
app.get('/mock-api/routes', (req, res) => {
const list = mockConfigs.map(({ method, path }) => ({ method, path }));
res.json(list);
});
// ✅ Swagger 配置
const swaggerDefinition = {
openapi: '3.0.0',
info: {
title: 'Mock API Docs',
version: '1.0.0',
description: 'Dynamically registered mock APIs'
},
servers: [] // 将由请求动态生成
};
function buildSwaggerSpecFromMocks(configs) {
const paths = {};
configs.forEach(({ method, path, swagger }) => {
const cleanPath = path.replace(/:([^/]+)/g, '{$1}');
const methodName = method.toLowerCase();
const summary = swagger?.summary || `Mocked ${method} ${path}`;
const description = swagger?.description || '';
const responses = swagger?.responses || {
200: {
description: 'Mock response',
content: {
'application/json': {
schema: { type: 'object' }
}
}
}
};
paths[cleanPath] = paths[cleanPath] || {};
paths[cleanPath][methodName] = {
summary,
description,
responses
};
});
return {
...swaggerDefinition,
paths
};
}
// ✅ Swagger UI 路由
app.use('/swagger', (req, res, next) => {
res.setHeader('Cache-Control', 'no-store');
next();
});
app.use('/swagger', swaggerUi.serve, (req, res, next) => {
const protocol = req.headers['x-forwarded-proto'] || req.protocol;
const host = req.get('host');
const dynamicSwaggerDefinition = {
...swaggerDefinition,
servers: [
{
url: `${protocol}://${host}`,
description: 'Current host'
}
]
};
const spec = buildSwaggerSpecFromMocks(mockConfigs);
const dynamicSpec = {
...spec,
servers: dynamicSwaggerDefinition.servers
};
swaggerUi.setup(dynamicSpec)(req, res, next);
});
// ✅ 启动服务
app.listen(PORT, () => {
console.log(`✅ Mock Server is running at http://localhost:${PORT}`);
console.log(`📚 Swagger UI available at http://localhost:${PORT}/swagger`);
});