befly 3.24.8 → 3.24.10

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.
@@ -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 {
@@ -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/")) {
@@ -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;
@@ -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);
@@ -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,
package/lib/dbUtil.js CHANGED
@@ -507,6 +507,12 @@ 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, (_match, left, dot, right) => {
512
+ return `${snakeCase(left)}${dot}${snakeCase(right)}`;
513
+ });
514
+ }
515
+
510
516
  export function processJoinOn(on) {
511
517
  if (!isString(on)) {
512
518
  return String(on);
@@ -517,12 +523,6 @@ export function processJoinOn(on) {
517
523
  return raw;
518
524
  }
519
525
 
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
526
  let result = "";
527
527
  let buffer = "";
528
528
  let quote = null;
@@ -540,7 +540,7 @@ export function processJoinOn(on) {
540
540
 
541
541
  if (ch === "'" || ch === '"' || ch === "`") {
542
542
  if (buffer.length > 0) {
543
- result += replaceSegment(buffer);
543
+ result += replaceJoinOnSegment(buffer);
544
544
  buffer = "";
545
545
  }
546
546
  quote = ch;
@@ -554,7 +554,7 @@ export function processJoinOn(on) {
554
554
  }
555
555
 
556
556
  if (buffer.length > 0) {
557
- result += replaceSegment(buffer);
557
+ result += replaceJoinOnSegment(buffer);
558
558
  }
559
559
 
560
560
  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() 影响。
package/lib/sqlBuilder.js CHANGED
@@ -3,8 +3,8 @@
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 构建器类
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"]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "befly",
3
- "version": "3.24.8",
3
+ "version": "3.24.10",
4
4
  "gitHead": "49c39d36695036e85fc64083cc43c1652fff96cb",
5
5
  "private": false,
6
6
  "description": "Befly - 为 Bun 专属打造的 JavaScript API 接口框架核心引擎",
package/plugins/email.js CHANGED
@@ -3,9 +3,10 @@
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
12
  async handler(befly) {
@@ -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