midway-fatcms 0.0.18 → 0.0.20

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/.prettierrc.js CHANGED
@@ -1,4 +1,5 @@
1
1
  module.exports = {
2
2
  ...require('mwts/.prettierrc.json'),
3
3
  printWidth: 500, // 与ESLint的max-len保持一致
4
+ endOfLine: 'crlf',
4
5
  }
@@ -28,7 +28,7 @@ let ProxyApiMangeApi = class ProxyApiMangeApi extends BaseApiController_1.BaseAp
28
28
  return this.executeSysSimpleSQL(SystemTables_1.SystemTables.sys_proxyapi, keys_1.KeysOfSimpleSQL.SIMPLE_INSERT, {
29
29
  validateCfg: {
30
30
  'data.proxy_name': [keys_1.KeysOfValidators.REQUIRED, keys_1.KeysOfValidators.STRING],
31
- 'data.path_prefix': [keys_1.KeysOfValidators.REQUIRED, keys_1.KeysOfValidators.STRING],
31
+ 'data.path_prefix': [keys_1.KeysOfValidators.STRING],
32
32
  'data.upstream_code': [keys_1.KeysOfValidators.REQUIRED, keys_1.KeysOfValidators.STRING],
33
33
  },
34
34
  });
@@ -37,6 +37,7 @@ let ProxyApiMangeApi = class ProxyApiMangeApi extends BaseApiController_1.BaseAp
37
37
  return this.executeSysSimpleSQL(SystemTables_1.SystemTables.sys_proxyapi, keys_1.KeysOfSimpleSQL.SIMPLE_UPDATE, {
38
38
  validateCfg: {
39
39
  'condition.id': [keys_1.KeysOfValidators.REQUIRED, keys_1.KeysOfValidators.NUMERIC],
40
+ 'data.path_prefix': [keys_1.KeysOfValidators.STRING],
40
41
  },
41
42
  });
42
43
  }
