befly 3.10.19 → 3.11.1
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/dist/befly.config.d.ts +1 -1
- package/dist/befly.config.js +3 -5
- package/dist/befly.js +15621 -0
- package/dist/befly.min.js +21 -0
- package/dist/checks/checkApi.js +2 -3
- package/dist/checks/checkHook.js +50 -3
- package/dist/checks/checkMenu.d.ts +2 -2
- package/dist/checks/checkMenu.js +3 -3
- package/dist/checks/checkPlugin.js +50 -3
- package/dist/checks/checkTable.d.ts +1 -1
- package/dist/checks/checkTable.js +1 -1
- package/dist/hooks/auth.d.ts +3 -1
- package/dist/hooks/auth.js +3 -1
- package/dist/hooks/cors.d.ts +3 -1
- package/dist/hooks/cors.js +3 -1
- package/dist/hooks/parser.d.ts +3 -1
- package/dist/hooks/parser.js +4 -3
- package/dist/hooks/permission.d.ts +3 -1
- package/dist/hooks/permission.js +5 -3
- package/dist/hooks/validator.d.ts +3 -1
- package/dist/hooks/validator.js +4 -2
- package/dist/{main.d.ts → index.d.ts} +1 -1
- package/dist/{main.js → index.js} +24 -24
- package/dist/lib/cacheHelper.js +2 -2
- package/dist/lib/cipher.d.ts +1 -1
- package/dist/lib/connect.d.ts +1 -1
- package/dist/lib/connect.js +1 -1
- package/dist/lib/dbHelper.d.ts +3 -3
- package/dist/lib/dbHelper.js +9 -11
- package/dist/lib/dbUtils.d.ts +1 -1
- package/dist/lib/dbUtils.js +2 -3
- package/dist/lib/jwt.d.ts +2 -2
- package/dist/lib/logger.d.ts +17 -7
- package/dist/lib/logger.js +620 -210
- package/dist/lib/redisHelper.js +2 -2
- package/dist/lib/sqlBuilder.d.ts +1 -1
- package/dist/lib/sqlBuilder.js +1 -1
- package/dist/lib/validator.d.ts +1 -1
- package/dist/lib/validator.js +1 -1
- package/dist/loader/loadApis.d.ts +2 -2
- package/dist/loader/loadApis.js +3 -3
- package/dist/loader/loadHooks.d.ts +3 -4
- package/dist/loader/loadHooks.js +6 -8
- package/dist/loader/loadPlugins.d.ts +4 -4
- package/dist/loader/loadPlugins.js +7 -7
- package/dist/plugins/cache.d.ts +4 -2
- package/dist/plugins/cache.js +3 -1
- package/dist/plugins/cipher.d.ts +3 -1
- package/dist/plugins/cipher.js +3 -1
- package/dist/plugins/config.d.ts +4 -2
- package/dist/plugins/config.js +2 -0
- package/dist/plugins/db.d.ts +4 -2
- package/dist/plugins/db.js +6 -4
- package/dist/plugins/jwt.d.ts +4 -2
- package/dist/plugins/jwt.js +3 -1
- package/dist/plugins/logger.d.ts +7 -3
- package/dist/plugins/logger.js +3 -1
- package/dist/plugins/redis.d.ts +4 -2
- package/dist/plugins/redis.js +5 -3
- package/dist/plugins/tool.d.ts +3 -1
- package/dist/plugins/tool.js +2 -0
- package/dist/router/api.d.ts +3 -3
- package/dist/router/api.js +5 -5
- package/dist/router/static.d.ts +1 -1
- package/dist/router/static.js +3 -3
- package/dist/scripts/ensureDist.js +218 -2
- package/dist/sync/syncApi.d.ts +2 -2
- package/dist/sync/syncApi.js +2 -2
- package/dist/sync/syncCache.d.ts +1 -1
- package/dist/sync/syncDev.d.ts +1 -1
- package/dist/sync/syncDev.js +2 -2
- package/dist/sync/syncMenu.d.ts +2 -2
- package/dist/sync/syncMenu.js +4 -4
- package/dist/sync/syncTable.d.ts +6 -6
- package/dist/sync/syncTable.js +4 -4
- package/dist/types/api.d.ts +4 -4
- package/dist/types/befly.d.ts +8 -12
- package/dist/types/cache.d.ts +2 -2
- package/dist/types/cipher.d.ts +1 -1
- package/dist/types/context.d.ts +1 -1
- package/dist/types/database.d.ts +1 -1
- package/dist/types/hook.d.ts +4 -2
- package/dist/types/logger.d.ts +14 -2
- package/dist/types/plugin.d.ts +3 -1
- package/dist/types/sync.d.ts +2 -2
- package/dist/utils/cors.d.ts +1 -1
- package/dist/utils/importDefault.js +1 -1
- package/dist/utils/loadMenuConfigs.d.ts +26 -2
- package/dist/utils/loadMenuConfigs.js +44 -3
- package/dist/utils/mergeAndConcat.d.ts +7 -0
- package/dist/utils/mergeAndConcat.js +72 -0
- package/dist/utils/processAtSymbol.d.ts +4 -0
- package/dist/utils/{processFields.js → processAtSymbol.js} +2 -2
- package/dist/utils/response.d.ts +1 -1
- package/dist/utils/response.js +1 -1
- package/dist/utils/scanAddons.js +3 -3
- package/dist/utils/scanConfig.js +6 -7
- package/dist/utils/scanCoreBuiltins.d.ts +3 -0
- package/dist/utils/scanCoreBuiltins.js +65 -0
- package/dist/utils/scanFiles.js +19 -6
- package/dist/utils/scanSources.d.ts +2 -2
- package/dist/utils/scanSources.js +16 -11
- package/dist/utils/sortModules.js +2 -2
- package/dist/utils/util.d.ts +84 -0
- package/dist/utils/util.js +262 -0
- package/package.json +20 -14
- package/dist/utils/arrayKeysToCamel.d.ts +0 -13
- package/dist/utils/arrayKeysToCamel.js +0 -18
- package/dist/utils/configTypes.d.ts +0 -1
- package/dist/utils/configTypes.js +0 -1
- package/dist/utils/genShortId.d.ts +0 -10
- package/dist/utils/genShortId.js +0 -12
- package/dist/utils/keysToCamel.d.ts +0 -10
- package/dist/utils/keysToCamel.js +0 -21
- package/dist/utils/keysToSnake.d.ts +0 -10
- package/dist/utils/keysToSnake.js +0 -21
- package/dist/utils/pickFields.d.ts +0 -4
- package/dist/utils/pickFields.js +0 -16
- package/dist/utils/processFields.d.ts +0 -4
- package/dist/utils/regex.d.ts +0 -145
- package/dist/utils/regex.js +0 -202
- package/dist/utils/sqlLog.d.ts +0 -14
- package/dist/utils/sqlLog.js +0 -25
- /package/dist/utils/{process.d.ts → processInfo.d.ts} +0 -0
- /package/dist/utils/{process.js → processInfo.js} +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { isPlainObject } from "./util";
|
|
2
|
+
function cloneDeepLoose(value) {
|
|
3
|
+
if (Array.isArray(value)) {
|
|
4
|
+
const arr = [];
|
|
5
|
+
for (const item of value) {
|
|
6
|
+
arr.push(cloneDeepLoose(item));
|
|
7
|
+
}
|
|
8
|
+
return arr;
|
|
9
|
+
}
|
|
10
|
+
if (isPlainObject(value)) {
|
|
11
|
+
const out = {};
|
|
12
|
+
for (const key of Object.keys(value)) {
|
|
13
|
+
out[key] = cloneDeepLoose(value[key]);
|
|
14
|
+
}
|
|
15
|
+
return out;
|
|
16
|
+
}
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
function mergeInto(target, source) {
|
|
20
|
+
if (source === undefined) {
|
|
21
|
+
return target;
|
|
22
|
+
}
|
|
23
|
+
if (Array.isArray(target) && Array.isArray(source)) {
|
|
24
|
+
for (const item of source) {
|
|
25
|
+
target.push(cloneDeepLoose(item));
|
|
26
|
+
}
|
|
27
|
+
return target;
|
|
28
|
+
}
|
|
29
|
+
if (isPlainObject(target) && isPlainObject(source)) {
|
|
30
|
+
for (const key of Object.keys(source)) {
|
|
31
|
+
const srcVal = source[key];
|
|
32
|
+
if (srcVal === undefined) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const curVal = target[key];
|
|
36
|
+
if (Array.isArray(curVal) && Array.isArray(srcVal)) {
|
|
37
|
+
const nextArr = [];
|
|
38
|
+
for (const item of curVal) {
|
|
39
|
+
nextArr.push(cloneDeepLoose(item));
|
|
40
|
+
}
|
|
41
|
+
for (const item of srcVal) {
|
|
42
|
+
nextArr.push(cloneDeepLoose(item));
|
|
43
|
+
}
|
|
44
|
+
target[key] = nextArr;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (isPlainObject(curVal) && isPlainObject(srcVal)) {
|
|
48
|
+
target[key] = mergeInto(cloneDeepLoose(curVal), srcVal);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
target[key] = cloneDeepLoose(srcVal);
|
|
52
|
+
}
|
|
53
|
+
return target;
|
|
54
|
+
}
|
|
55
|
+
return cloneDeepLoose(source);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 深度合并对象,并对数组执行 concat(保持 scanConfig 现有语义)。
|
|
59
|
+
* - undefined 会被忽略
|
|
60
|
+
* - plain object 深合并
|
|
61
|
+
* - array 与 array 合并为新数组(保持输入不被污染)
|
|
62
|
+
*/
|
|
63
|
+
export function mergeAndConcat(...items) {
|
|
64
|
+
let acc = {};
|
|
65
|
+
for (const item of items) {
|
|
66
|
+
if (item === undefined) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
acc = mergeInto(acc, item);
|
|
70
|
+
}
|
|
71
|
+
return acc;
|
|
72
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { presetFields } from "../configs/presetFields
|
|
1
|
+
import { presetFields } from "../configs/presetFields";
|
|
2
2
|
/**
|
|
3
3
|
* 处理字段定义:将 @ 符号引用替换为实际字段定义
|
|
4
4
|
*/
|
|
5
|
-
export function
|
|
5
|
+
export function processAtSymbol(fields, apiName, routePath) {
|
|
6
6
|
if (!fields || typeof fields !== "object")
|
|
7
7
|
return fields;
|
|
8
8
|
const processed = {};
|
package/dist/utils/response.d.ts
CHANGED
package/dist/utils/response.js
CHANGED
package/dist/utils/scanAddons.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { existsSync, readdirSync } from "node:fs";
|
|
2
|
-
import { camelCase } from "es-toolkit/string";
|
|
3
2
|
import { join, resolve } from "pathe";
|
|
4
|
-
import { appAddonsDir, appDir } from "../paths
|
|
5
|
-
import { isDirentDirectory } from "./isDirentDirectory
|
|
3
|
+
import { appAddonsDir, appDir } from "../paths";
|
|
4
|
+
import { isDirentDirectory } from "./isDirentDirectory";
|
|
5
|
+
import { camelCase } from "./util";
|
|
6
6
|
/** 扫描 node_modules/@befly-addon + 项目 addons/(项目优先级更高) */
|
|
7
7
|
export const scanAddons = () => {
|
|
8
8
|
const addonMap = new Map();
|
package/dist/utils/scanConfig.js
CHANGED
|
@@ -9,9 +9,8 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
9
9
|
import { existsSync } from "node:fs";
|
|
10
10
|
import { isAbsolute, join } from "node:path";
|
|
11
11
|
import { pathToFileURL } from "node:url";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { mergeAndConcat } from "merge-anything";
|
|
12
|
+
import { mergeAndConcat } from "./mergeAndConcat";
|
|
13
|
+
import { getByPath, isPlainObject, setByPath } from "./util";
|
|
15
14
|
/**
|
|
16
15
|
* 扫描并合并配置文件(矩阵搜索:dirs × files)
|
|
17
16
|
* @param options - 加载选项
|
|
@@ -68,9 +67,9 @@ export async function scanConfig(options) {
|
|
|
68
67
|
if (paths && paths.length > 0) {
|
|
69
68
|
const result = {};
|
|
70
69
|
for (const path of paths) {
|
|
71
|
-
const value =
|
|
70
|
+
const value = getByPath(firstConfig, path);
|
|
72
71
|
if (value !== undefined) {
|
|
73
|
-
|
|
72
|
+
setByPath(result, path, value);
|
|
74
73
|
}
|
|
75
74
|
}
|
|
76
75
|
return result;
|
|
@@ -94,9 +93,9 @@ export async function scanConfig(options) {
|
|
|
94
93
|
if (paths && paths.length > 0) {
|
|
95
94
|
const result = {};
|
|
96
95
|
for (const path of paths) {
|
|
97
|
-
const value =
|
|
96
|
+
const value = getByPath(finalConfig, path);
|
|
98
97
|
if (value !== undefined) {
|
|
99
|
-
|
|
98
|
+
setByPath(result, path, value);
|
|
100
99
|
}
|
|
101
100
|
}
|
|
102
101
|
return result;
|
|
@@ -0,0 +1,65 @@
|
|
|
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
|
+
function toCoreBuiltinScanFileResult(type, item) {
|
|
15
|
+
const name = item.name;
|
|
16
|
+
return {
|
|
17
|
+
source: "core",
|
|
18
|
+
type: type,
|
|
19
|
+
sourceName: "核心",
|
|
20
|
+
filePath: `core:${type}:${name}`,
|
|
21
|
+
relativePath: name,
|
|
22
|
+
fileName: name,
|
|
23
|
+
moduleName: name,
|
|
24
|
+
addonName: "",
|
|
25
|
+
fileBaseName: name,
|
|
26
|
+
fileDir: "(builtin)",
|
|
27
|
+
name: name,
|
|
28
|
+
enable: item ? item.enable : undefined,
|
|
29
|
+
deps: Array.isArray(item && item.deps) ? item.deps : [],
|
|
30
|
+
handler: item ? item.handler : null
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export function scanCoreBuiltinPlugins() {
|
|
34
|
+
const plugins = [];
|
|
35
|
+
const builtinPlugins = [
|
|
36
|
+
//
|
|
37
|
+
corePluginLogger,
|
|
38
|
+
corePluginRedis,
|
|
39
|
+
corePluginDb,
|
|
40
|
+
corePluginCache,
|
|
41
|
+
corePluginTool,
|
|
42
|
+
corePluginCipher,
|
|
43
|
+
corePluginJwt,
|
|
44
|
+
corePluginConfig
|
|
45
|
+
];
|
|
46
|
+
for (const plugin of builtinPlugins) {
|
|
47
|
+
plugins.push(toCoreBuiltinScanFileResult("plugin", plugin));
|
|
48
|
+
}
|
|
49
|
+
return plugins;
|
|
50
|
+
}
|
|
51
|
+
export function scanCoreBuiltinHooks() {
|
|
52
|
+
const hooks = [];
|
|
53
|
+
const builtinHooks = [
|
|
54
|
+
//
|
|
55
|
+
coreHookAuth,
|
|
56
|
+
coreHookCors,
|
|
57
|
+
coreHookParser,
|
|
58
|
+
coreHookValidator,
|
|
59
|
+
coreHookPermission
|
|
60
|
+
];
|
|
61
|
+
for (const hook of builtinHooks) {
|
|
62
|
+
hooks.push(toCoreBuiltinScanFileResult("hook", hook));
|
|
63
|
+
}
|
|
64
|
+
return hooks;
|
|
65
|
+
}
|
package/dist/utils/scanFiles.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
-
import { forOwn } from "es-toolkit/compat";
|
|
3
|
-
import { camelCase } from "es-toolkit/string";
|
|
4
2
|
import { relative, normalize, parse, join } from "pathe";
|
|
5
|
-
import { importDefault } from "./importDefault
|
|
3
|
+
import { importDefault } from "./importDefault";
|
|
4
|
+
import { camelCase, forOwn } from "./util";
|
|
6
5
|
function parseAddonNameFromPath(normalizedPath) {
|
|
7
6
|
// 期望路径中包含:/node_modules/@befly-addon/<addonName>/...
|
|
8
7
|
const parts = normalizedPath.split("/").filter(Boolean);
|
|
@@ -14,6 +13,18 @@ function parseAddonNameFromPath(normalizedPath) {
|
|
|
14
13
|
return null;
|
|
15
14
|
return addonName;
|
|
16
15
|
}
|
|
16
|
+
function parseLocalAddonNameFromPath(normalizedPath) {
|
|
17
|
+
// 兼容项目本地 addons:/addons/<addonName>/...
|
|
18
|
+
// 注意:normalizedPath 已通过 pathe.normalize 统一为 /
|
|
19
|
+
const parts = normalizedPath.split("/").filter(Boolean);
|
|
20
|
+
const idx = parts.lastIndexOf("addons");
|
|
21
|
+
if (idx < 0)
|
|
22
|
+
return null;
|
|
23
|
+
const addonName = parts[idx + 1];
|
|
24
|
+
if (typeof addonName !== "string" || addonName.trim() === "")
|
|
25
|
+
return null;
|
|
26
|
+
return addonName;
|
|
27
|
+
}
|
|
17
28
|
/**
|
|
18
29
|
* 扫描指定目录下的文件
|
|
19
30
|
* @param dir 目录路径
|
|
@@ -55,13 +66,15 @@ export async function scanFiles(dir, source, type, pattern) {
|
|
|
55
66
|
let addonName = "";
|
|
56
67
|
let moduleName = "";
|
|
57
68
|
if (source === "core") {
|
|
58
|
-
moduleName
|
|
69
|
+
// core:不做任何命名转换,直接使用文件名作为 moduleName(例如 auth / rate_limit)。
|
|
70
|
+
addonName = "";
|
|
71
|
+
moduleName = fileName;
|
|
59
72
|
}
|
|
60
73
|
else if (source === "app") {
|
|
61
74
|
moduleName = `app_${baseName}`;
|
|
62
75
|
}
|
|
63
76
|
else {
|
|
64
|
-
const parsedAddonName = parseAddonNameFromPath(normalizedFile);
|
|
77
|
+
const parsedAddonName = parseAddonNameFromPath(normalizedFile) || parseLocalAddonNameFromPath(normalizedFile);
|
|
65
78
|
if (!parsedAddonName) {
|
|
66
79
|
throw new Error(`scanFiles addon moduleName 解析失败:未找到 @befly-addon/<addon>/ 段落:${normalizedFile}`);
|
|
67
80
|
}
|
|
@@ -101,7 +114,7 @@ export async function scanFiles(dir, source, type, pattern) {
|
|
|
101
114
|
base[key] = value;
|
|
102
115
|
});
|
|
103
116
|
if (type === "api") {
|
|
104
|
-
base.routePrefix = source === "
|
|
117
|
+
base.routePrefix = source === "app" ? "/app" : `/addon/${addonName}`;
|
|
105
118
|
base.routePath = `/api${base.routePrefix}/${relativePath}`;
|
|
106
119
|
}
|
|
107
120
|
results.push(base);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AddonInfo } from "./scanAddons
|
|
2
|
-
import type { ScanFileResult } from "./scanFiles
|
|
1
|
+
import type { AddonInfo } from "./scanAddons";
|
|
2
|
+
import type { ScanFileResult } from "./scanFiles";
|
|
3
3
|
export type ScanSourcesResult = {
|
|
4
4
|
hooks: ScanFileResult[];
|
|
5
5
|
plugins: ScanFileResult[];
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { join } from "pathe";
|
|
2
|
-
import {
|
|
3
|
-
import { scanAddons } from "./scanAddons
|
|
4
|
-
import {
|
|
2
|
+
import { appDir } from "../paths";
|
|
3
|
+
import { scanAddons } from "./scanAddons";
|
|
4
|
+
import { scanCoreBuiltinHooks, scanCoreBuiltinPlugins } from "./scanCoreBuiltins";
|
|
5
|
+
import { scanFiles } from "./scanFiles";
|
|
5
6
|
export const scanSources = async () => {
|
|
6
7
|
const apis = [];
|
|
7
8
|
const plugins = [];
|
|
@@ -14,23 +15,27 @@ export const scanSources = async () => {
|
|
|
14
15
|
tables.push(...(await scanFiles(join(addon.fullPath, "tables"), "addon", "table", "*.json")));
|
|
15
16
|
}
|
|
16
17
|
// 处理插件
|
|
17
|
-
|
|
18
|
+
// core 内置插件:必须静态导入(支持 bun bundle 单文件)。
|
|
19
|
+
// 约束:core 插件名由 export default.name 指定。
|
|
20
|
+
plugins.push(...scanCoreBuiltinPlugins());
|
|
18
21
|
plugins.push(...(await scanFiles(join(appDir, "plugins"), "app", "plugin", "*.{ts,js}")));
|
|
19
22
|
for (const addon of addons) {
|
|
20
23
|
plugins.push(...(await scanFiles(join(addon.fullPath, "plugins"), "addon", "plugin", "*.{ts,js}")));
|
|
21
24
|
}
|
|
22
|
-
// 处理接口
|
|
23
|
-
apis.push(...(await scanFiles(join(coreDistDir, "apis"), "core", "api", "**/*.js")));
|
|
24
|
-
apis.push(...(await scanFiles(join(appDir, "apis"), "app", "api", "**/*.{ts,js}")));
|
|
25
|
-
for (const addon of addons) {
|
|
26
|
-
apis.push(...(await scanFiles(join(addon.fullPath, "apis"), "addon", "api", "**/*.{ts,js}")));
|
|
27
|
-
}
|
|
28
25
|
// 处理钩子
|
|
29
|
-
|
|
26
|
+
// core 内置钩子:必须静态导入(支持 bun bundle 单文件)。
|
|
27
|
+
// 约束:core 钩子名由 export default.name 指定。
|
|
28
|
+
hooks.push(...scanCoreBuiltinHooks());
|
|
30
29
|
hooks.push(...(await scanFiles(join(appDir, "hooks"), "app", "hook", "*.{ts,js}")));
|
|
31
30
|
for (const addon of addons) {
|
|
32
31
|
hooks.push(...(await scanFiles(join(addon.fullPath, "hooks"), "addon", "hook", "*.{ts,js}")));
|
|
33
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.fullPath, "apis"), "addon", "api", "**/*.{ts,js}")));
|
|
38
|
+
}
|
|
34
39
|
return {
|
|
35
40
|
hooks: hooks,
|
|
36
41
|
plugins: plugins,
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 注意:本文件用于集中维护 core 内部通用 utils。
|
|
3
|
+
* - 按项目规范:避免零散小文件噪音;实现集中在本文件,而不是做 re-export 聚合。
|
|
4
|
+
* - 仅在 packages/core 内部使用;core 对外不承诺这些路径导出。
|
|
5
|
+
*/
|
|
6
|
+
export declare function isPlainObject(value: unknown): value is Record<string, any>;
|
|
7
|
+
/**
|
|
8
|
+
* 激进空值判断(项目约定):
|
|
9
|
+
* - null/undefined => empty
|
|
10
|
+
* - "" / 全空白字符串 => empty
|
|
11
|
+
* - 0 / NaN => empty
|
|
12
|
+
* - false => empty
|
|
13
|
+
* - Array => length === 0
|
|
14
|
+
* - Map/Set => size === 0
|
|
15
|
+
* - plain object => 无自有 key
|
|
16
|
+
* - 其他类型 => false
|
|
17
|
+
*/
|
|
18
|
+
export declare function isEmpty(value: unknown): boolean;
|
|
19
|
+
export declare function forOwn(obj: unknown, iteratee: (value: any, key: string) => void): void;
|
|
20
|
+
/**
|
|
21
|
+
* 把字符串转为小驼峰。
|
|
22
|
+
* - 主要用于文件名/目录名(例如 my_plugin / my-plugin / my plugin)。
|
|
23
|
+
*/
|
|
24
|
+
export declare function camelCase(input: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* 把字符串转为 snake_case。
|
|
27
|
+
* - 主要用于表名/字段名(例如 userId -> user_id)。
|
|
28
|
+
*/
|
|
29
|
+
export declare function snakeCase(input: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* 对象字段名转小驼峰
|
|
32
|
+
* @param obj - 源对象
|
|
33
|
+
* @returns 字段名转为小驼峰格式的新对象
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* keysToCamel({ user_id: 123, user_name: 'John' }) // { userId: 123, userName: 'John' }
|
|
37
|
+
* keysToCamel({ created_at: 1697452800000 }) // { createdAt: 1697452800000 }
|
|
38
|
+
*/
|
|
39
|
+
export declare const keysToCamel: <T = any>(obj: Record<string, any>) => T;
|
|
40
|
+
/**
|
|
41
|
+
* 对象字段名转下划线
|
|
42
|
+
* @param obj - 源对象
|
|
43
|
+
* @returns 字段名转为下划线格式的新对象
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* keysToSnake({ userId: 123, userName: 'John' }) // { user_id: 123, user_name: 'John' }
|
|
47
|
+
* keysToSnake({ createdAt: 1697452800000 }) // { created_at: 1697452800000 }
|
|
48
|
+
*/
|
|
49
|
+
export declare const keysToSnake: <T = any>(obj: Record<string, any>) => T;
|
|
50
|
+
/**
|
|
51
|
+
* 数组对象字段名批量转小驼峰
|
|
52
|
+
* @param arr - 源数组
|
|
53
|
+
* @returns 字段名转为小驼峰格式的新数组
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* arrayKeysToCamel([
|
|
57
|
+
* { user_id: 1, user_name: 'John' },
|
|
58
|
+
* { user_id: 2, user_name: 'Jane' }
|
|
59
|
+
* ])
|
|
60
|
+
* // [{ userId: 1, userName: 'John' }, { userId: 2, userName: 'Jane' }]
|
|
61
|
+
*/
|
|
62
|
+
export declare const arrayKeysToCamel: <T = any>(arr: Record<string, any>[]) => T[];
|
|
63
|
+
export declare function getByPath(obj: unknown, path: string): unknown;
|
|
64
|
+
export declare function setByPath(target: Record<string, any>, path: string, value: unknown): void;
|
|
65
|
+
/**
|
|
66
|
+
* 返回一个移除指定 key 的浅拷贝。
|
|
67
|
+
* - 仅处理 plain object;其他类型返回空对象,避免日志场景抛错。
|
|
68
|
+
*/
|
|
69
|
+
export declare function omit<T extends Record<string, any>>(obj: unknown, keys: string[]): Partial<T>;
|
|
70
|
+
/**
|
|
71
|
+
* 挑选指定字段
|
|
72
|
+
*/
|
|
73
|
+
export declare const pickFields: <T extends Record<string, any>>(obj: T, keys: string[]) => Partial<T>;
|
|
74
|
+
export declare function keyBy<T>(items: T[], getKey: (item: T) => string): Record<string, T>;
|
|
75
|
+
/**
|
|
76
|
+
* 生成短 ID
|
|
77
|
+
* 由时间戳(base36)+ 随机字符组成,约 13 位
|
|
78
|
+
* - 前 8 位:时间戳(可排序)
|
|
79
|
+
* - 后 5 位:随机字符(防冲突)
|
|
80
|
+
* @returns 短 ID 字符串
|
|
81
|
+
* @example
|
|
82
|
+
* genShortId() // "lxyz1a2b3c4"
|
|
83
|
+
*/
|
|
84
|
+
export declare function genShortId(): string;
|