docs: 完善项目说明和注释

This commit is contained in:
湛兮
2026-05-26 11:06:13 +08:00
commit cd70caafbc
29 changed files with 3165 additions and 0 deletions
+99
View File
@@ -0,0 +1,99 @@
import Fastify from "fastify";
import { ZodError } from "zod";
import { pingDatabase } from "./db/pool";
import { catalogRoutes } from "./modules/catalog/catalog.controller";
import { employeeRoutes } from "./modules/employees/employee.controller";
import { HttpError } from "./shared/http-error";
import { ok } from "./shared/response";
// createApp 只创建并配置 Fastify 实例,不直接监听端口。
// 这样 server.ts 可以负责启动服务,测试代码也可以单独创建 app 实例。
export function createApp() {
const app = Fastify({
logger: true,
});
// 前端 Axios 默认会给 DELETE 带上 application/json;空 body 不应被当作服务端异常。
app.addContentTypeParser(
"application/json",
{ parseAs: "string" },
(_request, body, done) => {
if (body === "") {
done(null, undefined);
return;
}
try {
done(null, JSON.parse(body as string));
} catch (error) {
done(error as Error, undefined);
}
},
);
// 健康检查接口,供负载均衡器和监控系统使用。
app.get("/health", async () => {
await pingDatabase();
return ok({
status: "ok",
database: "up",
now: new Date().toISOString(),
});
});
// 注册业务路由,所有接口都以 /api 开头,便于区分静态资源和 API 请求。
app.register(catalogRoutes, { prefix: "/api" });
// 员工管理相关接口,包含员工的增删改查和状态更新等功能。
app.register(employeeRoutes, { prefix: "/api" });
// 全局错误处理器,捕获所有未处理的异常,并根据错误类型返回合适的 HTTP 状态码和错误信息。
app.setErrorHandler((error, request, reply) => {
if (error instanceof ZodError) {
return reply.code(400).send({
success: false,
error: {
code: "VALIDATION_ERROR",
message: "请求参数不合法",
details: error.issues,
},
});
}
if (error instanceof HttpError) {
return reply.code(error.statusCode).send({
success: false,
error: {
code: error.code,
message: error.message,
details: error.details,
},
});
}
const mysqlCode = (error as { code?: string }).code;
// 数据库唯一索引冲突也转成统一的业务错误响应,避免把 MySQL 原始错误直接暴露给调用方。
if (mysqlCode === "ER_DUP_ENTRY") {
return reply.code(409).send({
success: false,
error: {
code: "CONFLICT",
message: "数据已存在,请检查唯一字段",
},
});
}
request.log.error({ error }, "未处理的服务异常");
return reply.code(500).send({
success: false,
error: {
code: "INTERNAL_SERVER_ERROR",
message: "服务器内部错误",
},
});
});
return app;
}