@usethink/cf-core 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -0
- package/dist/features/anti-abuse/index.d.ts +62 -0
- package/dist/features/anti-abuse/index.d.ts.map +1 -0
- package/dist/features/anti-abuse/index.js +139 -0
- package/dist/features/anti-abuse/index.js.map +1 -0
- package/dist/features/email/index.d.ts +68 -0
- package/dist/features/email/index.d.ts.map +1 -0
- package/dist/features/email/index.js +120 -0
- package/dist/features/email/index.js.map +1 -0
- package/dist/features/payment/fetch-utils.d.ts +17 -0
- package/dist/features/payment/fetch-utils.d.ts.map +1 -0
- package/dist/features/payment/fetch-utils.js +56 -0
- package/dist/features/payment/fetch-utils.js.map +1 -0
- package/dist/features/payment/index.d.ts +20 -0
- package/dist/features/payment/index.d.ts.map +1 -0
- package/dist/features/payment/index.js +21 -0
- package/dist/features/payment/index.js.map +1 -0
- package/dist/features/payment/providers/alipay.d.ts +30 -0
- package/dist/features/payment/providers/alipay.d.ts.map +1 -0
- package/dist/features/payment/providers/alipay.js +149 -0
- package/dist/features/payment/providers/alipay.js.map +1 -0
- package/dist/features/payment/providers/stripe.d.ts +34 -0
- package/dist/features/payment/providers/stripe.d.ts.map +1 -0
- package/dist/features/payment/providers/stripe.js +168 -0
- package/dist/features/payment/providers/stripe.js.map +1 -0
- package/dist/features/payment/providers/trc20.d.ts +24 -0
- package/dist/features/payment/providers/trc20.d.ts.map +1 -0
- package/dist/features/payment/providers/trc20.js +96 -0
- package/dist/features/payment/providers/trc20.js.map +1 -0
- package/dist/features/payment/registry.d.ts +43 -0
- package/dist/features/payment/registry.d.ts.map +1 -0
- package/dist/features/payment/registry.js +65 -0
- package/dist/features/payment/registry.js.map +1 -0
- package/dist/features/payment/types.d.ts +72 -0
- package/dist/features/payment/types.d.ts.map +1 -0
- package/dist/features/payment/types.js +8 -0
- package/dist/features/payment/types.js.map +1 -0
- package/dist/features/thompson-router/index.d.ts +101 -0
- package/dist/features/thompson-router/index.d.ts.map +1 -0
- package/dist/features/thompson-router/index.js +186 -0
- package/dist/features/thompson-router/index.js.map +1 -0
- package/dist/features/webhook/index.d.ts +76 -0
- package/dist/features/webhook/index.d.ts.map +1 -0
- package/dist/features/webhook/index.js +127 -0
- package/dist/features/webhook/index.js.map +1 -0
- package/dist/src/audit.d.ts +45 -0
- package/dist/src/audit.d.ts.map +1 -0
- package/dist/src/audit.js +40 -0
- package/dist/src/audit.js.map +1 -0
- package/dist/src/auth/jwt.d.ts +33 -0
- package/dist/src/auth/jwt.d.ts.map +1 -0
- package/dist/src/auth/jwt.js +87 -0
- package/dist/src/auth/jwt.js.map +1 -0
- package/dist/src/auth/password.d.ts +26 -0
- package/dist/src/auth/password.d.ts.map +1 -0
- package/dist/src/auth/password.js +52 -0
- package/dist/src/auth/password.js.map +1 -0
- package/dist/src/bootstrap.d.ts +74 -0
- package/dist/src/bootstrap.d.ts.map +1 -0
- package/dist/src/bootstrap.js +231 -0
- package/dist/src/bootstrap.js.map +1 -0
- package/dist/src/cache.d.ts +52 -0
- package/dist/src/cache.d.ts.map +1 -0
- package/dist/src/cache.js +76 -0
- package/dist/src/cache.js.map +1 -0
- package/dist/src/config.d.ts +83 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +96 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/crypto.d.ts +33 -0
- package/dist/src/crypto.d.ts.map +1 -0
- package/dist/src/crypto.js +87 -0
- package/dist/src/crypto.js.map +1 -0
- package/dist/src/db/connection.d.ts +53 -0
- package/dist/src/db/connection.d.ts.map +1 -0
- package/dist/src/db/connection.js +104 -0
- package/dist/src/db/connection.js.map +1 -0
- package/dist/src/db/index.d.ts +6 -0
- package/dist/src/db/index.d.ts.map +1 -0
- package/dist/src/db/index.js +6 -0
- package/dist/src/db/index.js.map +1 -0
- package/dist/src/db/schema.d.ts +649 -0
- package/dist/src/db/schema.d.ts.map +1 -0
- package/dist/src/db/schema.js +76 -0
- package/dist/src/db/schema.js.map +1 -0
- package/dist/src/error.d.ts +47 -0
- package/dist/src/error.d.ts.map +1 -0
- package/dist/src/error.js +94 -0
- package/dist/src/error.js.map +1 -0
- package/dist/src/http.d.ts +83 -0
- package/dist/src/http.d.ts.map +1 -0
- package/dist/src/http.js +116 -0
- package/dist/src/http.js.map +1 -0
- package/dist/src/idempotency.d.ts +78 -0
- package/dist/src/idempotency.d.ts.map +1 -0
- package/dist/src/idempotency.js +84 -0
- package/dist/src/idempotency.js.map +1 -0
- package/dist/src/index.d.ts +31 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +45 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/logger.d.ts +31 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +45 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/middleware/admin-auth.d.ts +38 -0
- package/dist/src/middleware/admin-auth.d.ts.map +1 -0
- package/dist/src/middleware/admin-auth.js +55 -0
- package/dist/src/middleware/admin-auth.js.map +1 -0
- package/dist/src/middleware/api-key-auth.d.ts +42 -0
- package/dist/src/middleware/api-key-auth.d.ts.map +1 -0
- package/dist/src/middleware/api-key-auth.js +104 -0
- package/dist/src/middleware/api-key-auth.js.map +1 -0
- package/dist/src/middleware/index.d.ts +3 -0
- package/dist/src/middleware/index.d.ts.map +1 -0
- package/dist/src/middleware/index.js +3 -0
- package/dist/src/middleware/index.js.map +1 -0
- package/dist/src/rate-limit.d.ts +54 -0
- package/dist/src/rate-limit.d.ts.map +1 -0
- package/dist/src/rate-limit.js +134 -0
- package/dist/src/rate-limit.js.map +1 -0
- package/dist/src/security.d.ts +78 -0
- package/dist/src/security.d.ts.map +1 -0
- package/dist/src/security.js +175 -0
- package/dist/src/security.js.map +1 -0
- package/dist/src/types.d.ts +64 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +8 -0
- package/dist/src/types.js.map +1 -0
- package/features/anti-abuse/index.ts +180 -0
- package/features/anti-abuse/tests/index.test.ts +50 -0
- package/features/email/index.ts +172 -0
- package/features/email/tests/index.test.ts +44 -0
- package/features/payment/fetch-utils.ts +65 -0
- package/features/payment/index.ts +39 -0
- package/features/payment/providers/alipay.ts +171 -0
- package/features/payment/providers/stripe.ts +192 -0
- package/features/payment/providers/trc20.ts +115 -0
- package/features/payment/registry.ts +87 -0
- package/features/payment/tests/index.test.ts +506 -0
- package/features/payment/types.ts +93 -0
- package/features/telegram-miniapp/index.ts +109 -0
- package/features/telegram-miniapp/tests/index.test.ts +11 -0
- package/features/thompson-router/index.ts +243 -0
- package/features/thompson-router/tests/index.test.ts +93 -0
- package/features/webhook/index.ts +183 -0
- package/features/webhook/tests/index.test.ts +21 -0
- package/package.json +202 -0
- package/src/audit.ts +70 -0
- package/src/auth/jwt.ts +114 -0
- package/src/auth/password.ts +75 -0
- package/src/bootstrap.ts +322 -0
- package/src/cache.ts +78 -0
- package/src/config.ts +134 -0
- package/src/crypto.ts +106 -0
- package/src/db/connection.ts +127 -0
- package/src/db/index.ts +6 -0
- package/src/db/schema.ts +90 -0
- package/src/error.ts +125 -0
- package/src/http.ts +150 -0
- package/src/idempotency.ts +127 -0
- package/src/index.ts +85 -0
- package/src/logger.ts +63 -0
- package/src/middleware/admin-auth.ts +71 -0
- package/src/middleware/api-key-auth.ts +164 -0
- package/src/middleware/index.ts +2 -0
- package/src/rate-limit.ts +167 -0
- package/src/security.ts +219 -0
- package/src/types.ts +70 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../features/webhook/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 审计日志模块
|
|
3
|
+
*
|
|
4
|
+
* 提供管理员操作审计和通用事件日志。
|
|
5
|
+
* 设计为 fire-and-forget:写入失败不阻塞主流程。
|
|
6
|
+
* 内置 5% 概率自动清理旧日志,避免数据无限增长。
|
|
7
|
+
*
|
|
8
|
+
* 来源:eshop/vcode audit-service.ts 合并
|
|
9
|
+
*/
|
|
10
|
+
import { adminAuditLogs } from "./db/schema";
|
|
11
|
+
/**
|
|
12
|
+
* 通用 Drizzle 数据库接口(仅约束审计模块需要的方法)
|
|
13
|
+
*/
|
|
14
|
+
interface AuditDbLike {
|
|
15
|
+
insert: (table: typeof adminAuditLogs) => {
|
|
16
|
+
values: (data: {
|
|
17
|
+
id: string;
|
|
18
|
+
action: string;
|
|
19
|
+
targetType: string;
|
|
20
|
+
targetId: string;
|
|
21
|
+
metadataJson: string;
|
|
22
|
+
ipHash: string;
|
|
23
|
+
createdAt: string;
|
|
24
|
+
}) => Promise<unknown>;
|
|
25
|
+
};
|
|
26
|
+
$client?: {
|
|
27
|
+
execute: (sql: string) => Promise<unknown>;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export interface AuditInput {
|
|
31
|
+
action: string;
|
|
32
|
+
targetType?: string;
|
|
33
|
+
targetId?: string;
|
|
34
|
+
metadata?: unknown;
|
|
35
|
+
ipHash?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 写入管理员审计日志
|
|
39
|
+
*
|
|
40
|
+
* fire-and-forget 模式:调用方应使用 ctx.waitUntil() 或直接 await。
|
|
41
|
+
* 写入失败仅打印 warn,不抛异常。
|
|
42
|
+
*/
|
|
43
|
+
export declare function writeAdminAudit(db: AuditDbLike, input: AuditInput): Promise<void>;
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/audit.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C;;GAEG;AACH,UAAU,WAAW;IACnB,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,cAAc,KAAK;QACxC,MAAM,EAAE,CAAC,IAAI,EAAE;YACb,EAAE,EAAE,MAAM,CAAC;YACX,MAAM,EAAE,MAAM,CAAC;YACf,UAAU,EAAE,MAAM,CAAC;YACnB,QAAQ,EAAE,MAAM,CAAC;YACjB,YAAY,EAAE,MAAM,CAAC;YACrB,MAAM,EAAE,MAAM,CAAC;YACf,SAAS,EAAE,MAAM,CAAC;SACnB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;KACxB,CAAC;IACF,OAAO,CAAC,EAAE;QACR,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;KAC5C,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBvF"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 审计日志模块
|
|
3
|
+
*
|
|
4
|
+
* 提供管理员操作审计和通用事件日志。
|
|
5
|
+
* 设计为 fire-and-forget:写入失败不阻塞主流程。
|
|
6
|
+
* 内置 5% 概率自动清理旧日志,避免数据无限增长。
|
|
7
|
+
*
|
|
8
|
+
* 来源:eshop/vcode audit-service.ts 合并
|
|
9
|
+
*/
|
|
10
|
+
import { adminAuditLogs } from "./db/schema";
|
|
11
|
+
/**
|
|
12
|
+
* 写入管理员审计日志
|
|
13
|
+
*
|
|
14
|
+
* fire-and-forget 模式:调用方应使用 ctx.waitUntil() 或直接 await。
|
|
15
|
+
* 写入失败仅打印 warn,不抛异常。
|
|
16
|
+
*/
|
|
17
|
+
export async function writeAdminAudit(db, input) {
|
|
18
|
+
try {
|
|
19
|
+
await db.insert(adminAuditLogs).values({
|
|
20
|
+
id: crypto.randomUUID(),
|
|
21
|
+
action: input.action,
|
|
22
|
+
targetType: input.targetType || "",
|
|
23
|
+
targetId: input.targetId || "",
|
|
24
|
+
metadataJson: JSON.stringify(input.metadata || {}),
|
|
25
|
+
ipHash: input.ipHash || "",
|
|
26
|
+
createdAt: new Date().toISOString(),
|
|
27
|
+
});
|
|
28
|
+
// 5% 概率清理超过 90 天的旧日志
|
|
29
|
+
if (Math.random() < 0.05) {
|
|
30
|
+
try {
|
|
31
|
+
db.$client?.execute(`DELETE FROM admin_audit_logs WHERE created_at < datetime('now', '-90 days')`).catch(() => { });
|
|
32
|
+
}
|
|
33
|
+
catch { /* mock DB may not have execute */ }
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
console.warn("[audit] writeAdminAudit failed:", err instanceof Error ? err.message : String(err));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/audit.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AA8B7C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EAAe,EAAE,KAAiB;IACtE,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC;YACrC,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;YACvB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,EAAE;YAClC,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,EAAE;YAC9B,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;YAClD,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE;YAC1B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC,CAAC;QAEH,qBAAqB;QACrB,IAAI,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,EAAE,CAAC,OAAO,EAAE,OAAO,CACjB,6EAA6E,CAC9E,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACpB,CAAC;YAAC,MAAM,CAAC,CAAC,kCAAkC,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,iCAAiC,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACpG,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT 签发与验证(HMAC-SHA256)
|
|
3
|
+
*
|
|
4
|
+
* 纯 Web Crypto API 实现,零外部依赖。
|
|
5
|
+
* Workers 原生支持,性能优异。
|
|
6
|
+
*
|
|
7
|
+
* 来源:xtools src/lib/auth.ts
|
|
8
|
+
*/
|
|
9
|
+
export interface JwtPayload {
|
|
10
|
+
sub: string;
|
|
11
|
+
email: string;
|
|
12
|
+
iat: number;
|
|
13
|
+
exp: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 签发 JWT
|
|
17
|
+
*/
|
|
18
|
+
export declare function signJwt(userId: string, email: string, secret: string, expirySeconds?: number): Promise<string>;
|
|
19
|
+
/**
|
|
20
|
+
* 验证并解析 JWT — 验证失败返回 null
|
|
21
|
+
*/
|
|
22
|
+
export declare function verifyJwt(token: string, secret: string): Promise<JwtPayload | null>;
|
|
23
|
+
/**
|
|
24
|
+
* 从请求中提取 JWT Token
|
|
25
|
+
*
|
|
26
|
+
* 优先级:Authorization: Bearer > Cookie: token=
|
|
27
|
+
*/
|
|
28
|
+
export declare function extractJwt(c: {
|
|
29
|
+
req: {
|
|
30
|
+
header: (name: string) => string | undefined;
|
|
31
|
+
};
|
|
32
|
+
}): string | null;
|
|
33
|
+
//# sourceMappingURL=jwt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../../src/auth/jwt.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AA+BD;;GAEG;AACH,wBAAsB,OAAO,CAC3B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,aAAa,SAAiB,GAC7B,OAAO,CAAC,MAAM,CAAC,CAYjB;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAwBzF;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE;IAAE,GAAG,EAAE;QAAE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAA;KAAE,CAAA;CAAE,GAAG,MAAM,GAAG,IAAI,CAYtG"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT 签发与验证(HMAC-SHA256)
|
|
3
|
+
*
|
|
4
|
+
* 纯 Web Crypto API 实现,零外部依赖。
|
|
5
|
+
* Workers 原生支持,性能优异。
|
|
6
|
+
*
|
|
7
|
+
* 来源:xtools src/lib/auth.ts
|
|
8
|
+
*/
|
|
9
|
+
const DEFAULT_EXPIRY = 24 * 60 * 60; // 24 小时
|
|
10
|
+
function base64UrlEncode(data) {
|
|
11
|
+
const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
|
|
12
|
+
let binary = "";
|
|
13
|
+
for (const b of bytes)
|
|
14
|
+
binary += String.fromCharCode(b);
|
|
15
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
16
|
+
}
|
|
17
|
+
function base64UrlDecode(str) {
|
|
18
|
+
let base64 = str.replace(/-/g, "+").replace(/_/g, "/");
|
|
19
|
+
const padding = 4 - (base64.length % 4);
|
|
20
|
+
if (padding !== 4)
|
|
21
|
+
base64 += "=".repeat(padding);
|
|
22
|
+
const binary = atob(base64);
|
|
23
|
+
const bytes = new Uint8Array(binary.length);
|
|
24
|
+
for (let i = 0; i < binary.length; i++)
|
|
25
|
+
bytes[i] = binary.charCodeAt(i);
|
|
26
|
+
return bytes;
|
|
27
|
+
}
|
|
28
|
+
async function importHmacKey(secret) {
|
|
29
|
+
return crypto.subtle.importKey("raw", new TextEncoder().encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign", "verify"]);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 签发 JWT
|
|
33
|
+
*/
|
|
34
|
+
export async function signJwt(userId, email, secret, expirySeconds = DEFAULT_EXPIRY) {
|
|
35
|
+
const now = Math.floor(Date.now() / 1000);
|
|
36
|
+
const payload = { sub: userId, email, iat: now, exp: now + expirySeconds };
|
|
37
|
+
const header = base64UrlEncode(JSON.stringify({ alg: "HS256", typ: "JWT" }));
|
|
38
|
+
const body = base64UrlEncode(JSON.stringify(payload));
|
|
39
|
+
const signingInput = `${header}.${body}`;
|
|
40
|
+
const key = await importHmacKey(secret);
|
|
41
|
+
const signature = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(signingInput));
|
|
42
|
+
return `${signingInput}.${base64UrlEncode(new Uint8Array(signature))}`;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 验证并解析 JWT — 验证失败返回 null
|
|
46
|
+
*/
|
|
47
|
+
export async function verifyJwt(token, secret) {
|
|
48
|
+
try {
|
|
49
|
+
const parts = token.split(".");
|
|
50
|
+
if (parts.length !== 3)
|
|
51
|
+
return null;
|
|
52
|
+
const [header, body, signature] = parts;
|
|
53
|
+
const signingInput = `${header}.${body}`;
|
|
54
|
+
const key = await importHmacKey(secret);
|
|
55
|
+
const valid = await crypto.subtle.verify("HMAC", key, base64UrlDecode(signature), new TextEncoder().encode(signingInput));
|
|
56
|
+
if (!valid)
|
|
57
|
+
return null;
|
|
58
|
+
const payload = JSON.parse(new TextDecoder().decode(base64UrlDecode(body)));
|
|
59
|
+
if (payload.exp < Math.floor(Date.now() / 1000))
|
|
60
|
+
return null;
|
|
61
|
+
return payload;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* 从请求中提取 JWT Token
|
|
69
|
+
*
|
|
70
|
+
* 优先级:Authorization: Bearer > Cookie: token=
|
|
71
|
+
*/
|
|
72
|
+
export function extractJwt(c) {
|
|
73
|
+
const auth = c.req.header("Authorization");
|
|
74
|
+
if (auth?.startsWith("Bearer ")) {
|
|
75
|
+
const token = auth.slice(7).trim();
|
|
76
|
+
if (token.split(".").length === 3)
|
|
77
|
+
return token;
|
|
78
|
+
}
|
|
79
|
+
const cookie = c.req.header("Cookie");
|
|
80
|
+
if (cookie) {
|
|
81
|
+
const match = cookie.match(/(?:^|;\s*)token=([^;]+)/);
|
|
82
|
+
if (match)
|
|
83
|
+
return decodeURIComponent(match[1]);
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=jwt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../../src/auth/jwt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 密码哈希模块(PBKDF2-HMAC-SHA256)
|
|
3
|
+
*
|
|
4
|
+
* 纯 Web Crypto API 实现,零外部依赖。
|
|
5
|
+
* - 100,000 次迭代(OWASP 推荐最低值)
|
|
6
|
+
* - 16 字节随机 salt
|
|
7
|
+
* - 32 字节(256 bit)哈希输出
|
|
8
|
+
*
|
|
9
|
+
* 来源:xtools src/lib/auth.ts
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* 哈希密码
|
|
13
|
+
*
|
|
14
|
+
* @param password - 明文密码
|
|
15
|
+
* @param saltHex - 盐值 hex(可选,不提供则自动生成)
|
|
16
|
+
* @returns { hash, salt } — 均为 hex 字符串
|
|
17
|
+
*/
|
|
18
|
+
export declare function hashPassword(password: string, saltHex?: string): Promise<{
|
|
19
|
+
hash: string;
|
|
20
|
+
salt: string;
|
|
21
|
+
}>;
|
|
22
|
+
/**
|
|
23
|
+
* 验证密码 — 恒定时间比较(防 timing attack)
|
|
24
|
+
*/
|
|
25
|
+
export declare function verifyPassword(password: string, hashHex: string, saltHex: string): Promise<boolean>;
|
|
26
|
+
//# sourceMappingURL=password.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password.d.ts","sourceRoot":"","sources":["../../../src/auth/password.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAkBH;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAoBzC;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,OAAO,CAAC,CAQlB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 密码哈希模块(PBKDF2-HMAC-SHA256)
|
|
3
|
+
*
|
|
4
|
+
* 纯 Web Crypto API 实现,零外部依赖。
|
|
5
|
+
* - 100,000 次迭代(OWASP 推荐最低值)
|
|
6
|
+
* - 16 字节随机 salt
|
|
7
|
+
* - 32 字节(256 bit)哈希输出
|
|
8
|
+
*
|
|
9
|
+
* 来源:xtools src/lib/auth.ts
|
|
10
|
+
*/
|
|
11
|
+
const ITERATIONS = 100_000;
|
|
12
|
+
const SALT_LENGTH = 16;
|
|
13
|
+
const HASH_LENGTH = 32;
|
|
14
|
+
function toHex(bytes) {
|
|
15
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
16
|
+
}
|
|
17
|
+
function fromHex(hex) {
|
|
18
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
19
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
20
|
+
bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);
|
|
21
|
+
}
|
|
22
|
+
return bytes;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 哈希密码
|
|
26
|
+
*
|
|
27
|
+
* @param password - 明文密码
|
|
28
|
+
* @param saltHex - 盐值 hex(可选,不提供则自动生成)
|
|
29
|
+
* @returns { hash, salt } — 均为 hex 字符串
|
|
30
|
+
*/
|
|
31
|
+
export async function hashPassword(password, saltHex) {
|
|
32
|
+
const salt = saltHex
|
|
33
|
+
? fromHex(saltHex)
|
|
34
|
+
: crypto.getRandomValues(new Uint8Array(SALT_LENGTH));
|
|
35
|
+
const keyMaterial = await crypto.subtle.importKey("raw", new TextEncoder().encode(password), "PBKDF2", false, ["deriveBits"]);
|
|
36
|
+
const hashBuffer = await crypto.subtle.deriveBits({ name: "PBKDF2", salt, iterations: ITERATIONS, hash: "SHA-256" }, keyMaterial, HASH_LENGTH * 8);
|
|
37
|
+
return { hash: toHex(new Uint8Array(hashBuffer)), salt: toHex(salt) };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 验证密码 — 恒定时间比较(防 timing attack)
|
|
41
|
+
*/
|
|
42
|
+
export async function verifyPassword(password, hashHex, saltHex) {
|
|
43
|
+
const result = await hashPassword(password, saltHex);
|
|
44
|
+
if (result.hash.length !== hashHex.length)
|
|
45
|
+
return false;
|
|
46
|
+
let diff = 0;
|
|
47
|
+
for (let i = 0; i < result.hash.length; i++) {
|
|
48
|
+
diff |= result.hash.charCodeAt(i) ^ hashHex.charCodeAt(i);
|
|
49
|
+
}
|
|
50
|
+
return diff === 0;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=password.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password.js","sourceRoot":"","sources":["../../../src/auth/password.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,UAAU,GAAG,OAAO,CAAC;AAC3B,MAAM,WAAW,GAAG,EAAE,CAAC;AACvB,MAAM,WAAW,GAAG,EAAE,CAAC;AAEvB,SAAS,KAAK,CAAC,KAAiB;IAC9B,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAChF,CAAC;AAED,SAAS,OAAO,CAAC,GAAW;IAC1B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAgB,EAChB,OAAgB;IAEhB,MAAM,IAAI,GAAG,OAAO;QAClB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;QAClB,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;IAExD,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAC/C,KAAK,EACL,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAClC,QAAQ,EACR,KAAK,EACL,CAAC,YAAY,CAAC,CACf,CAAC;IAEF,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,CAC/C,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,EACjE,WAAW,EACX,WAAW,GAAG,CAAC,CAChB,CAAC;IAEF,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AACxE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,QAAgB,EAChB,OAAe,EACf,OAAe;IAEf,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACrD,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACxD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,IAAI,KAAK,CAAC,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker 入口工厂
|
|
3
|
+
*
|
|
4
|
+
* 将三项目 index.ts 中高度重复的 Worker 启动逻辑抽象为统一工厂函数:
|
|
5
|
+
* - 数据库初始化中间件
|
|
6
|
+
* - 请求体大小限制
|
|
7
|
+
* - 安全响应头注入
|
|
8
|
+
* - API 路由 / 静态资源分流
|
|
9
|
+
* - 全局错误处理
|
|
10
|
+
*
|
|
11
|
+
* 来源:eshop/xtools/vcode 三项目 index.ts 入口合并
|
|
12
|
+
*/
|
|
13
|
+
import { Hono } from "hono";
|
|
14
|
+
import { type SecurityHeadersOptions } from "./security";
|
|
15
|
+
export interface BootstrapOptions<TSchema extends Record<string, unknown> = Record<string, never>> {
|
|
16
|
+
/** Drizzle schema(传入后支持关系查询) */
|
|
17
|
+
schema?: TSchema;
|
|
18
|
+
/** API 路由前缀,默认 "/api" */
|
|
19
|
+
apiPrefix?: string;
|
|
20
|
+
/** 请求体大小限制(字节),默认 100KB */
|
|
21
|
+
maxBodySize?: number;
|
|
22
|
+
/**
|
|
23
|
+
* 请求级超时(毫秒),默认 25000(25 秒)。
|
|
24
|
+
* Cloudflare Workers 硬限制 30 秒,留 5 秒余量给 CF 运行时。
|
|
25
|
+
* 超时后请求会被中止并返回 504 Gateway Timeout。
|
|
26
|
+
*/
|
|
27
|
+
requestTimeoutMs?: number;
|
|
28
|
+
/** 安全响应头配置 */
|
|
29
|
+
securityHeaders?: SecurityHeadersOptions;
|
|
30
|
+
/**
|
|
31
|
+
* 错误告警回调 — 生产环境错误通知。
|
|
32
|
+
* 当请求处理过程中发生未捕获错误时调用,可用于发送到外部告警系统
|
|
33
|
+
* (如 Slack webhook、邮件、PagerDuty 等)。
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* onErrorAlert: async (error, context) => {
|
|
38
|
+
* await fetch("https://hooks.slack.com/...", {
|
|
39
|
+
* method: "POST",
|
|
40
|
+
* body: JSON.stringify({ text: `[ERROR] ${error.message}` }),
|
|
41
|
+
* });
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
onErrorAlert?: (error: Error, context: {
|
|
46
|
+
path: string;
|
|
47
|
+
method: string;
|
|
48
|
+
ip?: string;
|
|
49
|
+
}) => void | Promise<void>;
|
|
50
|
+
/** 注册 API 路由的回调 */
|
|
51
|
+
registerRoutes: (api: Hono<any>) => void;
|
|
52
|
+
/**
|
|
53
|
+
* 静态资源路由表 — 页面路径到 HTML 文件的映射
|
|
54
|
+
* @example { "/admin": "/admin.html", "/shop": "/index.html" }
|
|
55
|
+
*/
|
|
56
|
+
pageRoutes?: Record<string, string>;
|
|
57
|
+
/**
|
|
58
|
+
* SPA 路由 — 这些路径都返回同一个 HTML 文件
|
|
59
|
+
* @example { fallback: "/_app/index.html", paths: ["/shop", "/order"] }
|
|
60
|
+
*/
|
|
61
|
+
spaRoutes?: {
|
|
62
|
+
fallback: string;
|
|
63
|
+
paths: string[];
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* 长缓存路径前缀(如 /_app/assets/)
|
|
67
|
+
* 匹配的路径会设置 Cache-Control: immutable, max-age=31536000
|
|
68
|
+
*/
|
|
69
|
+
immutablePrefixes?: string[];
|
|
70
|
+
}
|
|
71
|
+
export declare function bootstrap<TSchema extends Record<string, unknown>>(options: BootstrapOptions<TSchema>): {
|
|
72
|
+
fetch(request: Request, env: Record<string, unknown>, ctx: ExecutionContext): Promise<Response>;
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=bootstrap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../src/bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAAwB,KAAK,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAE/E,MAAM,WAAW,gBAAgB,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IAC/F,gCAAgC;IAChC,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,cAAc;IACd,eAAe,CAAC,EAAE,sBAAsB,CAAC;IAEzC;;;;;;;;;;;;;;OAcG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9G,mBAAmB;IAEnB,cAAc,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IAEzC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEpC;;;OAGG;IACH,SAAS,CAAC,EAAE;QACV,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,EAAE,CAAC;KACjB,CAAC;IAEF;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAoDD,wBAAgB,SAAS,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/D,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC;mBAyHX,OAAO,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,gBAAgB;EAoEpF"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker 入口工厂
|
|
3
|
+
*
|
|
4
|
+
* 将三项目 index.ts 中高度重复的 Worker 启动逻辑抽象为统一工厂函数:
|
|
5
|
+
* - 数据库初始化中间件
|
|
6
|
+
* - 请求体大小限制
|
|
7
|
+
* - 安全响应头注入
|
|
8
|
+
* - API 路由 / 静态资源分流
|
|
9
|
+
* - 全局错误处理
|
|
10
|
+
*
|
|
11
|
+
* 来源:eshop/xtools/vcode 三项目 index.ts 入口合并
|
|
12
|
+
*/
|
|
13
|
+
import { Hono } from "hono";
|
|
14
|
+
import { initDatabaseWithHealthCheck } from "./db/connection";
|
|
15
|
+
import { fail } from "./http";
|
|
16
|
+
import { buildSecurityHeaders } from "./security";
|
|
17
|
+
/**
|
|
18
|
+
* 创建 Cloudflare Workers 应用
|
|
19
|
+
*
|
|
20
|
+
* 返回标准的 Workers fetch handler 导出对象。
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* import * as schema from "./db/schema";
|
|
25
|
+
* import { bootstrap } from "@usethink/cf-core/bootstrap";
|
|
26
|
+
*
|
|
27
|
+
* export default bootstrap({
|
|
28
|
+
* schema,
|
|
29
|
+
* registerRoutes: (api) => {
|
|
30
|
+
* api.route("/products", productRoutes);
|
|
31
|
+
* api.route("/orders", orderRoutes);
|
|
32
|
+
* },
|
|
33
|
+
* pageRoutes: { "/admin": "/admin.html" },
|
|
34
|
+
* spaRoutes: { fallback: "/_app/index.html", paths: ["/shop", "/order"] },
|
|
35
|
+
* immutablePrefixes: ["/_app/assets/"],
|
|
36
|
+
* });
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
/** 生成友好的 HTML 错误页面(内联 CSS,无外部依赖) */
|
|
40
|
+
function errorPageHtml(status, message) {
|
|
41
|
+
return `<!DOCTYPE html>
|
|
42
|
+
<html lang="zh-CN">
|
|
43
|
+
<head>
|
|
44
|
+
<meta charset="UTF-8">
|
|
45
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
46
|
+
<title>${status} - ${message}</title>
|
|
47
|
+
<style>
|
|
48
|
+
*{margin:0;padding:0;box-sizing:border-box}
|
|
49
|
+
body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;background:#0f0f0f;color:#e0e0e0;display:flex;align-items:center;justify-content:center;min-height:100vh;padding:20px}
|
|
50
|
+
.container{text-align:center;max-width:480px}
|
|
51
|
+
.code{font-size:6rem;font-weight:800;background:linear-gradient(135deg,#6c63ff,#a78bfa);-webkit-background-clip:text;-webkit-text-fill-color:transparent;line-height:1}
|
|
52
|
+
.msg{font-size:1.25rem;color:#888;margin:1rem 0 2rem}
|
|
53
|
+
a{color:#6c63ff;text-decoration:none;font-weight:500}
|
|
54
|
+
a:hover{text-decoration:underline}
|
|
55
|
+
</style>
|
|
56
|
+
</head>
|
|
57
|
+
<body>
|
|
58
|
+
<div class="container">
|
|
59
|
+
<p class="code">${status}</p>
|
|
60
|
+
<p class="msg">${message}</p>
|
|
61
|
+
<a href="/">← 返回首页</a>
|
|
62
|
+
</div>
|
|
63
|
+
</body>
|
|
64
|
+
</html>`;
|
|
65
|
+
}
|
|
66
|
+
export function bootstrap(options) {
|
|
67
|
+
const { schema, apiPrefix = "/api", maxBodySize = 1024 * 100, requestTimeoutMs = 25_000, securityHeaders: secOpts = {}, onErrorAlert, registerRoutes, pageRoutes = {}, spaRoutes, immutablePrefixes = [], } = options;
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
69
|
+
const api = new Hono();
|
|
70
|
+
// ── 请求级超时中间件(防止慢请求耗尽 Workers CPU) ──
|
|
71
|
+
api.use("*", async (c, next) => {
|
|
72
|
+
// /health 不受超时限制(用于监控探活)
|
|
73
|
+
if (c.req.path === "/health") {
|
|
74
|
+
await next();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const controller = new AbortController();
|
|
78
|
+
const timeoutId = setTimeout(() => controller.abort(), requestTimeoutMs);
|
|
79
|
+
try {
|
|
80
|
+
// 将 signal 传递给下游(路由可选择性使用)
|
|
81
|
+
c.set("abortSignal", controller.signal);
|
|
82
|
+
await next();
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
86
|
+
console.error(`[bootstrap:timeout] 请求超时 ${requestTimeoutMs}ms: ${c.req.method} ${c.req.path}`);
|
|
87
|
+
return fail(c, "请求处理超时", 504);
|
|
88
|
+
}
|
|
89
|
+
throw err;
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
clearTimeout(timeoutId);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
// ── DB 初始化中间件(带连接验证 + 重试) ──
|
|
96
|
+
api.use("*", async (c, next) => {
|
|
97
|
+
const isHealth = c.req.path === "/health";
|
|
98
|
+
try {
|
|
99
|
+
const db = await initDatabaseWithHealthCheck(c.env.TURSO_URL, c.env.TURSO_TOKEN, schema);
|
|
100
|
+
c.set("db", db);
|
|
101
|
+
if ("executionCtx" in c) {
|
|
102
|
+
c.set("executionCtx", c.env.executionCtx);
|
|
103
|
+
}
|
|
104
|
+
await next();
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
console.error("[bootstrap:db-init]", err);
|
|
108
|
+
if (isHealth) {
|
|
109
|
+
c.set("db", undefined);
|
|
110
|
+
await next();
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
return fail(c, "服务暂时不可用", 503);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
// ── 请求体大小限制 ──
|
|
117
|
+
api.use("*", async (c, next) => {
|
|
118
|
+
const len = parseInt(c.req.header("content-length") || "0");
|
|
119
|
+
if (len > maxBodySize)
|
|
120
|
+
return fail(c, `请求体过大(最大 ${Math.floor(maxBodySize / 1024)}KB)`, 413);
|
|
121
|
+
await next();
|
|
122
|
+
});
|
|
123
|
+
// ── 注册业务路由 ──
|
|
124
|
+
registerRoutes(api);
|
|
125
|
+
// ── 404 + 全局错误(浏览器返回 HTML,API 返回 JSON) ──
|
|
126
|
+
api.notFound((c) => {
|
|
127
|
+
const accept = c.req.header("accept") || "";
|
|
128
|
+
if (accept.includes("text/html")) {
|
|
129
|
+
return c.html(errorPageHtml(404, "页面未找到"), 404);
|
|
130
|
+
}
|
|
131
|
+
return fail(c, "API not found", 404);
|
|
132
|
+
});
|
|
133
|
+
api.onError((error, c) => {
|
|
134
|
+
console.error("[bootstrap:onError]", error?.constructor?.name, error?.message, error?.stack);
|
|
135
|
+
// 触发告警回调(如果配置了)
|
|
136
|
+
if (onErrorAlert) {
|
|
137
|
+
const ip = c.req.header("cf-connecting-ip") || c.req.header("x-forwarded-for") || "unknown";
|
|
138
|
+
// 异步发送告警,不阻塞响应
|
|
139
|
+
Promise.resolve(onErrorAlert(error, {
|
|
140
|
+
path: c.req.path,
|
|
141
|
+
method: c.req.method,
|
|
142
|
+
ip,
|
|
143
|
+
})).catch((alertErr) => {
|
|
144
|
+
console.error("[bootstrap:onErrorAlert] 告警发送失败:", alertErr);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
const accept = c.req.header("accept") || "";
|
|
148
|
+
if (accept.includes("text/html")) {
|
|
149
|
+
return c.html(errorPageHtml(500, "服务暂时不可用"), 500);
|
|
150
|
+
}
|
|
151
|
+
return fail(c, "服务暂时不可用", 500, { error: error?.message });
|
|
152
|
+
});
|
|
153
|
+
// ── 预计算安全响应头 ──
|
|
154
|
+
const defaultHeaders = buildSecurityHeaders(secOpts);
|
|
155
|
+
const adminHeaders = buildSecurityHeaders({ ...secOpts, allowUnsafeEval: true });
|
|
156
|
+
function applyHeaders(response, isImmutable = false, isAdmin = false) {
|
|
157
|
+
const headers = new Headers(response.headers);
|
|
158
|
+
const base = isAdmin ? adminHeaders : defaultHeaders;
|
|
159
|
+
for (const [k, v] of base)
|
|
160
|
+
headers.set(k, v);
|
|
161
|
+
if (isImmutable) {
|
|
162
|
+
headers.set("Cache-Control", "public, max-age=31536000, immutable");
|
|
163
|
+
}
|
|
164
|
+
return new Response(response.body, { status: response.status, statusText: response.statusText, headers });
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
async fetch(request, env, ctx) {
|
|
168
|
+
try {
|
|
169
|
+
const url = new URL(request.url);
|
|
170
|
+
const path = url.pathname;
|
|
171
|
+
// API 路由 → Hono
|
|
172
|
+
const prefix = apiPrefix.replace(/\/$/, "");
|
|
173
|
+
if (path === prefix || path.startsWith(`${prefix}/`)) {
|
|
174
|
+
url.pathname = path.replace(new RegExp(`^${prefix}`), "") || "/";
|
|
175
|
+
return api.fetch(new Request(url, request), env, ctx);
|
|
176
|
+
}
|
|
177
|
+
// 静态资源处理需要 ASSETS binding
|
|
178
|
+
const assets = env.ASSETS;
|
|
179
|
+
if (!assets) {
|
|
180
|
+
return new Response(JSON.stringify({ ok: false, error: "ASSETS binding not configured" }), {
|
|
181
|
+
status: 500,
|
|
182
|
+
headers: { "content-type": "application/json" },
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
// 长缓存静态资源
|
|
186
|
+
if (immutablePrefixes.some((p) => path.startsWith(p))) {
|
|
187
|
+
return applyHeaders(await assets.fetch(request), true);
|
|
188
|
+
}
|
|
189
|
+
// 页面路由(pageRoutes 精确匹配)
|
|
190
|
+
for (const [route, file] of Object.entries(pageRoutes)) {
|
|
191
|
+
if (path === route || path.startsWith(`${route}/`)) {
|
|
192
|
+
url.pathname = file;
|
|
193
|
+
const isAdmin = route === "/admin" || route.startsWith("/admin");
|
|
194
|
+
return applyHeaders(await assets.fetch(new Request(url, request)), false, isAdmin);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// SPA 路由
|
|
198
|
+
if (spaRoutes && spaRoutes.paths.some((p) => path === p || path.startsWith(`${p}/`))) {
|
|
199
|
+
url.pathname = spaRoutes.fallback;
|
|
200
|
+
const res = await assets.fetch(new Request(url, request));
|
|
201
|
+
if (res.ok)
|
|
202
|
+
return applyHeaders(res);
|
|
203
|
+
url.pathname = "/index.html";
|
|
204
|
+
return applyHeaders(await assets.fetch(new Request(url, request)));
|
|
205
|
+
}
|
|
206
|
+
// 根路径
|
|
207
|
+
if (path === "/") {
|
|
208
|
+
url.pathname = "/index.html";
|
|
209
|
+
return applyHeaders(await assets.fetch(new Request(url, request)));
|
|
210
|
+
}
|
|
211
|
+
// 其他静态资源
|
|
212
|
+
return applyHeaders(await assets.fetch(request));
|
|
213
|
+
}
|
|
214
|
+
catch (err) {
|
|
215
|
+
console.error("[bootstrap:fetch]", err);
|
|
216
|
+
const accept = request.headers.get("accept") || "";
|
|
217
|
+
if (accept.includes("text/html")) {
|
|
218
|
+
return new Response(errorPageHtml(500, "服务暂时不可用"), {
|
|
219
|
+
status: 500,
|
|
220
|
+
headers: { "content-type": "text/html; charset=utf-8" },
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
return new Response(JSON.stringify({ ok: false, error: "服务暂时不可用" }), {
|
|
224
|
+
status: 500,
|
|
225
|
+
headers: { "content-type": "application/json" },
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/bootstrap.ts"],"names":[],"mappings":"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"}
|