midway-fatcms 0.0.7 → 0.0.9
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/.qoder/skills/midway-fatcms/01-quick-start.md +231 -0
- package/.qoder/skills/midway-fatcms/02-crud-quick.md +375 -0
- package/.qoder/skills/midway-fatcms/03-crud-sharding.md +489 -0
- package/.qoder/skills/midway-fatcms/04-condition-operators.md +93 -0
- package/.qoder/skills/midway-fatcms/05-configuration.md +290 -0
- package/.qoder/skills/midway-fatcms/06-builtin-functions.md +241 -0
- package/.qoder/skills/midway-fatcms/07-examples.md +504 -0
- package/.qoder/skills/midway-fatcms/SKILL.md +96 -0
- package/README.md +9 -9
- package/dist/configuration.d.ts +10 -0
- package/dist/configuration.js +26 -0
- package/dist/controller/base/BaseApiController.d.ts +1 -2
- package/dist/controller/base/BaseApiController.js +0 -4
- package/dist/controller/gateway/DocGatewayController.js +1 -1
- package/dist/controller/helpers.controller.d.ts +6 -0
- package/dist/controller/helpers.controller.js +19 -0
- package/dist/controller/manage/FlowConfigManageApi.js +4 -2
- package/dist/controller/manage/SysConfigMangeApi.js +6 -1
- package/dist/controller/manage/UserAccountManageApi.js +7 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/libs/crud-pro/CrudPro.d.ts +51 -3
- package/dist/libs/crud-pro/CrudPro.js +111 -4
- package/dist/libs/crud-pro/exceptions.d.ts +7 -0
- package/dist/libs/crud-pro/exceptions.js +7 -0
- package/dist/libs/crud-pro/interfaces.d.ts +83 -12
- package/dist/libs/crud-pro/models/CrudResult.d.ts +116 -0
- package/dist/libs/crud-pro/models/CrudResult.js +126 -0
- package/dist/libs/crud-pro/models/RequestModel.d.ts +2 -2
- package/dist/libs/crud-pro/models/ServiceHub.d.ts +2 -0
- package/dist/libs/crud-pro/services/CrudProDataTypeConvertService.d.ts +70 -2
- package/dist/libs/crud-pro/services/CrudProDataTypeConvertService.js +205 -13
- package/dist/libs/crud-pro/services/CrudProExecuteSqlService.js +36 -2
- package/dist/libs/crud-pro/services/CrudProGenSqlCondition.js +8 -4
- package/dist/libs/crud-pro/services/CrudProTableMetaService.d.ts +36 -0
- package/dist/libs/crud-pro/services/CrudProTableMetaService.js +97 -4
- package/dist/libs/crud-pro/services/CurdProServiceHub.d.ts +2 -0
- package/dist/libs/crud-pro/services/CurdProServiceHub.js +6 -0
- package/dist/libs/crud-pro-quick/CrudProQuick.d.ts +382 -0
- package/dist/libs/crud-pro-quick/CrudProQuick.js +689 -0
- package/dist/libs/crud-pro-quick/fixSoftDelete.d.ts +30 -0
- package/dist/{service/curd → libs/crud-pro-quick}/fixSoftDelete.js +3 -6
- package/dist/libs/crud-pro-quick/index.d.ts +36 -0
- package/dist/libs/crud-pro-quick/index.js +49 -0
- package/dist/libs/crud-pro-quick/models.d.ts +33 -0
- package/dist/libs/crud-pro-quick/models.js +2 -0
- package/dist/libs/crud-sharding/ShardingBase.d.ts +78 -0
- package/dist/libs/crud-sharding/ShardingBase.js +179 -0
- package/dist/libs/crud-sharding/ShardingByCustomCrud.d.ts +35 -0
- package/dist/libs/crud-sharding/ShardingByCustomCrud.js +297 -0
- package/dist/libs/crud-sharding/ShardingByHashCrud.d.ts +38 -0
- package/dist/libs/crud-sharding/ShardingByHashCrud.js +86 -0
- package/dist/libs/crud-sharding/ShardingByKeyCrud.d.ts +39 -0
- package/dist/libs/crud-sharding/ShardingByKeyCrud.js +74 -0
- package/dist/libs/crud-sharding/ShardingByTimeCrud.d.ts +66 -0
- package/dist/libs/crud-sharding/ShardingByTimeCrud.js +524 -0
- package/dist/libs/crud-sharding/ShardingConfig.d.ts +25 -10
- package/dist/libs/crud-sharding/ShardingConfig.js +5 -5
- package/dist/libs/crud-sharding/ShardingMerger.d.ts +10 -18
- package/dist/libs/crud-sharding/ShardingMerger.js +27 -44
- package/dist/libs/crud-sharding/ShardingResult.d.ts +33 -0
- package/dist/libs/crud-sharding/ShardingResult.js +16 -0
- package/dist/libs/crud-sharding/ShardingTableCreator.d.ts +21 -4
- package/dist/libs/crud-sharding/ShardingTableCreator.js +193 -59
- package/dist/libs/crud-sharding/ShardingUtils.d.ts +48 -0
- package/dist/libs/crud-sharding/ShardingUtils.js +122 -1
- package/dist/libs/crud-sharding/TIME_COLUMN_CLEAN_SPEC.md +488 -0
- package/dist/libs/crud-sharding/index.d.ts +13 -15
- package/dist/libs/crud-sharding/index.js +33 -17
- package/dist/models/RedisKeys.d.ts +1 -0
- package/dist/models/RedisKeys.js +1 -0
- package/dist/models/bizmodels.d.ts +2 -6
- package/dist/service/SysAppService.d.ts +2 -2
- package/dist/service/SysAppService.js +16 -5
- package/dist/service/SysConfigService.d.ts +1 -1
- package/dist/service/SysConfigService.js +7 -2
- package/dist/service/SysDictDataService.js +14 -4
- package/dist/service/SysMenuService.js +7 -2
- package/dist/service/TableMetaCacheRedisSubscriber.d.ts +31 -0
- package/dist/service/TableMetaCacheRedisSubscriber.js +98 -0
- package/dist/service/curd/CurdMixService.d.ts +6 -4
- package/dist/service/curd/CurdMixService.js +16 -2
- package/dist/service/curd/CurdProService.d.ts +149 -29
- package/dist/service/curd/CurdProService.js +157 -38
- package/dist/service/flow/FlowConfigService.js +7 -2
- package/dist/service/flow/FlowInstanceCrudService.js +22 -19
- package/package.json +1 -1
- package/src/configuration.ts +27 -0
- package/src/controller/base/BaseApiController.ts +0 -5
- package/src/controller/gateway/DocGatewayController.ts +1 -1
- package/src/controller/helpers.controller.ts +15 -0
- package/src/controller/manage/CrudStandardDesignApi.ts +4 -3
- package/src/controller/manage/FlowConfigManageApi.ts +4 -2
- package/src/controller/manage/SysConfigMangeApi.ts +6 -1
- package/src/controller/manage/UserAccountManageApi.ts +7 -2
- package/src/index.ts +2 -2
- package/src/libs/crud-pro/CrudPro.ts +134 -7
- package/src/libs/crud-pro/exceptions.ts +8 -0
- package/src/libs/crud-pro/interfaces.ts +111 -15
- package/src/libs/crud-pro/models/CrudResult.ts +178 -0
- package/src/libs/crud-pro/models/RequestModel.ts +2 -2
- package/src/libs/crud-pro/models/ServiceHub.ts +4 -0
- package/src/libs/crud-pro/services/CrudProDataTypeConvertService.ts +238 -15
- package/src/libs/crud-pro/services/CrudProExecuteSqlService.ts +41 -2
- package/src/libs/crud-pro/services/CrudProGenSqlCondition.ts +11 -7
- package/src/libs/crud-pro/services/CrudProTableMetaService.ts +110 -3
- package/src/libs/crud-pro/services/CurdProServiceHub.ts +8 -0
- package/src/libs/crud-pro-quick/CrudProQuick.ts +782 -0
- package/src/{service/curd → libs/crud-pro-quick}/fixSoftDelete.ts +23 -13
- package/src/libs/crud-pro-quick/index.ts +52 -0
- package/src/libs/crud-pro-quick/models.ts +35 -0
- package/src/libs/crud-sharding/ShardingBase.ts +256 -0
- package/src/libs/crud-sharding/ShardingByCustomCrud.ts +329 -0
- package/src/libs/crud-sharding/ShardingByHashCrud.ts +111 -0
- package/src/libs/crud-sharding/ShardingByKeyCrud.ts +97 -0
- package/src/libs/crud-sharding/ShardingByTimeCrud.ts +628 -0
- package/src/libs/crud-sharding/ShardingConfig.ts +28 -10
- package/src/libs/crud-sharding/ShardingMerger.ts +35 -63
- package/src/libs/crud-sharding/ShardingResult.ts +29 -0
- package/src/libs/crud-sharding/ShardingTableCreator.ts +214 -71
- package/src/libs/crud-sharding/ShardingUtils.ts +137 -0
- package/src/libs/crud-sharding/TIME_COLUMN_CLEAN_SPEC.md +488 -0
- package/src/libs/crud-sharding/index.ts +30 -16
- package/src/models/RedisKeys.ts +1 -0
- package/src/models/bizmodels.ts +4 -7
- package/src/service/SysAppService.ts +18 -7
- package/src/service/SysConfigService.ts +8 -3
- package/src/service/SysDictDataService.ts +14 -4
- package/src/service/SysMenuService.ts +7 -2
- package/src/service/TableMetaCacheRedisSubscriber.ts +105 -0
- package/src/service/crudstd/CrudStdService.ts +2 -2
- package/src/service/curd/CurdMixService.ts +26 -5
- package/src/service/curd/CurdProService.ts +186 -45
- package/src/service/flow/FlowConfigService.ts +7 -2
- package/src/service/flow/FlowInstanceCrudService.ts +23 -20
- package/.qoder/skills/midway-fatcms-crud/SKILL.md +0 -375
- package/.qoder/skills/midway-fatcms-crud/examples.md +0 -990
- package/.qoder/skills/midway-fatcms-crud/reference.md +0 -568
- package/dist/libs/crud-pro/README.md +0 -809
- package/dist/libs/crud-pro/README_FUNC.md +0 -193
- package/dist/libs/crud-sharding/ROUTING_LOGIC.md +0 -944
- package/dist/libs/crud-sharding/ShardingCrudPro.d.ts +0 -363
- package/dist/libs/crud-sharding/ShardingCrudPro.js +0 -675
- package/dist/libs/crud-sharding/ShardingRouter.d.ts +0 -69
- package/dist/libs/crud-sharding/ShardingRouter.js +0 -377
- package/dist/models/StandardColumns.d.ts +0 -71
- package/dist/models/StandardColumns.js +0 -28
- package/dist/service/curd/CrudProQuick.d.ts +0 -190
- package/dist/service/curd/CrudProQuick.js +0 -319
- package/dist/service/curd/README.md +0 -1100
- package/dist/service/curd/fixSoftDelete.d.ts +0 -20
- package/src/libs/crud-pro/README.md +0 -809
- package/src/libs/crud-pro/README_FUNC.md +0 -193
- package/src/libs/crud-sharding/ROUTING_LOGIC.md +0 -944
- package/src/libs/crud-sharding/ShardingCrudPro.ts +0 -835
- package/src/libs/crud-sharding/ShardingRouter.ts +0 -512
- package/src/models/StandardColumns.ts +0 -76
- package/src/service/curd/CrudProQuick.ts +0 -360
- package/src/service/curd/README.md +0 -1100
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { IShardingConfig, IShardingRouterContext } from './ShardingConfig';
|
|
2
|
-
/**
|
|
3
|
-
* 表信息提供者接口
|
|
4
|
-
* 用于获取数据库中真实存在的表
|
|
5
|
-
*/
|
|
6
|
-
export interface ITableInfoProvider {
|
|
7
|
-
/**
|
|
8
|
-
* 获取所有真实存在的表名
|
|
9
|
-
* @returns 表名集合
|
|
10
|
-
*/
|
|
11
|
-
getExistingTables(): Promise<Set<string>>;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* 分表路由器
|
|
15
|
-
*/
|
|
16
|
-
export declare class ShardingRouter {
|
|
17
|
-
/**
|
|
18
|
-
* 插入类操作专用路由(从 data 提取字段)
|
|
19
|
-
*/
|
|
20
|
-
resolveForInsert(config: IShardingConfig, context: IShardingRouterContext): string;
|
|
21
|
-
/**
|
|
22
|
-
* 条件类操作专用路由(从 condition 提取字段)
|
|
23
|
-
*/
|
|
24
|
-
resolveForCondition(config: IShardingConfig, context: IShardingRouterContext): string | string[];
|
|
25
|
-
/**
|
|
26
|
-
* 查询专用路由(带表存在性过滤)
|
|
27
|
-
*/
|
|
28
|
-
resolveQuery(config: IShardingConfig, context: IShardingRouterContext, tableInfoProvider: ITableInfoProvider): Promise<string[]>;
|
|
29
|
-
/**
|
|
30
|
-
* 过滤出真实存在的分表
|
|
31
|
-
*/
|
|
32
|
-
filterExistingTables(candidateTables: string | string[], existingTables: Set<string>): string[];
|
|
33
|
-
private validateConfig;
|
|
34
|
-
private resolveTimeForInsert;
|
|
35
|
-
private resolveTimeForCondition;
|
|
36
|
-
private resolveRangeForInsert;
|
|
37
|
-
private resolveRangeForCondition;
|
|
38
|
-
private resolveHashForInsert;
|
|
39
|
-
private resolveHashForCondition;
|
|
40
|
-
private resolveCustomForInsert;
|
|
41
|
-
private resolveCustomForCondition;
|
|
42
|
-
private isTimeSharding;
|
|
43
|
-
private getRecentExistingTablesFromAll;
|
|
44
|
-
private intersectWithCondition;
|
|
45
|
-
private intersectTablesByTimeRange;
|
|
46
|
-
/**
|
|
47
|
-
* 将分表按时间后缀降序排列(新→旧)
|
|
48
|
-
*
|
|
49
|
-
* 分表名格式为 baseTable_suffix,后缀为时间格式(如 202403、20240101),
|
|
50
|
-
* 字典序即时间序,降序即新→旧。
|
|
51
|
-
*/
|
|
52
|
-
private sortTablesByTimeDesc;
|
|
53
|
-
private extractFromData;
|
|
54
|
-
private extractFromCondition;
|
|
55
|
-
private parseTimeValue;
|
|
56
|
-
private parseColumnValue;
|
|
57
|
-
private extractTimeFromData;
|
|
58
|
-
private tryExtractTimeFromCondition;
|
|
59
|
-
private extractTimeRange;
|
|
60
|
-
private extractColumnFromData;
|
|
61
|
-
private extractColumnFromCondition;
|
|
62
|
-
private generateTablesInRange;
|
|
63
|
-
private getRecentTables;
|
|
64
|
-
private getRecentCountByGranularity;
|
|
65
|
-
private calculateRangeIndex;
|
|
66
|
-
private calculateHash;
|
|
67
|
-
private simpleHash;
|
|
68
|
-
private formatTableName;
|
|
69
|
-
}
|
|
@@ -1,377 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ShardingRouter = void 0;
|
|
4
|
-
const moment = require("moment");
|
|
5
|
-
const ShardingConfig_1 = require("./ShardingConfig");
|
|
6
|
-
const ShardingUtils_1 = require("./ShardingUtils");
|
|
7
|
-
/**
|
|
8
|
-
* 空值合并(兼容低版本 Node.js)
|
|
9
|
-
* 返回第一个非 null/undefined 的值
|
|
10
|
-
*/
|
|
11
|
-
function coalesce(a, b) {
|
|
12
|
-
return a !== null && a !== undefined ? a : b;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* 分表路由器
|
|
16
|
-
*/
|
|
17
|
-
class ShardingRouter {
|
|
18
|
-
// ============ Public 方法 ============
|
|
19
|
-
/**
|
|
20
|
-
* 插入类操作专用路由(从 data 提取字段)
|
|
21
|
-
*/
|
|
22
|
-
resolveForInsert(config, context) {
|
|
23
|
-
this.validateConfig(config);
|
|
24
|
-
switch (config.type) {
|
|
25
|
-
case ShardingConfig_1.ShardingType.YEAR:
|
|
26
|
-
return this.resolveTimeForInsert(config, context, 'year');
|
|
27
|
-
case ShardingConfig_1.ShardingType.MONTH:
|
|
28
|
-
return this.resolveTimeForInsert(config, context, 'month');
|
|
29
|
-
case ShardingConfig_1.ShardingType.DAY:
|
|
30
|
-
return this.resolveTimeForInsert(config, context, 'day');
|
|
31
|
-
case ShardingConfig_1.ShardingType.RANGE:
|
|
32
|
-
return this.resolveRangeForInsert(config, context);
|
|
33
|
-
case ShardingConfig_1.ShardingType.HASH:
|
|
34
|
-
return this.resolveHashForInsert(config, context);
|
|
35
|
-
case ShardingConfig_1.ShardingType.CUSTOM:
|
|
36
|
-
return this.resolveCustomForInsert(config, context);
|
|
37
|
-
default:
|
|
38
|
-
return config.baseTable;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* 条件类操作专用路由(从 condition 提取字段)
|
|
43
|
-
*/
|
|
44
|
-
resolveForCondition(config, context) {
|
|
45
|
-
this.validateConfig(config);
|
|
46
|
-
switch (config.type) {
|
|
47
|
-
case ShardingConfig_1.ShardingType.YEAR:
|
|
48
|
-
return this.resolveTimeForCondition(config, context, 'year');
|
|
49
|
-
case ShardingConfig_1.ShardingType.MONTH:
|
|
50
|
-
return this.resolveTimeForCondition(config, context, 'month');
|
|
51
|
-
case ShardingConfig_1.ShardingType.DAY:
|
|
52
|
-
return this.resolveTimeForCondition(config, context, 'day');
|
|
53
|
-
case ShardingConfig_1.ShardingType.RANGE:
|
|
54
|
-
return this.resolveRangeForCondition(config, context);
|
|
55
|
-
case ShardingConfig_1.ShardingType.HASH:
|
|
56
|
-
return this.resolveHashForCondition(config, context);
|
|
57
|
-
case ShardingConfig_1.ShardingType.CUSTOM:
|
|
58
|
-
return this.resolveCustomForCondition(config, context);
|
|
59
|
-
default:
|
|
60
|
-
return config.baseTable;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* 查询专用路由(带表存在性过滤)
|
|
65
|
-
*/
|
|
66
|
-
async resolveQuery(config, context, tableInfoProvider) {
|
|
67
|
-
const existingTables = await tableInfoProvider.getExistingTables();
|
|
68
|
-
// 时间分表:从真实存在的表中取最近N张,再与条件取交集
|
|
69
|
-
if (this.isTimeSharding(config)) {
|
|
70
|
-
return this.getRecentExistingTablesFromAll(existingTables, config, context.condition);
|
|
71
|
-
}
|
|
72
|
-
// 非时间分表:先计算候选表,再过滤存在的表
|
|
73
|
-
const candidateResult = this.resolveForCondition(config, context);
|
|
74
|
-
const candidateTables = Array.isArray(candidateResult)
|
|
75
|
-
? candidateResult
|
|
76
|
-
: [candidateResult];
|
|
77
|
-
return this.filterExistingTables(candidateTables, existingTables);
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* 过滤出真实存在的分表
|
|
81
|
-
*/
|
|
82
|
-
filterExistingTables(candidateTables, existingTables) {
|
|
83
|
-
const candidates = Array.isArray(candidateTables) ? candidateTables : [candidateTables];
|
|
84
|
-
return candidates.filter(table => existingTables.has(table));
|
|
85
|
-
}
|
|
86
|
-
// ============ 配置校验 ============
|
|
87
|
-
validateConfig(config) {
|
|
88
|
-
if (!config.baseTable) {
|
|
89
|
-
throw new Error('[ShardingRouter] baseTable 不能为空');
|
|
90
|
-
}
|
|
91
|
-
if ((config.type === ShardingConfig_1.ShardingType.RANGE || config.type === ShardingConfig_1.ShardingType.HASH) && !config.shardingColumn) {
|
|
92
|
-
throw new Error(`[ShardingRouter] ${config.type} 分表必须指定 shardingColumn`);
|
|
93
|
-
}
|
|
94
|
-
if (config.type === ShardingConfig_1.ShardingType.CUSTOM && !config.customRouter) {
|
|
95
|
-
throw new Error('[ShardingRouter] CUSTOM 分表必须提供 customRouter 函数');
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
// ============ 时间分表路由 ============
|
|
99
|
-
resolveTimeForInsert(config, context, granularity) {
|
|
100
|
-
const { baseTable, timeColumn } = config;
|
|
101
|
-
const timeValue = this.extractTimeFromData(context.data, timeColumn);
|
|
102
|
-
const suffix = (0, ShardingUtils_1.getTimeSuffix)(timeValue, granularity);
|
|
103
|
-
return this.formatTableName(baseTable, suffix, config);
|
|
104
|
-
}
|
|
105
|
-
resolveTimeForCondition(config, context, granularity) {
|
|
106
|
-
const { baseTable, timeColumn } = config;
|
|
107
|
-
const condition = context.condition || {};
|
|
108
|
-
const timeRange = this.extractTimeRange(condition, timeColumn);
|
|
109
|
-
const singleTimeValue = this.tryExtractTimeFromCondition(condition, timeColumn);
|
|
110
|
-
if (timeRange) {
|
|
111
|
-
return this.generateTablesInRange(baseTable, timeRange.start, timeRange.end, granularity, config);
|
|
112
|
-
}
|
|
113
|
-
if (singleTimeValue) {
|
|
114
|
-
const suffix = (0, ShardingUtils_1.getTimeSuffix)(singleTimeValue, granularity);
|
|
115
|
-
return this.formatTableName(baseTable, suffix, config);
|
|
116
|
-
}
|
|
117
|
-
const recentCount = this.getRecentCountByGranularity(granularity, config);
|
|
118
|
-
return this.getRecentTables(baseTable, granularity, recentCount, config);
|
|
119
|
-
}
|
|
120
|
-
// ============ 范围分表路由 ============
|
|
121
|
-
resolveRangeForInsert(config, context) {
|
|
122
|
-
const { baseTable, tableCount = 10, shardingColumn } = config;
|
|
123
|
-
const value = this.extractColumnFromData(context.data, shardingColumn);
|
|
124
|
-
const index = this.calculateRangeIndex(value, tableCount);
|
|
125
|
-
return this.formatTableName(baseTable, String(index), config);
|
|
126
|
-
}
|
|
127
|
-
resolveRangeForCondition(config, context) {
|
|
128
|
-
const { baseTable, tableCount = 10, shardingColumn } = config;
|
|
129
|
-
const value = this.extractColumnFromCondition(context.condition, shardingColumn);
|
|
130
|
-
const index = this.calculateRangeIndex(value, tableCount);
|
|
131
|
-
return this.formatTableName(baseTable, String(index), config);
|
|
132
|
-
}
|
|
133
|
-
// ============ 哈希分表路由 ============
|
|
134
|
-
resolveHashForInsert(config, context) {
|
|
135
|
-
const { baseTable, tableCount = 16, shardingColumn } = config;
|
|
136
|
-
const value = this.extractColumnFromData(context.data, shardingColumn);
|
|
137
|
-
const index = this.calculateHash(value, tableCount);
|
|
138
|
-
return this.formatTableName(baseTable, String(index).padStart(2, '0'), config);
|
|
139
|
-
}
|
|
140
|
-
resolveHashForCondition(config, context) {
|
|
141
|
-
const { baseTable, tableCount = 16, shardingColumn } = config;
|
|
142
|
-
const value = this.extractColumnFromCondition(context.condition, shardingColumn);
|
|
143
|
-
const index = this.calculateHash(value, tableCount);
|
|
144
|
-
return this.formatTableName(baseTable, String(index).padStart(2, '0'), config);
|
|
145
|
-
}
|
|
146
|
-
// ============ 自定义分表路由 ============
|
|
147
|
-
resolveCustomForInsert(config, context) {
|
|
148
|
-
const result = config.customRouter(context);
|
|
149
|
-
return Array.isArray(result) ? result[0] : result;
|
|
150
|
-
}
|
|
151
|
-
resolveCustomForCondition(config, context) {
|
|
152
|
-
return config.customRouter(context);
|
|
153
|
-
}
|
|
154
|
-
// ============ 查询相关私有方法 ============
|
|
155
|
-
isTimeSharding(config) {
|
|
156
|
-
return [ShardingConfig_1.ShardingType.YEAR, ShardingConfig_1.ShardingType.MONTH, ShardingConfig_1.ShardingType.DAY].includes(config.type);
|
|
157
|
-
}
|
|
158
|
-
getRecentExistingTablesFromAll(existingTables, config, condition) {
|
|
159
|
-
const baseTablePrefix = `${config.baseTable}_`;
|
|
160
|
-
const shardingTables = Array.from(existingTables).filter(t => t.startsWith(baseTablePrefix));
|
|
161
|
-
if (shardingTables.length === 0) {
|
|
162
|
-
return [];
|
|
163
|
-
}
|
|
164
|
-
shardingTables.sort();
|
|
165
|
-
// 配置了 recentTableCount:取最近N张,再与条件取交集
|
|
166
|
-
if (config.recentTableCount !== undefined) {
|
|
167
|
-
const recentTables = shardingTables.slice(-config.recentTableCount);
|
|
168
|
-
return this.intersectWithCondition(recentTables, config, condition);
|
|
169
|
-
}
|
|
170
|
-
// 未配置 recentTableCount:所有表与条件取交集,最多取3张
|
|
171
|
-
const intersected = this.intersectWithCondition(shardingTables, config, condition);
|
|
172
|
-
return intersected.slice(0, 3);
|
|
173
|
-
}
|
|
174
|
-
intersectWithCondition(tables, config, condition) {
|
|
175
|
-
if (!condition) {
|
|
176
|
-
return this.sortTablesByTimeDesc(tables);
|
|
177
|
-
}
|
|
178
|
-
const timeColumn = config.timeColumn;
|
|
179
|
-
const timeRange = this.extractTimeRange(condition, timeColumn);
|
|
180
|
-
if (timeRange) {
|
|
181
|
-
return this.intersectTablesByTimeRange(tables, timeRange, config);
|
|
182
|
-
}
|
|
183
|
-
const singleTimeValue = this.tryExtractTimeFromCondition(condition, timeColumn);
|
|
184
|
-
if (singleTimeValue) {
|
|
185
|
-
const suffix = (0, ShardingUtils_1.getTimeSuffix)(singleTimeValue, config.type);
|
|
186
|
-
const targetTable = `${config.baseTable}_${suffix}`;
|
|
187
|
-
return tables.includes(targetTable) ? [targetTable] : [];
|
|
188
|
-
}
|
|
189
|
-
return this.sortTablesByTimeDesc(tables);
|
|
190
|
-
}
|
|
191
|
-
intersectTablesByTimeRange(tables, timeRange, config) {
|
|
192
|
-
const startSuffix = (0, ShardingUtils_1.getTimeSuffix)(timeRange.start, config.type);
|
|
193
|
-
const endSuffix = (0, ShardingUtils_1.getTimeSuffix)(timeRange.end, config.type);
|
|
194
|
-
const baseTablePrefix = `${config.baseTable}_`;
|
|
195
|
-
const prefixLen = baseTablePrefix.length;
|
|
196
|
-
return this.sortTablesByTimeDesc(tables.filter(table => {
|
|
197
|
-
const suffix = table.substring(prefixLen);
|
|
198
|
-
return suffix >= startSuffix && suffix <= endSuffix;
|
|
199
|
-
}));
|
|
200
|
-
}
|
|
201
|
-
// ============ 排序 ============
|
|
202
|
-
/**
|
|
203
|
-
* 将分表按时间后缀降序排列(新→旧)
|
|
204
|
-
*
|
|
205
|
-
* 分表名格式为 baseTable_suffix,后缀为时间格式(如 202403、20240101),
|
|
206
|
-
* 字典序即时间序,降序即新→旧。
|
|
207
|
-
*/
|
|
208
|
-
sortTablesByTimeDesc(tables) {
|
|
209
|
-
return [...tables].sort((a, b) => b.localeCompare(a));
|
|
210
|
-
}
|
|
211
|
-
// ============ 值提取:基础方法 ============
|
|
212
|
-
extractFromData(data, column) {
|
|
213
|
-
return data === null || data === void 0 ? void 0 : data[column];
|
|
214
|
-
}
|
|
215
|
-
extractFromCondition(condition, column) {
|
|
216
|
-
return condition === null || condition === void 0 ? void 0 : condition[column];
|
|
217
|
-
}
|
|
218
|
-
parseTimeValue(value, source, operation) {
|
|
219
|
-
if (value === undefined || value === null) {
|
|
220
|
-
throw new Error(`[ShardingRouter] ${operation} 操作无法从 ${source} 中获取时间分表字段的值`);
|
|
221
|
-
}
|
|
222
|
-
const m = moment(value);
|
|
223
|
-
if (!m.isValid()) {
|
|
224
|
-
throw new Error(`[ShardingRouter] 无法解析时间分表字段的值:${value}`);
|
|
225
|
-
}
|
|
226
|
-
return m.toDate();
|
|
227
|
-
}
|
|
228
|
-
parseColumnValue(value, source, operation) {
|
|
229
|
-
if (value === undefined || value === null) {
|
|
230
|
-
throw new Error(`[ShardingRouter] ${operation} 操作无法从 ${source} 中获取分表字段的值`);
|
|
231
|
-
}
|
|
232
|
-
return value;
|
|
233
|
-
}
|
|
234
|
-
// ============ 值提取:时间字段 ============
|
|
235
|
-
extractTimeFromData(data, column) {
|
|
236
|
-
const value = this.extractFromData(data, column);
|
|
237
|
-
return this.parseTimeValue(value, 'data', 'insert');
|
|
238
|
-
}
|
|
239
|
-
tryExtractTimeFromCondition(condition, column) {
|
|
240
|
-
const value = this.extractFromCondition(condition, column);
|
|
241
|
-
if (value === undefined || value === null) {
|
|
242
|
-
return null;
|
|
243
|
-
}
|
|
244
|
-
const m = moment(value);
|
|
245
|
-
if (!m.isValid()) {
|
|
246
|
-
return null;
|
|
247
|
-
}
|
|
248
|
-
return m.toDate();
|
|
249
|
-
}
|
|
250
|
-
extractTimeRange(condition, column) {
|
|
251
|
-
const colCond = condition[column];
|
|
252
|
-
if (!colCond || typeof colCond !== 'object')
|
|
253
|
-
return null;
|
|
254
|
-
const start = coalesce(colCond.$gte, colCond.$gt);
|
|
255
|
-
const end = coalesce(colCond.$lte, colCond.$lt);
|
|
256
|
-
if (start && end) {
|
|
257
|
-
const startMoment = moment(start);
|
|
258
|
-
const endMoment = moment(end);
|
|
259
|
-
if (!startMoment.isValid() || !endMoment.isValid()) {
|
|
260
|
-
return null;
|
|
261
|
-
}
|
|
262
|
-
return {
|
|
263
|
-
start: startMoment.toDate(),
|
|
264
|
-
end: endMoment.toDate(),
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
if (start) {
|
|
268
|
-
const startMoment = moment(start);
|
|
269
|
-
if (!startMoment.isValid()) {
|
|
270
|
-
return null;
|
|
271
|
-
}
|
|
272
|
-
return {
|
|
273
|
-
start: startMoment.toDate(),
|
|
274
|
-
end: new Date(),
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
if (end) {
|
|
278
|
-
const endMoment = moment(end);
|
|
279
|
-
if (!endMoment.isValid()) {
|
|
280
|
-
return null;
|
|
281
|
-
}
|
|
282
|
-
return {
|
|
283
|
-
start: new Date(0),
|
|
284
|
-
end: endMoment.toDate(),
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
return null;
|
|
288
|
-
}
|
|
289
|
-
// ============ 值提取:分表字段 ============
|
|
290
|
-
extractColumnFromData(data, column) {
|
|
291
|
-
const value = this.extractFromData(data, column);
|
|
292
|
-
return this.parseColumnValue(value, 'data', 'insert');
|
|
293
|
-
}
|
|
294
|
-
extractColumnFromCondition(condition, column) {
|
|
295
|
-
const value = this.extractFromCondition(condition, column);
|
|
296
|
-
return this.parseColumnValue(value, 'condition', '查询/更新/删除');
|
|
297
|
-
}
|
|
298
|
-
// ============ 时间处理 ============
|
|
299
|
-
generateTablesInRange(baseTable, start, end, granularity, config) {
|
|
300
|
-
const tables = [];
|
|
301
|
-
const current = moment(start);
|
|
302
|
-
const maxTables = 100;
|
|
303
|
-
while (current.toDate() <= end && tables.length < maxTables) {
|
|
304
|
-
const suffix = (0, ShardingUtils_1.getTimeSuffix)(current.toDate(), granularity);
|
|
305
|
-
tables.push(this.formatTableName(baseTable, suffix, config));
|
|
306
|
-
switch (granularity) {
|
|
307
|
-
case 'year':
|
|
308
|
-
current.add(1, 'year');
|
|
309
|
-
break;
|
|
310
|
-
case 'month':
|
|
311
|
-
current.add(1, 'month');
|
|
312
|
-
break;
|
|
313
|
-
case 'day':
|
|
314
|
-
current.add(1, 'day');
|
|
315
|
-
break;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
return tables;
|
|
319
|
-
}
|
|
320
|
-
getRecentTables(baseTable, granularity, count, config) {
|
|
321
|
-
const tables = [];
|
|
322
|
-
const current = moment();
|
|
323
|
-
for (let i = 0; i < count; i++) {
|
|
324
|
-
const suffix = (0, ShardingUtils_1.getTimeSuffix)(current.toDate(), granularity);
|
|
325
|
-
tables.unshift(this.formatTableName(baseTable, suffix, config));
|
|
326
|
-
switch (granularity) {
|
|
327
|
-
case 'year':
|
|
328
|
-
current.subtract(1, 'year');
|
|
329
|
-
break;
|
|
330
|
-
case 'month':
|
|
331
|
-
current.subtract(1, 'month');
|
|
332
|
-
break;
|
|
333
|
-
case 'day':
|
|
334
|
-
current.subtract(1, 'day');
|
|
335
|
-
break;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
return tables;
|
|
339
|
-
}
|
|
340
|
-
getRecentCountByGranularity(granularity, config) {
|
|
341
|
-
if (config.recentTableCount !== undefined && config.recentTableCount > 0) {
|
|
342
|
-
return config.recentTableCount;
|
|
343
|
-
}
|
|
344
|
-
switch (granularity) {
|
|
345
|
-
case 'year':
|
|
346
|
-
return 3;
|
|
347
|
-
case 'month':
|
|
348
|
-
return 12;
|
|
349
|
-
case 'day':
|
|
350
|
-
return 7;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
// ============ 计算相关 ============
|
|
354
|
-
calculateRangeIndex(value, count) {
|
|
355
|
-
if (typeof value === 'number') {
|
|
356
|
-
return Math.abs(value) % count;
|
|
357
|
-
}
|
|
358
|
-
return Math.abs(this.simpleHash(String(value))) % count;
|
|
359
|
-
}
|
|
360
|
-
calculateHash(value, count) {
|
|
361
|
-
return Math.abs(this.simpleHash(String(value))) % count;
|
|
362
|
-
}
|
|
363
|
-
simpleHash(str) {
|
|
364
|
-
let hash = 5381;
|
|
365
|
-
for (let i = 0; i < str.length; i++) {
|
|
366
|
-
hash = ((hash << 5) + hash) + str.charCodeAt(i);
|
|
367
|
-
hash = hash & hash;
|
|
368
|
-
}
|
|
369
|
-
return hash;
|
|
370
|
-
}
|
|
371
|
-
// ============ 格式化 ============
|
|
372
|
-
formatTableName(baseTable, suffix, config) {
|
|
373
|
-
const formattedSuffix = config.suffixFormatter ? config.suffixFormatter(suffix) : suffix;
|
|
374
|
-
return `${baseTable}_${formattedSuffix}`;
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
exports.ShardingRouter = ShardingRouter;
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 标准表结构字段类型定义
|
|
3
|
-
*
|
|
4
|
-
* 常用标准字段(推荐所有表都包含):
|
|
5
|
-
* - deleted_at: 软删除标记,0=未删除,时间戳=已删除
|
|
6
|
-
* - deleted_by: 删除人ID
|
|
7
|
-
* - created_by: 创建人ID
|
|
8
|
-
* - created_at: 创建时间
|
|
9
|
-
* - modified_by: 最后修改人ID
|
|
10
|
-
* - modified_at: 最后修改时间
|
|
11
|
-
*
|
|
12
|
-
* 完整标准字段(需要记录详细用户信息时使用):
|
|
13
|
-
* - created_account_type: 创建人账号类型
|
|
14
|
-
* - created_avatar: 创建人头像
|
|
15
|
-
* - created_nickname: 创建人昵称
|
|
16
|
-
* - modified_account_type: 修改人账号类型
|
|
17
|
-
* - modified_avatar: 修改人头像
|
|
18
|
-
* - modified_nickname: 修改人昵称
|
|
19
|
-
*/
|
|
20
|
-
/**
|
|
21
|
-
* 常用标准表结构字段(6个字段)
|
|
22
|
-
*
|
|
23
|
-
* 推荐所有业务表都包含这些字段:
|
|
24
|
-
* - deleted_at: 删除时间戳,0=未删除
|
|
25
|
-
* - deleted_by: 删除人ID
|
|
26
|
-
* - created_by: 创建人ID
|
|
27
|
-
* - created_at: 创建时间(毫秒时间戳)
|
|
28
|
-
* - modified_by: 修改人ID
|
|
29
|
-
* - modified_at: 修改时间(毫秒时间戳)
|
|
30
|
-
*/
|
|
31
|
-
export interface ICommonStandardColumns {
|
|
32
|
-
deleted_at?: number;
|
|
33
|
-
deleted_by?: string;
|
|
34
|
-
created_by?: string;
|
|
35
|
-
created_at?: number;
|
|
36
|
-
modified_by?: string;
|
|
37
|
-
modified_at?: number;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* 完整标准表结构字段(12个字段)
|
|
41
|
-
*
|
|
42
|
-
* 在常用字段基础上增加用户详细信息:
|
|
43
|
-
* - created_account_type: 创建人账号类型
|
|
44
|
-
* - created_avatar: 创建人头像URL
|
|
45
|
-
* - created_nickname: 创建人昵称
|
|
46
|
-
* - modified_account_type: 修改人账号类型
|
|
47
|
-
* - modified_avatar: 修改人头像URL
|
|
48
|
-
* - modified_nickname: 修改人昵称
|
|
49
|
-
*/
|
|
50
|
-
export interface IFullStandardColumns extends ICommonStandardColumns {
|
|
51
|
-
created_account_type?: string;
|
|
52
|
-
created_avatar?: string;
|
|
53
|
-
created_nickname?: string;
|
|
54
|
-
modified_account_type?: string;
|
|
55
|
-
modified_avatar?: string;
|
|
56
|
-
modified_nickname?: string;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* 包含常用标准字段的数据模型
|
|
60
|
-
*/
|
|
61
|
-
export declare type StandardDataModel<T = {}> = T & ICommonStandardColumns;
|
|
62
|
-
/**
|
|
63
|
-
* 包含完整标准字段的数据模型
|
|
64
|
-
*/
|
|
65
|
-
export declare type FullStandardDataModel<T = {}> = T & IFullStandardColumns;
|
|
66
|
-
/**
|
|
67
|
-
* 未删除查询条件
|
|
68
|
-
*/
|
|
69
|
-
export declare const NotDeletedCondition: {
|
|
70
|
-
deleted_at: 0;
|
|
71
|
-
};
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* 标准表结构字段类型定义
|
|
4
|
-
*
|
|
5
|
-
* 常用标准字段(推荐所有表都包含):
|
|
6
|
-
* - deleted_at: 软删除标记,0=未删除,时间戳=已删除
|
|
7
|
-
* - deleted_by: 删除人ID
|
|
8
|
-
* - created_by: 创建人ID
|
|
9
|
-
* - created_at: 创建时间
|
|
10
|
-
* - modified_by: 最后修改人ID
|
|
11
|
-
* - modified_at: 最后修改时间
|
|
12
|
-
*
|
|
13
|
-
* 完整标准字段(需要记录详细用户信息时使用):
|
|
14
|
-
* - created_account_type: 创建人账号类型
|
|
15
|
-
* - created_avatar: 创建人头像
|
|
16
|
-
* - created_nickname: 创建人昵称
|
|
17
|
-
* - modified_account_type: 修改人账号类型
|
|
18
|
-
* - modified_avatar: 修改人头像
|
|
19
|
-
* - modified_nickname: 修改人昵称
|
|
20
|
-
*/
|
|
21
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.NotDeletedCondition = void 0;
|
|
23
|
-
/**
|
|
24
|
-
* 未删除查询条件
|
|
25
|
-
*/
|
|
26
|
-
exports.NotDeletedCondition = {
|
|
27
|
-
deleted_at: 0,
|
|
28
|
-
};
|