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.
Files changed (178) hide show
  1. package/README.md +0 -129
  2. package/befly.js +12769 -0
  3. package/befly.min.js +47 -0
  4. package/package.json +18 -29
  5. package/dist/befly.config.d.ts +0 -7
  6. package/dist/befly.config.js +0 -128
  7. package/dist/befly.js +0 -17276
  8. package/dist/befly.min.js +0 -23
  9. package/dist/checks/checkApi.d.ts +0 -1
  10. package/dist/checks/checkApi.js +0 -124
  11. package/dist/checks/checkConfig.d.ts +0 -9
  12. package/dist/checks/checkConfig.js +0 -255
  13. package/dist/checks/checkHook.d.ts +0 -1
  14. package/dist/checks/checkHook.js +0 -132
  15. package/dist/checks/checkMenu.d.ts +0 -3
  16. package/dist/checks/checkMenu.js +0 -106
  17. package/dist/checks/checkPlugin.d.ts +0 -1
  18. package/dist/checks/checkPlugin.js +0 -132
  19. package/dist/checks/checkTable.d.ts +0 -7
  20. package/dist/checks/checkTable.js +0 -431
  21. package/dist/configs/presetRegexp.d.ts +0 -145
  22. package/dist/configs/presetRegexp.js +0 -218
  23. package/dist/hooks/auth.d.ts +0 -3
  24. package/dist/hooks/auth.js +0 -24
  25. package/dist/hooks/cors.d.ts +0 -7
  26. package/dist/hooks/cors.js +0 -36
  27. package/dist/hooks/parser.d.ts +0 -10
  28. package/dist/hooks/parser.js +0 -76
  29. package/dist/hooks/permission.d.ts +0 -10
  30. package/dist/hooks/permission.js +0 -64
  31. package/dist/hooks/validator.d.ts +0 -7
  32. package/dist/hooks/validator.js +0 -52
  33. package/dist/index.d.ts +0 -28
  34. package/dist/index.js +0 -316
  35. package/dist/lib/asyncContext.d.ts +0 -21
  36. package/dist/lib/asyncContext.js +0 -27
  37. package/dist/lib/cacheHelper.d.ts +0 -128
  38. package/dist/lib/cacheHelper.js +0 -477
  39. package/dist/lib/cacheKeys.d.ts +0 -27
  40. package/dist/lib/cacheKeys.js +0 -37
  41. package/dist/lib/cipher.d.ts +0 -153
  42. package/dist/lib/cipher.js +0 -237
  43. package/dist/lib/connect.d.ts +0 -95
  44. package/dist/lib/connect.js +0 -313
  45. package/dist/lib/dbHelper.d.ts +0 -229
  46. package/dist/lib/dbHelper.js +0 -1069
  47. package/dist/lib/dbUtils.d.ts +0 -91
  48. package/dist/lib/dbUtils.js +0 -544
  49. package/dist/lib/jwt.d.ts +0 -13
  50. package/dist/lib/jwt.js +0 -77
  51. package/dist/lib/logger.d.ts +0 -46
  52. package/dist/lib/logger.js +0 -731
  53. package/dist/lib/redisHelper.d.ts +0 -193
  54. package/dist/lib/redisHelper.js +0 -598
  55. package/dist/lib/sqlBuilder.d.ts +0 -160
  56. package/dist/lib/sqlBuilder.js +0 -837
  57. package/dist/lib/sqlCheck.d.ts +0 -23
  58. package/dist/lib/sqlCheck.js +0 -119
  59. package/dist/lib/validator.d.ts +0 -45
  60. package/dist/lib/validator.js +0 -424
  61. package/dist/loader/loadApis.d.ts +0 -12
  62. package/dist/loader/loadApis.js +0 -71
  63. package/dist/loader/loadHooks.d.ts +0 -7
  64. package/dist/loader/loadHooks.js +0 -50
  65. package/dist/loader/loadPlugins.d.ts +0 -8
  66. package/dist/loader/loadPlugins.js +0 -69
  67. package/dist/paths.d.ts +0 -93
  68. package/dist/paths.js +0 -100
  69. package/dist/plugins/cache.d.ts +0 -10
  70. package/dist/plugins/cache.js +0 -24
  71. package/dist/plugins/cipher.d.ts +0 -7
  72. package/dist/plugins/cipher.js +0 -14
  73. package/dist/plugins/config.d.ts +0 -3
  74. package/dist/plugins/config.js +0 -9
  75. package/dist/plugins/db.d.ts +0 -10
  76. package/dist/plugins/db.js +0 -48
  77. package/dist/plugins/jwt.d.ts +0 -6
  78. package/dist/plugins/jwt.js +0 -13
  79. package/dist/plugins/logger.d.ts +0 -10
  80. package/dist/plugins/logger.js +0 -21
  81. package/dist/plugins/redis.d.ts +0 -10
  82. package/dist/plugins/redis.js +0 -40
  83. package/dist/plugins/tool.d.ts +0 -75
  84. package/dist/plugins/tool.js +0 -105
  85. package/dist/router/api.d.ts +0 -14
  86. package/dist/router/api.js +0 -109
  87. package/dist/router/static.d.ts +0 -9
  88. package/dist/router/static.js +0 -56
  89. package/dist/scripts/ensureDist.d.ts +0 -1
  90. package/dist/scripts/ensureDist.js +0 -296
  91. package/dist/sync/syncApi.d.ts +0 -3
  92. package/dist/sync/syncApi.js +0 -140
  93. package/dist/sync/syncCache.d.ts +0 -2
  94. package/dist/sync/syncCache.js +0 -14
  95. package/dist/sync/syncDev.d.ts +0 -6
  96. package/dist/sync/syncDev.js +0 -166
  97. package/dist/sync/syncMenu.d.ts +0 -14
  98. package/dist/sync/syncMenu.js +0 -308
  99. package/dist/sync/syncTable.d.ts +0 -126
  100. package/dist/sync/syncTable.js +0 -1129
  101. package/dist/types/api.d.ts +0 -175
  102. package/dist/types/api.js +0 -4
  103. package/dist/types/befly.d.ts +0 -231
  104. package/dist/types/befly.js +0 -4
  105. package/dist/types/cache.d.ts +0 -96
  106. package/dist/types/cache.js +0 -4
  107. package/dist/types/cipher.d.ts +0 -27
  108. package/dist/types/cipher.js +0 -7
  109. package/dist/types/common.d.ts +0 -127
  110. package/dist/types/common.js +0 -5
  111. package/dist/types/context.d.ts +0 -39
  112. package/dist/types/context.js +0 -4
  113. package/dist/types/coreError.d.ts +0 -31
  114. package/dist/types/coreError.js +0 -38
  115. package/dist/types/crypto.d.ts +0 -20
  116. package/dist/types/crypto.js +0 -4
  117. package/dist/types/database.d.ts +0 -182
  118. package/dist/types/database.js +0 -4
  119. package/dist/types/hook.d.ts +0 -30
  120. package/dist/types/hook.js +0 -19
  121. package/dist/types/jwt.d.ts +0 -76
  122. package/dist/types/jwt.js +0 -4
  123. package/dist/types/logger.d.ts +0 -95
  124. package/dist/types/logger.js +0 -6
  125. package/dist/types/plugin.d.ts +0 -27
  126. package/dist/types/plugin.js +0 -17
  127. package/dist/types/redis.d.ts +0 -80
  128. package/dist/types/redis.js +0 -4
  129. package/dist/types/roleApisCache.d.ts +0 -21
  130. package/dist/types/roleApisCache.js +0 -8
  131. package/dist/types/sync.d.ts +0 -93
  132. package/dist/types/sync.js +0 -4
  133. package/dist/types/table.d.ts +0 -34
  134. package/dist/types/table.js +0 -4
  135. package/dist/types/validate.d.ts +0 -113
  136. package/dist/types/validate.js +0 -4
  137. package/dist/utils/calcPerfTime.d.ts +0 -4
  138. package/dist/utils/calcPerfTime.js +0 -13
  139. package/dist/utils/cors.d.ts +0 -8
  140. package/dist/utils/cors.js +0 -17
  141. package/dist/utils/dbFieldRules.d.ts +0 -31
  142. package/dist/utils/dbFieldRules.js +0 -94
  143. package/dist/utils/fieldClear.d.ts +0 -11
  144. package/dist/utils/fieldClear.js +0 -57
  145. package/dist/utils/formatYmdHms.d.ts +0 -1
  146. package/dist/utils/formatYmdHms.js +0 -20
  147. package/dist/utils/getClientIp.d.ts +0 -6
  148. package/dist/utils/getClientIp.js +0 -39
  149. package/dist/utils/importDefault.d.ts +0 -1
  150. package/dist/utils/importDefault.js +0 -53
  151. package/dist/utils/isDirentDirectory.d.ts +0 -3
  152. package/dist/utils/isDirentDirectory.js +0 -18
  153. package/dist/utils/loadMenuConfigs.d.ts +0 -11
  154. package/dist/utils/loadMenuConfigs.js +0 -130
  155. package/dist/utils/loggerUtils.d.ts +0 -18
  156. package/dist/utils/loggerUtils.js +0 -171
  157. package/dist/utils/mergeAndConcat.d.ts +0 -7
  158. package/dist/utils/mergeAndConcat.js +0 -77
  159. package/dist/utils/normalizeFieldDefinition.d.ts +0 -18
  160. package/dist/utils/normalizeFieldDefinition.js +0 -27
  161. package/dist/utils/processInfo.d.ts +0 -26
  162. package/dist/utils/processInfo.js +0 -41
  163. package/dist/utils/response.d.ts +0 -20
  164. package/dist/utils/response.js +0 -96
  165. package/dist/utils/scanAddons.d.ts +0 -15
  166. package/dist/utils/scanAddons.js +0 -35
  167. package/dist/utils/scanCoreBuiltins.d.ts +0 -3
  168. package/dist/utils/scanCoreBuiltins.js +0 -72
  169. package/dist/utils/scanFiles.d.ts +0 -32
  170. package/dist/utils/scanFiles.js +0 -124
  171. package/dist/utils/scanSources.d.ts +0 -10
  172. package/dist/utils/scanSources.js +0 -46
  173. package/dist/utils/sortModules.d.ts +0 -28
  174. package/dist/utils/sortModules.js +0 -105
  175. package/dist/utils/sqlUtil.d.ts +0 -33
  176. package/dist/utils/sqlUtil.js +0 -146
  177. package/dist/utils/util.d.ts +0 -172
  178. package/dist/utils/util.js +0 -517
@@ -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[];
@@ -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,3 +0,0 @@
1
- import type { ScanFileResult } from "./scanFiles";
2
- export declare function scanCoreBuiltinPlugins(): ScanFileResult[];
3
- export declare function scanCoreBuiltinHooks(): ScanFileResult[];
@@ -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[]>;
@@ -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
- }
@@ -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;