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:
54
src/server/static.ts
Normal file
54
src/server/static.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import type { RuntimeMode } from "../shared/api";
|
||||
import { createHeaders } from "./helpers";
|
||||
import type { StaticAssets } from "./app";
|
||||
|
||||
export function serveStaticAsset(pathname: string, staticAssets: StaticAssets, mode: RuntimeMode): Response {
|
||||
if (pathname === "/") {
|
||||
return htmlResponse(staticAssets.indexHtml, mode);
|
||||
}
|
||||
|
||||
const asset = staticAssets.files[pathname];
|
||||
|
||||
if (asset) {
|
||||
return new Response(asset, {
|
||||
headers: createHeaders(mode, {
|
||||
"Content-Type": contentTypeFor(pathname),
|
||||
"Cache-Control": "public, max-age=31536000, immutable",
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
if (pathname.startsWith("/assets/") || hasFileExtension(pathname)) {
|
||||
return new Response("Not Found", {
|
||||
status: 404,
|
||||
headers: createHeaders(mode, { "Content-Type": "text/plain; charset=utf-8" }),
|
||||
});
|
||||
}
|
||||
|
||||
return htmlResponse(staticAssets.indexHtml, mode);
|
||||
}
|
||||
|
||||
export function htmlResponse(indexHtml: Blob, mode: RuntimeMode): Response {
|
||||
return new Response(indexHtml, {
|
||||
headers: createHeaders(mode, {
|
||||
"Content-Type": "text/html; charset=utf-8",
|
||||
"Cache-Control": "no-cache",
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
export function hasFileExtension(pathname: string): boolean {
|
||||
return /\/[^/]+\.[^/]+$/.test(pathname);
|
||||
}
|
||||
|
||||
export function contentTypeFor(pathname: string): string {
|
||||
if (pathname.endsWith(".js") || pathname.endsWith(".mjs")) return "text/javascript; charset=utf-8";
|
||||
if (pathname.endsWith(".css")) return "text/css; charset=utf-8";
|
||||
if (pathname.endsWith(".svg")) return "image/svg+xml";
|
||||
if (pathname.endsWith(".json")) return "application/json; charset=utf-8";
|
||||
if (pathname.endsWith(".png")) return "image/png";
|
||||
if (pathname.endsWith(".jpg") || pathname.endsWith(".jpeg")) return "image/jpeg";
|
||||
if (pathname.endsWith(".ico")) return "image/x-icon";
|
||||
|
||||
return "application/octet-stream";
|
||||
}
|
||||
Reference in New Issue
Block a user