befly 3.16.9 → 3.16.11
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 +12769 -0
- package/befly.min.js +47 -0
- package/package.json +18 -29
- package/dist/befly.config.d.ts +0 -7
- package/dist/befly.config.js +0 -128
- package/dist/befly.js +0 -17276
- package/dist/befly.min.js +0 -23
- package/dist/checks/checkApi.d.ts +0 -1
- package/dist/checks/checkApi.js +0 -124
- 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 -10
- package/dist/hooks/permission.js +0 -64
- 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 -1069
- 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 -140
- 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 -175
- 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/utils/response.js
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { Logger } from "../lib/logger";
|
|
2
|
-
/**
|
|
3
|
-
* 创建错误响应(专用于 Hook 中间件)
|
|
4
|
-
* 在钩子中提前拦截请求时使用
|
|
5
|
-
* @param ctx - 请求上下文
|
|
6
|
-
* @param msg - 错误消息
|
|
7
|
-
* @param code - 错误码,默认 1
|
|
8
|
-
* @param data - 附加数据,默认 null
|
|
9
|
-
* @param detail - 详细信息,用于标记具体提示位置,默认 null
|
|
10
|
-
* @param reasonCode - 拦截原因标识(用于统计/聚合),默认 null
|
|
11
|
-
* @returns Response 对象
|
|
12
|
-
*/
|
|
13
|
-
export function ErrorResponse(ctx, msg, code = 1, data = null, detail = null, reasonCode = null) {
|
|
14
|
-
// 记录拦截日志
|
|
15
|
-
if (ctx.requestId) {
|
|
16
|
-
// requestId/route/user/duration 等字段由 ALS 统一注入,避免在 msg 中重复拼接
|
|
17
|
-
Logger.info({
|
|
18
|
-
event: "request_blocked",
|
|
19
|
-
reason: msg,
|
|
20
|
-
reasonCode: reasonCode,
|
|
21
|
-
code: code,
|
|
22
|
-
detail: detail,
|
|
23
|
-
msg: "request blocked"
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
return Response.json({
|
|
27
|
-
code: code,
|
|
28
|
-
msg: msg,
|
|
29
|
-
data: data,
|
|
30
|
-
detail: detail
|
|
31
|
-
}, {
|
|
32
|
-
headers: ctx.corsHeaders
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* 创建最终响应(专用于 API 路由结尾)
|
|
37
|
-
* 自动处理 ctx.response/ctx.result,并记录请求日志
|
|
38
|
-
* @param ctx - 请求上下文
|
|
39
|
-
* @returns Response 对象
|
|
40
|
-
*/
|
|
41
|
-
export function FinalResponse(ctx) {
|
|
42
|
-
// 记录请求日志
|
|
43
|
-
if (ctx.api && ctx.requestId) {
|
|
44
|
-
// requestId/route/user/duration 等字段由 ALS 统一注入,避免在 msg 中重复拼接
|
|
45
|
-
Logger.info({
|
|
46
|
-
event: "request_done",
|
|
47
|
-
msg: "request done"
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
// 1. 如果已经有 response,直接返回
|
|
51
|
-
if (ctx.response) {
|
|
52
|
-
return ctx.response;
|
|
53
|
-
}
|
|
54
|
-
// 2. 如果有 result,格式化为响应
|
|
55
|
-
if (ctx.result !== undefined) {
|
|
56
|
-
let result = ctx.result;
|
|
57
|
-
// 如果是字符串,自动包裹为成功响应
|
|
58
|
-
if (typeof result === "string") {
|
|
59
|
-
result = {
|
|
60
|
-
code: 0,
|
|
61
|
-
msg: result
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
// 如果是对象,自动补充 code: 0
|
|
65
|
-
else if (result && typeof result === "object") {
|
|
66
|
-
if (!("code" in result)) {
|
|
67
|
-
result = {
|
|
68
|
-
code: 0,
|
|
69
|
-
...result
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
// 处理 BigInt 序列化问题
|
|
74
|
-
if (result && typeof result === "object") {
|
|
75
|
-
const jsonString = JSON.stringify(result, (key, value) => (typeof value === "bigint" ? value.toString() : value));
|
|
76
|
-
return new Response(jsonString, {
|
|
77
|
-
headers: {
|
|
78
|
-
...ctx.corsHeaders,
|
|
79
|
-
"Content-Type": "application/json"
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
|
-
return Response.json(result, {
|
|
85
|
-
headers: ctx.corsHeaders
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
// 3. 默认响应:没有生成响应
|
|
90
|
-
return Response.json({
|
|
91
|
-
code: 1,
|
|
92
|
-
msg: "未生成响应"
|
|
93
|
-
}, {
|
|
94
|
-
headers: ctx.corsHeaders
|
|
95
|
-
});
|
|
96
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export type AddonSource = "addon" | "app";
|
|
2
|
-
export interface AddonInfo {
|
|
3
|
-
/** addon 来源 */
|
|
4
|
-
source: AddonSource;
|
|
5
|
-
/** addon 来源中文名 */
|
|
6
|
-
sourceName: string;
|
|
7
|
-
/** addon 名称(目录名,通常是 demo/admin 等) */
|
|
8
|
-
name: string;
|
|
9
|
-
/** camelCase(name) */
|
|
10
|
-
camelName: string;
|
|
11
|
-
/** addon 根目录绝对路径 */
|
|
12
|
-
rootDir: string;
|
|
13
|
-
}
|
|
14
|
-
/** 扫描 node_modules/@befly-addon + 项目 addons/(项目优先级更高) */
|
|
15
|
-
export declare const scanAddons: () => AddonInfo[];
|
package/dist/utils/scanAddons.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { existsSync, readdirSync } from "node:fs";
|
|
2
|
-
import { join, resolve } from "pathe";
|
|
3
|
-
import { appDir } from "../paths";
|
|
4
|
-
import { isDirentDirectory } from "./isDirentDirectory";
|
|
5
|
-
import { camelCase } from "./util";
|
|
6
|
-
/** 扫描 node_modules/@befly-addon + 项目 addons/(项目优先级更高) */
|
|
7
|
-
export const scanAddons = () => {
|
|
8
|
-
const addonMap = new Map();
|
|
9
|
-
const scanBaseDir = (baseDir, source, sourceName) => {
|
|
10
|
-
if (!existsSync(baseDir)) {
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
const entries = readdirSync(baseDir, { withFileTypes: true });
|
|
14
|
-
for (const entry of entries) {
|
|
15
|
-
if (entry.name.startsWith("_")) {
|
|
16
|
-
continue;
|
|
17
|
-
}
|
|
18
|
-
if (!isDirentDirectory(baseDir, entry)) {
|
|
19
|
-
continue;
|
|
20
|
-
}
|
|
21
|
-
const rootDir = resolve(baseDir, entry.name);
|
|
22
|
-
const info = {
|
|
23
|
-
source: source,
|
|
24
|
-
sourceName: sourceName,
|
|
25
|
-
name: entry.name,
|
|
26
|
-
camelName: camelCase(entry.name),
|
|
27
|
-
rootDir: rootDir
|
|
28
|
-
};
|
|
29
|
-
addonMap.set(entry.name, info);
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
// node_modules 中的 @befly-addon
|
|
33
|
-
scanBaseDir(join(appDir, "node_modules", "@befly-addon"), "addon", "组件");
|
|
34
|
-
return Array.from(addonMap.values());
|
|
35
|
-
};
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import coreHookAuth from "../hooks/auth";
|
|
2
|
-
import coreHookCors from "../hooks/cors";
|
|
3
|
-
import coreHookParser from "../hooks/parser";
|
|
4
|
-
import coreHookPermission from "../hooks/permission";
|
|
5
|
-
import coreHookValidator from "../hooks/validator";
|
|
6
|
-
import corePluginCache from "../plugins/cache";
|
|
7
|
-
import corePluginCipher from "../plugins/cipher";
|
|
8
|
-
import corePluginConfig from "../plugins/config";
|
|
9
|
-
import corePluginDb from "../plugins/db";
|
|
10
|
-
import corePluginJwt from "../plugins/jwt";
|
|
11
|
-
import corePluginLogger from "../plugins/logger";
|
|
12
|
-
import corePluginRedis from "../plugins/redis";
|
|
13
|
-
import corePluginTool from "../plugins/tool";
|
|
14
|
-
import { isPlainObject } from "./util";
|
|
15
|
-
function toCoreBuiltinScanFileResult(type, item) {
|
|
16
|
-
const record = (isPlainObject(item) ? item : {});
|
|
17
|
-
const name = typeof record["name"] === "string" ? String(record["name"]) : "";
|
|
18
|
-
const customKeys = isPlainObject(item) ? Object.keys(item) : [];
|
|
19
|
-
const depsRaw = record["deps"];
|
|
20
|
-
const deps = Array.isArray(depsRaw) ? depsRaw.filter((x) => typeof x === "string") : [];
|
|
21
|
-
const out = {
|
|
22
|
-
source: "core",
|
|
23
|
-
type: type,
|
|
24
|
-
sourceName: "核心",
|
|
25
|
-
filePath: `core:${type}:${name}`,
|
|
26
|
-
relativePath: name,
|
|
27
|
-
fileName: name,
|
|
28
|
-
moduleName: name,
|
|
29
|
-
addonName: "",
|
|
30
|
-
fileBaseName: name,
|
|
31
|
-
fileDir: "(builtin)",
|
|
32
|
-
name: name,
|
|
33
|
-
enable: record["enable"],
|
|
34
|
-
deps: deps,
|
|
35
|
-
handler: record["handler"] ?? null,
|
|
36
|
-
customKeys: customKeys
|
|
37
|
-
};
|
|
38
|
-
return out;
|
|
39
|
-
}
|
|
40
|
-
export function scanCoreBuiltinPlugins() {
|
|
41
|
-
const plugins = [];
|
|
42
|
-
const builtinPlugins = [
|
|
43
|
-
//
|
|
44
|
-
corePluginLogger,
|
|
45
|
-
corePluginRedis,
|
|
46
|
-
corePluginDb,
|
|
47
|
-
corePluginCache,
|
|
48
|
-
corePluginTool,
|
|
49
|
-
corePluginCipher,
|
|
50
|
-
corePluginJwt,
|
|
51
|
-
corePluginConfig
|
|
52
|
-
];
|
|
53
|
-
for (const plugin of builtinPlugins) {
|
|
54
|
-
plugins.push(toCoreBuiltinScanFileResult("plugin", plugin));
|
|
55
|
-
}
|
|
56
|
-
return plugins;
|
|
57
|
-
}
|
|
58
|
-
export function scanCoreBuiltinHooks() {
|
|
59
|
-
const hooks = [];
|
|
60
|
-
const builtinHooks = [
|
|
61
|
-
//
|
|
62
|
-
coreHookAuth,
|
|
63
|
-
coreHookCors,
|
|
64
|
-
coreHookParser,
|
|
65
|
-
coreHookValidator,
|
|
66
|
-
coreHookPermission
|
|
67
|
-
];
|
|
68
|
-
for (const hook of builtinHooks) {
|
|
69
|
-
hooks.push(toCoreBuiltinScanFileResult("hook", hook));
|
|
70
|
-
}
|
|
71
|
-
return hooks;
|
|
72
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
export type ScanFileSource = "app" | "addon" | "core";
|
|
2
|
-
export type ScanFileType = "api" | "table" | "plugin" | "hook";
|
|
3
|
-
export interface ScanFileResultBase {
|
|
4
|
-
source: ScanFileSource;
|
|
5
|
-
type: ScanFileType;
|
|
6
|
-
sourceName: string;
|
|
7
|
-
filePath: string;
|
|
8
|
-
relativePath: string;
|
|
9
|
-
fileName: string;
|
|
10
|
-
/** 模块名(用于 deps 依赖图 key 与运行时挂载 key) */
|
|
11
|
-
moduleName: string;
|
|
12
|
-
/** addon 名:addon 来源为真实值;core/app 统一为空字符串("") */
|
|
13
|
-
addonName: string;
|
|
14
|
-
fileBaseName: string;
|
|
15
|
-
fileDir: string;
|
|
16
|
-
/** default export 的自有 key 集合(用于记录模块自定义属性/结构校验) */
|
|
17
|
-
customKeys?: string[];
|
|
18
|
-
}
|
|
19
|
-
export type ScanFileResult = (ScanFileResultBase & {
|
|
20
|
-
type: "table";
|
|
21
|
-
content: Record<string, unknown>;
|
|
22
|
-
}) | (ScanFileResultBase & {
|
|
23
|
-
type: Exclude<ScanFileType, "table">;
|
|
24
|
-
} & Record<string, unknown>);
|
|
25
|
-
/**
|
|
26
|
-
* 扫描指定目录下的文件
|
|
27
|
-
* @param dir 目录路径
|
|
28
|
-
* @param source 文件来源(app/addon/core)
|
|
29
|
-
* @param type 文件类型(api/table/plugin/hook)
|
|
30
|
-
* @param pattern Glob模式
|
|
31
|
-
*/
|
|
32
|
-
export declare function scanFiles(dir: string, source: ScanFileSource, type: ScanFileType, pattern: string): Promise<ScanFileResult[]>;
|
package/dist/utils/scanFiles.js
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
|
-
import { relative, normalize, parse, join } from "pathe";
|
|
3
|
-
import { importDefault } from "./importDefault";
|
|
4
|
-
import { camelCase, forOwn, isPlainObject } from "./util";
|
|
5
|
-
function parseAddonNameFromPath(normalizedPath) {
|
|
6
|
-
// 期望路径中包含:/node_modules/@befly-addon/<addonName>/...
|
|
7
|
-
const parts = normalizedPath.split("/").filter(Boolean);
|
|
8
|
-
const idx = parts.indexOf("@befly-addon");
|
|
9
|
-
if (idx < 0)
|
|
10
|
-
return null;
|
|
11
|
-
const addonName = parts[idx + 1];
|
|
12
|
-
if (typeof addonName !== "string" || addonName.trim() === "")
|
|
13
|
-
return null;
|
|
14
|
-
return addonName;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* 扫描指定目录下的文件
|
|
18
|
-
* @param dir 目录路径
|
|
19
|
-
* @param source 文件来源(app/addon/core)
|
|
20
|
-
* @param type 文件类型(api/table/plugin/hook)
|
|
21
|
-
* @param pattern Glob模式
|
|
22
|
-
*/
|
|
23
|
-
export async function scanFiles(dir, source, type, pattern) {
|
|
24
|
-
if (!existsSync(dir))
|
|
25
|
-
return [];
|
|
26
|
-
const normalizedDir = normalize(dir);
|
|
27
|
-
const glob = new Bun.Glob(pattern);
|
|
28
|
-
const results = [];
|
|
29
|
-
try {
|
|
30
|
-
const files = await glob.scan({
|
|
31
|
-
cwd: dir,
|
|
32
|
-
onlyFiles: true,
|
|
33
|
-
absolute: true,
|
|
34
|
-
followSymlinks: true
|
|
35
|
-
});
|
|
36
|
-
for await (const file of files) {
|
|
37
|
-
if (file.endsWith(".d.ts"))
|
|
38
|
-
continue;
|
|
39
|
-
// 使用 pathe.normalize 统一路径分隔符为 /
|
|
40
|
-
const normalizedFile = normalize(file);
|
|
41
|
-
// 获取文件名(去除扩展名)
|
|
42
|
-
const fileName = parse(normalizedFile).name;
|
|
43
|
-
// 计算相对路径(去除扩展名)
|
|
44
|
-
const relativePathWithExt = relative(normalizedDir, normalizedFile);
|
|
45
|
-
const parsedRelativePath = parse(relativePathWithExt);
|
|
46
|
-
const relativePath = parsedRelativePath.dir ? join(parsedRelativePath.dir, parsedRelativePath.name) : parsedRelativePath.name;
|
|
47
|
-
// 固定默认过滤(不可关闭):忽略下划线开头的文件/目录
|
|
48
|
-
if (fileName.startsWith("_"))
|
|
49
|
-
continue;
|
|
50
|
-
if (relativePath.split("/").some((part) => part.startsWith("_")))
|
|
51
|
-
continue;
|
|
52
|
-
const content = await importDefault(normalizedFile, {});
|
|
53
|
-
// 记录 default export 的自有 key 集合(任何类型都记录,用于自定义属性审计/结构校验)。
|
|
54
|
-
// 注意:在合并导出对象后还会写回一次 customKeys,避免用户导出同名字段覆盖该元信息。
|
|
55
|
-
const baseName = camelCase(fileName);
|
|
56
|
-
let addonName = "";
|
|
57
|
-
let moduleName = "";
|
|
58
|
-
if (source === "core") {
|
|
59
|
-
// core:不做任何命名转换,直接使用文件名作为 moduleName(例如 auth / rate_limit)。
|
|
60
|
-
addonName = "";
|
|
61
|
-
moduleName = fileName;
|
|
62
|
-
}
|
|
63
|
-
else if (source === "app") {
|
|
64
|
-
moduleName = `app_${baseName}`;
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
const parsedAddonName = parseAddonNameFromPath(normalizedFile);
|
|
68
|
-
if (!parsedAddonName) {
|
|
69
|
-
throw new Error(`scanFiles addon moduleName 解析失败:未找到 @befly-addon/<addon>/ 段落:${normalizedFile}`);
|
|
70
|
-
}
|
|
71
|
-
addonName = parsedAddonName;
|
|
72
|
-
moduleName = `addon_${camelCase(addonName)}_${baseName}`;
|
|
73
|
-
}
|
|
74
|
-
const base = {
|
|
75
|
-
source: source,
|
|
76
|
-
type: type,
|
|
77
|
-
sourceName: source === "core" ? "核心" : source === "addon" ? "组件" : "项目",
|
|
78
|
-
filePath: normalizedFile,
|
|
79
|
-
relativePath: relativePath,
|
|
80
|
-
fileName: fileName,
|
|
81
|
-
moduleName: moduleName,
|
|
82
|
-
addonName: addonName,
|
|
83
|
-
fileBaseName: parse(normalizedFile).base,
|
|
84
|
-
fileDir: dir,
|
|
85
|
-
customKeys: isPlainObject(content) ? Object.keys(content) : []
|
|
86
|
-
};
|
|
87
|
-
if (type === "table") {
|
|
88
|
-
base["content"] = isPlainObject(content) ? content : {};
|
|
89
|
-
results.push(base);
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
if (type === "api") {
|
|
93
|
-
// 运行时 auth 必须是 boolean:
|
|
94
|
-
// - checkApi 会校验 auth 类型
|
|
95
|
-
// - permission hook 以 ctx.api.auth === false 判断公开接口
|
|
96
|
-
// DB 存储的 0/1 由 syncApi 负责转换写入。
|
|
97
|
-
base["auth"] = true;
|
|
98
|
-
base["rawBody"] = false;
|
|
99
|
-
base["method"] = "POST";
|
|
100
|
-
base["fields"] = {};
|
|
101
|
-
base["required"] = [];
|
|
102
|
-
}
|
|
103
|
-
if (type === "plugin" || type === "hook") {
|
|
104
|
-
base["deps"] = [];
|
|
105
|
-
base["name"] = "";
|
|
106
|
-
base["handler"] = null;
|
|
107
|
-
}
|
|
108
|
-
forOwn(content, (value, key) => {
|
|
109
|
-
base[key] = value;
|
|
110
|
-
});
|
|
111
|
-
if (type === "api") {
|
|
112
|
-
base["routePrefix"] = source === "app" ? "/app" : `/addon/${addonName}`;
|
|
113
|
-
base["path"] = `/api${base["routePrefix"]}/${relativePath}`;
|
|
114
|
-
}
|
|
115
|
-
results.push(base);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
catch (error) {
|
|
119
|
-
const wrappedError = new Error(`scanFiles failed: source=${source} type=${type} dir=${normalizedDir} pattern=${pattern}`);
|
|
120
|
-
wrappedError.cause = error;
|
|
121
|
-
throw wrappedError;
|
|
122
|
-
}
|
|
123
|
-
return results;
|
|
124
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { AddonInfo } from "./scanAddons";
|
|
2
|
-
import type { ScanFileResult } from "./scanFiles";
|
|
3
|
-
export type ScanSourcesResult = {
|
|
4
|
-
hooks: ScanFileResult[];
|
|
5
|
-
plugins: ScanFileResult[];
|
|
6
|
-
apis: ScanFileResult[];
|
|
7
|
-
tables: ScanFileResult[];
|
|
8
|
-
addons: AddonInfo[];
|
|
9
|
-
};
|
|
10
|
-
export declare const scanSources: () => Promise<ScanSourcesResult>;
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { join } from "pathe";
|
|
2
|
-
import { appDir } from "../paths";
|
|
3
|
-
import { scanAddons } from "./scanAddons";
|
|
4
|
-
import { scanCoreBuiltinHooks, scanCoreBuiltinPlugins } from "./scanCoreBuiltins";
|
|
5
|
-
import { scanFiles } from "./scanFiles";
|
|
6
|
-
export const scanSources = async () => {
|
|
7
|
-
const apis = [];
|
|
8
|
-
const plugins = [];
|
|
9
|
-
const hooks = [];
|
|
10
|
-
const tables = [];
|
|
11
|
-
const addons = await scanAddons();
|
|
12
|
-
// 处理表格
|
|
13
|
-
tables.push(...(await scanFiles(join(appDir, "tables"), "app", "table", "*.json")));
|
|
14
|
-
for (const addon of addons) {
|
|
15
|
-
tables.push(...(await scanFiles(join(addon.rootDir, "tables"), "addon", "table", "*.json")));
|
|
16
|
-
}
|
|
17
|
-
// 处理插件
|
|
18
|
-
// core 内置插件:必须静态导入(支持 bun bundle 单文件)。
|
|
19
|
-
// 约束:core 插件名由 export default.name 指定。
|
|
20
|
-
plugins.push(...scanCoreBuiltinPlugins());
|
|
21
|
-
plugins.push(...(await scanFiles(join(appDir, "plugins"), "app", "plugin", "*.{ts,js}")));
|
|
22
|
-
for (const addon of addons) {
|
|
23
|
-
plugins.push(...(await scanFiles(join(addon.rootDir, "plugins"), "addon", "plugin", "*.{ts,js}")));
|
|
24
|
-
}
|
|
25
|
-
// 处理钩子
|
|
26
|
-
// core 内置钩子:必须静态导入(支持 bun bundle 单文件)。
|
|
27
|
-
// 约束:core 钩子名由 export default.name 指定。
|
|
28
|
-
hooks.push(...scanCoreBuiltinHooks());
|
|
29
|
-
hooks.push(...(await scanFiles(join(appDir, "hooks"), "app", "hook", "*.{ts,js}")));
|
|
30
|
-
for (const addon of addons) {
|
|
31
|
-
hooks.push(...(await scanFiles(join(addon.rootDir, "hooks"), "addon", "hook", "*.{ts,js}")));
|
|
32
|
-
}
|
|
33
|
-
// 处理接口
|
|
34
|
-
// 说明:core 没有内置 apis;接口只从「项目(app)」与「组件(addon)」中扫描加载。
|
|
35
|
-
apis.push(...(await scanFiles(join(appDir, "apis"), "app", "api", "**/*.{ts,js}")));
|
|
36
|
-
for (const addon of addons) {
|
|
37
|
-
apis.push(...(await scanFiles(join(addon.rootDir, "apis"), "addon", "api", "**/*.{ts,js}")));
|
|
38
|
-
}
|
|
39
|
-
return {
|
|
40
|
-
hooks: hooks,
|
|
41
|
-
plugins: plugins,
|
|
42
|
-
apis: apis,
|
|
43
|
-
tables: tables,
|
|
44
|
-
addons: addons
|
|
45
|
-
};
|
|
46
|
-
};
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
export type SortModulesByDepsOptions<T> = {
|
|
2
|
-
/**
|
|
3
|
-
* 用于日志的模块标签(如:"插件"、"钩子")
|
|
4
|
-
*/
|
|
5
|
-
moduleLabel?: string;
|
|
6
|
-
/**
|
|
7
|
-
* 生成模块名(用于 deps 解析与排序 key)。
|
|
8
|
-
* 默认:camelCase(item.fileName)
|
|
9
|
-
*/
|
|
10
|
-
getName?: (item: T) => string;
|
|
11
|
-
/**
|
|
12
|
-
* 获取 deps。
|
|
13
|
-
* 默认:item.deps
|
|
14
|
-
*/
|
|
15
|
-
getDeps?: (item: T) => string[];
|
|
16
|
-
};
|
|
17
|
-
/**
|
|
18
|
-
* 按 deps 拓扑排序 scanSources 扫描得到的插件/钩子。
|
|
19
|
-
*
|
|
20
|
-
* 说明:
|
|
21
|
-
* - 输入为 scanSources/scanFiles 的条目数组:每个条目包含 fileName 与 deps。
|
|
22
|
-
* - deps 里的字符串会与 getName(item) 的结果匹配。
|
|
23
|
-
* - 若出现:重复 name、缺失依赖、循环依赖,则返回 false。
|
|
24
|
-
*/
|
|
25
|
-
export declare function sortModules<T extends {
|
|
26
|
-
fileName: string;
|
|
27
|
-
deps?: any;
|
|
28
|
-
}>(items: T[], options?: SortModulesByDepsOptions<T>): T[] | false;
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { Logger } from "../lib/logger";
|
|
2
|
-
import { camelCase } from "./util";
|
|
3
|
-
/**
|
|
4
|
-
* 按 deps 拓扑排序 scanSources 扫描得到的插件/钩子。
|
|
5
|
-
*
|
|
6
|
-
* 说明:
|
|
7
|
-
* - 输入为 scanSources/scanFiles 的条目数组:每个条目包含 fileName 与 deps。
|
|
8
|
-
* - deps 里的字符串会与 getName(item) 的结果匹配。
|
|
9
|
-
* - 若出现:重复 name、缺失依赖、循环依赖,则返回 false。
|
|
10
|
-
*/
|
|
11
|
-
export function sortModules(items, options = {}) {
|
|
12
|
-
const moduleLabel = options.moduleLabel || "模块";
|
|
13
|
-
const getName = options.getName ||
|
|
14
|
-
((item) => {
|
|
15
|
-
const moduleName = item.moduleName;
|
|
16
|
-
if (typeof moduleName === "string" && moduleName.trim() !== "") {
|
|
17
|
-
return moduleName;
|
|
18
|
-
}
|
|
19
|
-
return camelCase(item.fileName);
|
|
20
|
-
});
|
|
21
|
-
const getDeps = options.getDeps ||
|
|
22
|
-
((item) => {
|
|
23
|
-
const deps = item.deps;
|
|
24
|
-
if (!Array.isArray(deps)) {
|
|
25
|
-
return [];
|
|
26
|
-
}
|
|
27
|
-
return deps.filter((x) => typeof x === "string");
|
|
28
|
-
});
|
|
29
|
-
const result = [];
|
|
30
|
-
const visited = new Set();
|
|
31
|
-
const visiting = new Set();
|
|
32
|
-
const nameToItem = {};
|
|
33
|
-
let isPass = true;
|
|
34
|
-
// 1) 建表 + 重名检查
|
|
35
|
-
for (const item of items) {
|
|
36
|
-
const name = getName(item);
|
|
37
|
-
if (typeof name !== "string" || name.trim() === "") {
|
|
38
|
-
Logger.error({ item: item, msg: `${moduleLabel} 名称解析失败(getName 返回空字符串)` });
|
|
39
|
-
isPass = false;
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
if (nameToItem[name]) {
|
|
43
|
-
Logger.error({
|
|
44
|
-
name: name,
|
|
45
|
-
first: nameToItem[name],
|
|
46
|
-
second: item,
|
|
47
|
-
msg: `${moduleLabel} 名称重复,无法根据 deps 唯一定位`
|
|
48
|
-
});
|
|
49
|
-
isPass = false;
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
nameToItem[name] = item;
|
|
53
|
-
}
|
|
54
|
-
if (!isPass)
|
|
55
|
-
return false;
|
|
56
|
-
// 2) 依赖存在性检查 + deps 类型检查
|
|
57
|
-
for (const item of items) {
|
|
58
|
-
const name = getName(item);
|
|
59
|
-
const deps = getDeps(item);
|
|
60
|
-
if (!Array.isArray(deps)) {
|
|
61
|
-
Logger.error({ module: name, item: item, msg: `${moduleLabel} 的 deps 必须是数组` });
|
|
62
|
-
isPass = false;
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
for (const dep of deps) {
|
|
66
|
-
if (typeof dep !== "string") {
|
|
67
|
-
Logger.error({ module: name, dependency: dep, item: item, msg: `${moduleLabel} 的 deps 必须是字符串数组` });
|
|
68
|
-
isPass = false;
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
if (!nameToItem[dep]) {
|
|
72
|
-
Logger.error({ module: name, dependency: dep, msg: `${moduleLabel} 依赖未找到` });
|
|
73
|
-
isPass = false;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
if (!isPass)
|
|
78
|
-
return false;
|
|
79
|
-
// 3) 拓扑排序(DFS)
|
|
80
|
-
const visit = (name) => {
|
|
81
|
-
if (visited.has(name))
|
|
82
|
-
return;
|
|
83
|
-
if (visiting.has(name)) {
|
|
84
|
-
Logger.error({ module: name, msg: `${moduleLabel} 循环依赖` });
|
|
85
|
-
isPass = false;
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
const item = nameToItem[name];
|
|
89
|
-
if (!item)
|
|
90
|
-
return;
|
|
91
|
-
const deps = getDeps(item);
|
|
92
|
-
visiting.add(name);
|
|
93
|
-
for (const dep of deps) {
|
|
94
|
-
visit(dep);
|
|
95
|
-
}
|
|
96
|
-
visiting.delete(name);
|
|
97
|
-
visited.add(name);
|
|
98
|
-
result.push(item);
|
|
99
|
-
};
|
|
100
|
-
for (const item of items) {
|
|
101
|
-
const name = getName(item);
|
|
102
|
-
visit(name);
|
|
103
|
-
}
|
|
104
|
-
return isPass ? result : false;
|
|
105
|
-
}
|
package/dist/utils/sqlUtil.d.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { JsonValue, SqlValue } from "../types/common";
|
|
2
|
-
/**
|
|
3
|
-
* SQL 通用工具函数(core 内部使用)。
|
|
4
|
-
*
|
|
5
|
-
* 约束:
|
|
6
|
-
* - 只做字符串/参数/结果规范化(允许生成 SQL 字符串,但不执行 SQL)
|
|
7
|
-
* - 尽量不依赖业务字段类型语义(array_* / FieldDefinition 等)
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* MySQL DDL 的 COMMENT \"...\" 字面量转义:仅转义双引号。
|
|
11
|
-
* 说明:当前 SyncTable 使用双引号包裹 COMMENT 内容。
|
|
12
|
-
*/
|
|
13
|
-
export declare function escapeComment(str: string): string;
|
|
14
|
-
/**
|
|
15
|
-
* 将 information_schema 返回的 COLUMN_DEFAULT 规整为可 JSON 表达的值。
|
|
16
|
-
*
|
|
17
|
-
* 说明:MySQL 驱动可能返回 string/number/null,也可能返回其他可转字符串的类型。
|
|
18
|
-
*/
|
|
19
|
-
export declare function normalizeColumnDefaultValue(value: unknown): JsonValue;
|
|
20
|
-
export declare function isSqlValue(value: unknown): value is SqlValue;
|
|
21
|
-
/**
|
|
22
|
-
* 将外部输入参数(unknown[])转换为 DbHelper/sqlInfo 可接受的 SqlValue[]。
|
|
23
|
-
*
|
|
24
|
-
* 规则:
|
|
25
|
-
* - bigint -> string
|
|
26
|
-
* - 其他不可序列化值 -> String(value)
|
|
27
|
-
*/
|
|
28
|
-
export declare function toSqlParams(params: unknown[] | undefined): SqlValue[];
|
|
29
|
-
export type SqlRunResult = {
|
|
30
|
-
changes?: number | bigint;
|
|
31
|
-
lastInsertRowid?: number | bigint;
|
|
32
|
-
};
|
|
33
|
-
export declare function toNumberFromSql(value: unknown): number;
|