refactor: 全面优化后端代码质量与架构
- app.ts 单体路由拆分为 routes/ + helpers + middleware + static 独立模块 - 类型去重:CheckFailure/CheckResult 以 shared/api.ts 为唯一源头,收紧 phase 联合类型 - es-toolkit 替换:isPlainObject/isNil/isEmptyObject/isEqual/isError/Semaphore/groupBy - Bun 内置 API:Object.fromEntries 替代手写 headersToRecord - bun:sqlite 规范:prepare() → query() 利用内置缓存,避免 N+1 查询 - 新增 getLatestChecksMap/allGetTargetStats 批量查询方法 - 新增 backend-code-quality/api-route-separation/batch-data-queries 规范 - 补充 openspec/config.yaml 后端开发规范与 DEVELOPMENT.md 后端开发指引
This commit is contained in:
58
src/server/middleware.ts
Normal file
58
src/server/middleware.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import type { RuntimeMode } from "../shared/api";
|
||||
import { allowsGetHead, createApiError, jsonResponse, methodNotAllowedResponse } from "./helpers";
|
||||
|
||||
export function guardGetHead(method: string, mode: RuntimeMode): Response | null {
|
||||
if (!allowsGetHead(method)) {
|
||||
return methodNotAllowedResponse(["GET", "HEAD"], mode);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validateTargetId(idStr: string, mode: RuntimeMode): { id: number } | Response {
|
||||
const id = Number(idStr);
|
||||
if (!Number.isInteger(id) || id <= 0) {
|
||||
return jsonResponse(createApiError("Invalid target ID", 400), { mode, status: 400 });
|
||||
}
|
||||
return { id };
|
||||
}
|
||||
|
||||
export function validateTimeRange(
|
||||
from: string | null,
|
||||
to: string | null,
|
||||
mode: RuntimeMode,
|
||||
): { from: string; to: string } | Response {
|
||||
if (!from || !to) {
|
||||
return jsonResponse(createApiError("from and to parameters are required", 400), { mode, status: 400 });
|
||||
}
|
||||
|
||||
if (isNaN(new Date(from).getTime()) || isNaN(new Date(to).getTime())) {
|
||||
return jsonResponse(createApiError("Invalid from or to parameter format", 400), { mode, status: 400 });
|
||||
}
|
||||
|
||||
return { from, to };
|
||||
}
|
||||
|
||||
export function validatePagination(
|
||||
pageParam: string | null,
|
||||
pageSizeParam: string | null,
|
||||
mode: RuntimeMode,
|
||||
): { page: number; pageSize: number } | Response {
|
||||
let page = 1;
|
||||
let pageSize = 20;
|
||||
|
||||
if (pageParam !== null) {
|
||||
page = Number(pageParam);
|
||||
if (!Number.isInteger(page) || page <= 0) {
|
||||
return jsonResponse(createApiError("Invalid page parameter", 400), { mode, status: 400 });
|
||||
}
|
||||
}
|
||||
|
||||
if (pageSizeParam !== null) {
|
||||
pageSize = Number(pageSizeParam);
|
||||
if (!Number.isInteger(pageSize) || pageSize <= 0) {
|
||||
return jsonResponse(createApiError("Invalid pageSize parameter", 400), { mode, status: 400 });
|
||||
}
|
||||
}
|
||||
|
||||
return { page, pageSize };
|
||||
}
|
||||
Reference in New Issue
Block a user