@@ -13,23 +13,9 @@ const REGEX_STRING_TYPE = /^(varchar|char|text|longtext|mediumtext|tinytext|nvar
13
13
  /** PG / MySQL 原生 boolean 列名 */
14
14
  const REGEX_NATIVE_BOOLEAN_TYPE = /^(boolean|bool)$/;
15
15
  /** 含 WHERE 条件的操作类型(查询/删除/更新) */
16
- const CONDITION_TYPES = new Set([
17
- keys_1.KeysOfSimpleSQL.SIMPLE_QUERY,
18
- keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_ONE,
19
- keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_PAGE,
20
- keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_COUNT,
21
- keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_EXIST,
22
- keys_1.KeysOfSimpleSQL.SIMPLE_DELETE,
23
- keys_1.KeysOfSimpleSQL.SIMPLE_UPDATE,
24
- ]);
16
+ const CONDITION_TYPES = new Set([keys_1.KeysOfSimpleSQL.SIMPLE_QUERY, keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_ONE, keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_PAGE, keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_COUNT, keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_EXIST, keys_1.KeysOfSimpleSQL.SIMPLE_DELETE, keys_1.KeysOfSimpleSQL.SIMPLE_UPDATE]);
25
17
  /** INSERT/UPDATE 操作类型 */
26
- const INSERT_OR_UPDATE_TYPES = new Set([
27
- keys_1.KeysOfSimpleSQL.SIMPLE_INSERT,
28
- keys_1.KeysOfSimpleSQL.SIMPLE_UPDATE,
29
- keys_1.KeysOfSimpleSQL.SIMPLE_INSERT_ON_DUPLICATE_UPDATE,
30
- keys_1.KeysOfSimpleSQL.SIMPLE_INSERT_OR_UPDATE,
31
- keys_1.KeysOfSimpleSQL.SIMPLE_BATCH_INSERT,
32
- ]);
18
+ const INSERT_OR_UPDATE_TYPES = new Set([keys_1.KeysOfSimpleSQL.SIMPLE_INSERT, keys_1.KeysOfSimpleSQL.SIMPLE_UPDATE, keys_1.KeysOfSimpleSQL.SIMPLE_INSERT_ON_DUPLICATE_UPDATE, keys_1.KeysOfSimpleSQL.SIMPLE_INSERT_OR_UPDATE, keys_1.KeysOfSimpleSQL.SIMPLE_BATCH_INSERT]);
33
19
  // ============ 工具函数 ============
34
20
  function isIntegerType(type) {
35
21
  return REGEX_INTEGER_TYPE.test(type);
@@ -265,9 +251,7 @@ class DataConvertHandler {
265
251
  if (typeof value === 'boolean') {
266
252
  return value ? 't' : 'f';
267
253
  }
268
- const escaped = ('' + value)
269
- .replace(/\\/g, '\\\\')
270
- .replace(/"/g, '\\"');
254
+ const escaped = ('' + value).replace(/\\/g, '\\\\').replace(/"/g, '\\"');
271
255
  return '"' + escaped + '"';
272
256
  }
273
257
  /** 对象/数组 → JSON 字符串,跳过 $sqlFunc、Date、Buffer */
@@ -1,19 +1,27 @@
1
1
  /**
2
- * 128 位雪花 ID 生成器(独立于 MixinUtils.generateSnowflakeId,原 63 位算法不变)
2
+ * 128 位雪花 ID 生成器(优化版)
3
3
  *
4
4
  * 位布局(128 bit,无符号,BigInt 拼接后 Base58 编码返回):
5
- * - 64 bit 时间戳:相对 2024-01-01 00:00:00 UTC 的毫秒偏移
6
- * - 16 bit 机器ID:0-65535,优先参数 > 环境变量 SNOWFLAKE_MACHINE_ID > process.pid 低 16 位
7
- * - 48 bit 序列号:同一毫秒内自增,约 2.8e14 个/ms,实际不会耗尽
5
+ * - 41 bit 时间戳:相对 2024-01-01 00:00:00 UTC 的毫秒偏移,可用约 69 年(至 ~2093 年)
6
+ * - 10 bit 机器ID:0-1023,与标准 64 位雪花 ID 一致,优先参数 > 环境变量 > process.pid
7
+ * - 77 bit 序列号:同一毫秒内自增,2^77 ≈ 1.5×10²³,无需考虑耗尽
8
8
  *
9
- * 输出:Bitcoin 字母表 Base58(无 0/O/I/l),当前约 21 字符,理论最大 22 字符,建议 VARCHAR(24)
9
+ * 输出:Bitcoin 字母表 Base58(无 0/O/I/l),左填充 '1' 至恒定 22 字符,建议 VARCHAR(24)
10
+ * 时间戳在高位,ID 随时间单调递增,适合做数据库主键。
11
+ * 2^128-1 < 58^22,故 22 字符足以覆盖全部 128 位取值范围。
10
12
  */
11
13
  declare const EPOCH: bigint;
12
14
  /**
13
- * 生成 128 位雪花 ID(Base58 字符串)
15
+ * 生成 128 位雪花 ID(Base58 字符串,恒定 22 字符)
14
16
  *
15
- * @param machineId 机器ID(0-65535),不传则依次从环境变量 SNOWFLAKE_MACHINE_ID、process.pid 获取
16
- * @returns Base58 编码的 128 位雪花 ID
17
+ * 位布局:41 bit 时间戳 | 10 bit 机器ID | 77 bit 序列号
18
+ * 时间戳采用 41 bit(与标准 64 位雪花 ID 一致),毫秒精度,可用约 69 年。
19
+ * 机器ID 采用 10 bit(0-1023),与标准 64 位雪花 ID 一致,防止多机 ID 冲突。
20
+ * 时间戳在高位,ID 随时间单调递增,适合做数据库主键。
21
+ * Base58 输出左填充 '1'(零字符)至 22 字符,保证长度恒定且不破坏字典序排序。
22
+ *
23
+ * @param machineId 机器ID(0-1023),不传则依次从环境变量 SNOWFLAKE_MACHINE_ID、process.pid 获取
24
+ * @returns Base58 编码的 128 位雪花 ID(恒定 22 字符)
17
25
  */
18
26
  declare function generateSnowflakeIdExt(machineId?: number): string;
19
27
  export { generateSnowflakeIdExt, EPOCH as SNOWFLAKE_EXT_EPOCH };
@@ -1,22 +1,27 @@
1
1
  "use strict";
2
2
  /**
3
- * 128 位雪花 ID 生成器(独立于 MixinUtils.generateSnowflakeId,原 63 位算法不变)
3
+ * 128 位雪花 ID 生成器(优化版)
4
4
  *
5
5
  * 位布局(128 bit,无符号,BigInt 拼接后 Base58 编码返回):
6
- * - 64 bit 时间戳:相对 2024-01-01 00:00:00 UTC 的毫秒偏移
7
- * - 16 bit 机器ID:0-65535,优先参数 > 环境变量 SNOWFLAKE_MACHINE_ID > process.pid 低 16 位
8
- * - 48 bit 序列号:同一毫秒内自增,约 2.8e14 个/ms,实际不会耗尽
6
+ * - 41 bit 时间戳:相对 2024-01-01 00:00:00 UTC 的毫秒偏移,可用约 69 年(至 ~2093 年)
7
+ * - 10 bit 机器ID:0-1023,与标准 64 位雪花 ID 一致,优先参数 > 环境变量 > process.pid
8
+ * - 77 bit 序列号:同一毫秒内自增,2^77 ≈ 1.5×10²³,无需考虑耗尽
9
9
  *
10
- * 输出:Bitcoin 字母表 Base58(无 0/O/I/l),当前约 21 字符,理论最大 22 字符,建议 VARCHAR(24)
10
+ * 输出:Bitcoin 字母表 Base58(无 0/O/I/l),左填充 '1' 至恒定 22 字符,建议 VARCHAR(24)
11
+ * 时间戳在高位,ID 随时间单调递增,适合做数据库主键。
12
+ * 2^128-1 < 58^22,故 22 字符足以覆盖全部 128 位取值范围。
11
13
  */
12
14
  Object.defineProperty(exports, "__esModule", { value: true });
13
15
  exports.SNOWFLAKE_EXT_EPOCH = exports.generateSnowflakeIdExt = void 0;
14
16
  const EPOCH = BigInt(1704067200000); // 2024-01-01 00:00:00 UTC
15
17
  exports.SNOWFLAKE_EXT_EPOCH = EPOCH;
16
- const TS_SHIFT = BigInt(64);
17
- const MID_SHIFT = BigInt(48);
18
- const MID_MASK = BigInt(0xffff);
19
- const SEQ_MASK = BigInt('0xffffffffffff'); // 48 bit
18
+ const TS_BITS = BigInt(41);
19
+ const MID_BITS = BigInt(10);
20
+ const SEQ_BITS = BigInt(77);
21
+ const TS_MASK = (BigInt(1) << TS_BITS) - BigInt(1); // 41 bit
22
+ const MID_MASK = (BigInt(1) << MID_BITS) - BigInt(1); // 10 bit
23
+ const SEQ_MASK = (BigInt(1) << SEQ_BITS) - BigInt(1); // 77 bit
24
+ const PAD_LENGTH = 22;
20
25
  const SEQ_START = BigInt(1);
21
26
  const DRIFT_TOLERANCE = BigInt(5);
22
27
  /** Bitcoin Base58 字母表 */
@@ -38,7 +43,7 @@ function encodeBase58(value) {
38
43
  }
39
44
  return result;
40
45
  }
41
- /** 解析机器 ID(16 bit) */
46
+ /** 解析机器 ID(10 bit,0-1023) */
42
47
  function resolveMachineId(machineId) {
43
48
  var _a;
44
49
  let mid = Number(machineId);
@@ -55,10 +60,16 @@ function resolveMachineId(machineId) {
55
60
  return BigInt(Math.abs(mid)) & MID_MASK;
56
61
  }
57
62
  /**
58
- * 生成 128 位雪花 ID(Base58 字符串)
63
+ * 生成 128 位雪花 ID(Base58 字符串,恒定 22 字符)
59
64
  *
60
- * @param machineId 机器ID(0-65535),不传则依次从环境变量 SNOWFLAKE_MACHINE_ID、process.pid 获取
61
- * @returns Base58 编码的 128 位雪花 ID
65
+ * 位布局:41 bit 时间戳 | 10 bit 机器ID | 77 bit 序列号
66
+ * 时间戳采用 41 bit(与标准 64 位雪花 ID 一致),毫秒精度,可用约 69 年。
67
+ * 机器ID 采用 10 bit(0-1023),与标准 64 位雪花 ID 一致,防止多机 ID 冲突。
68
+ * 时间戳在高位,ID 随时间单调递增,适合做数据库主键。
69
+ * Base58 输出左填充 '1'(零字符)至 22 字符,保证长度恒定且不破坏字典序排序。
70
+ *
71
+ * @param machineId 机器ID(0-1023),不传则依次从环境变量 SNOWFLAKE_MACHINE_ID、process.pid 获取
72
+ * @returns Base58 编码的 128 位雪花 ID(恒定 22 字符)
62
73
  */
63
74
  function generateSnowflakeIdExt(machineId) {
64
75
  const mid = resolveMachineId(machineId);
@@ -74,16 +85,12 @@ function generateSnowflakeIdExt(machineId) {
74
85
  }
75
86
  if (ts === snowflakeExtLastTs) {
76
87
  snowflakeExtSeq = (snowflakeExtSeq + BigInt(1)) & SEQ_MASK;
77
- if (snowflakeExtSeq === BigInt(0)) {
78
- ts = snowflakeExtLastTs + BigInt(1);
79
- snowflakeExtSeq = SEQ_START;
80
- }
81
88
  }
82
89
  else {
83
90
  snowflakeExtSeq = SEQ_START;
84
91
  }
85
92
  snowflakeExtLastTs = ts;
86
- const id = (ts << TS_SHIFT) | (mid << MID_SHIFT) | snowflakeExtSeq;
87
- return encodeBase58(id);
93
+ const id = ((ts & TS_MASK) << (MID_BITS + SEQ_BITS)) | (mid << SEQ_BITS) | snowflakeExtSeq;
94
+ return encodeBase58(id).padStart(PAD_LENGTH, BASE58_ALPHABET[0]);
88
95
  }
89
96
  exports.generateSnowflakeIdExt = generateSnowflakeIdExt;
@@ -1,6 +1,6 @@
1
- import { KeysOfSimpleSQL } from "../../libs/crud-pro/models/keys";
2
- import { IRequestModel, IVisitor } from "../../libs/crud-pro/interfaces";
3
- import { IRequestCfgModel2 } from "./models";
1
+ import { KeysOfSimpleSQL } from '../../libs/crud-pro/models/keys';
2
+ import { IRequestModel, IVisitor } from '../../libs/crud-pro/interfaces';
3
+ import { IRequestCfgModel2 } from './models';
4
4
  /**
5
5
  * 软删除处理函数
6
6
  *
@@ -10,4 +10,4 @@ import { IRequestCfgModel2 } from "./models";
10
10
  * @param visitor 获取当前用户信息的函数(用于软删除时记录删除人)
11
11
  */
12
12
  declare function fixSoftDelete(oldSqlSimpleName: KeysOfSimpleSQL, cfgModel: IRequestCfgModel2, params: IRequestModel, visitor?: IVisitor): void;
13
- export { fixSoftDelete, };
13
+ export { fixSoftDelete };
@@ -43,9 +43,7 @@ function fixSoftDelete1(oldSqlSimpleName, cfgModel, params, visitor) {
43
43
  cfgModel.sqlSimpleName = keys_1.KeysOfSimpleSQL.SIMPLE_UPDATE;
44
44
  }
45
45
  // QUERY 操作:强制查询未删除的记录
46
- if (keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_ONE === oldSqlSimpleName
47
- || keys_1.KeysOfSimpleSQL.SIMPLE_QUERY === oldSqlSimpleName
48
- || keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_PAGE === oldSqlSimpleName) {
46
+ if (keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_ONE === oldSqlSimpleName || keys_1.KeysOfSimpleSQL.SIMPLE_QUERY === oldSqlSimpleName || keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_PAGE === oldSqlSimpleName) {
49
47
  if (!params.condition) {
50
48
  params.condition = {};
51
49
  }
@@ -78,9 +76,7 @@ function fixSoftDelete2(oldSqlSimpleName, cfgModel, params, visitor) {
78
76
  cfgModel.sqlSimpleName = keys_1.KeysOfSimpleSQL.SIMPLE_UPDATE;
79
77
  }
80
78
  // QUERY 操作:强制查询未删除的记录
81
- if (keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_ONE === oldSqlSimpleName
82
- || keys_1.KeysOfSimpleSQL.SIMPLE_QUERY === oldSqlSimpleName
83
- || keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_PAGE === oldSqlSimpleName) {
79
+ if (keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_ONE === oldSqlSimpleName || keys_1.KeysOfSimpleSQL.SIMPLE_QUERY === oldSqlSimpleName || keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_PAGE === oldSqlSimpleName) {
84
80
  if (!params.condition) {
85
81
  params.condition = {};
86
82
  }
@@ -1,7 +1,7 @@
1
1
  import { ColumnRelation, IRequestCfgModel, IRequestModel, ISqlCfgModel, ITableListResult, ITableNamesOptions, ITableNamesQuery, ExecuteSQLResult } from '../../libs/crud-pro/interfaces';
2
2
  import { IRequestCfgModel2 } from '../../models/bizmodels';
3
3
  import { ExecuteContext } from '../../libs/crud-pro/models/ExecuteContext';
4
- import { ShardingBase } from "../../libs/crud-sharding";
4
+ import { ShardingBase } from '../../libs/crud-sharding';
5
5
  import { IGetQuickCrudParam, IGetShardingCrudParam } from './CurdProService';
6
6
  export interface ILinkColumnRelationParam {
7
7
  columnsRelations: ColumnRelation[];
@@ -76,7 +76,8 @@ let ProxyApiLoadService = class ProxyApiLoadService extends BaseService_1.BaseSe
76
76
  for (let i = 0; i < entities.length; i++) {
77
77
  const entity = entities[i];
78
78
  if (entity.status === 1) {
79
- const path_prefix2 = '/' + entity.upstream_code + entity.path_prefix;
79
+ const pathPrefix = (0, ProxyApiUtils_1.normalizePathPrefix)(entity.path_prefix);
80
+ const path_prefix2 = '/' + entity.upstream_code + pathPrefix;
80
81
  routeTrie.addRoute(path_prefix2, new RouteHandler_1.RouteHandler(entity));
81
82
  }
82
83
  }
@@ -12,4 +12,6 @@ export declare const BALANCE_STRATEGY: {
12
12
  * @param str
13
13
  * @param mod
14
14
  */
15
+ /** path_prefix 为空表示代理上游根路径;单独的 "/" 会在路由树中注册无效节点,统一归一化为空 */
16
+ export declare function normalizePathPrefix(path_prefix: string | null | undefined): string;
15
17
  export declare function stringHashMod(str: string, mod: number): number;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.stringHashMod = exports.BALANCE_STRATEGY = void 0;
3
+ exports.stringHashMod = exports.normalizePathPrefix = exports.BALANCE_STRATEGY = void 0;
4
4
  const md5 = require("md5");
5
5
  exports.BALANCE_STRATEGY = {
6
6
  ROUND_ROBIN: 'ROUND_ROBIN',
@@ -16,6 +16,14 @@ exports.BALANCE_STRATEGY = {
16
16
  * @param str
17
17
  * @param mod
18
18
  */
19
+ /** path_prefix 为空表示代理上游根路径;单独的 "/" 会在路由树中注册无效节点,统一归一化为空 */
20
+ function normalizePathPrefix(path_prefix) {
21
+ if (path_prefix === '/' || path_prefix == null) {
22
+ return '';
23
+ }
24
+ return path_prefix;
25
+ }
26
+ exports.normalizePathPrefix = normalizePathPrefix;
19
27
  function stringHashMod(str, mod) {
20
28
  if (!str) {
21
29
  throw new Error('stringHashMod str is required');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "midway-fatcms",
3
- "version": "0.0.18",
3
+ "version": "0.0.20",
4
4
  "description": "This is a midway component sample",
5
5
  "main": "dist/index.js",
6
6
  "typings": "index.d.ts",
@@ -36,16 +36,17 @@ export class HomeController extends BaseApiController {
36
36
  return this.ctx.render('404_workbench', infos);
37
37
  }
38
38
 
39
-
40
39
  const html_content = workbenchInfo.html_content || '未配置HTML模版';
41
40
 
42
41
  const userInfo = await this.getUserAndRefreshSessionInfo();
43
42
 
44
43
  // 形如(不带域名):/ns/app/abc-app-path?aa=2332
45
- const urlcsrftoken = await privateAES.time_encrypt_utf8_base64(JSON.stringify({
46
- url: this.ctx.req.url,
47
- timestamp: Date.now(),
48
- }));
44
+ const urlcsrftoken = await privateAES.time_encrypt_utf8_base64(
45
+ JSON.stringify({
46
+ url: this.ctx.req.url,
47
+ timestamp: Date.now(),
48
+ })
49
+ );
49
50
  const fatcmscsrftoken = await privateAES.time_encrypt_utf8_base64('' + Date.now());
50
51
 
51
52
  const utils = createRenderUtils({
@@ -70,7 +71,6 @@ export class HomeController extends BaseApiController {
70
71
  return await this.authService.refreshSession(userSessionInfo);
71
72
  }
72
73
 
73
-
74
74
  @Get('/robots.txt')
75
75
  async robots(): Promise<string> {
76
76
  return `User-agent: * \nDisallow: /ns/api/manage/`;
@@ -27,7 +27,7 @@ export class ProxyApiMangeApi extends BaseApiController {
27
27
  return this.executeSysSimpleSQL(SystemTables.sys_proxyapi, KeysOfSimpleSQL.SIMPLE_INSERT, {
28
28
  validateCfg: {
29
29
  'data.proxy_name': [KeysOfValidators.REQUIRED, KeysOfValidators.STRING],
30
- 'data.path_prefix': [KeysOfValidators.REQUIRED, KeysOfValidators.STRING],
30
+ 'data.path_prefix': [KeysOfValidators.STRING],
31
31
  'data.upstream_code': [KeysOfValidators.REQUIRED, KeysOfValidators.STRING],
32
32
  },
33
33
  });
@@ -38,6 +38,7 @@ export class ProxyApiMangeApi extends BaseApiController {
38
38
  return this.executeSysSimpleSQL(SystemTables.sys_proxyapi, KeysOfSimpleSQL.SIMPLE_UPDATE, {
39
39
  validateCfg: {
40
40
  'condition.id': [KeysOfValidators.REQUIRED, KeysOfValidators.NUMERIC],
41
+ 'data.path_prefix': [KeysOfValidators.STRING],
41
42
  },
42
43
  });
43
44
  }