initial commit
This commit is contained in:
454
mock/interface.mock.ts
Normal file
454
mock/interface.mock.ts
Normal file
@@ -0,0 +1,454 @@
|
||||
import type {
|
||||
InterfaceChangeLogItem,
|
||||
InterfaceDocInfo,
|
||||
InterfaceExportResponse,
|
||||
InterfaceFormValues,
|
||||
InterfaceGatewayFormValues,
|
||||
InterfaceGatewayPolicy,
|
||||
InterfaceIntegrationInfo,
|
||||
InterfaceItem,
|
||||
InterfaceListParams,
|
||||
InterfaceMockInfo,
|
||||
InterfaceRoutePreview,
|
||||
} from '@/pages/InterfaceManagement/data';
|
||||
import type { Request, Response } from 'express';
|
||||
import type { ParamsDictionary } from 'express-serve-static-core';
|
||||
|
||||
type InterfaceListQuery = Omit<InterfaceListParams, 'current' | 'pageSize'> & {
|
||||
current?: string;
|
||||
pageSize?: string;
|
||||
};
|
||||
|
||||
const interfaceList: InterfaceItem[] = [
|
||||
{
|
||||
id: 'api-1001',
|
||||
name: '用户列表查询',
|
||||
method: 'GET',
|
||||
path: '/api/users',
|
||||
owner: '李娜',
|
||||
status: 'active',
|
||||
version: 'v1',
|
||||
description: '分页获取用户列表',
|
||||
createdAt: '2024-10-01 09:30:00',
|
||||
updatedAt: '2024-10-10 18:20:00',
|
||||
},
|
||||
{
|
||||
id: 'api-1002',
|
||||
name: '新增订单',
|
||||
method: 'POST',
|
||||
path: '/api/orders',
|
||||
owner: '王彬',
|
||||
status: 'active',
|
||||
version: 'v2',
|
||||
description: '创建新的订单记录',
|
||||
createdAt: '2024-09-18 13:10:00',
|
||||
updatedAt: '2024-10-05 11:05:00',
|
||||
},
|
||||
{
|
||||
id: 'api-1003',
|
||||
name: '库存调整',
|
||||
method: 'PUT',
|
||||
path: '/api/inventory/adjust',
|
||||
owner: '赵敏',
|
||||
status: 'deprecated',
|
||||
version: 'v1',
|
||||
description: '旧库存调整接口,计划下线',
|
||||
createdAt: '2024-08-02 08:45:00',
|
||||
updatedAt: '2024-09-21 16:40:00',
|
||||
},
|
||||
{
|
||||
id: 'api-1004',
|
||||
name: '删除文章',
|
||||
method: 'DELETE',
|
||||
path: '/api/articles/:id',
|
||||
owner: '陈曦',
|
||||
status: 'disabled',
|
||||
version: 'v1',
|
||||
description: '文章删除功能已暂时关闭',
|
||||
createdAt: '2024-07-12 10:20:00',
|
||||
updatedAt: '2024-08-20 19:10:00',
|
||||
},
|
||||
];
|
||||
|
||||
const interfaceDocMap: Record<string, InterfaceDocInfo> = {
|
||||
'api-1001': {
|
||||
docUrl: 'https://docs.example.com/interfaces/api-1001',
|
||||
exampleText:
|
||||
'curl -X GET https://api.example.com/api/users?page=1&pageSize=10',
|
||||
updatedAt: '2024-10-10 18:20:00',
|
||||
owner: '李娜',
|
||||
},
|
||||
'api-1002': {
|
||||
docUrl: 'https://docs.example.com/interfaces/api-1002',
|
||||
exampleText: 'curl -X POST https://api.example.com/api/orders -d "{}"',
|
||||
updatedAt: '2024-10-05 11:05:00',
|
||||
owner: '王彬',
|
||||
},
|
||||
};
|
||||
|
||||
const gatewayPolicyMap: Record<string, InterfaceGatewayPolicy> = {
|
||||
'api-1001': {
|
||||
routeId: 'route-api-1001',
|
||||
rateLimit: '2000 次/分钟',
|
||||
authType: 'OAuth2 + 签名校验',
|
||||
timeoutMs: 3000,
|
||||
},
|
||||
'api-1002': {
|
||||
routeId: 'route-api-1002',
|
||||
rateLimit: '1200 次/分钟',
|
||||
authType: 'API Key',
|
||||
timeoutMs: 5000,
|
||||
},
|
||||
};
|
||||
|
||||
const mockInfoMap: Record<string, InterfaceMockInfo> = {
|
||||
'api-1001': {
|
||||
requestSample:
|
||||
'curl -X GET https://api.example.com/api/users?page=1&pageSize=10',
|
||||
responseSample: '{"success":true,"data":[{"id":"1"}],"total":1}',
|
||||
latency: '120ms',
|
||||
mockEnabled: true,
|
||||
mockUrl: 'https://mock.example.com/interfaces/api-1001',
|
||||
},
|
||||
'api-1002': {
|
||||
requestSample: 'curl -X POST https://api.example.com/api/orders -d "{}"',
|
||||
responseSample: '{"success":true,"data":{"id":"100"}}',
|
||||
latency: '210ms',
|
||||
mockEnabled: false,
|
||||
mockUrl: 'https://mock.example.com/interfaces/api-1002',
|
||||
},
|
||||
};
|
||||
|
||||
const integrationInfoMap: Record<string, InterfaceIntegrationInfo> = {
|
||||
'api-1001': {
|
||||
partner: '物流平台 A',
|
||||
channel: 'API Key + IP 白名单',
|
||||
status: '已接入',
|
||||
consoleUrl: 'https://console.example.com/integrations/api-1001',
|
||||
},
|
||||
'api-1002': {
|
||||
partner: '支付平台 B',
|
||||
channel: 'JWT + 双向 TLS',
|
||||
status: '对接中',
|
||||
consoleUrl: 'https://console.example.com/integrations/api-1002',
|
||||
},
|
||||
};
|
||||
|
||||
const changeLogMap: Record<string, InterfaceChangeLogItem[]> = {
|
||||
'api-1001': [
|
||||
{
|
||||
id: 'log-1',
|
||||
time: '2024-10-10 18:20',
|
||||
description: '调整响应字段,新增可选字段 note',
|
||||
operator: '李娜',
|
||||
},
|
||||
{
|
||||
id: 'log-2',
|
||||
time: '2024-09-18 13:10',
|
||||
description: '接口首次发布',
|
||||
operator: '王彬',
|
||||
},
|
||||
],
|
||||
'api-1002': [
|
||||
{
|
||||
id: 'log-3',
|
||||
time: '2024-10-05 11:05',
|
||||
description: '补充校验规则与异常码',
|
||||
operator: '王彬',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const parseNumber = (value: string | undefined, fallback: number) => {
|
||||
const parsed = Number(value);
|
||||
return Number.isNaN(parsed) ? fallback : parsed;
|
||||
};
|
||||
|
||||
const getInterfaceItem = (id: string) =>
|
||||
interfaceList.find((item) => item.id === id);
|
||||
|
||||
const ensureGatewayPolicy = (id: string): InterfaceGatewayPolicy => {
|
||||
if (!gatewayPolicyMap[id]) {
|
||||
gatewayPolicyMap[id] = {
|
||||
routeId: `route-${id}`,
|
||||
rateLimit: '2000 次/分钟',
|
||||
authType: 'OAuth2 + 签名校验',
|
||||
timeoutMs: 3000,
|
||||
};
|
||||
}
|
||||
return gatewayPolicyMap[id];
|
||||
};
|
||||
|
||||
const ensureMockInfo = (id: string): InterfaceMockInfo => {
|
||||
if (!mockInfoMap[id]) {
|
||||
const item = getInterfaceItem(id);
|
||||
mockInfoMap[id] = {
|
||||
requestSample: `curl -X ${item?.method ?? 'GET'} https://api.example.com${
|
||||
item?.path ?? '/api/example'
|
||||
}`,
|
||||
responseSample: '{"success":true}',
|
||||
latency: '120ms',
|
||||
mockEnabled: false,
|
||||
mockUrl: `https://mock.example.com/interfaces/${id}`,
|
||||
};
|
||||
}
|
||||
return mockInfoMap[id];
|
||||
};
|
||||
|
||||
export default {
|
||||
'GET /api/interfaces': (
|
||||
req: Request<ParamsDictionary, unknown, unknown, InterfaceListQuery>,
|
||||
res: Response,
|
||||
) => {
|
||||
const { current, pageSize, name, method, path, owner, status, version } =
|
||||
req.query;
|
||||
const currentPage = parseNumber(current, 1);
|
||||
const size = parseNumber(pageSize, 10);
|
||||
|
||||
let dataSource = [...interfaceList];
|
||||
|
||||
if (name) {
|
||||
dataSource = dataSource.filter((item) => item.name.includes(name));
|
||||
}
|
||||
|
||||
if (method) {
|
||||
dataSource = dataSource.filter((item) => item.method === method);
|
||||
}
|
||||
|
||||
if (path) {
|
||||
dataSource = dataSource.filter((item) => item.path.includes(path));
|
||||
}
|
||||
|
||||
if (owner) {
|
||||
dataSource = dataSource.filter((item) => item.owner.includes(owner));
|
||||
}
|
||||
|
||||
if (status) {
|
||||
dataSource = dataSource.filter((item) => item.status === status);
|
||||
}
|
||||
|
||||
if (version) {
|
||||
dataSource = dataSource.filter((item) => item.version.includes(version));
|
||||
}
|
||||
|
||||
const start = (currentPage - 1) * size;
|
||||
const end = start + size;
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: dataSource.slice(start, end),
|
||||
total: dataSource.length,
|
||||
});
|
||||
},
|
||||
|
||||
'POST /api/interfaces': (
|
||||
req: Request<ParamsDictionary, InterfaceItem, InterfaceFormValues>,
|
||||
res: Response,
|
||||
) => {
|
||||
const now = new Date().toISOString();
|
||||
const newItem: InterfaceItem = {
|
||||
id: `api-${Date.now()}`,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
...req.body,
|
||||
};
|
||||
interfaceList.unshift(newItem);
|
||||
res.json(newItem);
|
||||
},
|
||||
|
||||
'PUT /api/interfaces/:id': (
|
||||
req: Request<{ id: string }, InterfaceItem, InterfaceFormValues>,
|
||||
res: Response,
|
||||
) => {
|
||||
const { id } = req.params;
|
||||
const index = interfaceList.findIndex((item) => item.id === id);
|
||||
if (index >= 0) {
|
||||
interfaceList[index] = {
|
||||
...interfaceList[index],
|
||||
...req.body,
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
res.json(interfaceList[index]);
|
||||
return;
|
||||
}
|
||||
|
||||
res.status(404).json({
|
||||
success: false,
|
||||
data: interfaceList,
|
||||
total: interfaceList.length,
|
||||
});
|
||||
},
|
||||
|
||||
'DELETE /api/interfaces/:id': (
|
||||
req: Request<{ id: string }>,
|
||||
res: Response,
|
||||
) => {
|
||||
const { id } = req.params;
|
||||
const index = interfaceList.findIndex((item) => item.id === id);
|
||||
if (index >= 0) {
|
||||
interfaceList.splice(index, 1);
|
||||
res.json({ success: true });
|
||||
return;
|
||||
}
|
||||
res.status(404).json({ success: false });
|
||||
},
|
||||
|
||||
'GET /api/interfaces/:id/doc': (
|
||||
req: Request<{ id: string }>,
|
||||
res: Response<InterfaceDocInfo>,
|
||||
) => {
|
||||
const { id } = req.params;
|
||||
const item = getInterfaceItem(id);
|
||||
if (!item) {
|
||||
res.status(404).end();
|
||||
return;
|
||||
}
|
||||
const docInfo: InterfaceDocInfo = interfaceDocMap[id] ?? {
|
||||
docUrl: `https://docs.example.com/interfaces/${id}`,
|
||||
exampleText: `curl -X ${item.method} https://api.example.com${item.path}`,
|
||||
updatedAt: item.updatedAt,
|
||||
owner: item.owner,
|
||||
};
|
||||
interfaceDocMap[id] = docInfo;
|
||||
res.json(docInfo);
|
||||
},
|
||||
|
||||
'GET /api/interfaces/:id/gateway': (
|
||||
req: Request<{ id: string }>,
|
||||
res: Response<InterfaceGatewayPolicy>,
|
||||
) => {
|
||||
const { id } = req.params;
|
||||
res.json(ensureGatewayPolicy(id));
|
||||
},
|
||||
|
||||
'PUT /api/interfaces/:id/gateway': (
|
||||
req: Request<
|
||||
{ id: string },
|
||||
InterfaceGatewayPolicy,
|
||||
InterfaceGatewayFormValues
|
||||
>,
|
||||
res: Response<InterfaceGatewayPolicy>,
|
||||
) => {
|
||||
const { id } = req.params;
|
||||
const currentPolicy = ensureGatewayPolicy(id);
|
||||
const nextPolicy: InterfaceGatewayPolicy = {
|
||||
...currentPolicy,
|
||||
rateLimit: req.body.rateLimit,
|
||||
authType: req.body.authType,
|
||||
timeoutMs: req.body.timeoutMs,
|
||||
};
|
||||
gatewayPolicyMap[id] = nextPolicy;
|
||||
res.json(nextPolicy);
|
||||
},
|
||||
|
||||
'GET /api/interfaces/:id/gateway/preview': (
|
||||
req: Request<{ id: string }>,
|
||||
res: Response<InterfaceRoutePreview>,
|
||||
) => {
|
||||
const { id } = req.params;
|
||||
const item = getInterfaceItem(id);
|
||||
if (!item) {
|
||||
res.status(404).end();
|
||||
return;
|
||||
}
|
||||
const policy = ensureGatewayPolicy(id);
|
||||
const preview: InterfaceRoutePreview = {
|
||||
routeId: policy.routeId,
|
||||
upstream: 'https://gateway.example.com',
|
||||
path: item.path,
|
||||
method: item.method,
|
||||
timeoutMs: policy.timeoutMs,
|
||||
rateLimit: policy.rateLimit,
|
||||
authType: policy.authType,
|
||||
};
|
||||
res.json(preview);
|
||||
},
|
||||
|
||||
'GET /api/interfaces/:id/mock': (
|
||||
req: Request<{ id: string }>,
|
||||
res: Response<InterfaceMockInfo>,
|
||||
) => {
|
||||
const { id } = req.params;
|
||||
res.json(ensureMockInfo(id));
|
||||
},
|
||||
|
||||
'POST /api/interfaces/:id/debug': (
|
||||
req: Request<{ id: string }>,
|
||||
res: Response<{ success: boolean; message: string }>,
|
||||
) => {
|
||||
const { id } = req.params;
|
||||
const mockInfo = ensureMockInfo(id);
|
||||
mockInfo.mockEnabled = true;
|
||||
mockInfo.latency = '98ms';
|
||||
res.json({ success: true, message: 'debug-started' });
|
||||
},
|
||||
|
||||
'GET /api/interfaces/:id/integrations': (
|
||||
req: Request<{ id: string }>,
|
||||
res: Response<InterfaceIntegrationInfo>,
|
||||
) => {
|
||||
const { id } = req.params;
|
||||
const info =
|
||||
integrationInfoMap[id] ??
|
||||
({
|
||||
partner: '待配置',
|
||||
channel: '未配置',
|
||||
status: '未接入',
|
||||
consoleUrl: 'https://console.example.com/integrations',
|
||||
} as InterfaceIntegrationInfo);
|
||||
integrationInfoMap[id] = info;
|
||||
res.json(info);
|
||||
},
|
||||
|
||||
'POST /api/interfaces/:id/integrations': (
|
||||
req: Request<
|
||||
{ id: string },
|
||||
InterfaceIntegrationInfo,
|
||||
Pick<InterfaceIntegrationInfo, 'partner' | 'channel'>
|
||||
>,
|
||||
res: Response<InterfaceIntegrationInfo>,
|
||||
) => {
|
||||
const { id } = req.params;
|
||||
const info: InterfaceIntegrationInfo = {
|
||||
partner: req.body.partner,
|
||||
channel: req.body.channel,
|
||||
status: '已接入',
|
||||
consoleUrl: `https://console.example.com/integrations/${id}`,
|
||||
};
|
||||
integrationInfoMap[id] = info;
|
||||
res.json(info);
|
||||
},
|
||||
|
||||
'POST /api/interfaces/:id/integrations/key': (
|
||||
req: Request<{ id: string }>,
|
||||
res: Response<InterfaceIntegrationInfo>,
|
||||
) => {
|
||||
const { id } = req.params;
|
||||
const info = integrationInfoMap[id] ?? {
|
||||
partner: '待配置',
|
||||
channel: '未配置',
|
||||
status: '未接入',
|
||||
consoleUrl: `https://console.example.com/integrations/${id}`,
|
||||
};
|
||||
res.json(info);
|
||||
},
|
||||
|
||||
'GET /api/interfaces/:id/changelog': (
|
||||
req: Request<{ id: string }>,
|
||||
res: Response<InterfaceChangeLogItem[]>,
|
||||
) => {
|
||||
const { id } = req.params;
|
||||
res.json(changeLogMap[id] ?? []);
|
||||
},
|
||||
|
||||
'GET /api/interfaces/:id/changelog/export': (
|
||||
req: Request<{ id: string }>,
|
||||
res: Response<InterfaceExportResponse>,
|
||||
) => {
|
||||
const { id } = req.params;
|
||||
res.json({
|
||||
downloadUrl: `https://download.example.com/interfaces/${id}/changelog.csv`,
|
||||
fileName: `interface-${id}-changelog.csv`,
|
||||
});
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user