befly 3.16.10 → 3.17.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 +0 -129
- package/befly.js +16413 -0
- package/befly.min.js +72 -0
- package/package.json +19 -29
- package/scripts/syncDb/context.js +99 -0
- package/scripts/syncDb/diff.js +133 -0
- package/scripts/syncDb/index.js +70 -0
- package/scripts/syncDb/query.js +26 -0
- package/scripts/syncDb/report.js +190 -0
- package/scripts/syncDb/transform.js +111 -0
- package/dist/befly.config.d.ts +0 -7
- package/dist/befly.config.js +0 -128
- package/dist/befly.js +0 -17348
- package/dist/befly.min.js +0 -23
- package/dist/checks/checkApi.d.ts +0 -1
- package/dist/checks/checkApi.js +0 -139
- package/dist/checks/checkConfig.d.ts +0 -9
- package/dist/checks/checkConfig.js +0 -255
- package/dist/checks/checkHook.d.ts +0 -1
- package/dist/checks/checkHook.js +0 -132
- package/dist/checks/checkMenu.d.ts +0 -3
- package/dist/checks/checkMenu.js +0 -106
- package/dist/checks/checkPlugin.d.ts +0 -1
- package/dist/checks/checkPlugin.js +0 -132
- package/dist/checks/checkTable.d.ts +0 -7
- package/dist/checks/checkTable.js +0 -431
- package/dist/configs/presetRegexp.d.ts +0 -145
- package/dist/configs/presetRegexp.js +0 -218
- package/dist/hooks/auth.d.ts +0 -3
- package/dist/hooks/auth.js +0 -24
- package/dist/hooks/cors.d.ts +0 -7
- package/dist/hooks/cors.js +0 -36
- package/dist/hooks/parser.d.ts +0 -10
- package/dist/hooks/parser.js +0 -76
- package/dist/hooks/permission.d.ts +0 -11
- package/dist/hooks/permission.js +0 -78
- package/dist/hooks/validator.d.ts +0 -7
- package/dist/hooks/validator.js +0 -52
- package/dist/index.d.ts +0 -28
- package/dist/index.js +0 -316
- package/dist/lib/asyncContext.d.ts +0 -21
- package/dist/lib/asyncContext.js +0 -27
- package/dist/lib/cacheHelper.d.ts +0 -128
- package/dist/lib/cacheHelper.js +0 -477
- package/dist/lib/cacheKeys.d.ts +0 -27
- package/dist/lib/cacheKeys.js +0 -37
- package/dist/lib/cipher.d.ts +0 -153
- package/dist/lib/cipher.js +0 -237
- package/dist/lib/connect.d.ts +0 -95
- package/dist/lib/connect.js +0 -313
- package/dist/lib/dbHelper.d.ts +0 -229
- package/dist/lib/dbHelper.js +0 -1099
- package/dist/lib/dbUtils.d.ts +0 -91
- package/dist/lib/dbUtils.js +0 -544
- package/dist/lib/jwt.d.ts +0 -13
- package/dist/lib/jwt.js +0 -77
- package/dist/lib/logger.d.ts +0 -46
- package/dist/lib/logger.js +0 -731
- package/dist/lib/redisHelper.d.ts +0 -193
- package/dist/lib/redisHelper.js +0 -598
- package/dist/lib/sqlBuilder.d.ts +0 -160
- package/dist/lib/sqlBuilder.js +0 -837
- package/dist/lib/sqlCheck.d.ts +0 -23
- package/dist/lib/sqlCheck.js +0 -119
- package/dist/lib/validator.d.ts +0 -45
- package/dist/lib/validator.js +0 -424
- package/dist/loader/loadApis.d.ts +0 -12
- package/dist/loader/loadApis.js +0 -71
- package/dist/loader/loadHooks.d.ts +0 -7
- package/dist/loader/loadHooks.js +0 -50
- package/dist/loader/loadPlugins.d.ts +0 -8
- package/dist/loader/loadPlugins.js +0 -69
- package/dist/paths.d.ts +0 -93
- package/dist/paths.js +0 -100
- package/dist/plugins/cache.d.ts +0 -10
- package/dist/plugins/cache.js +0 -24
- package/dist/plugins/cipher.d.ts +0 -7
- package/dist/plugins/cipher.js +0 -14
- package/dist/plugins/config.d.ts +0 -3
- package/dist/plugins/config.js +0 -9
- package/dist/plugins/db.d.ts +0 -10
- package/dist/plugins/db.js +0 -48
- package/dist/plugins/jwt.d.ts +0 -6
- package/dist/plugins/jwt.js +0 -13
- package/dist/plugins/logger.d.ts +0 -10
- package/dist/plugins/logger.js +0 -21
- package/dist/plugins/redis.d.ts +0 -10
- package/dist/plugins/redis.js +0 -40
- package/dist/plugins/tool.d.ts +0 -75
- package/dist/plugins/tool.js +0 -105
- package/dist/router/api.d.ts +0 -14
- package/dist/router/api.js +0 -109
- package/dist/router/static.d.ts +0 -9
- package/dist/router/static.js +0 -56
- package/dist/scripts/ensureDist.d.ts +0 -1
- package/dist/scripts/ensureDist.js +0 -296
- package/dist/sync/syncApi.d.ts +0 -3
- package/dist/sync/syncApi.js +0 -163
- package/dist/sync/syncCache.d.ts +0 -2
- package/dist/sync/syncCache.js +0 -14
- package/dist/sync/syncDev.d.ts +0 -6
- package/dist/sync/syncDev.js +0 -166
- package/dist/sync/syncMenu.d.ts +0 -14
- package/dist/sync/syncMenu.js +0 -308
- package/dist/sync/syncTable.d.ts +0 -126
- package/dist/sync/syncTable.js +0 -1129
- package/dist/types/api.d.ts +0 -177
- package/dist/types/api.js +0 -4
- package/dist/types/befly.d.ts +0 -231
- package/dist/types/befly.js +0 -4
- package/dist/types/cache.d.ts +0 -96
- package/dist/types/cache.js +0 -4
- package/dist/types/cipher.d.ts +0 -27
- package/dist/types/cipher.js +0 -7
- package/dist/types/common.d.ts +0 -127
- package/dist/types/common.js +0 -5
- package/dist/types/context.d.ts +0 -39
- package/dist/types/context.js +0 -4
- package/dist/types/coreError.d.ts +0 -31
- package/dist/types/coreError.js +0 -38
- package/dist/types/crypto.d.ts +0 -20
- package/dist/types/crypto.js +0 -4
- package/dist/types/database.d.ts +0 -182
- package/dist/types/database.js +0 -4
- package/dist/types/hook.d.ts +0 -30
- package/dist/types/hook.js +0 -19
- package/dist/types/jwt.d.ts +0 -76
- package/dist/types/jwt.js +0 -4
- package/dist/types/logger.d.ts +0 -95
- package/dist/types/logger.js +0 -6
- package/dist/types/plugin.d.ts +0 -27
- package/dist/types/plugin.js +0 -17
- package/dist/types/redis.d.ts +0 -80
- package/dist/types/redis.js +0 -4
- package/dist/types/roleApisCache.d.ts +0 -21
- package/dist/types/roleApisCache.js +0 -8
- package/dist/types/sync.d.ts +0 -93
- package/dist/types/sync.js +0 -4
- package/dist/types/table.d.ts +0 -34
- package/dist/types/table.js +0 -4
- package/dist/types/validate.d.ts +0 -113
- package/dist/types/validate.js +0 -4
- package/dist/utils/calcPerfTime.d.ts +0 -4
- package/dist/utils/calcPerfTime.js +0 -13
- package/dist/utils/cors.d.ts +0 -8
- package/dist/utils/cors.js +0 -17
- package/dist/utils/dbFieldRules.d.ts +0 -31
- package/dist/utils/dbFieldRules.js +0 -94
- package/dist/utils/fieldClear.d.ts +0 -11
- package/dist/utils/fieldClear.js +0 -57
- package/dist/utils/formatYmdHms.d.ts +0 -1
- package/dist/utils/formatYmdHms.js +0 -20
- package/dist/utils/getClientIp.d.ts +0 -6
- package/dist/utils/getClientIp.js +0 -39
- package/dist/utils/importDefault.d.ts +0 -1
- package/dist/utils/importDefault.js +0 -53
- package/dist/utils/isDirentDirectory.d.ts +0 -3
- package/dist/utils/isDirentDirectory.js +0 -18
- package/dist/utils/loadMenuConfigs.d.ts +0 -11
- package/dist/utils/loadMenuConfigs.js +0 -130
- package/dist/utils/loggerUtils.d.ts +0 -18
- package/dist/utils/loggerUtils.js +0 -171
- package/dist/utils/mergeAndConcat.d.ts +0 -7
- package/dist/utils/mergeAndConcat.js +0 -77
- package/dist/utils/normalizeFieldDefinition.d.ts +0 -18
- package/dist/utils/normalizeFieldDefinition.js +0 -27
- package/dist/utils/processInfo.d.ts +0 -26
- package/dist/utils/processInfo.js +0 -41
- package/dist/utils/response.d.ts +0 -20
- package/dist/utils/response.js +0 -96
- package/dist/utils/scanAddons.d.ts +0 -15
- package/dist/utils/scanAddons.js +0 -35
- package/dist/utils/scanCoreBuiltins.d.ts +0 -3
- package/dist/utils/scanCoreBuiltins.js +0 -72
- package/dist/utils/scanFiles.d.ts +0 -32
- package/dist/utils/scanFiles.js +0 -124
- package/dist/utils/scanSources.d.ts +0 -10
- package/dist/utils/scanSources.js +0 -46
- package/dist/utils/sortModules.d.ts +0 -28
- package/dist/utils/sortModules.js +0 -105
- package/dist/utils/sqlUtil.d.ts +0 -33
- package/dist/utils/sqlUtil.js +0 -146
- package/dist/utils/util.d.ts +0 -172
- package/dist/utils/util.js +0 -517
package/dist/plugins/tool.d.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 工具插件
|
|
3
|
-
* 提供常用的工具函数
|
|
4
|
-
*/
|
|
5
|
-
import type { JsonValue } from "../types/common";
|
|
6
|
-
import type { RequestContext } from "../types/context";
|
|
7
|
-
import type { Plugin } from "../types/plugin";
|
|
8
|
-
type ToolExtra = Record<string, JsonValue | undefined>;
|
|
9
|
-
/**
|
|
10
|
-
* 成功响应
|
|
11
|
-
* @param msg - 消息
|
|
12
|
-
* @param data - 数据(可选)
|
|
13
|
-
* @param other - 其他字段(可选)
|
|
14
|
-
* @returns 成功响应对象
|
|
15
|
-
*/
|
|
16
|
-
export declare function Yes<TData extends JsonValue = JsonValue, TOther extends ToolExtra = ToolExtra>(msg: string, data?: TData, other?: TOther): {
|
|
17
|
-
code: 0;
|
|
18
|
-
msg: string;
|
|
19
|
-
data: TData;
|
|
20
|
-
} & TOther;
|
|
21
|
-
/**
|
|
22
|
-
* 失败响应
|
|
23
|
-
* @param msg - 消息
|
|
24
|
-
* @param data - 数据(可选)
|
|
25
|
-
* @param other - 其他字段(可选)
|
|
26
|
-
* @returns 失败响应对象
|
|
27
|
-
*/
|
|
28
|
-
export declare function No<TData extends JsonValue = JsonValue, TOther extends ToolExtra = ToolExtra>(msg: string, data?: TData, other?: TOther): {
|
|
29
|
-
code: 1;
|
|
30
|
-
msg: string;
|
|
31
|
-
data: TData;
|
|
32
|
-
} & TOther;
|
|
33
|
-
/**
|
|
34
|
-
* 响应选项
|
|
35
|
-
*/
|
|
36
|
-
interface ResponseOptions {
|
|
37
|
-
/** HTTP 状态码,默认 200 */
|
|
38
|
-
status?: number;
|
|
39
|
-
/** Content-Type,默认根据 data 类型自动判断 */
|
|
40
|
-
contentType?: string;
|
|
41
|
-
/** 额外的响应头 */
|
|
42
|
-
headers?: Record<string, string>;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* 统一响应函数
|
|
46
|
-
*
|
|
47
|
-
* 自动识别数据类型并设置正确的 Content-Type:
|
|
48
|
-
* - 对象 → application/json
|
|
49
|
-
* - 字符串 → text/plain
|
|
50
|
-
* - 可通过 options.contentType 手动指定
|
|
51
|
-
*
|
|
52
|
-
* @param ctx 请求上下文
|
|
53
|
-
* @param data 响应数据(对象或字符串)
|
|
54
|
-
* @param options 响应选项
|
|
55
|
-
* @returns Response 对象
|
|
56
|
-
*
|
|
57
|
-
* @example
|
|
58
|
-
* // JSON 响应(自动)
|
|
59
|
-
* return Raw(ctx, { code: 'SUCCESS', message: '成功' });
|
|
60
|
-
*
|
|
61
|
-
* // 纯文本响应(自动)
|
|
62
|
-
* return Raw(ctx, 'success');
|
|
63
|
-
*
|
|
64
|
-
* // XML 响应(手动指定)
|
|
65
|
-
* return Raw(ctx, xmlString, { contentType: 'application/xml' });
|
|
66
|
-
*
|
|
67
|
-
* // 自定义状态码和额外头
|
|
68
|
-
* return Raw(ctx, { error: 'Not Found' }, {
|
|
69
|
-
* status: 404,
|
|
70
|
-
* headers: { 'X-Custom': 'value' }
|
|
71
|
-
* });
|
|
72
|
-
*/
|
|
73
|
-
export declare function Raw(ctx: RequestContext, data: JsonValue | string, options?: ResponseOptions): Response;
|
|
74
|
-
declare const toolPlugin: Plugin;
|
|
75
|
-
export default toolPlugin;
|
package/dist/plugins/tool.js
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 工具插件
|
|
3
|
-
* 提供常用的工具函数
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* 成功响应
|
|
7
|
-
* @param msg - 消息
|
|
8
|
-
* @param data - 数据(可选)
|
|
9
|
-
* @param other - 其他字段(可选)
|
|
10
|
-
* @returns 成功响应对象
|
|
11
|
-
*/
|
|
12
|
-
export function Yes(msg, data = {}, other = {}) {
|
|
13
|
-
return {
|
|
14
|
-
code: 0,
|
|
15
|
-
msg: msg,
|
|
16
|
-
data: data,
|
|
17
|
-
...other
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* 失败响应
|
|
22
|
-
* @param msg - 消息
|
|
23
|
-
* @param data - 数据(可选)
|
|
24
|
-
* @param other - 其他字段(可选)
|
|
25
|
-
* @returns 失败响应对象
|
|
26
|
-
*/
|
|
27
|
-
export function No(msg, data = null, other = {}) {
|
|
28
|
-
return {
|
|
29
|
-
code: 1,
|
|
30
|
-
msg: msg,
|
|
31
|
-
data: data,
|
|
32
|
-
...other
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* 统一响应函数
|
|
37
|
-
*
|
|
38
|
-
* 自动识别数据类型并设置正确的 Content-Type:
|
|
39
|
-
* - 对象 → application/json
|
|
40
|
-
* - 字符串 → text/plain
|
|
41
|
-
* - 可通过 options.contentType 手动指定
|
|
42
|
-
*
|
|
43
|
-
* @param ctx 请求上下文
|
|
44
|
-
* @param data 响应数据(对象或字符串)
|
|
45
|
-
* @param options 响应选项
|
|
46
|
-
* @returns Response 对象
|
|
47
|
-
*
|
|
48
|
-
* @example
|
|
49
|
-
* // JSON 响应(自动)
|
|
50
|
-
* return Raw(ctx, { code: 'SUCCESS', message: '成功' });
|
|
51
|
-
*
|
|
52
|
-
* // 纯文本响应(自动)
|
|
53
|
-
* return Raw(ctx, 'success');
|
|
54
|
-
*
|
|
55
|
-
* // XML 响应(手动指定)
|
|
56
|
-
* return Raw(ctx, xmlString, { contentType: 'application/xml' });
|
|
57
|
-
*
|
|
58
|
-
* // 自定义状态码和额外头
|
|
59
|
-
* return Raw(ctx, { error: 'Not Found' }, {
|
|
60
|
-
* status: 404,
|
|
61
|
-
* headers: { 'X-Custom': 'value' }
|
|
62
|
-
* });
|
|
63
|
-
*/
|
|
64
|
-
export function Raw(ctx, data, options = {}) {
|
|
65
|
-
const { status = 200, contentType, headers = {} } = options;
|
|
66
|
-
// 自动判断 Content-Type
|
|
67
|
-
let finalContentType = contentType;
|
|
68
|
-
let body;
|
|
69
|
-
if (typeof data === "string") {
|
|
70
|
-
// 字符串类型
|
|
71
|
-
body = data;
|
|
72
|
-
if (!finalContentType) {
|
|
73
|
-
// 自动判断:XML 或纯文本
|
|
74
|
-
finalContentType = data.trim().startsWith("<") ? "application/xml" : "text/plain";
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
// JSON 序列化(对象/数组/原始值均可)
|
|
79
|
-
body = JSON.stringify(data);
|
|
80
|
-
finalContentType = finalContentType || "application/json";
|
|
81
|
-
}
|
|
82
|
-
// 合并响应头
|
|
83
|
-
const responseHeaders = {
|
|
84
|
-
...ctx.corsHeaders,
|
|
85
|
-
"Content-Type": finalContentType,
|
|
86
|
-
...headers
|
|
87
|
-
};
|
|
88
|
-
return new Response(body, {
|
|
89
|
-
status: status,
|
|
90
|
-
headers: responseHeaders
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
const toolPlugin = {
|
|
94
|
-
name: "tool",
|
|
95
|
-
enable: true,
|
|
96
|
-
deps: [],
|
|
97
|
-
handler: () => {
|
|
98
|
-
return {
|
|
99
|
-
Yes: Yes,
|
|
100
|
-
No: No,
|
|
101
|
-
Raw: Raw
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
export default toolPlugin;
|
package/dist/router/api.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* API路由处理器
|
|
3
|
-
* 处理 /api/* 路径的请求
|
|
4
|
-
*/
|
|
5
|
-
import type { ApiRoute } from "../types/api";
|
|
6
|
-
import type { BeflyContext } from "../types/befly";
|
|
7
|
-
import type { Hook } from "../types/hook";
|
|
8
|
-
/**
|
|
9
|
-
* API处理器工厂函数
|
|
10
|
-
* @param apis - API路由映射表
|
|
11
|
-
* @param hooks - 钩子列表
|
|
12
|
-
* @param context - 应用上下文
|
|
13
|
-
*/
|
|
14
|
-
export declare function apiHandler(apis: Map<string, ApiRoute>, hooks: Hook[], context: BeflyContext): (req: Request, server?: any) => Promise<Response>;
|
package/dist/router/api.js
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* API路由处理器
|
|
3
|
-
* 处理 /api/* 路径的请求
|
|
4
|
-
*/
|
|
5
|
-
import { withCtx } from "../lib/asyncContext";
|
|
6
|
-
import { Logger } from "../lib/logger";
|
|
7
|
-
// 相对导入
|
|
8
|
-
import { getClientIp } from "../utils/getClientIp";
|
|
9
|
-
import { FinalResponse } from "../utils/response";
|
|
10
|
-
import { genShortId } from "../utils/util";
|
|
11
|
-
/**
|
|
12
|
-
* API处理器工厂函数
|
|
13
|
-
* @param apis - API路由映射表
|
|
14
|
-
* @param hooks - 钩子列表
|
|
15
|
-
* @param context - 应用上下文
|
|
16
|
-
*/
|
|
17
|
-
export function apiHandler(apis, hooks, context) {
|
|
18
|
-
return async (req, server) => {
|
|
19
|
-
// 1. 生成请求 ID
|
|
20
|
-
const requestId = genShortId();
|
|
21
|
-
// 2. 创建请求上下文
|
|
22
|
-
const url = new URL(req.url);
|
|
23
|
-
// 只用接口路径做存在性判断与匹配:不要把 method 拼进 key
|
|
24
|
-
// 说明:apisMap 的 key 来源于 scanFiles/loadApis 生成的 path(例如 /api/core/xxx)
|
|
25
|
-
const apiPath = url.pathname || "/";
|
|
26
|
-
const clientIp = getClientIp(req, server);
|
|
27
|
-
const now = Date.now();
|
|
28
|
-
const ctx = {
|
|
29
|
-
method: req.method,
|
|
30
|
-
body: {},
|
|
31
|
-
user: {},
|
|
32
|
-
req: req,
|
|
33
|
-
now: now,
|
|
34
|
-
ip: clientIp,
|
|
35
|
-
headers: req.headers,
|
|
36
|
-
route: apiPath,
|
|
37
|
-
requestId: requestId,
|
|
38
|
-
corsHeaders: {
|
|
39
|
-
"X-Request-ID": requestId
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
const api = apis.get(apiPath);
|
|
43
|
-
if (api) {
|
|
44
|
-
ctx.api = api;
|
|
45
|
-
}
|
|
46
|
-
return withCtx({
|
|
47
|
-
requestId: requestId,
|
|
48
|
-
method: req.method,
|
|
49
|
-
route: apiPath,
|
|
50
|
-
ip: clientIp,
|
|
51
|
-
now: now
|
|
52
|
-
}, async () => {
|
|
53
|
-
try {
|
|
54
|
-
// 4. 串联执行所有钩子
|
|
55
|
-
for (const hook of hooks) {
|
|
56
|
-
await hook.handler(context, ctx);
|
|
57
|
-
// 如果钩子已经设置了 response,停止执行
|
|
58
|
-
if (ctx.response) {
|
|
59
|
-
return ctx.response;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
// hooks 全部通过后记录请求日志(拦截请求仅由 ErrorResponse 记录)
|
|
63
|
-
if (ctx.api && req.method !== "OPTIONS") {
|
|
64
|
-
const logData = {
|
|
65
|
-
event: "request",
|
|
66
|
-
apiName: ctx.api.name
|
|
67
|
-
};
|
|
68
|
-
if (ctx.body && Object.keys(ctx.body).length > 0) {
|
|
69
|
-
logData["body"] = ctx.body;
|
|
70
|
-
}
|
|
71
|
-
logData["msg"] = "request";
|
|
72
|
-
Logger.info(logData);
|
|
73
|
-
}
|
|
74
|
-
// 5. 执行 API handler
|
|
75
|
-
if (!ctx.api) {
|
|
76
|
-
if (req.method !== "OPTIONS") {
|
|
77
|
-
ctx.response = Response.json({
|
|
78
|
-
code: 1,
|
|
79
|
-
msg: "接口不存在"
|
|
80
|
-
}, {
|
|
81
|
-
headers: ctx.corsHeaders
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
else if (ctx.api.handler) {
|
|
86
|
-
const result = await ctx.api.handler(context, ctx);
|
|
87
|
-
if (result instanceof Response) {
|
|
88
|
-
ctx.response = result;
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
ctx.result = result;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
// 7. 返回响应(自动处理 response/result/日志)
|
|
95
|
-
return FinalResponse(ctx);
|
|
96
|
-
}
|
|
97
|
-
catch (err) {
|
|
98
|
-
// 全局错误处理
|
|
99
|
-
const errorPath = ctx.api ? apiPath : req.url;
|
|
100
|
-
Logger.error({ err: err, path: errorPath, msg: "请求错误" });
|
|
101
|
-
ctx.result = {
|
|
102
|
-
code: 1,
|
|
103
|
-
msg: "内部服务错误"
|
|
104
|
-
};
|
|
105
|
-
return FinalResponse(ctx);
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
};
|
|
109
|
-
}
|
package/dist/router/static.d.ts
DELETED
package/dist/router/static.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 静态文件路由处理器
|
|
3
|
-
* 处理 /* 路径的静态文件请求
|
|
4
|
-
*/
|
|
5
|
-
// 外部依赖
|
|
6
|
-
import { join } from "pathe";
|
|
7
|
-
import { Logger } from "../lib/logger";
|
|
8
|
-
// 相对导入
|
|
9
|
-
import { appDir } from "../paths";
|
|
10
|
-
import { setCorsOptions } from "../utils/cors";
|
|
11
|
-
/**
|
|
12
|
-
* 静态文件处理器工厂
|
|
13
|
-
*/
|
|
14
|
-
export function staticHandler(corsConfig = undefined) {
|
|
15
|
-
return async (req) => {
|
|
16
|
-
// 设置 CORS 响应头
|
|
17
|
-
const corsHeaders = setCorsOptions(req, corsConfig);
|
|
18
|
-
const url = new URL(req.url);
|
|
19
|
-
const filePath = join(appDir, "public", url.pathname);
|
|
20
|
-
try {
|
|
21
|
-
// OPTIONS预检请求
|
|
22
|
-
if (req.method === "OPTIONS") {
|
|
23
|
-
return new Response(null, {
|
|
24
|
-
status: 204,
|
|
25
|
-
headers: corsHeaders
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
const file = Bun.file(filePath);
|
|
29
|
-
if (await file.exists()) {
|
|
30
|
-
return new Response(file, {
|
|
31
|
-
headers: {
|
|
32
|
-
"Content-Type": file.type || "application/octet-stream",
|
|
33
|
-
...corsHeaders
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
return Response.json({
|
|
39
|
-
code: 1,
|
|
40
|
-
msg: "文件未找到"
|
|
41
|
-
}, {
|
|
42
|
-
headers: corsHeaders
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
catch (error) {
|
|
47
|
-
Logger.error({ err: error, msg: "静态文件处理失败" });
|
|
48
|
-
return Response.json({
|
|
49
|
-
code: 1,
|
|
50
|
-
msg: "文件读取失败"
|
|
51
|
-
}, {
|
|
52
|
-
headers: corsHeaders
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,296 +0,0 @@
|
|
|
1
|
-
// 内部依赖(Node.js 内置模块)
|
|
2
|
-
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
3
|
-
import { dirname, resolve } from "node:path";
|
|
4
|
-
function isTsSourcePath(p) {
|
|
5
|
-
// 注意:.d.ts 是构建产物,必须允许;这里仅阻断指向源码的 .ts 入口。
|
|
6
|
-
if (!p.endsWith(".ts")) {
|
|
7
|
-
return false;
|
|
8
|
-
}
|
|
9
|
-
if (p.endsWith(".d.ts") || p.endsWith(".d.mts") || p.endsWith(".d.cts")) {
|
|
10
|
-
return false;
|
|
11
|
-
}
|
|
12
|
-
return true;
|
|
13
|
-
}
|
|
14
|
-
function isRecord(value) {
|
|
15
|
-
return typeof value === "object" && value !== null;
|
|
16
|
-
}
|
|
17
|
-
function collectExportPaths(exportsValue, out) {
|
|
18
|
-
if (typeof exportsValue === "string") {
|
|
19
|
-
out.push(exportsValue);
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
if (Array.isArray(exportsValue)) {
|
|
23
|
-
for (const item of exportsValue) {
|
|
24
|
-
collectExportPaths(item, out);
|
|
25
|
-
}
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
if (!isRecord(exportsValue)) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
for (const value of Object.values(exportsValue)) {
|
|
32
|
-
collectExportPaths(value, out);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
function assertPathExists(packageRoot, relativeOrBare) {
|
|
36
|
-
if (!relativeOrBare.startsWith("./")) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
if (relativeOrBare.includes("*")) {
|
|
40
|
-
const beforeStar = relativeOrBare.split("*")[0] ?? "";
|
|
41
|
-
const dirPath = resolve(packageRoot, beforeStar);
|
|
42
|
-
if (!existsSync(dirPath)) {
|
|
43
|
-
process.stderr.write(`[ensureDist] missing export directory: ${beforeStar}\n`);
|
|
44
|
-
process.exit(1);
|
|
45
|
-
}
|
|
46
|
-
const stat = statSync(dirPath);
|
|
47
|
-
if (!stat.isDirectory()) {
|
|
48
|
-
process.stderr.write(`[ensureDist] export directory is not a directory: ${beforeStar}\n`);
|
|
49
|
-
process.exit(1);
|
|
50
|
-
}
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
const absPath = resolve(packageRoot, relativeOrBare);
|
|
54
|
-
if (!existsSync(absPath)) {
|
|
55
|
-
process.stderr.write(`[ensureDist] missing export file: ${relativeOrBare}\n`);
|
|
56
|
-
process.exit(1);
|
|
57
|
-
}
|
|
58
|
-
const stat = statSync(absPath);
|
|
59
|
-
if (!stat.isFile()) {
|
|
60
|
-
process.stderr.write(`[ensureDist] export path is not a file: ${relativeOrBare}\n`);
|
|
61
|
-
process.exit(1);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
function findTsImportSpecifiers(content) {
|
|
65
|
-
const matches = [];
|
|
66
|
-
const patterns = [/from\s+["'][^"']+\.ts["']/g, /import\(\s*["'][^"']+\.ts["']\s*\)/g, /<reference\s+path=["'][^"']+\.ts["']\s*\/>/g];
|
|
67
|
-
for (const pattern of patterns) {
|
|
68
|
-
const found = content.match(pattern);
|
|
69
|
-
if (found && found.length > 0) {
|
|
70
|
-
matches.push(...found);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return matches;
|
|
74
|
-
}
|
|
75
|
-
function collectExportTypePaths(exportsValue, out) {
|
|
76
|
-
if (!isRecord(exportsValue)) {
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
for (const value of Object.values(exportsValue)) {
|
|
80
|
-
if (typeof value === "string") {
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
|
-
if (Array.isArray(value)) {
|
|
84
|
-
for (const item of value) {
|
|
85
|
-
collectExportTypePaths(item, out);
|
|
86
|
-
}
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
if (!isRecord(value)) {
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
const typesPath = value["types"];
|
|
93
|
-
if (typeof typesPath === "string") {
|
|
94
|
-
out.push(typesPath);
|
|
95
|
-
}
|
|
96
|
-
collectExportTypePaths(value, out);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
function expandDtsExportPath(packageRoot, exportPath) {
|
|
100
|
-
if (!exportPath.startsWith("./")) {
|
|
101
|
-
return [];
|
|
102
|
-
}
|
|
103
|
-
if (!exportPath.includes("*")) {
|
|
104
|
-
return [resolve(packageRoot, exportPath)];
|
|
105
|
-
}
|
|
106
|
-
const beforeStar = exportPath.split("*")[0] ?? "";
|
|
107
|
-
const dirPath = resolve(packageRoot, beforeStar);
|
|
108
|
-
if (!existsSync(dirPath)) {
|
|
109
|
-
return [];
|
|
110
|
-
}
|
|
111
|
-
const stat = statSync(dirPath);
|
|
112
|
-
if (!stat.isDirectory()) {
|
|
113
|
-
return [];
|
|
114
|
-
}
|
|
115
|
-
const files = readdirSync(dirPath);
|
|
116
|
-
return files.filter((file) => file.endsWith(".d.ts")).map((file) => resolve(dirPath, file));
|
|
117
|
-
}
|
|
118
|
-
function findDtsSpecifiers(content) {
|
|
119
|
-
const specifiers = [];
|
|
120
|
-
const patterns = [/from\s+["']([^"']+)["']/g, /import\(\s*["']([^"']+)["']\s*\)/g, /<reference\s+path=["']([^"']+)["']\s*\/>/g];
|
|
121
|
-
for (const pattern of patterns) {
|
|
122
|
-
for (const match of content.matchAll(pattern)) {
|
|
123
|
-
const spec = match[1];
|
|
124
|
-
if (typeof spec === "string" && spec.length > 0) {
|
|
125
|
-
specifiers.push(spec);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return specifiers;
|
|
130
|
-
}
|
|
131
|
-
function resolveLocalDtsDependency(fromDtsPath, specifier) {
|
|
132
|
-
if (!specifier.startsWith("./") && !specifier.startsWith("../")) {
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
|
-
if (specifier.endsWith(".json")) {
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
const baseDir = dirname(fromDtsPath);
|
|
139
|
-
const absNoCheck = resolve(baseDir, specifier);
|
|
140
|
-
const tryPaths = [];
|
|
141
|
-
if (specifier.endsWith(".d.ts")) {
|
|
142
|
-
tryPaths.push(absNoCheck);
|
|
143
|
-
}
|
|
144
|
-
else if (specifier.endsWith(".js") || specifier.endsWith(".mjs") || specifier.endsWith(".cjs")) {
|
|
145
|
-
const replaced = absNoCheck.replace(/\.(mjs|cjs|js)$/u, ".d.ts");
|
|
146
|
-
tryPaths.push(replaced);
|
|
147
|
-
tryPaths.push(`${absNoCheck}.d.ts`);
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
tryPaths.push(`${absNoCheck}.d.ts`);
|
|
151
|
-
}
|
|
152
|
-
tryPaths.push(resolve(absNoCheck, "index.d.ts"));
|
|
153
|
-
for (const p of tryPaths) {
|
|
154
|
-
if (existsSync(p)) {
|
|
155
|
-
return p;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
return null;
|
|
159
|
-
}
|
|
160
|
-
function collectReachableDtsFromEntrypoints(distDir, entrypoints) {
|
|
161
|
-
const visited = new Set();
|
|
162
|
-
const queue = [];
|
|
163
|
-
for (const entry of entrypoints) {
|
|
164
|
-
if (!entry.startsWith(distDir)) {
|
|
165
|
-
continue;
|
|
166
|
-
}
|
|
167
|
-
if (existsSync(entry) && entry.endsWith(".d.ts")) {
|
|
168
|
-
queue.push(entry);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
while (queue.length > 0) {
|
|
172
|
-
const current = queue.pop();
|
|
173
|
-
if (!current) {
|
|
174
|
-
continue;
|
|
175
|
-
}
|
|
176
|
-
if (visited.has(current)) {
|
|
177
|
-
continue;
|
|
178
|
-
}
|
|
179
|
-
visited.add(current);
|
|
180
|
-
const content = readFileSync(current, { encoding: "utf8" });
|
|
181
|
-
const specifiers = findDtsSpecifiers(content);
|
|
182
|
-
for (const specifier of specifiers) {
|
|
183
|
-
const resolved = resolveLocalDtsDependency(current, specifier);
|
|
184
|
-
if (!resolved) {
|
|
185
|
-
continue;
|
|
186
|
-
}
|
|
187
|
-
if (!resolved.startsWith(distDir)) {
|
|
188
|
-
continue;
|
|
189
|
-
}
|
|
190
|
-
if (!visited.has(resolved)) {
|
|
191
|
-
queue.push(resolved);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
return Array.from(visited);
|
|
196
|
-
}
|
|
197
|
-
function main() {
|
|
198
|
-
const packageRoot = process.cwd();
|
|
199
|
-
const pkgPath = resolve(packageRoot, "package.json");
|
|
200
|
-
if (!existsSync(pkgPath)) {
|
|
201
|
-
process.stderr.write("[ensureDist] package.json not found\n");
|
|
202
|
-
process.exit(1);
|
|
203
|
-
}
|
|
204
|
-
const pkg = JSON.parse(readFileSync(pkgPath, { encoding: "utf8" }));
|
|
205
|
-
// 额外一致性校验:默认入口必须走 dist 产物(JS + DTS 分离)。
|
|
206
|
-
if (typeof pkg.main !== "string" || !pkg.main.startsWith("./dist/")) {
|
|
207
|
-
process.stderr.write("[ensureDist] package.json main must be a string under ./dist/\n");
|
|
208
|
-
process.exit(1);
|
|
209
|
-
}
|
|
210
|
-
if (typeof pkg.types !== "string" || !pkg.types.startsWith("./dist/")) {
|
|
211
|
-
process.stderr.write("[ensureDist] package.json types must be a string under ./dist/\n");
|
|
212
|
-
process.exit(1);
|
|
213
|
-
}
|
|
214
|
-
if (isTsSourcePath(pkg.main) || isTsSourcePath(pkg.types)) {
|
|
215
|
-
process.stderr.write("[ensureDist] package.json main/types must not point to .ts source files\n");
|
|
216
|
-
process.exit(1);
|
|
217
|
-
}
|
|
218
|
-
if (!isRecord(pkg.exports) || !isRecord(pkg.exports["."])) {
|
|
219
|
-
process.stderr.write("[ensureDist] package.json exports['.'] must be an object with { types, default }\n");
|
|
220
|
-
process.exit(1);
|
|
221
|
-
}
|
|
222
|
-
const dotExport = pkg.exports["."];
|
|
223
|
-
const dotTypes = dotExport["types"];
|
|
224
|
-
const dotDefault = dotExport["default"];
|
|
225
|
-
if (dotTypes !== pkg.types) {
|
|
226
|
-
process.stderr.write("[ensureDist] exports['.'].types must equal package.json types\n");
|
|
227
|
-
process.exit(1);
|
|
228
|
-
}
|
|
229
|
-
if (dotDefault !== pkg.main) {
|
|
230
|
-
process.stderr.write("[ensureDist] exports['.'].default must equal package.json main\n");
|
|
231
|
-
process.exit(1);
|
|
232
|
-
}
|
|
233
|
-
if (typeof dotTypes === "string" && isTsSourcePath(dotTypes)) {
|
|
234
|
-
process.stderr.write("[ensureDist] exports['.'].types must not point to .ts source files\n");
|
|
235
|
-
process.exit(1);
|
|
236
|
-
}
|
|
237
|
-
if (typeof dotDefault === "string" && isTsSourcePath(dotDefault)) {
|
|
238
|
-
process.stderr.write("[ensureDist] exports['.'].default must not point to .ts source files\n");
|
|
239
|
-
process.exit(1);
|
|
240
|
-
}
|
|
241
|
-
const distDir = resolve(packageRoot, "dist");
|
|
242
|
-
if (!existsSync(distDir)) {
|
|
243
|
-
process.stderr.write("[ensureDist] dist/ not found (did you run build?)\n");
|
|
244
|
-
process.exit(1);
|
|
245
|
-
}
|
|
246
|
-
// dist-only 发布规范:从对外可达入口(pkg.types + exports.*.types)出发的声明闭包中,
|
|
247
|
-
// 任何 .d.ts 都不允许引用源码 .ts(防止消费者类型解析回退到源码)。
|
|
248
|
-
{
|
|
249
|
-
const exportTypePaths = [];
|
|
250
|
-
if (typeof pkg.types === "string") {
|
|
251
|
-
exportTypePaths.push(pkg.types);
|
|
252
|
-
}
|
|
253
|
-
collectExportTypePaths(pkg.exports, exportTypePaths);
|
|
254
|
-
const entryDtsAbsPaths = new Set();
|
|
255
|
-
for (const exportPath of exportTypePaths) {
|
|
256
|
-
for (const absPath of expandDtsExportPath(packageRoot, exportPath)) {
|
|
257
|
-
entryDtsAbsPaths.add(absPath);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
if (entryDtsAbsPaths.size === 0) {
|
|
261
|
-
process.stderr.write("[ensureDist] no exported .d.ts entrypoints found (types/exports.types)\n");
|
|
262
|
-
process.exit(1);
|
|
263
|
-
}
|
|
264
|
-
const reachableDtsPaths = collectReachableDtsFromEntrypoints(distDir, Array.from(entryDtsAbsPaths));
|
|
265
|
-
if (reachableDtsPaths.length === 0) {
|
|
266
|
-
process.stderr.write("[ensureDist] no reachable .d.ts files found from exported entrypoints\n");
|
|
267
|
-
process.exit(1);
|
|
268
|
-
}
|
|
269
|
-
const offenders = [];
|
|
270
|
-
for (const absPath of reachableDtsPaths) {
|
|
271
|
-
const content = readFileSync(absPath, { encoding: "utf8" });
|
|
272
|
-
const matches = findTsImportSpecifiers(content);
|
|
273
|
-
if (matches.length > 0) {
|
|
274
|
-
offenders.push({ filePath: absPath, matches: matches });
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
if (offenders.length > 0) {
|
|
278
|
-
process.stderr.write("[ensureDist] exported declaration files must not reference .ts source files\n");
|
|
279
|
-
process.stderr.write(`${JSON.stringify(offenders, null, 4)}\n`);
|
|
280
|
-
process.exit(1);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
const paths = [];
|
|
284
|
-
if (typeof pkg.main === "string") {
|
|
285
|
-
paths.push(pkg.main);
|
|
286
|
-
}
|
|
287
|
-
if (typeof pkg.types === "string") {
|
|
288
|
-
paths.push(pkg.types);
|
|
289
|
-
}
|
|
290
|
-
collectExportPaths(pkg.exports, paths);
|
|
291
|
-
for (const p of paths) {
|
|
292
|
-
assertPathExists(packageRoot, p);
|
|
293
|
-
}
|
|
294
|
-
process.stdout.write("[ensureDist] OK\n");
|
|
295
|
-
}
|
|
296
|
-
main();
|
package/dist/sync/syncApi.d.ts
DELETED