befly 3.10.17 → 3.10.19
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 +83 -307
- package/dist/befly.config.d.ts +7 -0
- package/{befly.config.ts → dist/befly.config.js} +8 -31
- package/dist/checks/checkApi.d.ts +1 -0
- package/{checks/checkApi.ts → dist/checks/checkApi.js} +10 -27
- package/dist/checks/checkHook.d.ts +1 -0
- package/{checks/checkHook.ts → dist/checks/checkHook.js} +10 -19
- package/dist/checks/checkMenu.d.ts +7 -0
- package/{checks/checkMenu.ts → dist/checks/checkMenu.js} +15 -50
- package/dist/checks/checkPlugin.d.ts +1 -0
- package/{checks/checkPlugin.ts → dist/checks/checkPlugin.js} +10 -19
- package/dist/checks/checkTable.d.ts +6 -0
- package/{checks/checkTable.ts → dist/checks/checkTable.js} +16 -40
- package/dist/configs/presetFields.d.ts +4 -0
- package/{configs/presetFields.ts → dist/configs/presetFields.js} +1 -1
- package/dist/configs/presetRegexp.d.ts +145 -0
- package/{utils/regex.ts → dist/configs/presetRegexp.js} +8 -31
- package/dist/hooks/auth.d.ts +5 -0
- package/{hooks/auth.ts → dist/hooks/auth.js} +5 -9
- package/dist/hooks/cors.d.ts +9 -0
- package/{hooks/cors.ts → dist/hooks/cors.js} +2 -12
- package/dist/hooks/parser.d.ts +12 -0
- package/{hooks/parser.ts → dist/hooks/parser.js} +27 -42
- package/dist/hooks/permission.d.ts +12 -0
- package/{hooks/permission.ts → dist/hooks/permission.js} +11 -22
- package/dist/hooks/validator.d.ts +9 -0
- package/{hooks/validator.ts → dist/hooks/validator.js} +5 -12
- package/dist/lib/asyncContext.d.ts +21 -0
- package/dist/lib/asyncContext.js +27 -0
- package/dist/lib/cacheHelper.d.ts +95 -0
- package/{lib/cacheHelper.ts → dist/lib/cacheHelper.js} +43 -103
- package/dist/lib/cacheKeys.d.ts +23 -0
- package/{lib/cacheKeys.ts → dist/lib/cacheKeys.js} +5 -10
- package/dist/lib/cipher.d.ts +153 -0
- package/{lib/cipher.ts → dist/lib/cipher.js} +23 -44
- package/dist/lib/connect.d.ts +91 -0
- package/{lib/connect.ts → dist/lib/connect.js} +46 -87
- package/dist/lib/dbDialect.d.ts +87 -0
- package/{lib/dbDialect.ts → dist/lib/dbDialect.js} +32 -112
- package/dist/lib/dbHelper.d.ts +204 -0
- package/{lib/dbHelper.ts → dist/lib/dbHelper.js} +73 -230
- package/dist/lib/dbUtils.d.ts +68 -0
- package/{lib/dbUtils.ts → dist/lib/dbUtils.js} +49 -123
- package/dist/lib/jwt.d.ts +13 -0
- package/{lib/jwt.ts → dist/lib/jwt.js} +11 -32
- package/dist/lib/logger.d.ts +32 -0
- package/{lib/logger.ts → dist/lib/logger.js} +201 -278
- package/dist/lib/redisHelper.d.ts +185 -0
- package/{lib/redisHelper.ts → dist/lib/redisHelper.js} +95 -139
- package/dist/lib/sqlBuilder.d.ts +160 -0
- package/{lib/sqlBuilder.ts → dist/lib/sqlBuilder.js} +131 -277
- package/dist/lib/sqlCheck.d.ts +23 -0
- package/{lib/sqlCheck.ts → dist/lib/sqlCheck.js} +24 -41
- package/dist/lib/validator.d.ts +45 -0
- package/{lib/validator.ts → dist/lib/validator.js} +43 -60
- package/dist/loader/loadApis.d.ts +12 -0
- package/{loader/loadApis.ts → dist/loader/loadApis.js} +7 -17
- package/dist/loader/loadHooks.d.ts +8 -0
- package/{loader/loadHooks.ts → dist/loader/loadHooks.js} +5 -19
- package/dist/loader/loadPlugins.d.ts +8 -0
- package/{loader/loadPlugins.ts → dist/loader/loadPlugins.js} +8 -20
- package/dist/main.d.ts +26 -0
- package/{main.ts → dist/main.js} +39 -78
- package/dist/paths.d.ts +93 -0
- package/{paths.ts → dist/paths.js} +6 -19
- package/dist/plugins/cache.d.ts +14 -0
- package/{plugins/cache.ts → dist/plugins/cache.js} +4 -11
- package/dist/plugins/cipher.d.ts +10 -0
- package/{plugins/cipher.ts → dist/plugins/cipher.js} +1 -5
- package/dist/plugins/config.d.ts +10 -0
- package/dist/plugins/config.js +6 -0
- package/dist/plugins/db.d.ts +14 -0
- package/{plugins/db.ts → dist/plugins/db.js} +5 -13
- package/dist/plugins/jwt.d.ts +10 -0
- package/{plugins/jwt.ts → dist/plugins/jwt.js} +2 -7
- package/dist/plugins/logger.d.ts +28 -0
- package/{plugins/logger.ts → dist/plugins/logger.js} +2 -7
- package/dist/plugins/redis.d.ts +14 -0
- package/{plugins/redis.ts → dist/plugins/redis.js} +4 -9
- package/dist/plugins/tool.d.ts +79 -0
- package/{plugins/tool.ts → dist/plugins/tool.js} +7 -30
- package/dist/router/api.d.ts +14 -0
- package/dist/router/api.js +107 -0
- package/dist/router/static.d.ts +9 -0
- package/{router/static.ts → dist/router/static.js} +17 -31
- package/dist/scripts/ensureDist.d.ts +1 -0
- package/dist/scripts/ensureDist.js +80 -0
- package/dist/sync/syncApi.d.ts +3 -0
- package/{sync/syncApi.ts → dist/sync/syncApi.js} +33 -53
- package/dist/sync/syncCache.d.ts +2 -0
- package/{sync/syncCache.ts → dist/sync/syncCache.js} +1 -6
- package/dist/sync/syncDev.d.ts +6 -0
- package/{sync/syncDev.ts → dist/sync/syncDev.js} +27 -60
- package/dist/sync/syncMenu.d.ts +14 -0
- package/{sync/syncMenu.ts → dist/sync/syncMenu.js} +61 -121
- package/dist/sync/syncTable.d.ts +151 -0
- package/{sync/syncTable.ts → dist/sync/syncTable.js} +168 -375
- package/{types → dist/types}/api.d.ts +12 -51
- package/dist/types/api.js +4 -0
- package/{types → dist/types}/befly.d.ts +32 -223
- package/dist/types/befly.js +4 -0
- package/{types → dist/types}/cache.d.ts +7 -15
- package/dist/types/cache.js +4 -0
- package/dist/types/cipher.d.ts +27 -0
- package/dist/types/cipher.js +7 -0
- package/{types → dist/types}/common.d.ts +8 -33
- package/dist/types/common.js +5 -0
- package/{types → dist/types}/context.d.ts +3 -5
- package/dist/types/context.js +4 -0
- package/{types → dist/types}/crypto.d.ts +0 -3
- package/dist/types/crypto.js +4 -0
- package/dist/types/database.d.ts +138 -0
- package/dist/types/database.js +4 -0
- package/dist/types/hook.d.ts +15 -0
- package/dist/types/hook.js +6 -0
- package/dist/types/jwt.d.ts +75 -0
- package/dist/types/jwt.js +4 -0
- package/dist/types/logger.d.ts +47 -0
- package/dist/types/logger.js +6 -0
- package/dist/types/plugin.d.ts +14 -0
- package/dist/types/plugin.js +6 -0
- package/dist/types/redis.d.ts +71 -0
- package/dist/types/redis.js +4 -0
- package/{types/roleApisCache.ts → dist/types/roleApisCache.d.ts} +0 -2
- package/dist/types/roleApisCache.js +8 -0
- package/dist/types/sync.d.ts +92 -0
- package/dist/types/sync.js +4 -0
- package/dist/types/table.d.ts +34 -0
- package/dist/types/table.js +4 -0
- package/dist/types/validate.d.ts +67 -0
- package/dist/types/validate.js +4 -0
- package/dist/utils/arrayKeysToCamel.d.ts +13 -0
- package/{utils/arrayKeysToCamel.ts → dist/utils/arrayKeysToCamel.js} +4 -4
- package/dist/utils/calcPerfTime.d.ts +4 -0
- package/{utils/calcPerfTime.ts → dist/utils/calcPerfTime.js} +3 -3
- package/dist/utils/configTypes.d.ts +1 -0
- package/dist/utils/configTypes.js +1 -0
- package/dist/utils/convertBigIntFields.d.ts +11 -0
- package/{utils/convertBigIntFields.ts → dist/utils/convertBigIntFields.js} +5 -9
- package/dist/utils/cors.d.ts +8 -0
- package/{utils/cors.ts → dist/utils/cors.js} +1 -3
- package/dist/utils/disableMenusGlob.d.ts +13 -0
- package/{utils/disableMenusGlob.ts → dist/utils/disableMenusGlob.js} +9 -29
- package/dist/utils/fieldClear.d.ts +11 -0
- package/{utils/fieldClear.ts → dist/utils/fieldClear.js} +15 -33
- package/dist/utils/genShortId.d.ts +10 -0
- package/{utils/genShortId.ts → dist/utils/genShortId.js} +1 -1
- package/dist/utils/getClientIp.d.ts +6 -0
- package/{utils/getClientIp.ts → dist/utils/getClientIp.js} +1 -7
- package/dist/utils/importDefault.d.ts +1 -0
- package/dist/utils/importDefault.js +29 -0
- package/dist/utils/isDirentDirectory.d.ts +2 -0
- package/{utils/isDirentDirectory.ts → dist/utils/isDirentDirectory.js} +3 -8
- package/dist/utils/keysToCamel.d.ts +10 -0
- package/{utils/keysToCamel.ts → dist/utils/keysToCamel.js} +4 -5
- package/dist/utils/keysToSnake.d.ts +10 -0
- package/{utils/keysToSnake.ts → dist/utils/keysToSnake.js} +4 -5
- package/dist/utils/loadMenuConfigs.d.ts +5 -0
- package/{utils/loadMenuConfigs.ts → dist/utils/loadMenuConfigs.js} +22 -49
- package/dist/utils/pickFields.d.ts +4 -0
- package/{utils/pickFields.ts → dist/utils/pickFields.js} +2 -5
- package/dist/utils/process.d.ts +24 -0
- package/{utils/process.ts → dist/utils/process.js} +2 -18
- package/dist/utils/processFields.d.ts +4 -0
- package/{utils/processFields.ts → dist/utils/processFields.js} +4 -8
- package/dist/utils/regex.d.ts +145 -0
- package/{configs/presetRegexp.ts → dist/utils/regex.js} +8 -31
- package/dist/utils/response.d.ts +20 -0
- package/{utils/response.ts → dist/utils/response.js} +27 -48
- package/dist/utils/scanAddons.d.ts +17 -0
- package/{utils/scanAddons.ts → dist/utils/scanAddons.js} +4 -38
- package/dist/utils/scanConfig.d.ts +26 -0
- package/{utils/scanConfig.ts → dist/utils/scanConfig.js} +22 -59
- package/dist/utils/scanFiles.d.ts +30 -0
- package/{utils/scanFiles.ts → dist/utils/scanFiles.js} +25 -65
- package/dist/utils/scanSources.d.ts +10 -0
- package/{utils/scanSources.ts → dist/utils/scanSources.js} +16 -39
- package/dist/utils/sortModules.d.ts +28 -0
- package/{utils/sortModules.ts → dist/utils/sortModules.js} +24 -64
- package/dist/utils/sqlLog.d.ts +14 -0
- package/{utils/sqlLog.ts → dist/utils/sqlLog.js} +2 -14
- package/package.json +15 -32
- package/.gitignore +0 -0
- package/bunfig.toml +0 -3
- package/docs/README.md +0 -98
- package/docs/api/api.md +0 -1921
- package/docs/guide/examples.md +0 -926
- package/docs/guide/quickstart.md +0 -354
- package/docs/hooks/auth.md +0 -38
- package/docs/hooks/cors.md +0 -28
- package/docs/hooks/hook.md +0 -838
- package/docs/hooks/parser.md +0 -19
- package/docs/hooks/rateLimit.md +0 -47
- package/docs/infra/redis.md +0 -628
- package/docs/plugins/cipher.md +0 -61
- package/docs/plugins/database.md +0 -189
- package/docs/plugins/plugin.md +0 -986
- package/docs/reference/addon.md +0 -510
- package/docs/reference/config.md +0 -573
- package/docs/reference/logger.md +0 -495
- package/docs/reference/sync.md +0 -478
- package/docs/reference/table.md +0 -763
- package/docs/reference/validator.md +0 -620
- package/lib/asyncContext.ts +0 -43
- package/plugins/config.ts +0 -13
- package/router/api.ts +0 -130
- package/tsconfig.json +0 -54
- package/types/database.d.ts +0 -541
- package/types/hook.d.ts +0 -25
- package/types/jwt.d.ts +0 -118
- package/types/logger.d.ts +0 -65
- package/types/plugin.d.ts +0 -19
- package/types/redis.d.ts +0 -83
- package/types/sync.d.ts +0 -398
- package/types/table.d.ts +0 -216
- package/types/validate.d.ts +0 -69
- package/utils/configTypes.ts +0 -3
- package/utils/importDefault.ts +0 -21
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* JWT 插件
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
import type { BeflyContext } from "../types/befly.js";
|
|
6
|
-
import type { Plugin } from "../types/plugin.js";
|
|
7
|
-
|
|
8
4
|
import { Jwt } from "../lib/jwt.js";
|
|
9
|
-
|
|
10
5
|
export default {
|
|
11
6
|
deps: [],
|
|
12
|
-
handler: (context
|
|
7
|
+
handler: (context) => {
|
|
13
8
|
return new Jwt(context.config ? context.config.auth : undefined);
|
|
14
9
|
}
|
|
15
|
-
}
|
|
10
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 日志插件
|
|
3
|
+
* 提供全局日志功能
|
|
4
|
+
*/
|
|
5
|
+
import type { BeflyContext } from "../types/befly.ts";
|
|
6
|
+
/**
|
|
7
|
+
* 日志插件
|
|
8
|
+
*/
|
|
9
|
+
declare const _default: {
|
|
10
|
+
deps: never[];
|
|
11
|
+
handler(context: BeflyContext): Promise<{
|
|
12
|
+
info(...args: [] | [msg: string, ...args: unknown[]] | [msg: string, err: Error, ...args: unknown[]] | [err: Error, msg?: string | undefined, ...args: unknown[]] | [obj: {
|
|
13
|
+
[x: string]: any;
|
|
14
|
+
}, msg?: string | undefined, ...args: unknown[]]): any;
|
|
15
|
+
warn(...args: [] | [msg: string, ...args: unknown[]] | [msg: string, err: Error, ...args: unknown[]] | [err: Error, msg?: string | undefined, ...args: unknown[]] | [obj: {
|
|
16
|
+
[x: string]: any;
|
|
17
|
+
}, msg?: string | undefined, ...args: unknown[]]): any;
|
|
18
|
+
error(...args: [] | [msg: string, ...args: unknown[]] | [msg: string, err: Error, ...args: unknown[]] | [err: Error, msg?: string | undefined, ...args: unknown[]] | [obj: {
|
|
19
|
+
[x: string]: any;
|
|
20
|
+
}, msg?: string | undefined, ...args: unknown[]]): any;
|
|
21
|
+
debug(...args: [] | [msg: string, ...args: unknown[]] | [msg: string, err: Error, ...args: unknown[]] | [err: Error, msg?: string | undefined, ...args: unknown[]] | [obj: {
|
|
22
|
+
[x: string]: any;
|
|
23
|
+
}, msg?: string | undefined, ...args: unknown[]]): any;
|
|
24
|
+
configure: typeof import("../lib/logger.ts").configure;
|
|
25
|
+
setMock: typeof import("../lib/logger.ts").setMockLogger;
|
|
26
|
+
}>;
|
|
27
|
+
};
|
|
28
|
+
export default _default;
|
|
@@ -2,22 +2,17 @@
|
|
|
2
2
|
* 日志插件
|
|
3
3
|
* 提供全局日志功能
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
|
-
import type { BeflyContext } from "../types/befly.js";
|
|
7
|
-
import type { Plugin } from "../types/plugin.js";
|
|
8
|
-
|
|
9
5
|
import { Logger } from "../lib/logger.js";
|
|
10
|
-
|
|
11
6
|
/**
|
|
12
7
|
* 日志插件
|
|
13
8
|
*/
|
|
14
9
|
export default {
|
|
15
10
|
deps: [],
|
|
16
|
-
async handler(context
|
|
11
|
+
async handler(context) {
|
|
17
12
|
// 配置 Logger
|
|
18
13
|
if (context.config && context.config.logger) {
|
|
19
14
|
Logger.configure(context.config.logger);
|
|
20
15
|
}
|
|
21
16
|
return Logger;
|
|
22
17
|
}
|
|
23
|
-
}
|
|
18
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redis 插件
|
|
3
|
+
* 初始化 Redis 连接和助手工具
|
|
4
|
+
*/
|
|
5
|
+
import type { BeflyContext } from "../types/befly.ts";
|
|
6
|
+
import { RedisHelper } from "../lib/redisHelper.ts";
|
|
7
|
+
/**
|
|
8
|
+
* Redis 插件
|
|
9
|
+
*/
|
|
10
|
+
declare const _default: {
|
|
11
|
+
deps: string[];
|
|
12
|
+
handler(context: BeflyContext): Promise<Record<string, never> | RedisHelper>;
|
|
13
|
+
};
|
|
14
|
+
export default _default;
|
|
@@ -2,30 +2,25 @@
|
|
|
2
2
|
* Redis 插件
|
|
3
3
|
* 初始化 Redis 连接和助手工具
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
|
-
import type { BeflyContext } from "../types/befly.js";
|
|
7
|
-
import type { Plugin } from "../types/plugin.js";
|
|
8
|
-
|
|
9
5
|
import { Connect } from "../lib/connect.js";
|
|
10
6
|
import { Logger } from "../lib/logger.js";
|
|
11
7
|
import { RedisHelper } from "../lib/redisHelper.js";
|
|
12
|
-
|
|
13
8
|
/**
|
|
14
9
|
* Redis 插件
|
|
15
10
|
*/
|
|
16
11
|
export default {
|
|
17
12
|
deps: ["logger"],
|
|
18
|
-
async handler(context
|
|
13
|
+
async handler(context) {
|
|
19
14
|
const redisConfig = context.config && context.config.redis ? context.config.redis : {};
|
|
20
15
|
try {
|
|
21
16
|
// 启动期已建立 Redis 连接;这里仅校验连接存在
|
|
22
17
|
Connect.getRedis();
|
|
23
|
-
|
|
24
18
|
// 返回 RedisHelper 实例
|
|
25
19
|
return new RedisHelper(redisConfig.prefix);
|
|
26
|
-
}
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
27
22
|
Logger.error({ err: error }, "Redis 初始化失败");
|
|
28
23
|
throw error;
|
|
29
24
|
}
|
|
30
25
|
}
|
|
31
|
-
}
|
|
26
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 工具插件
|
|
3
|
+
* 提供常用的工具函数
|
|
4
|
+
*/
|
|
5
|
+
import type { RequestContext } from "../types/context.ts";
|
|
6
|
+
/**
|
|
7
|
+
* 成功响应
|
|
8
|
+
* @param msg - 消息
|
|
9
|
+
* @param data - 数据(可选)
|
|
10
|
+
* @param other - 其他字段(可选)
|
|
11
|
+
* @returns 成功响应对象
|
|
12
|
+
*/
|
|
13
|
+
export declare function Yes(msg: string, data?: any, other?: Record<string, any>): {
|
|
14
|
+
code: number;
|
|
15
|
+
msg: string;
|
|
16
|
+
data: any;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* 失败响应
|
|
20
|
+
* @param msg - 消息
|
|
21
|
+
* @param data - 数据(可选)
|
|
22
|
+
* @param other - 其他字段(可选)
|
|
23
|
+
* @returns 失败响应对象
|
|
24
|
+
*/
|
|
25
|
+
export declare function No(msg: string, data?: any, other?: Record<string, any>): {
|
|
26
|
+
code: number;
|
|
27
|
+
msg: string;
|
|
28
|
+
data: any;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* 响应选项
|
|
32
|
+
*/
|
|
33
|
+
interface ResponseOptions {
|
|
34
|
+
/** HTTP 状态码,默认 200 */
|
|
35
|
+
status?: number;
|
|
36
|
+
/** Content-Type,默认根据 data 类型自动判断 */
|
|
37
|
+
contentType?: string;
|
|
38
|
+
/** 额外的响应头 */
|
|
39
|
+
headers?: Record<string, string>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 统一响应函数
|
|
43
|
+
*
|
|
44
|
+
* 自动识别数据类型并设置正确的 Content-Type:
|
|
45
|
+
* - 对象 → application/json
|
|
46
|
+
* - 字符串 → text/plain
|
|
47
|
+
* - 可通过 options.contentType 手动指定
|
|
48
|
+
*
|
|
49
|
+
* @param ctx 请求上下文
|
|
50
|
+
* @param data 响应数据(对象或字符串)
|
|
51
|
+
* @param options 响应选项
|
|
52
|
+
* @returns Response 对象
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* // JSON 响应(自动)
|
|
56
|
+
* return Raw(ctx, { code: 'SUCCESS', message: '成功' });
|
|
57
|
+
*
|
|
58
|
+
* // 纯文本响应(自动)
|
|
59
|
+
* return Raw(ctx, 'success');
|
|
60
|
+
*
|
|
61
|
+
* // XML 响应(手动指定)
|
|
62
|
+
* return Raw(ctx, xmlString, { contentType: 'application/xml' });
|
|
63
|
+
*
|
|
64
|
+
* // 自定义状态码和额外头
|
|
65
|
+
* return Raw(ctx, { error: 'Not Found' }, {
|
|
66
|
+
* status: 404,
|
|
67
|
+
* headers: { 'X-Custom': 'value' }
|
|
68
|
+
* });
|
|
69
|
+
*/
|
|
70
|
+
export declare function Raw(ctx: RequestContext, data: Record<string, any> | string, options?: ResponseOptions): Response;
|
|
71
|
+
declare const _default: {
|
|
72
|
+
deps: never[];
|
|
73
|
+
handler: () => {
|
|
74
|
+
Yes: typeof Yes;
|
|
75
|
+
No: typeof No;
|
|
76
|
+
Raw: typeof Raw;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
export default _default;
|
|
@@ -2,11 +2,6 @@
|
|
|
2
2
|
* 工具插件
|
|
3
3
|
* 提供常用的工具函数
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
|
-
import type { RequestContext } from "../types/context.js";
|
|
7
|
-
// 类型导入
|
|
8
|
-
import type { Plugin } from "../types/plugin.js";
|
|
9
|
-
|
|
10
5
|
/**
|
|
11
6
|
* 成功响应
|
|
12
7
|
* @param msg - 消息
|
|
@@ -14,7 +9,7 @@ import type { Plugin } from "../types/plugin.js";
|
|
|
14
9
|
* @param other - 其他字段(可选)
|
|
15
10
|
* @returns 成功响应对象
|
|
16
11
|
*/
|
|
17
|
-
export function Yes(msg
|
|
12
|
+
export function Yes(msg, data = {}, other = {}) {
|
|
18
13
|
return {
|
|
19
14
|
code: 0,
|
|
20
15
|
msg: msg,
|
|
@@ -22,7 +17,6 @@ export function Yes(msg: string, data: any = {}, other: Record<string, any> = {}
|
|
|
22
17
|
...other
|
|
23
18
|
};
|
|
24
19
|
}
|
|
25
|
-
|
|
26
20
|
/**
|
|
27
21
|
* 失败响应
|
|
28
22
|
* @param msg - 消息
|
|
@@ -30,7 +24,7 @@ export function Yes(msg: string, data: any = {}, other: Record<string, any> = {}
|
|
|
30
24
|
* @param other - 其他字段(可选)
|
|
31
25
|
* @returns 失败响应对象
|
|
32
26
|
*/
|
|
33
|
-
export function No(msg
|
|
27
|
+
export function No(msg, data = null, other = {}) {
|
|
34
28
|
return {
|
|
35
29
|
code: 1,
|
|
36
30
|
msg: msg,
|
|
@@ -38,19 +32,6 @@ export function No(msg: string, data: any = null, other: Record<string, any> = {
|
|
|
38
32
|
...other
|
|
39
33
|
};
|
|
40
34
|
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* 响应选项
|
|
44
|
-
*/
|
|
45
|
-
interface ResponseOptions {
|
|
46
|
-
/** HTTP 状态码,默认 200 */
|
|
47
|
-
status?: number;
|
|
48
|
-
/** Content-Type,默认根据 data 类型自动判断 */
|
|
49
|
-
contentType?: string;
|
|
50
|
-
/** 额外的响应头 */
|
|
51
|
-
headers?: Record<string, string>;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
35
|
/**
|
|
55
36
|
* 统一响应函数
|
|
56
37
|
*
|
|
@@ -80,13 +61,11 @@ interface ResponseOptions {
|
|
|
80
61
|
* headers: { 'X-Custom': 'value' }
|
|
81
62
|
* });
|
|
82
63
|
*/
|
|
83
|
-
export function Raw(ctx
|
|
64
|
+
export function Raw(ctx, data, options = {}) {
|
|
84
65
|
const { status = 200, contentType, headers = {} } = options;
|
|
85
|
-
|
|
86
66
|
// 自动判断 Content-Type
|
|
87
67
|
let finalContentType = contentType;
|
|
88
|
-
let body
|
|
89
|
-
|
|
68
|
+
let body;
|
|
90
69
|
if (typeof data === "string") {
|
|
91
70
|
// 字符串类型
|
|
92
71
|
body = data;
|
|
@@ -94,25 +73,23 @@ export function Raw(ctx: RequestContext, data: Record<string, any> | string, opt
|
|
|
94
73
|
// 自动判断:XML 或纯文本
|
|
95
74
|
finalContentType = data.trim().startsWith("<") ? "application/xml" : "text/plain";
|
|
96
75
|
}
|
|
97
|
-
}
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
98
78
|
// 对象类型,JSON 序列化
|
|
99
79
|
body = JSON.stringify(data);
|
|
100
80
|
finalContentType = finalContentType || "application/json";
|
|
101
81
|
}
|
|
102
|
-
|
|
103
82
|
// 合并响应头
|
|
104
83
|
const responseHeaders = {
|
|
105
84
|
...ctx.corsHeaders,
|
|
106
85
|
"Content-Type": finalContentType,
|
|
107
86
|
...headers
|
|
108
87
|
};
|
|
109
|
-
|
|
110
88
|
return new Response(body, {
|
|
111
89
|
status: status,
|
|
112
90
|
headers: responseHeaders
|
|
113
91
|
});
|
|
114
92
|
}
|
|
115
|
-
|
|
116
93
|
export default {
|
|
117
94
|
deps: [],
|
|
118
95
|
handler: () => {
|
|
@@ -122,4 +99,4 @@ export default {
|
|
|
122
99
|
Raw: Raw
|
|
123
100
|
};
|
|
124
101
|
}
|
|
125
|
-
}
|
|
102
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API路由处理器
|
|
3
|
+
* 处理 /api/* 路径的请求
|
|
4
|
+
*/
|
|
5
|
+
import type { ApiRoute } from "../types/api.ts";
|
|
6
|
+
import type { BeflyContext } from "../types/befly.ts";
|
|
7
|
+
import type { Hook } from "../types/hook.ts";
|
|
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>;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API路由处理器
|
|
3
|
+
* 处理 /api/* 路径的请求
|
|
4
|
+
*/
|
|
5
|
+
import { withCtx } from "../lib/asyncContext.js";
|
|
6
|
+
import { Logger } from "../lib/logger.js";
|
|
7
|
+
// 相对导入
|
|
8
|
+
import { genShortId } from "../utils/genShortId.js";
|
|
9
|
+
import { getClientIp } from "../utils/getClientIp.js";
|
|
10
|
+
import { FinalResponse } from "../utils/response.js";
|
|
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 生成的 routePath(例如 /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
|
+
api: apis.get(apiPath),
|
|
42
|
+
response: undefined,
|
|
43
|
+
result: undefined
|
|
44
|
+
};
|
|
45
|
+
return withCtx({
|
|
46
|
+
requestId: requestId,
|
|
47
|
+
method: req.method,
|
|
48
|
+
route: apiPath,
|
|
49
|
+
ip: clientIp,
|
|
50
|
+
now: now
|
|
51
|
+
}, async () => {
|
|
52
|
+
try {
|
|
53
|
+
// 4. 串联执行所有钩子
|
|
54
|
+
for (const hook of hooks) {
|
|
55
|
+
await hook.handler(context, ctx);
|
|
56
|
+
// 如果钩子已经设置了 response,停止执行
|
|
57
|
+
if (ctx.response) {
|
|
58
|
+
return ctx.response;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// hooks 全部通过后记录请求日志(拦截请求仅由 ErrorResponse 记录)
|
|
62
|
+
if (ctx.api && req.method !== "OPTIONS") {
|
|
63
|
+
const logData = {
|
|
64
|
+
event: "request",
|
|
65
|
+
apiName: ctx.api.name
|
|
66
|
+
};
|
|
67
|
+
if (ctx.body && Object.keys(ctx.body).length > 0) {
|
|
68
|
+
logData.body = ctx.body;
|
|
69
|
+
}
|
|
70
|
+
Logger.info(logData, "request");
|
|
71
|
+
}
|
|
72
|
+
// 5. 执行 API handler
|
|
73
|
+
if (!ctx.api) {
|
|
74
|
+
if (req.method !== "OPTIONS") {
|
|
75
|
+
ctx.response = Response.json({
|
|
76
|
+
code: 1,
|
|
77
|
+
msg: "接口不存在"
|
|
78
|
+
}, {
|
|
79
|
+
headers: ctx.corsHeaders
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else if (ctx.api.handler) {
|
|
84
|
+
const result = await ctx.api.handler(context, ctx);
|
|
85
|
+
if (result instanceof Response) {
|
|
86
|
+
ctx.response = result;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
ctx.result = result;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// 7. 返回响应(自动处理 response/result/日志)
|
|
93
|
+
return FinalResponse(ctx);
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
// 全局错误处理
|
|
97
|
+
const errorPath = ctx.api ? apiPath : req.url;
|
|
98
|
+
Logger.error({ err: err, path: errorPath }, "请求错误");
|
|
99
|
+
ctx.result = {
|
|
100
|
+
code: 1,
|
|
101
|
+
msg: "内部服务错误"
|
|
102
|
+
};
|
|
103
|
+
return FinalResponse(ctx);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
}
|
|
@@ -2,29 +2,21 @@
|
|
|
2
2
|
* 静态文件路由处理器
|
|
3
3
|
* 处理 /* 路径的静态文件请求
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
|
-
// 类型导入
|
|
7
|
-
import type { CorsConfig } from "../types/befly.js";
|
|
8
|
-
|
|
9
5
|
// 外部依赖
|
|
10
6
|
import { join } from "pathe";
|
|
11
|
-
|
|
12
7
|
import { Logger } from "../lib/logger.js";
|
|
13
8
|
// 相对导入
|
|
14
9
|
import { appDir } from "../paths.js";
|
|
15
10
|
import { setCorsOptions } from "../utils/cors.js";
|
|
16
|
-
|
|
17
11
|
/**
|
|
18
12
|
* 静态文件处理器工厂
|
|
19
13
|
*/
|
|
20
|
-
export function staticHandler(corsConfig
|
|
21
|
-
return async (req
|
|
14
|
+
export function staticHandler(corsConfig = undefined) {
|
|
15
|
+
return async (req) => {
|
|
22
16
|
// 设置 CORS 响应头
|
|
23
17
|
const corsHeaders = setCorsOptions(req, corsConfig);
|
|
24
|
-
|
|
25
18
|
const url = new URL(req.url);
|
|
26
19
|
const filePath = join(appDir, "public", url.pathname);
|
|
27
|
-
|
|
28
20
|
try {
|
|
29
21
|
// OPTIONS预检请求
|
|
30
22
|
if (req.method === "OPTIONS") {
|
|
@@ -33,7 +25,6 @@ export function staticHandler(corsConfig: CorsConfig | undefined = undefined) {
|
|
|
33
25
|
headers: corsHeaders
|
|
34
26
|
});
|
|
35
27
|
}
|
|
36
|
-
|
|
37
28
|
const file = Bun.file(filePath);
|
|
38
29
|
if (await file.exists()) {
|
|
39
30
|
return new Response(file, {
|
|
@@ -42,29 +33,24 @@ export function staticHandler(corsConfig: CorsConfig | undefined = undefined) {
|
|
|
42
33
|
...corsHeaders
|
|
43
34
|
}
|
|
44
35
|
});
|
|
45
|
-
} else {
|
|
46
|
-
return Response.json(
|
|
47
|
-
{
|
|
48
|
-
code: 1,
|
|
49
|
-
msg: "文件未找到"
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
headers: corsHeaders
|
|
53
|
-
}
|
|
54
|
-
);
|
|
55
36
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return Response.json(
|
|
60
|
-
{
|
|
37
|
+
else {
|
|
38
|
+
return Response.json({
|
|
61
39
|
code: 1,
|
|
62
|
-
msg: "
|
|
63
|
-
},
|
|
64
|
-
{
|
|
40
|
+
msg: "文件未找到"
|
|
41
|
+
}, {
|
|
65
42
|
headers: corsHeaders
|
|
66
|
-
}
|
|
67
|
-
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
Logger.error({ err: error }, "静态文件处理失败");
|
|
48
|
+
return Response.json({
|
|
49
|
+
code: 1,
|
|
50
|
+
msg: "文件读取失败"
|
|
51
|
+
}, {
|
|
52
|
+
headers: corsHeaders
|
|
53
|
+
});
|
|
68
54
|
}
|
|
69
55
|
};
|
|
70
56
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// 内部依赖(Node.js 内置模块)
|
|
2
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
function isRecord(value) {
|
|
5
|
+
return typeof value === "object" && value !== null;
|
|
6
|
+
}
|
|
7
|
+
function collectExportPaths(exportsValue, out) {
|
|
8
|
+
if (typeof exportsValue === "string") {
|
|
9
|
+
out.push(exportsValue);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
if (Array.isArray(exportsValue)) {
|
|
13
|
+
for (const item of exportsValue) {
|
|
14
|
+
collectExportPaths(item, out);
|
|
15
|
+
}
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (!isRecord(exportsValue)) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
for (const value of Object.values(exportsValue)) {
|
|
22
|
+
collectExportPaths(value, out);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function assertPathExists(packageRoot, relativeOrBare) {
|
|
26
|
+
if (!relativeOrBare.startsWith("./")) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (relativeOrBare.includes("*")) {
|
|
30
|
+
const beforeStar = relativeOrBare.split("*")[0] ?? "";
|
|
31
|
+
const dirPath = resolve(packageRoot, beforeStar);
|
|
32
|
+
if (!existsSync(dirPath)) {
|
|
33
|
+
process.stderr.write(`[ensureDist] missing export directory: ${beforeStar}\n`);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
const stat = statSync(dirPath);
|
|
37
|
+
if (!stat.isDirectory()) {
|
|
38
|
+
process.stderr.write(`[ensureDist] export directory is not a directory: ${beforeStar}\n`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const absPath = resolve(packageRoot, relativeOrBare);
|
|
44
|
+
if (!existsSync(absPath)) {
|
|
45
|
+
process.stderr.write(`[ensureDist] missing export file: ${relativeOrBare}\n`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
const stat = statSync(absPath);
|
|
49
|
+
if (!stat.isFile()) {
|
|
50
|
+
process.stderr.write(`[ensureDist] export path is not a file: ${relativeOrBare}\n`);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function main() {
|
|
55
|
+
const packageRoot = process.cwd();
|
|
56
|
+
const pkgPath = resolve(packageRoot, "package.json");
|
|
57
|
+
if (!existsSync(pkgPath)) {
|
|
58
|
+
process.stderr.write("[ensureDist] package.json not found\n");
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
const pkg = JSON.parse(readFileSync(pkgPath, { encoding: "utf8" }));
|
|
62
|
+
const distDir = resolve(packageRoot, "dist");
|
|
63
|
+
if (!existsSync(distDir)) {
|
|
64
|
+
process.stderr.write("[ensureDist] dist/ not found (did you run build?)\n");
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
const paths = [];
|
|
68
|
+
if (typeof pkg.main === "string") {
|
|
69
|
+
paths.push(pkg.main);
|
|
70
|
+
}
|
|
71
|
+
if (typeof pkg.types === "string") {
|
|
72
|
+
paths.push(pkg.types);
|
|
73
|
+
}
|
|
74
|
+
collectExportPaths(pkg.exports, paths);
|
|
75
|
+
for (const p of paths) {
|
|
76
|
+
assertPathExists(packageRoot, p);
|
|
77
|
+
}
|
|
78
|
+
process.stdout.write("[ensureDist] OK\n");
|
|
79
|
+
}
|
|
80
|
+
main();
|