befly 2.3.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/apis/health/info.ts +64 -0
  2. package/apis/tool/tokenCheck.ts +51 -0
  3. package/bin/befly.ts +202 -0
  4. package/checks/conflict.ts +408 -0
  5. package/checks/table.ts +284 -0
  6. package/config/env.ts +218 -0
  7. package/config/reserved.ts +96 -0
  8. package/main.ts +101 -0
  9. package/package.json +45 -16
  10. package/plugins/{db.js → db.ts} +25 -12
  11. package/plugins/logger.ts +28 -0
  12. package/plugins/redis.ts +51 -0
  13. package/plugins/tool.ts +34 -0
  14. package/scripts/syncDb/apply.ts +171 -0
  15. package/scripts/syncDb/constants.ts +70 -0
  16. package/scripts/syncDb/ddl.ts +182 -0
  17. package/scripts/syncDb/helpers.ts +172 -0
  18. package/scripts/syncDb/index.ts +215 -0
  19. package/scripts/syncDb/schema.ts +199 -0
  20. package/scripts/syncDb/sqlite.ts +50 -0
  21. package/scripts/syncDb/state.ts +104 -0
  22. package/scripts/syncDb/table.ts +204 -0
  23. package/scripts/syncDb/tableCreate.ts +142 -0
  24. package/scripts/syncDb/tests/constants.test.ts +104 -0
  25. package/scripts/syncDb/tests/ddl.test.ts +134 -0
  26. package/scripts/syncDb/tests/helpers.test.ts +70 -0
  27. package/scripts/syncDb/types.ts +92 -0
  28. package/scripts/syncDb/version.ts +73 -0
  29. package/scripts/syncDb.ts +9 -0
  30. package/scripts/syncDev.ts +112 -0
  31. package/system.ts +149 -0
  32. package/tables/_common.json +21 -0
  33. package/tables/admin.json +10 -0
  34. package/tsconfig.json +58 -0
  35. package/types/api.d.ts +246 -0
  36. package/types/befly.d.ts +234 -0
  37. package/types/common.d.ts +215 -0
  38. package/types/context.ts +167 -0
  39. package/types/crypto.d.ts +23 -0
  40. package/types/database.d.ts +278 -0
  41. package/types/index.d.ts +16 -0
  42. package/types/index.ts +459 -0
  43. package/types/jwt.d.ts +99 -0
  44. package/types/logger.d.ts +43 -0
  45. package/types/plugin.d.ts +109 -0
  46. package/types/redis.d.ts +44 -0
  47. package/types/tool.d.ts +67 -0
  48. package/types/validator.d.ts +45 -0
  49. package/utils/addonHelper.ts +60 -0
  50. package/utils/api.ts +23 -0
  51. package/utils/{colors.js → colors.ts} +79 -21
  52. package/utils/crypto.ts +308 -0
  53. package/utils/datetime.ts +51 -0
  54. package/utils/dbHelper.ts +142 -0
  55. package/utils/errorHandler.ts +68 -0
  56. package/utils/index.ts +46 -0
  57. package/utils/jwt.ts +493 -0
  58. package/utils/logger.ts +284 -0
  59. package/utils/objectHelper.ts +68 -0
  60. package/utils/pluginHelper.ts +62 -0
  61. package/utils/redisHelper.ts +338 -0
  62. package/utils/response.ts +38 -0
  63. package/utils/{sqlBuilder.js → sqlBuilder.ts} +233 -97
  64. package/utils/sqlHelper.ts +447 -0
  65. package/utils/tableHelper.ts +167 -0
  66. package/utils/tool.ts +230 -0
  67. package/utils/typeHelper.ts +101 -0
  68. package/utils/validate.ts +451 -0
  69. package/utils/{xml.js → xml.ts} +100 -74
  70. package/.npmrc +0 -3
  71. package/.prettierignore +0 -2
  72. package/.prettierrc +0 -11
  73. package/apis/health/info.js +0 -49
  74. package/apis/tool/tokenCheck.js +0 -29
  75. package/checks/table.js +0 -221
  76. package/config/env.js +0 -62
  77. package/main.js +0 -579
  78. package/plugins/logger.js +0 -14
  79. package/plugins/redis.js +0 -32
  80. package/plugins/tool.js +0 -8
  81. package/scripts/syncDb.js +0 -603
  82. package/system.js +0 -118
  83. package/tables/common.json +0 -16
  84. package/tables/tool.json +0 -6
  85. package/utils/api.js +0 -27
  86. package/utils/crypto.js +0 -260
  87. package/utils/index.js +0 -387
  88. package/utils/jwt.js +0 -387
  89. package/utils/logger.js +0 -143
  90. package/utils/redisHelper.js +0 -74
  91. package/utils/sqlManager.js +0 -471
  92. package/utils/tool.js +0 -31
  93. package/utils/validate.js +0 -228
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Befly 日期时间工具
3
+ * 提供日期格式化和性能计时功能
4
+ */
5
+
6
+ /**
7
+ * 格式化日期
8
+ * @param date - 日期对象、时间戳或日期字符串
9
+ * @param format - 格式化模板(支持 YYYY, MM, DD, HH, mm, ss)
10
+ * @returns 格式化后的日期字符串
11
+ *
12
+ * @example
13
+ * formatDate(new Date('2025-10-11 15:30:45')) // '2025-10-11 15:30:45'
14
+ * formatDate(new Date('2025-10-11'), 'YYYY-MM-DD') // '2025-10-11'
15
+ * formatDate(1728648645000, 'YYYY/MM/DD HH:mm') // '2025/10/11 15:30'
16
+ * formatDate('2025-10-11', 'MM-DD') // '10-11'
17
+ */
18
+ export const formatDate = (date: Date | string | number = new Date(), format: string = 'YYYY-MM-DD HH:mm:ss'): string => {
19
+ const d = new Date(date);
20
+ const year = d.getFullYear();
21
+ const month = String(d.getMonth() + 1).padStart(2, '0');
22
+ const day = String(d.getDate()).padStart(2, '0');
23
+ const hour = String(d.getHours()).padStart(2, '0');
24
+ const minute = String(d.getMinutes()).padStart(2, '0');
25
+ const second = String(d.getSeconds()).padStart(2, '0');
26
+
27
+ return format.replace('YYYY', String(year)).replace('MM', month).replace('DD', day).replace('HH', hour).replace('mm', minute).replace('ss', second);
28
+ };
29
+
30
+ /**
31
+ * 计算性能时间差
32
+ * 用于测量代码执行时间(使用 Bun.nanoseconds())
33
+ * @param startTime - 开始时间(Bun.nanoseconds()返回值)
34
+ * @param endTime - 结束时间(可选,默认为当前时间)
35
+ * @returns 时间差(毫秒或秒)
36
+ *
37
+ * @example
38
+ * const start = Bun.nanoseconds();
39
+ * // ... 执行代码 ...
40
+ * const elapsed = calcPerfTime(start); // '15.23 毫秒' 或 '2.45 秒'
41
+ */
42
+ export const calcPerfTime = (startTime: number, endTime: number = Bun.nanoseconds()): string => {
43
+ const elapsedMs = (endTime - startTime) / 1_000_000;
44
+
45
+ if (elapsedMs < 1000) {
46
+ return `${elapsedMs.toFixed(2)} 毫秒`;
47
+ } else {
48
+ const elapsedSeconds = elapsedMs / 1000;
49
+ return `${elapsedSeconds.toFixed(2)} 秒`;
50
+ }
51
+ };
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Befly 数据库工具
3
+ * 提供数据库连接和表名转换功能
4
+ */
5
+
6
+ import { SQL } from 'bun';
7
+ import { Env } from '../config/env.js';
8
+ import { Logger } from './logger.js';
9
+ import type { SqlClientOptions } from '../types/database.js';
10
+
11
+ /**
12
+ * 转换为蛇形命名(snake_case)
13
+ * 用于将小驼峰命名的表名转换为数据库约定的蛇形命名
14
+ * @param name - 小驼峰命名的字符串
15
+ * @returns 蛇形命名的字符串
16
+ *
17
+ * @example
18
+ * toSnakeTableName('userTable') // 'user_table'
19
+ * toSnakeTableName('testNewFormat') // 'test_new_format'
20
+ * toSnakeTableName('common') // 'common'
21
+ * toSnakeTableName('APIKey') // 'api_key'
22
+ */
23
+ export const toSnakeTableName = (name: string): string => {
24
+ if (!name) return name;
25
+ return String(name)
26
+ .replace(/([a-z0-9])([A-Z])/g, '$1_$2')
27
+ .replace(/([A-Z]+)([A-Z][a-z0-9]+)/g, '$1_$2')
28
+ .toLowerCase();
29
+ };
30
+
31
+ /**
32
+ * 构建数据库连接字符串
33
+ * 根据环境变量自动构建 SQLite、PostgreSQL 或 MySQL 的连接 URL
34
+ * @returns 数据库连接字符串
35
+ * @throws 如果配置不完整或数据库类型不支持
36
+ *
37
+ * @example
38
+ * // SQLite 内存数据库
39
+ * buildDatabaseUrl() // 'sqlite://:memory:' (当 DB_NAME 为空或 ':memory:')
40
+ *
41
+ * // SQLite 文件数据库
42
+ * buildDatabaseUrl() // 'sqlite://database.db'
43
+ * buildDatabaseUrl() // 'sqlite://./data/app.db'
44
+ * buildDatabaseUrl() // 'sqlite:///absolute/path/db.sqlite'
45
+ *
46
+ * // PostgreSQL
47
+ * buildDatabaseUrl() // 'postgres://user:pass@localhost:5432/dbname'
48
+ *
49
+ * // MySQL
50
+ * buildDatabaseUrl() // 'mysql://user:pass@localhost:3306/dbname'
51
+ */
52
+ export const buildDatabaseUrl = (): string => {
53
+ const type = Env.DB_TYPE || '';
54
+ const host = Env.DB_HOST || '';
55
+ const port = Env.DB_PORT;
56
+ const user = encodeURIComponent(Env.DB_USER || '');
57
+ const pass = encodeURIComponent(Env.DB_PASS || '');
58
+ const name = Env.DB_NAME || '';
59
+
60
+ if (!type) throw new Error('DB_TYPE 未配置');
61
+ if (!name && type !== 'sqlite') throw new Error('DB_NAME 未配置');
62
+
63
+ if (type === 'sqlite') {
64
+ // 支持内存数据库
65
+ if (!name || name === ':memory:') {
66
+ return 'sqlite://:memory:';
67
+ }
68
+ // 支持绝对路径(以 / 或盘符开头,如 /path 或 C:\path)
69
+ if (name.startsWith('/') || /^[a-zA-Z]:/.test(name)) {
70
+ return `sqlite://${name}`;
71
+ }
72
+ // 相对路径和普通文件名
73
+ return `sqlite://${name}`;
74
+ }
75
+
76
+ if (type === 'postgresql' || type === 'postgres') {
77
+ if (!host || !port) throw new Error('DB_HOST/DB_PORT 未配置');
78
+ const auth = user || pass ? `${user}:${pass}@` : '';
79
+ return `postgres://${auth}${host}:${port}/${encodeURIComponent(name)}`;
80
+ }
81
+
82
+ if (type === 'mysql') {
83
+ if (!host || !port) throw new Error('DB_HOST/DB_PORT 未配置');
84
+ const auth = user || pass ? `${user}:${pass}@` : '';
85
+ return `mysql://${auth}${host}:${port}/${encodeURIComponent(name)}`;
86
+ }
87
+
88
+ throw new Error(`不支持的 DB_TYPE: ${type}`);
89
+ };
90
+
91
+ /**
92
+ * 创建 SQL 客户端
93
+ * 根据配置创建并测试数据库连接
94
+ * @param options - SQL 客户端选项
95
+ * @returns SQL 客户端实例
96
+ * @throws 如果连接失败
97
+ *
98
+ * @example
99
+ * const sql = await createSqlClient();
100
+ * const users = await sql`SELECT * FROM users`;
101
+ *
102
+ * // 自定义连接池大小
103
+ * const sql = await createSqlClient({ max: 10 });
104
+ */
105
+ export async function createSqlClient(options: SqlClientOptions = {}): Promise<any> {
106
+ const finalUrl = buildDatabaseUrl();
107
+ let sql: any = null;
108
+
109
+ if (Env.DB_TYPE === 'sqlite') {
110
+ sql = new SQL(finalUrl);
111
+ } else {
112
+ sql = new SQL({
113
+ url: finalUrl,
114
+ max: options.max ?? 1,
115
+ bigint: options.bigint ?? true,
116
+ ...options
117
+ });
118
+ }
119
+
120
+ try {
121
+ // 连接健康检查
122
+ let version = '';
123
+ if (Env.DB_TYPE === 'sqlite') {
124
+ const v = await sql`SELECT sqlite_version() AS version`;
125
+ version = v?.[0]?.version;
126
+ } else if (Env.DB_TYPE === 'postgresql' || Env.DB_TYPE === 'postgres') {
127
+ const v = await sql`SELECT version() AS version`;
128
+ version = v?.[0]?.version;
129
+ } else {
130
+ const v = await sql`SELECT VERSION() AS version`;
131
+ version = v?.[0]?.version;
132
+ }
133
+ Logger.info(`数据库连接成功,version: ${version}`);
134
+ return sql;
135
+ } catch (error) {
136
+ Logger.error('数据库连接测试失败:', error);
137
+ try {
138
+ await sql.close();
139
+ } catch {}
140
+ throw error;
141
+ }
142
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * 错误处理器
3
+ * 提供统一的错误处理策略
4
+ */
5
+
6
+ import { Logger } from './logger.js';
7
+
8
+ /**
9
+ * 错误处理器类
10
+ * 提供两种简单的错误处理方式:
11
+ * - critical: 关键错误,记录日志并退出进程
12
+ * - warning: 警告错误,只记录日志继续运行
13
+ */
14
+ export class ErrorHandler {
15
+ /**
16
+ * 处理关键错误(会退出进程)
17
+ * 用于:系统检查失败、核心插件失败、配置错误等
18
+ *
19
+ * @param message - 错误消息
20
+ * @param error - 错误对象(可选)
21
+ * @param meta - 额外的元数据(可选)
22
+ */
23
+ static critical(message: string, error?: Error, meta?: Record<string, any>): never {
24
+ Logger.error({
25
+ level: 'CRITICAL',
26
+ msg: message,
27
+ error: error?.message,
28
+ stack: error?.stack,
29
+ ...meta
30
+ });
31
+
32
+ Logger.error('系统即将退出...');
33
+ process.exit(1);
34
+ }
35
+
36
+ /**
37
+ * 处理警告错误(记录但继续运行)
38
+ * 用于:用户插件失败、单个API加载失败等非关键错误
39
+ *
40
+ * @param message - 警告消息
41
+ * @param error - 错误对象(可选)
42
+ * @param meta - 额外的元数据(可选)
43
+ */
44
+ static warning(message: string, error?: Error, meta?: Record<string, any>): void {
45
+ Logger.warn({
46
+ level: 'WARNING',
47
+ msg: message,
48
+ error: error?.message,
49
+ stack: error?.stack,
50
+ ...meta
51
+ });
52
+ }
53
+
54
+ /**
55
+ * 处理信息级别的提示
56
+ * 用于:非错误的重要信息提示
57
+ *
58
+ * @param message - 信息消息
59
+ * @param meta - 额外的元数据(可选)
60
+ */
61
+ static info(message: string, meta?: Record<string, any>): void {
62
+ Logger.info({
63
+ level: 'INFO',
64
+ msg: message,
65
+ ...meta
66
+ });
67
+ }
68
+ }
package/utils/index.ts ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Befly 工具函数集 - TypeScript 版本
3
+ *
4
+ * 本文件作为统一导出入口,从各个专用工具模块重新导出功能
5
+ * 保持向后兼容性,支持从 utils/index.js 导入所有工具函数
6
+ */
7
+
8
+ // ========== API 响应工具 ==========
9
+ export { Yes, No } from './response.js';
10
+
11
+ // ========== 类型判断工具 ==========
12
+ export { isType, isEmptyObject, isEmptyArray } from './typeHelper.js';
13
+
14
+ // ========== 对象操作工具 ==========
15
+ export { pickFields, omitFields } from './objectHelper.js';
16
+
17
+ // ========== 日期时间工具 ==========
18
+ export { formatDate, calcPerfTime } from './datetime.js';
19
+
20
+ // ========== 数据库工具 ==========
21
+ export { toSnakeTableName, buildDatabaseUrl, createSqlClient } from './dbHelper.js';
22
+
23
+ // ========== 表定义工具 ==========
24
+ export { parseRule, loadTableFields, pickTableFields } from './tableHelper.js';
25
+
26
+ // ========== 插件系统工具 ==========
27
+ export { sortPlugins } from './pluginHelper.js';
28
+
29
+ // 导出其他模块
30
+ export { Colors } from './colors.js';
31
+ export { Logger } from './logger.js';
32
+ export { Validator } from './validate.js';
33
+ export { SqlBuilder } from './sqlBuilder.js';
34
+ export { SqlHelper } from './sqlHelper.js';
35
+ export { RedisHelper, initRedisClient, getRedisClient, closeRedisClient } from './redisHelper.js';
36
+ export { Jwt } from './jwt.js';
37
+ export { Crypto2 } from './crypto.js';
38
+ export { Xml } from './xml.js';
39
+ export { Api } from './api.js';
40
+ export { Tool } from './tool.js';
41
+
42
+ // 类型导出
43
+ export type { QueryOptions, InsertOptions, UpdateOptions, DeleteOptions, ListResult, TransactionCallback } from './sqlHelper.js';
44
+ export type { JwtPayload } from './jwt.js';
45
+ export type { EncodingType, HashAlgorithm } from './crypto.js';
46
+ export type { XmlParseOptions } from './xml.js';