- 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 后端开发指引
55 lines
1.8 KiB
TypeScript
55 lines
1.8 KiB
TypeScript
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";
|
|
}
|