befly 3.24.9 → 3.24.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.
@@ -23,7 +23,7 @@ export default {
23
23
  auth: true,
24
24
  fields: {},
25
25
  required: [],
26
- handler: async (befly, _ctx) => {
26
+ handler: async (befly) => {
27
27
  try {
28
28
  const results = {
29
29
  apis: { success: false, count: 0 },
@@ -1,4 +1,5 @@
1
1
  import os from "node:os";
2
+
2
3
  import { isString } from "#root/utils/is.js";
3
4
 
4
5
  export default {
@@ -10,7 +10,7 @@ export default {
10
10
  state: { name: "状态", input: "integer", min: 0, max: 2 }
11
11
  },
12
12
  required: [],
13
- handler: async (befly, _ctx) => {
13
+ handler: async (befly) => {
14
14
  try {
15
15
  const menus = await befly.mysql.getAll({
16
16
  table: "beflyMenu"
@@ -10,7 +10,7 @@ export default {
10
10
  state: { name: "状态", input: "integer", min: 0, max: 2 }
11
11
  },
12
12
  required: [],
13
- handler: async (befly, _ctx) => {
13
+ handler: async (befly) => {
14
14
  const roles = await befly.mysql.getList({
15
15
  limit: 30,
16
16
  table: "beflyRole",
@@ -1,5 +1,5 @@
1
- import { isString } from "#root/utils/is.js";
2
1
  import sysConfigTable from "#root/tables/sysConfig.json";
2
+ import { isString } from "#root/utils/is.js";
3
3
 
4
4
  export default {
5
5
  name: "根据代码获取配置值",
@@ -43,7 +43,20 @@ export default {
43
43
  const where = {};
44
44
 
45
45
  if (keyword) {
46
- where["$or"] = [{ pagePath$like: keyword }, { pageName$like: keyword }, { message$like: keyword }, { errorType$like: keyword }, { productName$like: keyword }, { productCode$like: keyword }, { productVersion$like: keyword }, { browserName$like: keyword }, { osName$like: keyword }, { deviceType$like: keyword }, { deviceVendor$like: keyword }, { deviceModel$like: keyword }];
46
+ where["$or"] = [
47
+ { pagePath$like: keyword },
48
+ { pageName$like: keyword },
49
+ { message$like: keyword },
50
+ { errorType$like: keyword },
51
+ { productName$like: keyword },
52
+ { productCode$like: keyword },
53
+ { productVersion$like: keyword },
54
+ { browserName$like: keyword },
55
+ { osName$like: keyword },
56
+ { deviceType$like: keyword },
57
+ { deviceVendor$like: keyword },
58
+ { deviceModel$like: keyword }
59
+ ];
47
60
  }
48
61
 
49
62
  if (errorType) {
@@ -1,4 +1,5 @@
1
1
  import { UAParser } from "ua-parser-js";
2
+
2
3
  import { getDateYmdNumber, getTimeBucketStart } from "#root/utils/datetime.js";
3
4
 
4
5
  const VISIT_STATS_BUCKET_MS = 30 * 60 * 1000;
@@ -1,7 +1,7 @@
1
1
  import { UAParser } from "ua-parser-js";
2
2
 
3
- import { isValidPositiveInt } from "#root/utils/is.js";
4
3
  import { getDateYmdNumber } from "#root/utils/datetime.js";
4
+ import { isValidPositiveInt } from "#root/utils/is.js";
5
5
 
6
6
  function getInfoStatsMember(ctx) {
7
7
  if (isValidPositiveInt(ctx.userId)) {
@@ -1,6 +1,6 @@
1
+ import { isValidPositiveInt } from "../utils/is.js";
1
2
  // 相对导入
2
3
  import { ErrorResponse } from "../utils/response.js";
3
- import { isValidPositiveInt } from "../utils/is.js";
4
4
 
5
5
  /**
6
6
  * 权限检查钩子
@@ -1,7 +1,7 @@
1
1
  // 相对导入
2
2
  import { Validator } from "../lib/validator.js";
3
- import { ErrorResponse } from "../utils/response.js";
4
3
  import { isPlainObject } from "../utils/is.js";
4
+ import { ErrorResponse } from "../utils/response.js";
5
5
  import { snakeCase } from "../utils/util.js";
6
6
 
7
7
  /**
package/index.js CHANGED
@@ -3,10 +3,6 @@
3
3
  * 提供简洁的框架接口,核心逻辑已提取到 loader 层
4
4
  */
5
5
 
6
- // 配置
7
- import beflyConfig from "#root/configs/beflyConfig.json";
8
- import beflyMenus from "#root/configs/beflyMenus.json";
9
-
10
6
  // 检查
11
7
  import { checkApi } from "#root/checks/api.js";
12
8
  import { checkConfig } from "#root/checks/config.js";
@@ -14,6 +10,9 @@ import { checkHook } from "#root/checks/hook.js";
14
10
  import { checkMenu } from "#root/checks/menu.js";
15
11
  import { checkPlugin } from "#root/checks/plugin.js";
16
12
  import { checkTable } from "#root/checks/table.js";
13
+ // 配置
14
+ import beflyConfig from "#root/configs/beflyConfig.json";
15
+ import beflyMenus from "#root/configs/beflyMenus.json";
17
16
  // ========== 相对导入(项目内部文件) ==========
18
17
  // 基础设施
19
18
  import { Connect } from "#root/lib/connect.js";
@@ -28,9 +27,9 @@ import { syncDev } from "#root/sync/dev.js";
28
27
  import { syncMenu } from "#root/sync/menu.js";
29
28
  // 工具
30
29
  import { calcPerfTime } from "#root/utils/calcPerfTime.js";
31
- import { scanSources } from "#root/utils/scanSources.js";
32
- import { isPrimaryProcess } from "#root/utils/is.js";
33
30
  import { deepMerge } from "#root/utils/deepMerge.js";
31
+ import { isPrimaryProcess } from "#root/utils/is.js";
32
+ import { scanSources } from "#root/utils/scanSources.js";
34
33
 
35
34
  export { syncDb } from "#root/scripts/syncDb/index.js";
36
35
  export { xmlParse } from "#root/lib/xmlParse.js";
@@ -169,7 +168,7 @@ export class Befly {
169
168
  await Connect.connectMysql(this.context.config.mysql);
170
169
 
171
170
  // 加载插件
172
- for (const item of this.plugins.sort((a, b) => a.order - b.order)) {
171
+ for (const item of this.plugins.toSorted((a, b) => a.order - b.order)) {
173
172
  this.context[item.fileName] = await item.handler(this.context);
174
173
  }
175
174
  await ensureSyncPrerequisites(this.context);
@@ -183,7 +182,7 @@ export class Befly {
183
182
  }
184
183
 
185
184
  // 加载钩子
186
- this.hooks = this.hooks.sort((a, b) => a.order - b.order);
185
+ this.hooks = this.hooks.toSorted((a, b) => a.order - b.order);
187
186
 
188
187
  // 加载所有 API
189
188
  this.apis = Object.fromEntries(this.apis.map((api) => [api.apiPath, api]));
@@ -198,11 +197,11 @@ export class Befly {
198
197
  // 开发模式下启用详细错误信息
199
198
  development: this.context.env.RUN_MODE === "development",
200
199
  // 空闲连接超时时间(秒),防止恶意连接占用资源
201
- fetch: async (req, server) => {
200
+ fetch: async (req, httpServer) => {
202
201
  const url = new URL(req.url);
203
202
 
204
203
  if (url.pathname.startsWith("/api/")) {
205
- return apiFetch(req, server);
204
+ return apiFetch(req, httpServer);
206
205
  }
207
206
 
208
207
  if (url.pathname.startsWith("/public/")) {
@@ -236,11 +235,6 @@ export class Befly {
236
235
  Logger.info(`服务器监听地址: ${server.url}`);
237
236
  Logger.info(`Mysql 数据库地址:${this.context.config.mysql.hostname}`);
238
237
  Logger.info(`Redis 缓存地址:${this.context.config.redis.hostname}`);
239
- console.log(`${this.context.config.appName} 启动成功!`);
240
- console.log(`服务器启动耗时: ${finalStartupTime}`);
241
- console.log(`服务器监听地址: ${server.url}`);
242
- console.log(`Mysql 数据库地址:${this.context.config.mysql.hostname}`);
243
- console.log(`Redis 缓存地址:${this.context.config.redis.hostname}`);
244
238
  // 注意:作为库代码,这里不注册 SIGINT/SIGTERM 处理器,也不调用 process.exit。
245
239
  // 宿主应用应自行处理信号并决定退出策略(包括是否调用 server.stop / Connect.disconnect / Logger.flush)。
246
240
  return server;
@@ -3,8 +3,8 @@
3
3
  * 负责在服务器启动时缓存接口、菜单和角色权限到 Redis
4
4
  */
5
5
 
6
- import { Logger } from "./logger.js";
7
6
  import { isNonEmptyString, isNullable, isString } from "../utils/is.js";
7
+ import { Logger } from "./logger.js";
8
8
 
9
9
  /**
10
10
  * 缓存助手类
@@ -110,7 +110,7 @@ export class CacheHelper {
110
110
 
111
111
  for (const roleCode of roleCodes) {
112
112
  const apiPaths = roleApiPathsMap.get(roleCode) || [];
113
- const members = Array.from(new Set(apiPaths)).sort();
113
+ const members = Array.from(new Set(apiPaths)).toSorted();
114
114
 
115
115
  if (members.length > 0) {
116
116
  items.push({ key: `role:apis:${roleCode}`, members: members });
@@ -168,7 +168,7 @@ export class CacheHelper {
168
168
 
169
169
  for (const roleCode of roleCodes) {
170
170
  const menuPaths = roleMenuPathsMap.get(roleCode) || [];
171
- const members = Array.from(new Set(menuPaths)).sort();
171
+ const members = Array.from(new Set(menuPaths)).toSorted();
172
172
 
173
173
  if (members.length > 0) {
174
174
  items.push({ key: `role:menus:${roleCode}`, members: members });
package/lib/connect.js CHANGED
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import { RedisClient, SQL } from "bun";
7
+
7
8
  import { Logger } from "./logger.js";
8
9
 
9
10
  function getRunMode() {
package/lib/dbHelper.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { fieldClear } from "../utils/fieldClear.js";
2
2
  import { isNonEmptyString, isNullable, isNumber, isPlainObject, isString } from "../utils/is.js";
3
3
  import { camelCase, canConvertToNumber, keysToSnake, snakeCase } from "../utils/util.js";
4
- import { Logger } from "./logger.js";
5
4
  import { DbParse } from "./dbParse.js";
6
- import { SqlBuilder } from "./sqlBuilder.js";
7
5
  import { deserializeArrayFields, parseTableRef, serializeArrayFields } from "./dbUtil.js";
6
+ import { Logger } from "./logger.js";
7
+ import { SqlBuilder } from "./sqlBuilder.js";
8
8
 
9
9
  function quoteIdentMySql(identifier) {
10
10
  if (!isString(identifier)) {
@@ -29,38 +29,38 @@ function normalizeSqlMetaNumber(value) {
29
29
  return typeof value === "number" && Number.isFinite(value) ? value : 0;
30
30
  }
31
31
 
32
- function normalizeBigIntValues(value) {
33
- if (isNullable(value)) {
34
- return value;
35
- }
36
-
37
- const convertRecord = (source) => {
38
- const converted = {};
32
+ function convertBigIntRecord(source) {
33
+ const converted = {};
39
34
 
40
- for (const [key, item] of Object.entries(source)) {
41
- let nextValue = item;
35
+ for (const [key, item] of Object.entries(source)) {
36
+ let nextValue = item;
42
37
 
43
- if (typeof item === "bigint") {
44
- const convertedNumber = canConvertToNumber(item);
45
- if (convertedNumber !== null) {
46
- nextValue = convertedNumber;
47
- } else {
48
- nextValue = String(item);
49
- }
38
+ if (typeof item === "bigint") {
39
+ const convertedNumber = canConvertToNumber(item);
40
+ if (convertedNumber !== null) {
41
+ nextValue = convertedNumber;
42
+ } else {
43
+ nextValue = String(item);
50
44
  }
51
-
52
- converted[key] = nextValue;
53
45
  }
54
46
 
55
- return converted;
56
- };
47
+ converted[key] = nextValue;
48
+ }
49
+
50
+ return converted;
51
+ }
52
+
53
+ function normalizeBigIntValues(value) {
54
+ if (isNullable(value)) {
55
+ return value;
56
+ }
57
57
 
58
58
  if (Array.isArray(value)) {
59
- return value.map((item) => convertRecord(item));
59
+ return value.map((item) => convertBigIntRecord(item));
60
60
  }
61
61
 
62
62
  if (typeof value === "object") {
63
- return convertRecord(value);
63
+ return convertBigIntRecord(value);
64
64
  }
65
65
 
66
66
  return value;
@@ -435,14 +435,14 @@ class DbHelper {
435
435
  return normalizeBigIntValues(deserializedList);
436
436
  }
437
437
 
438
- _prepareWriteInputData(data) {
438
+ prepareWriteInputData(data) {
439
439
  return serializeArrayFields(keysToSnake(fieldClear(data, { excludeValues: [null, undefined] })));
440
440
  }
441
441
 
442
- _prepareWriteUserData(data, allowState) {
442
+ prepareWriteUserData(data, allowState) {
443
443
  const result = {};
444
444
 
445
- for (const [key, value] of Object.entries(this._prepareWriteInputData(data))) {
445
+ for (const [key, value] of Object.entries(this.prepareWriteInputData(data))) {
446
446
  if (key === "id") continue;
447
447
  if (key === "created_at") continue;
448
448
  if (key === "updated_at") continue;
@@ -454,8 +454,8 @@ class DbHelper {
454
454
  return result;
455
455
  }
456
456
 
457
- _buildInsertRow(options) {
458
- const result = options.beflyMode === "manual" ? this._prepareWriteInputData(options.data) : this._prepareWriteUserData(options.data, false);
457
+ buildInsertRow(options) {
458
+ const result = options.beflyMode === "manual" ? this.prepareWriteInputData(options.data) : this.prepareWriteUserData(options.data, false);
459
459
 
460
460
  if (options.beflyMode === "auto") {
461
461
  assertTimeIdValue(options.id);
@@ -471,8 +471,8 @@ class DbHelper {
471
471
  return result;
472
472
  }
473
473
 
474
- _buildUpdateRow(options) {
475
- const result = options.beflyMode === "manual" ? this._prepareWriteInputData(options.data) : this._prepareWriteUserData(options.data, options.allowState);
474
+ buildUpdateRow(options) {
475
+ const result = options.beflyMode === "manual" ? this.prepareWriteInputData(options.data) : this.prepareWriteUserData(options.data, options.allowState);
476
476
  if (options.beflyMode !== "manual") {
477
477
  result.updated_at = options.now;
478
478
  }
@@ -508,7 +508,7 @@ class DbHelper {
508
508
  return {
509
509
  ids: [],
510
510
  processedList: dataList.map((data) =>
511
- this._buildInsertRow({
511
+ this.buildInsertRow({
512
512
  data: data,
513
513
  now: now,
514
514
  beflyMode: this.beflyMode
@@ -541,7 +541,7 @@ class DbHelper {
541
541
  assertGeneratedBatchId(id, snakeTable, index);
542
542
  }
543
543
 
544
- return this._buildInsertRow({
544
+ return this.buildInsertRow({
545
545
  data: data,
546
546
  id: id,
547
547
  now: now,
@@ -710,7 +710,11 @@ class DbHelper {
710
710
  }
711
711
 
712
712
  if (result.length >= MAX_LIMIT) {
713
- Logger.warn(`getAll 达到最大限制 ${MAX_LIMIT},实际总数 ${total},只返回前 ${MAX_LIMIT} 条`, { table: options.table, limit: MAX_LIMIT, total: total });
713
+ Logger.warn(`getAll 达到最大限制 ${MAX_LIMIT},实际总数 ${total},只返回前 ${MAX_LIMIT} 条`, {
714
+ table: options.table,
715
+ limit: MAX_LIMIT,
716
+ total: total
717
+ });
714
718
  }
715
719
 
716
720
  const lists = this.normalizeListData(result);
@@ -740,7 +744,7 @@ class DbHelper {
740
744
  async insData(options) {
741
745
  const parsed = this.createDbParse().parseInsert(options);
742
746
  const { table, snakeTable, data } = parsed;
743
- const inputData = this._prepareWriteInputData(data);
747
+ const inputData = this.prepareWriteInputData(data);
744
748
  assertWriteDataHasFields(inputData, "插入数据必须至少有一个字段", snakeTable);
745
749
  const now = Date.now();
746
750
  const insertRows = await this.createInsertRows(table, snakeTable, [data], now);
@@ -853,7 +857,7 @@ class DbHelper {
853
857
  const fieldSet = new Set();
854
858
 
855
859
  for (const item of dataList) {
856
- const userData = this._prepareWriteUserData(item.data, true);
860
+ const userData = this.prepareWriteUserData(item.data, true);
857
861
 
858
862
  for (const key of Object.keys(userData)) {
859
863
  fieldSet.add(key);
@@ -862,7 +866,7 @@ class DbHelper {
862
866
  processedList.push({ id: item.id, data: userData });
863
867
  }
864
868
 
865
- const fields = Array.from(fieldSet).sort();
869
+ const fields = Array.from(fieldSet).toSorted();
866
870
  if (fields.length === 0) {
867
871
  return {
868
872
  data: 0,
@@ -892,10 +896,10 @@ class DbHelper {
892
896
 
893
897
  async updData(options) {
894
898
  const parsed = this.createDbParse().parseUpdate(options);
895
- const inputData = this._prepareWriteInputData(parsed.data);
899
+ const inputData = this.prepareWriteInputData(parsed.data);
896
900
  assertWriteDataHasFields(inputData, "更新数据必须至少有一个字段", parsed.snakeTable);
897
901
 
898
- const processed = this._buildUpdateRow({
902
+ const processed = this.buildUpdateRow({
899
903
  data: parsed.data,
900
904
  now: Date.now(),
901
905
  allowState: true,
@@ -918,7 +922,7 @@ class DbHelper {
918
922
  let processed;
919
923
 
920
924
  if (parsed.deleteMode === "manual") {
921
- processed = this._prepareWriteInputData(parsed.data);
925
+ processed = this.prepareWriteInputData(parsed.data);
922
926
  assertWriteDataHasFields(processed, "delData 在 beflyMode=manual 时 data 必须至少有一个字段", parsed.snakeTable);
923
927
  } else {
924
928
  const now = Date.now();
package/lib/dbParse.js CHANGED
@@ -805,9 +805,9 @@ export class DbParse {
805
805
 
806
806
  let prepared;
807
807
  if (hasLeftJoin) {
808
- prepared = await this._normalizeLeftJoinReadOptions(options, cleanWhere, classifiedFields);
808
+ prepared = await this.normalizeLeftJoinReadOptions(options, cleanWhere, classifiedFields);
809
809
  } else {
810
- prepared = await this._normalizeSingleTableReadOptions(options, cleanWhere, classifiedFields);
810
+ prepared = await this.normalizeSingleTableReadOptions(options, cleanWhere, classifiedFields);
811
811
  }
812
812
 
813
813
  if (mode === "list") {
@@ -823,7 +823,7 @@ export class DbParse {
823
823
  const hasLeftJoin = Array.isArray(options.leftJoin) && options.leftJoin.length > 0;
824
824
 
825
825
  if (hasLeftJoin) {
826
- return this._normalizeLeftJoinCountOptions(options, cleanWhere);
826
+ return this.normalizeLeftJoinCountOptions(options, cleanWhere);
827
827
  }
828
828
 
829
829
  const snakeTable = snakeCase(Array.isArray(options.table) ? options.table[0] : options.table);
@@ -841,7 +841,7 @@ export class DbParse {
841
841
 
842
842
  parseExists(options) {
843
843
  validateNoLeftJoinReadOptions(options, "exists", "exists 不支持 leftJoin(请使用显式 query 或拆分查询)");
844
- return this._prepareSingleTableWhere(options.table, options.where, true, false, "exists");
844
+ return this.prepareSingleTableWhere(options.table, options.where, true, false, "exists");
845
845
  }
846
846
 
847
847
  parseInsert(options) {
@@ -871,7 +871,7 @@ export class DbParse {
871
871
  return {
872
872
  table: options.table,
873
873
  snakeTable: snakeCase(options.table),
874
- where: this._prepareSingleTableWhere(options.table, options.where, true, true, "updData").where,
874
+ where: this.prepareSingleTableWhere(options.table, options.where, true, true, "updData").where,
875
875
  data: options.data
876
876
  };
877
877
  }
@@ -884,7 +884,7 @@ export class DbParse {
884
884
  const result = {
885
885
  table: options.table,
886
886
  snakeTable: snakeCase(options.table),
887
- where: this._prepareSingleTableWhere(options.table, options.where, !force, true, label, deleteMode).where,
887
+ where: this.prepareSingleTableWhere(options.table, options.where, !force, true, label, deleteMode).where,
888
888
  deleteMode: deleteMode
889
889
  };
890
890
 
@@ -923,7 +923,7 @@ export class DbParse {
923
923
 
924
924
  parseIncrement(table, field, where, value, label = "increment") {
925
925
  validateIncrementOptions(table, field, where, value, label);
926
- const prepared = this._prepareSingleTableWhere(table, where, true, true, label);
926
+ const prepared = this.prepareSingleTableWhere(table, where, true, true, label);
927
927
  return {
928
928
  table: table,
929
929
  snakeTable: prepared.snakeTable,
@@ -933,9 +933,9 @@ export class DbParse {
933
933
  };
934
934
  }
935
935
 
936
- async _normalizeLeftJoinReadOptions(options, cleanWhere, classifiedFields) {
936
+ async normalizeLeftJoinReadOptions(options, cleanWhere, classifiedFields) {
937
937
  const mainTableRef = options.table[0];
938
- const processedFields = await this._joinFieldsToSnake(mainTableRef, classifiedFields);
938
+ const processedFields = await this.joinFieldsToSnake(mainTableRef, classifiedFields);
939
939
  const joinTableRefs = options.table.slice(1);
940
940
  const normalizedTableRef = normalizeTableRef(mainTableRef);
941
941
  const mainQualifier = getTableQualifier(mainTableRef);
@@ -953,7 +953,7 @@ export class DbParse {
953
953
  };
954
954
  }
955
955
 
956
- _normalizeLeftJoinCountOptions(options, cleanWhere) {
956
+ normalizeLeftJoinCountOptions(options, cleanWhere) {
957
957
  const mainTableRef = options.table[0];
958
958
  const joinTableRefs = options.table.slice(1);
959
959
  const normalizedTableRef = normalizeTableRef(mainTableRef);
@@ -972,7 +972,7 @@ export class DbParse {
972
972
  };
973
973
  }
974
974
 
975
- async _normalizeSingleTableReadOptions(options, cleanWhere, classifiedFields) {
975
+ async normalizeSingleTableReadOptions(options, cleanWhere, classifiedFields) {
976
976
  const tableRef = Array.isArray(options.table) ? options.table[0] : options.table;
977
977
  const snakeTable = snakeCase(tableRef);
978
978
  const processedFields = await fieldsToSnake(tableRef, classifiedFields, this.getTableColumns);
@@ -989,7 +989,7 @@ export class DbParse {
989
989
  };
990
990
  }
991
991
 
992
- _prepareSingleTableWhere(table, where, useDefaultStateFilter, required, label, beflyMode = this.beflyMode) {
992
+ prepareSingleTableWhere(table, where, useDefaultStateFilter, required, label, beflyMode = this.beflyMode) {
993
993
  const snakeTable = snakeCase(table);
994
994
  const normalizedWhere = whereKeysToSnake(clearDeep(where || {}));
995
995
  if (required) {
@@ -1002,7 +1002,7 @@ export class DbParse {
1002
1002
  };
1003
1003
  }
1004
1004
 
1005
- async _joinFieldsToSnake(mainTableRef, classifiedFields) {
1005
+ async joinFieldsToSnake(mainTableRef, classifiedFields) {
1006
1006
  if (classifiedFields.type !== "join") {
1007
1007
  return [];
1008
1008
  }
package/lib/dbUtil.js CHANGED
@@ -507,6 +507,15 @@ export function processJoinOrderBy(orderBy) {
507
507
  return normalizeOrderBy(orderBy, processJoinField);
508
508
  }
509
509
 
510
+ function replaceJoinOnSegment(segment) {
511
+ return segment.replace(/([a-zA-Z_][a-zA-Z0-9_]*)(\s*\.\s*)([a-zA-Z_][a-zA-Z0-9_]*)/g, (...matchParts) => {
512
+ const left = matchParts[1];
513
+ const dot = matchParts[2];
514
+ const right = matchParts[3];
515
+ return `${snakeCase(left)}${dot}${snakeCase(right)}`;
516
+ });
517
+ }
518
+
510
519
  export function processJoinOn(on) {
511
520
  if (!isString(on)) {
512
521
  return String(on);
@@ -517,12 +526,6 @@ export function processJoinOn(on) {
517
526
  return raw;
518
527
  }
519
528
 
520
- const replaceSegment = (segment) => {
521
- return segment.replace(/([a-zA-Z_][a-zA-Z0-9_]*)(\s*\.\s*)([a-zA-Z_][a-zA-Z0-9_]*)/g, (_match, left, dot, right) => {
522
- return `${snakeCase(left)}${dot}${snakeCase(right)}`;
523
- });
524
- };
525
-
526
529
  let result = "";
527
530
  let buffer = "";
528
531
  let quote = null;
@@ -540,7 +543,7 @@ export function processJoinOn(on) {
540
543
 
541
544
  if (ch === "'" || ch === '"' || ch === "`") {
542
545
  if (buffer.length > 0) {
543
- result += replaceSegment(buffer);
546
+ result += replaceJoinOnSegment(buffer);
544
547
  buffer = "";
545
548
  }
546
549
  quote = ch;
@@ -554,7 +557,7 @@ export function processJoinOn(on) {
554
557
  }
555
558
 
556
559
  if (buffer.length > 0) {
557
- result += replaceSegment(buffer);
560
+ result += replaceJoinOnSegment(buffer);
558
561
  }
559
562
 
560
563
  return result;
package/lib/logger.js CHANGED
@@ -7,8 +7,8 @@ import { stat } from "node:fs/promises";
7
7
  import { join as nodePathJoin, resolve as nodePathResolve } from "node:path";
8
8
 
9
9
  import { formatYmdHms } from "../utils/datetime.js";
10
- import { buildSensitiveKeyMatcher, sanitizeLogObject } from "../utils/loggerUtils.js";
11
10
  import { isFiniteNumber, isNumber, isPlainObject, isString } from "../utils/is.js";
11
+ import { buildSensitiveKeyMatcher, sanitizeLogObject } from "../utils/loggerUtils.js";
12
12
  import { normalizePositiveInt } from "../utils/util.js";
13
13
 
14
14
  // 注意:Logger 可能在运行时/测试中被 process.chdir() 影响。
@@ -531,7 +531,7 @@ function logWrite(level, input) {
531
531
  * 日志实例(延迟初始化)
532
532
  */
533
533
  export const Logger = {
534
- info(msg, data) {
534
+ info: function (msg, data) {
535
535
  if (isPlainObject(msg)) {
536
536
  logWrite("info", msg);
537
537
  return;
@@ -539,7 +539,7 @@ export const Logger = {
539
539
 
540
540
  logWrite("info", { msg: msg, data: data });
541
541
  },
542
- warn(msg, data) {
542
+ warn: function (msg, data) {
543
543
  if (isPlainObject(msg)) {
544
544
  logWrite("warn", msg);
545
545
  return;
@@ -547,7 +547,7 @@ export const Logger = {
547
547
 
548
548
  logWrite("warn", { msg: msg, data: data });
549
549
  },
550
- error(msg, err, data) {
550
+ error: function (msg, err, data) {
551
551
  if (isPlainObject(msg)) {
552
552
  logWrite("error", msg);
553
553
  return;
@@ -555,7 +555,7 @@ export const Logger = {
555
555
 
556
556
  logWrite("error", { msg: msg, err: err, data: data });
557
557
  },
558
- debug(msg, data) {
558
+ debug: function (msg, data) {
559
559
  if (isPlainObject(msg)) {
560
560
  logWrite("debug", msg);
561
561
  return;
@@ -563,16 +563,16 @@ export const Logger = {
563
563
 
564
564
  logWrite("debug", { msg: msg, data: data });
565
565
  },
566
- async flush() {
566
+ flush: async function () {
567
567
  await flush();
568
568
  },
569
- configure(cfg) {
569
+ configure: function (cfg) {
570
570
  configure(cfg);
571
571
  },
572
- setMock(mock) {
572
+ setMock: function (mock) {
573
573
  setMockLogger(mock);
574
574
  },
575
- async shutdown() {
575
+ shutdown: async function () {
576
576
  await shutdown();
577
577
  }
578
578
  };
package/lib/sqlBuilder.js CHANGED
@@ -3,19 +3,19 @@
3
3
  * 提供链式 API 构建 SQL 查询
4
4
  */
5
5
 
6
- import { escapeField, escapeTable, resolveQuoteIdent } from "./dbUtil.js";
7
6
  import { isNonEmptyString } from "../utils/is.js";
7
+ import { escapeField, escapeTable, resolveQuoteIdent } from "./dbUtil.js";
8
8
 
9
9
  /**
10
10
  * SQL 构建器类
11
11
  */
12
12
  export class SqlBuilder {
13
- _model;
14
- _quoteIdent;
13
+ queryModel;
14
+ quoteIdentifier;
15
15
 
16
16
  constructor(options = {}) {
17
- this._quoteIdent = resolveQuoteIdent(options);
18
- this._model = {
17
+ this.quoteIdentifier = resolveQuoteIdent(options);
18
+ this.queryModel = {
19
19
  select: [],
20
20
  from: null,
21
21
  where: { type: "group", join: "AND", items: [] },
@@ -30,7 +30,7 @@ export class SqlBuilder {
30
30
  * 重置构建器状态
31
31
  */
32
32
  reset() {
33
- this._model = {
33
+ this.queryModel = {
34
34
  select: [],
35
35
  from: null,
36
36
  where: { type: "group", join: "AND", items: [] },
@@ -42,8 +42,8 @@ export class SqlBuilder {
42
42
  return this;
43
43
  }
44
44
 
45
- _compileOperatorNode(node) {
46
- const escapedField = escapeField(node.field, this._quoteIdent);
45
+ compileOperatorNode(node) {
46
+ const escapedField = escapeField(node.field, this.quoteIdentifier);
47
47
 
48
48
  switch (node.operator) {
49
49
  case "$not":
@@ -87,7 +87,7 @@ export class SqlBuilder {
87
87
  }
88
88
  }
89
89
 
90
- _compileWhereNode(node) {
90
+ compileWhereNode(node) {
91
91
  if (!node) {
92
92
  return { sql: "", params: [] };
93
93
  }
@@ -100,7 +100,7 @@ export class SqlBuilder {
100
100
  }
101
101
 
102
102
  if (node.type === "op") {
103
- return this._compileOperatorNode(node);
103
+ return this.compileOperatorNode(node);
104
104
  }
105
105
 
106
106
  if (node.type !== "group" || !node.items || node.items.length === 0) {
@@ -111,7 +111,7 @@ export class SqlBuilder {
111
111
  const params = [];
112
112
 
113
113
  for (const item of node.items) {
114
- const built = this._compileWhereNode(item);
114
+ const built = this.compileWhereNode(item);
115
115
  if (!built.sql) {
116
116
  continue;
117
117
  }
@@ -136,7 +136,7 @@ export class SqlBuilder {
136
136
  * 获取 WHERE 条件(供 DbHelper 使用)
137
137
  */
138
138
  getWhereConditions() {
139
- const result = this._compileWhereNode(this._model.where);
139
+ const result = this.compileWhereNode(this.queryModel.where);
140
140
  return { sql: result.sql, params: result.params };
141
141
  }
142
142
 
@@ -146,12 +146,12 @@ export class SqlBuilder {
146
146
  select(fields = "*") {
147
147
  if (Array.isArray(fields)) {
148
148
  for (const field of fields) {
149
- this._model.select.push({ type: "field", value: field });
149
+ this.queryModel.select.push({ type: "field", value: field });
150
150
  }
151
151
  return this;
152
152
  }
153
153
 
154
- this._model.select.push({ type: "field", value: fields });
154
+ this.queryModel.select.push({ type: "field", value: fields });
155
155
  return this;
156
156
  }
157
157
 
@@ -159,7 +159,7 @@ export class SqlBuilder {
159
159
  * SELECT 原始表达式(不做转义)
160
160
  */
161
161
  selectRaw(expr) {
162
- this._model.select.push({ type: "raw", value: expr });
162
+ this.queryModel.select.push({ type: "raw", value: expr });
163
163
  return this;
164
164
  }
165
165
 
@@ -167,7 +167,7 @@ export class SqlBuilder {
167
167
  * FROM 表名
168
168
  */
169
169
  from(table) {
170
- this._model.from = { type: "table", value: table.trim() };
170
+ this.queryModel.from = { type: "table", value: table.trim() };
171
171
  return this;
172
172
  }
173
173
 
@@ -175,7 +175,7 @@ export class SqlBuilder {
175
175
  * FROM 原始表达式(不做转义)
176
176
  */
177
177
  fromRaw(tableExpr) {
178
- this._model.from = { type: "raw", value: tableExpr.trim() };
178
+ this.queryModel.from = { type: "raw", value: tableExpr.trim() };
179
179
  return this;
180
180
  }
181
181
 
@@ -183,19 +183,19 @@ export class SqlBuilder {
183
183
  * WHERE 条件
184
184
  */
185
185
  where(conditionOrField) {
186
- if (this._model.where.items.length === 0) {
187
- this._model.where = conditionOrField;
186
+ if (this.queryModel.where.items.length === 0) {
187
+ this.queryModel.where = conditionOrField;
188
188
  return this;
189
189
  }
190
190
 
191
191
  if (conditionOrField.type === "group" && conditionOrField.join === "AND") {
192
192
  for (const item of conditionOrField.items) {
193
- this._model.where.items.push(item);
193
+ this.queryModel.where.items.push(item);
194
194
  }
195
195
  return this;
196
196
  }
197
197
 
198
- this._model.where.items.push(conditionOrField);
198
+ this.queryModel.where.items.push(conditionOrField);
199
199
  return this;
200
200
  }
201
201
 
@@ -208,7 +208,7 @@ export class SqlBuilder {
208
208
  paramList = params;
209
209
  }
210
210
 
211
- this._model.where.items.push({ type: "raw", sql: sql, params: paramList });
211
+ this.queryModel.where.items.push({ type: "raw", sql: sql, params: paramList });
212
212
  return this;
213
213
  }
214
214
 
@@ -216,7 +216,7 @@ export class SqlBuilder {
216
216
  * LEFT JOIN
217
217
  */
218
218
  leftJoin(table, on) {
219
- this._model.joins.push({ type: "left", table: table, on: on });
219
+ this.queryModel.joins.push({ type: "left", table: table, on: on });
220
220
  return this;
221
221
  }
222
222
 
@@ -226,7 +226,7 @@ export class SqlBuilder {
226
226
  */
227
227
  orderBy(fields) {
228
228
  for (const item of fields) {
229
- this._model.orderBy.push({ field: item.field, dir: item.dir });
229
+ this.queryModel.orderBy.push({ field: item.field, dir: item.dir });
230
230
  }
231
231
  return this;
232
232
  }
@@ -235,8 +235,8 @@ export class SqlBuilder {
235
235
  * LIMIT
236
236
  */
237
237
  limit(count, offset) {
238
- this._model.limit = count;
239
- this._model.offset = offset;
238
+ this.queryModel.limit = count;
239
+ this.queryModel.offset = offset;
240
240
  return this;
241
241
  }
242
242
 
@@ -244,7 +244,7 @@ export class SqlBuilder {
244
244
  * OFFSET
245
245
  */
246
246
  offset(count) {
247
- this._model.offset = count;
247
+ this.queryModel.offset = count;
248
248
  return this;
249
249
  }
250
250
 
@@ -253,29 +253,29 @@ export class SqlBuilder {
253
253
  */
254
254
  toSelectSql() {
255
255
  let selectSql = "*";
256
- if (this._model.select.length > 0) {
257
- selectSql = this._model.select
256
+ if (this.queryModel.select.length > 0) {
257
+ selectSql = this.queryModel.select
258
258
  .map((item) => {
259
259
  if (item.type === "raw") {
260
260
  return item.value;
261
261
  }
262
- return escapeField(item.value, this._quoteIdent);
262
+ return escapeField(item.value, this.quoteIdentifier);
263
263
  })
264
264
  .join(", ");
265
265
  }
266
266
 
267
267
  const params = [];
268
- let fromSql = this._model.from.value;
269
- if (this._model.from.type !== "raw") {
270
- fromSql = escapeTable(this._model.from.value, this._quoteIdent);
268
+ let fromSql = this.queryModel.from.value;
269
+ if (this.queryModel.from.type !== "raw") {
270
+ fromSql = escapeTable(this.queryModel.from.value, this.quoteIdentifier);
271
271
  }
272
272
  let sql = `SELECT ${selectSql} FROM ${fromSql}`;
273
273
 
274
- if (this._model.joins.length > 0) {
275
- sql += ` ${this._model.joins.map((join) => `${join.type.toUpperCase()} JOIN ${escapeTable(join.table, this._quoteIdent)} ON ${join.on}`).join(" ")}`;
274
+ if (this.queryModel.joins.length > 0) {
275
+ sql += ` ${this.queryModel.joins.map((join) => `${join.type.toUpperCase()} JOIN ${escapeTable(join.table, this.quoteIdentifier)} ON ${join.on}`).join(" ")}`;
276
276
  }
277
277
 
278
- const whereResult = this._compileWhereNode(this._model.where);
278
+ const whereResult = this.compileWhereNode(this.queryModel.where);
279
279
  if (whereResult.sql) {
280
280
  sql += ` WHERE ${whereResult.sql}`;
281
281
  for (const param of whereResult.params) {
@@ -283,14 +283,14 @@ export class SqlBuilder {
283
283
  }
284
284
  }
285
285
 
286
- if (this._model.orderBy.length > 0) {
287
- sql += ` ORDER BY ${this._model.orderBy.map((item) => `${escapeField(item.field, this._quoteIdent)} ${item.dir}`).join(", ")}`;
286
+ if (this.queryModel.orderBy.length > 0) {
287
+ sql += ` ORDER BY ${this.queryModel.orderBy.map((item) => `${escapeField(item.field, this.quoteIdentifier)} ${item.dir}`).join(", ")}`;
288
288
  }
289
289
 
290
- if (this._model.limit !== null) {
291
- sql += ` LIMIT ${this._model.limit}`;
292
- if (this._model.offset !== null && this._model.offset !== undefined) {
293
- sql += ` OFFSET ${this._model.offset}`;
290
+ if (this.queryModel.limit !== null) {
291
+ sql += ` LIMIT ${this.queryModel.limit}`;
292
+ if (this.queryModel.offset !== null && this.queryModel.offset !== undefined) {
293
+ sql += ` OFFSET ${this.queryModel.offset}`;
294
294
  }
295
295
  }
296
296
 
@@ -301,7 +301,7 @@ export class SqlBuilder {
301
301
  * 构建 INSERT 查询
302
302
  */
303
303
  toInsertSql(table, data) {
304
- const escapedTable = escapeTable(table, this._quoteIdent);
304
+ const escapedTable = escapeTable(table, this.quoteIdentifier);
305
305
 
306
306
  if (Array.isArray(data)) {
307
307
  if (data.length === 0) {
@@ -310,7 +310,7 @@ export class SqlBuilder {
310
310
 
311
311
  const firstRow = data[0] || {};
312
312
  const fields = Object.keys(firstRow);
313
- const escapedFields = fields.map((field) => escapeField(field, this._quoteIdent));
313
+ const escapedFields = fields.map((field) => escapeField(field, this.quoteIdentifier));
314
314
  const placeholders = fields.map(() => "?").join(", ");
315
315
  const values = data.map(() => `(${placeholders})`).join(", ");
316
316
  const params = [];
@@ -329,7 +329,7 @@ export class SqlBuilder {
329
329
 
330
330
  const fields = Object.keys(data);
331
331
 
332
- const escapedFields = fields.map((field) => escapeField(field, this._quoteIdent));
332
+ const escapedFields = fields.map((field) => escapeField(field, this.quoteIdentifier));
333
333
  const placeholders = fields.map(() => "?").join(", ");
334
334
  const params = [];
335
335
  for (const field of fields) {
@@ -353,13 +353,13 @@ export class SqlBuilder {
353
353
  params.push(value);
354
354
  }
355
355
 
356
- const whereResult = this._compileWhereNode(this._model.where);
356
+ const whereResult = this.compileWhereNode(this.queryModel.where);
357
357
  for (const param of whereResult.params) {
358
358
  params.push(param);
359
359
  }
360
360
 
361
361
  return {
362
- sql: `UPDATE ${escapeTable(table, this._quoteIdent)} SET ${fields.map((field) => `${escapeField(field, this._quoteIdent)} = ?`).join(", ")} WHERE ${whereResult.sql}`,
362
+ sql: `UPDATE ${escapeTable(table, this.quoteIdentifier)} SET ${fields.map((field) => `${escapeField(field, this.quoteIdentifier)} = ?`).join(", ")} WHERE ${whereResult.sql}`,
363
363
  params: params
364
364
  };
365
365
  }
@@ -368,9 +368,9 @@ export class SqlBuilder {
368
368
  * 构建 DELETE 查询
369
369
  */
370
370
  toDeleteSql(table) {
371
- const whereResult = this._compileWhereNode(this._model.where);
371
+ const whereResult = this.compileWhereNode(this.queryModel.where);
372
372
  return {
373
- sql: `DELETE FROM ${escapeTable(table, this._quoteIdent)} WHERE ${whereResult.sql}`,
373
+ sql: `DELETE FROM ${escapeTable(table, this.quoteIdentifier)} WHERE ${whereResult.sql}`,
374
374
  params: whereResult.params
375
375
  };
376
376
  }
@@ -380,17 +380,17 @@ export class SqlBuilder {
380
380
  */
381
381
  toCountSql() {
382
382
  const params = [];
383
- let fromSql = this._model.from.value;
384
- if (this._model.from.type !== "raw") {
385
- fromSql = escapeTable(this._model.from.value, this._quoteIdent);
383
+ let fromSql = this.queryModel.from.value;
384
+ if (this.queryModel.from.type !== "raw") {
385
+ fromSql = escapeTable(this.queryModel.from.value, this.quoteIdentifier);
386
386
  }
387
387
  let sql = `SELECT COUNT(*) as total FROM ${fromSql}`;
388
388
 
389
- if (this._model.joins.length > 0) {
390
- sql += ` ${this._model.joins.map((join) => `${join.type.toUpperCase()} JOIN ${escapeTable(join.table, this._quoteIdent)} ON ${join.on}`).join(" ")}`;
389
+ if (this.queryModel.joins.length > 0) {
390
+ sql += ` ${this.queryModel.joins.map((join) => `${join.type.toUpperCase()} JOIN ${escapeTable(join.table, this.quoteIdentifier)} ON ${join.on}`).join(" ")}`;
391
391
  }
392
392
 
393
- const whereResult = this._compileWhereNode(this._model.where);
393
+ const whereResult = this.compileWhereNode(this.queryModel.where);
394
394
  if (whereResult.sql) {
395
395
  sql += ` WHERE ${whereResult.sql}`;
396
396
  for (const param of whereResult.params) {
package/lib/validator.js CHANGED
@@ -3,10 +3,10 @@
3
3
  * 纯静态类设计,简洁易用
4
4
  */
5
5
 
6
- import RegexAliases from "../configs/regexpAlias.json";
7
6
  import { FIELD_RULE_DEFAULT_MAX, FIELD_RULE_DEFAULT_MIN, FIELD_RULE_INPUT_TYPES } from "../configs/constConfig.js";
8
- import { getCompiledRegex } from "../utils/regexpUtil.js";
7
+ import RegexAliases from "../configs/regexpAlias.json";
9
8
  import { isFiniteNumber, isIntegerNumber, isJsonObject, isJsonPrimitive, isJsonStructure, isNullable, isNumber, isPlainObject, isRegexInput, isString } from "../utils/is.js";
9
+ import { getCompiledRegex } from "../utils/regexpUtil.js";
10
10
 
11
11
  const INPUT_TYPE_SET = new Set(FIELD_RULE_INPUT_TYPES);
12
12
  const RULE_ALLOWED_KEYS = new Set(["input", "check", "name", "min", "max", "detail"]);
@@ -50,10 +50,10 @@ export class Validator {
50
50
 
51
51
  // 参数检查
52
52
  if (!isPlainObject(data)) {
53
- return this.buildResult({ _error: "数据必须是对象格式" });
53
+ return this.buildResult({ rootError: "数据必须是对象格式" });
54
54
  }
55
55
  if (!isPlainObject(rules)) {
56
- return this.buildResult({ _error: "验证规则必须是对象格式" });
56
+ return this.buildResult({ rootError: "验证规则必须是对象格式" });
57
57
  }
58
58
 
59
59
  // 检查必填字段
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "befly",
3
- "version": "3.24.9",
3
+ "version": "3.24.11",
4
4
  "gitHead": "49c39d36695036e85fc64083cc43c1652fff96cb",
5
5
  "private": false,
6
6
  "description": "Befly - 为 Bun 专属打造的 JavaScript API 接口框架核心引擎",
package/paths.js CHANGED
@@ -15,8 +15,8 @@ import { fileURLToPath } from "node:url";
15
15
  import { dirname, isAbsolute, join, normalize, resolve } from "pathe";
16
16
 
17
17
  // 当前文件的路径信息
18
- const __filename = fileURLToPath(import.meta.url);
19
- const __dirname = dirname(__filename);
18
+ const moduleFilePath = fileURLToPath(import.meta.url);
19
+ const moduleDir = dirname(moduleFilePath);
20
20
 
21
21
  // ==================== Core 框架路径 ====================
22
22
 
@@ -24,48 +24,48 @@ const __dirname = dirname(__filename);
24
24
  * Core 框架根目录
25
25
  * @description packages/core/
26
26
  */
27
- export const coreDir = __dirname;
27
+ export const coreDir = moduleDir;
28
28
 
29
29
  /**
30
30
  * Core 框架 dist 目录
31
31
  * @description 源码态为 packages/core/dist;dist 运行态为 packages/core/dist
32
32
  */
33
- export const coreDistDir = normalize(__dirname).endsWith("/dist") ? __dirname : join(__dirname, "dist");
33
+ export const coreDistDir = normalize(moduleDir).endsWith("/dist") ? moduleDir : join(moduleDir, "dist");
34
34
 
35
35
  /**
36
36
  * Core 框架检查目录
37
37
  * @description packages/core/checks/
38
38
  * @usage 存放启动检查模块(返回 boolean 的 default 函数)
39
39
  */
40
- export const coreCheckDir = join(__dirname, "checks");
40
+ export const coreCheckDir = join(moduleDir, "checks");
41
41
 
42
42
  /**
43
43
  * Core 框架插件目录
44
44
  * @description packages/core/plugins/
45
45
  * @usage 存放内置插件(mysql, logger, redis, tool 等)
46
46
  */
47
- export const corePluginDir = join(__dirname, "plugins");
47
+ export const corePluginDir = join(moduleDir, "plugins");
48
48
 
49
49
  /**
50
50
  * Core 框架钩子目录
51
51
  * @description packages/core/hooks/
52
52
  * @usage 存放内置钩子(auth, cors, parser 等)
53
53
  */
54
- export const coreHookDir = join(__dirname, "hooks");
54
+ export const coreHookDir = join(moduleDir, "hooks");
55
55
 
56
56
  /**
57
57
  * Core 框架 API 目录
58
58
  * @description packages/core/apis/
59
59
  * @usage 存放框架级别的 API 接口
60
60
  */
61
- export const coreApiDir = join(__dirname, "apis");
61
+ export const coreApiDir = join(moduleDir, "apis");
62
62
 
63
63
  /**
64
64
  * Core 框架表定义目录
65
65
  * @description packages/core/tables/
66
66
  * @usage 存放框架核心表定义(JSON 格式)
67
67
  */
68
- export const coreTableDir = join(__dirname, "tables");
68
+ export const coreTableDir = join(moduleDir, "tables");
69
69
 
70
70
  // ==================== 用户项目路径 ====================
71
71
 
package/plugins/cache.js CHANGED
@@ -10,7 +10,7 @@ import { CacheHelper } from "../lib/cacheHelper.js";
10
10
  */
11
11
  export default {
12
12
  order: 6,
13
- async handler(befly) {
13
+ handler: async function (befly) {
14
14
  return new CacheHelper({ mysql: befly.mysql, redis: befly.redis });
15
15
  }
16
16
  };
package/plugins/email.js CHANGED
@@ -3,12 +3,13 @@
3
3
  * 提供邮件发送功能,支持 SMTP 配置
4
4
  */
5
5
 
6
- import { Logger } from "../lib/logger.js";
7
6
  import nodemailer from "nodemailer";
8
7
 
8
+ import { Logger } from "../lib/logger.js";
9
+
9
10
  export default {
10
11
  order: 7,
11
- async handler(befly) {
12
+ handler: async function (befly) {
12
13
  const config = befly?.config?.email || {};
13
14
  let transporter = null;
14
15
 
package/plugins/logger.js CHANGED
@@ -10,7 +10,7 @@ import { Logger } from "../lib/logger.js";
10
10
  */
11
11
  export default {
12
12
  order: 2,
13
- async handler(befly) {
13
+ handler: async function (befly) {
14
14
  // 配置 Logger
15
15
  if (befly.config && befly.config.logger) {
16
16
  Logger.configure(befly.config.logger);
package/plugins/mysql.js CHANGED
@@ -12,7 +12,7 @@ import { Logger } from "../lib/logger.js";
12
12
  */
13
13
  export default {
14
14
  order: 5,
15
- async handler(befly) {
15
+ handler: async function (befly) {
16
16
  try {
17
17
  // 创建数据库管理器实例
18
18
  const dbManager = new DbHelper({
package/plugins/redis.js CHANGED
@@ -12,7 +12,7 @@ import { RedisHelper } from "../lib/redisHelper.js";
12
12
  */
13
13
  export default {
14
14
  order: 4,
15
- async handler(befly) {
15
+ handler: async function (befly) {
16
16
  const env = befly.config?.runMode;
17
17
  const redisPrefix = befly.config?.redis?.prefix;
18
18
  try {
@@ -7,6 +7,7 @@ import { Logger } from "#root/lib/logger.js";
7
7
  import { importDefault } from "#root/utils/importDefault.js";
8
8
  import { isNonEmptyString, isPlainObject } from "#root/utils/is.js";
9
9
  import { camelCase } from "#root/utils/util.js";
10
+
10
11
  import { buildSyncDbDiff, groupSyncDbColumns } from "./diff.js";
11
12
  import { printSyncDbProcessLog } from "./report.js";
12
13
 
@@ -65,7 +66,7 @@ export async function prepareSyncDbBaseContext(mysqlConfig) {
65
66
  }
66
67
  }
67
68
  if (skippedBeflyTables.size > 0) {
68
- const skippedTables = Array.from(skippedBeflyTables).sort((left, right) => left.localeCompare(right));
69
+ const skippedTables = Array.from(skippedBeflyTables).toSorted((left, right) => left.localeCompare(right));
69
70
  Logger.info("已跳过 befly_ 前缀表,不参与对比", {
70
71
  skippedTableCount: skippedBeflyTables.size,
71
72
  skippedTables: skippedTables
@@ -2,6 +2,7 @@ import { join } from "node:path";
2
2
 
3
3
  import { isNonEmptyString, isPlainObject } from "#root/utils/is.js";
4
4
  import { camelCase, snakeCase } from "#root/utils/util.js";
5
+
5
6
  import { printSyncDbProcessLog } from "./report.js";
6
7
  import { toSyncDbFieldDef } from "./transform.js";
7
8
 
@@ -2,8 +2,9 @@ import { join, resolve } from "node:path";
2
2
 
3
3
  import { Connect } from "#root/lib/connect.js";
4
4
  import { Logger } from "#root/lib/logger.js";
5
- import { applySyncDbDiff } from "./diff.js";
5
+
6
6
  import { prepareSyncDbBaseContext } from "./context.js";
7
+ import { applySyncDbDiff } from "./diff.js";
7
8
  import { printSyncDbDiffSummary, printSyncDbProcessLog, writeSyncDbReport } from "./report.js";
8
9
 
9
10
  export async function syncDb(mysqlConfig) {
@@ -4,6 +4,7 @@ import { dirname } from "node:path";
4
4
  import { Logger } from "#root/lib/logger.js";
5
5
  import { isNonEmptyString } from "#root/utils/is.js";
6
6
  import { camelCase } from "#root/utils/util.js";
7
+
7
8
  import { toSyncDbFieldDef } from "./transform.js";
8
9
 
9
10
  export function printSyncDbProcessLog(message) {
@@ -13,7 +13,7 @@ export function fieldClear(data, options = {}) {
13
13
  const { pickKeys, omitKeys, keepValues, excludeValues, keepMap } = options;
14
14
 
15
15
  const filterObj = (obj) => {
16
- let result = {};
16
+ const result = {};
17
17
  let keys = Object.keys(obj);
18
18
  if (pickKeys && pickKeys.length) {
19
19
  keys = keys.filter((k) => pickKeys.includes(k));
@@ -1,5 +1,5 @@
1
- import { isMinLengthString } from "./is.js";
2
1
  import RegexAliases from "../configs/regexpAlias.json";
2
+ import { isMinLengthString } from "./is.js";
3
3
 
4
4
  const regexCache = new Map();
5
5