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.
Files changed (159) hide show
  1. package/.qoder/skills/midway-fatcms/01-quick-start.md +231 -0
  2. package/.qoder/skills/midway-fatcms/02-crud-quick.md +375 -0
  3. package/.qoder/skills/midway-fatcms/03-crud-sharding.md +489 -0
  4. package/.qoder/skills/midway-fatcms/04-condition-operators.md +93 -0
  5. package/.qoder/skills/midway-fatcms/05-configuration.md +290 -0
  6. package/.qoder/skills/midway-fatcms/06-builtin-functions.md +241 -0
  7. package/.qoder/skills/midway-fatcms/07-examples.md +504 -0
  8. package/.qoder/skills/midway-fatcms/SKILL.md +96 -0
  9. package/README.md +9 -9
  10. package/dist/configuration.d.ts +10 -0
  11. package/dist/configuration.js +26 -0
  12. package/dist/controller/base/BaseApiController.d.ts +1 -2
  13. package/dist/controller/base/BaseApiController.js +0 -4
  14. package/dist/controller/gateway/DocGatewayController.js +1 -1
  15. package/dist/controller/helpers.controller.d.ts +6 -0
  16. package/dist/controller/helpers.controller.js +19 -0
  17. package/dist/controller/manage/FlowConfigManageApi.js +4 -2
  18. package/dist/controller/manage/SysConfigMangeApi.js +6 -1
  19. package/dist/controller/manage/UserAccountManageApi.js +7 -2
  20. package/dist/index.d.ts +2 -2
  21. package/dist/index.js +2 -2
  22. package/dist/libs/crud-pro/CrudPro.d.ts +51 -3
  23. package/dist/libs/crud-pro/CrudPro.js +111 -4
  24. package/dist/libs/crud-pro/exceptions.d.ts +7 -0
  25. package/dist/libs/crud-pro/exceptions.js +7 -0
  26. package/dist/libs/crud-pro/interfaces.d.ts +83 -12
  27. package/dist/libs/crud-pro/models/CrudResult.d.ts +116 -0
  28. package/dist/libs/crud-pro/models/CrudResult.js +126 -0
  29. package/dist/libs/crud-pro/models/RequestModel.d.ts +2 -2
  30. package/dist/libs/crud-pro/models/ServiceHub.d.ts +2 -0
  31. package/dist/libs/crud-pro/services/CrudProDataTypeConvertService.d.ts +70 -2
  32. package/dist/libs/crud-pro/services/CrudProDataTypeConvertService.js +205 -13
  33. package/dist/libs/crud-pro/services/CrudProExecuteSqlService.js +36 -2
  34. package/dist/libs/crud-pro/services/CrudProGenSqlCondition.js +8 -4
  35. package/dist/libs/crud-pro/services/CrudProTableMetaService.d.ts +36 -0
  36. package/dist/libs/crud-pro/services/CrudProTableMetaService.js +97 -4
  37. package/dist/libs/crud-pro/services/CurdProServiceHub.d.ts +2 -0
  38. package/dist/libs/crud-pro/services/CurdProServiceHub.js +6 -0
  39. package/dist/libs/crud-pro-quick/CrudProQuick.d.ts +382 -0
  40. package/dist/libs/crud-pro-quick/CrudProQuick.js +689 -0
  41. package/dist/libs/crud-pro-quick/fixSoftDelete.d.ts +30 -0
  42. package/dist/{service/curd → libs/crud-pro-quick}/fixSoftDelete.js +3 -6
  43. package/dist/libs/crud-pro-quick/index.d.ts +36 -0
  44. package/dist/libs/crud-pro-quick/index.js +49 -0
  45. package/dist/libs/crud-pro-quick/models.d.ts +33 -0
  46. package/dist/libs/crud-pro-quick/models.js +2 -0
  47. package/dist/libs/crud-sharding/ShardingBase.d.ts +78 -0
  48. package/dist/libs/crud-sharding/ShardingBase.js +179 -0
  49. package/dist/libs/crud-sharding/ShardingByCustomCrud.d.ts +35 -0
  50. package/dist/libs/crud-sharding/ShardingByCustomCrud.js +297 -0
  51. package/dist/libs/crud-sharding/ShardingByHashCrud.d.ts +38 -0
  52. package/dist/libs/crud-sharding/ShardingByHashCrud.js +86 -0
  53. package/dist/libs/crud-sharding/ShardingByKeyCrud.d.ts +39 -0
  54. package/dist/libs/crud-sharding/ShardingByKeyCrud.js +74 -0
  55. package/dist/libs/crud-sharding/ShardingByTimeCrud.d.ts +66 -0
  56. package/dist/libs/crud-sharding/ShardingByTimeCrud.js +524 -0
  57. package/dist/libs/crud-sharding/ShardingConfig.d.ts +25 -10
  58. package/dist/libs/crud-sharding/ShardingConfig.js +5 -5
  59. package/dist/libs/crud-sharding/ShardingMerger.d.ts +10 -18
  60. package/dist/libs/crud-sharding/ShardingMerger.js +27 -44
  61. package/dist/libs/crud-sharding/ShardingResult.d.ts +33 -0
  62. package/dist/libs/crud-sharding/ShardingResult.js +16 -0
  63. package/dist/libs/crud-sharding/ShardingTableCreator.d.ts +21 -4
  64. package/dist/libs/crud-sharding/ShardingTableCreator.js +193 -59
  65. package/dist/libs/crud-sharding/ShardingUtils.d.ts +48 -0
  66. package/dist/libs/crud-sharding/ShardingUtils.js +122 -1
  67. package/dist/libs/crud-sharding/TIME_COLUMN_CLEAN_SPEC.md +488 -0
  68. package/dist/libs/crud-sharding/index.d.ts +13 -15
  69. package/dist/libs/crud-sharding/index.js +33 -17
  70. package/dist/models/RedisKeys.d.ts +1 -0
  71. package/dist/models/RedisKeys.js +1 -0
  72. package/dist/models/bizmodels.d.ts +2 -6
  73. package/dist/service/SysAppService.d.ts +2 -2
  74. package/dist/service/SysAppService.js +16 -5
  75. package/dist/service/SysConfigService.d.ts +1 -1
  76. package/dist/service/SysConfigService.js +7 -2
  77. package/dist/service/SysDictDataService.js +14 -4
  78. package/dist/service/SysMenuService.js +7 -2
  79. package/dist/service/TableMetaCacheRedisSubscriber.d.ts +31 -0
  80. package/dist/service/TableMetaCacheRedisSubscriber.js +98 -0
  81. package/dist/service/curd/CurdMixService.d.ts +6 -4
  82. package/dist/service/curd/CurdMixService.js +16 -2
  83. package/dist/service/curd/CurdProService.d.ts +149 -29
  84. package/dist/service/curd/CurdProService.js +157 -38
  85. package/dist/service/flow/FlowConfigService.js +7 -2
  86. package/dist/service/flow/FlowInstanceCrudService.js +22 -19
  87. package/package.json +1 -1
  88. package/src/configuration.ts +27 -0
  89. package/src/controller/base/BaseApiController.ts +0 -5
  90. package/src/controller/gateway/DocGatewayController.ts +1 -1
  91. package/src/controller/helpers.controller.ts +15 -0
  92. package/src/controller/manage/CrudStandardDesignApi.ts +4 -3
  93. package/src/controller/manage/FlowConfigManageApi.ts +4 -2
  94. package/src/controller/manage/SysConfigMangeApi.ts +6 -1
  95. package/src/controller/manage/UserAccountManageApi.ts +7 -2
  96. package/src/index.ts +2 -2
  97. package/src/libs/crud-pro/CrudPro.ts +134 -7
  98. package/src/libs/crud-pro/exceptions.ts +8 -0
  99. package/src/libs/crud-pro/interfaces.ts +111 -15
  100. package/src/libs/crud-pro/models/CrudResult.ts +178 -0
  101. package/src/libs/crud-pro/models/RequestModel.ts +2 -2
  102. package/src/libs/crud-pro/models/ServiceHub.ts +4 -0
  103. package/src/libs/crud-pro/services/CrudProDataTypeConvertService.ts +238 -15
  104. package/src/libs/crud-pro/services/CrudProExecuteSqlService.ts +41 -2
  105. package/src/libs/crud-pro/services/CrudProGenSqlCondition.ts +11 -7
  106. package/src/libs/crud-pro/services/CrudProTableMetaService.ts +110 -3
  107. package/src/libs/crud-pro/services/CurdProServiceHub.ts +8 -0
  108. package/src/libs/crud-pro-quick/CrudProQuick.ts +782 -0
  109. package/src/{service/curd → libs/crud-pro-quick}/fixSoftDelete.ts +23 -13
  110. package/src/libs/crud-pro-quick/index.ts +52 -0
  111. package/src/libs/crud-pro-quick/models.ts +35 -0
  112. package/src/libs/crud-sharding/ShardingBase.ts +256 -0
  113. package/src/libs/crud-sharding/ShardingByCustomCrud.ts +329 -0
  114. package/src/libs/crud-sharding/ShardingByHashCrud.ts +111 -0
  115. package/src/libs/crud-sharding/ShardingByKeyCrud.ts +97 -0
  116. package/src/libs/crud-sharding/ShardingByTimeCrud.ts +628 -0
  117. package/src/libs/crud-sharding/ShardingConfig.ts +28 -10
  118. package/src/libs/crud-sharding/ShardingMerger.ts +35 -63
  119. package/src/libs/crud-sharding/ShardingResult.ts +29 -0
  120. package/src/libs/crud-sharding/ShardingTableCreator.ts +214 -71
  121. package/src/libs/crud-sharding/ShardingUtils.ts +137 -0
  122. package/src/libs/crud-sharding/TIME_COLUMN_CLEAN_SPEC.md +488 -0
  123. package/src/libs/crud-sharding/index.ts +30 -16
  124. package/src/models/RedisKeys.ts +1 -0
  125. package/src/models/bizmodels.ts +4 -7
  126. package/src/service/SysAppService.ts +18 -7
  127. package/src/service/SysConfigService.ts +8 -3
  128. package/src/service/SysDictDataService.ts +14 -4
  129. package/src/service/SysMenuService.ts +7 -2
  130. package/src/service/TableMetaCacheRedisSubscriber.ts +105 -0
  131. package/src/service/crudstd/CrudStdService.ts +2 -2
  132. package/src/service/curd/CurdMixService.ts +26 -5
  133. package/src/service/curd/CurdProService.ts +186 -45
  134. package/src/service/flow/FlowConfigService.ts +7 -2
  135. package/src/service/flow/FlowInstanceCrudService.ts +23 -20
  136. package/.qoder/skills/midway-fatcms-crud/SKILL.md +0 -375
  137. package/.qoder/skills/midway-fatcms-crud/examples.md +0 -990
  138. package/.qoder/skills/midway-fatcms-crud/reference.md +0 -568
  139. package/dist/libs/crud-pro/README.md +0 -809
  140. package/dist/libs/crud-pro/README_FUNC.md +0 -193
  141. package/dist/libs/crud-sharding/ROUTING_LOGIC.md +0 -944
  142. package/dist/libs/crud-sharding/ShardingCrudPro.d.ts +0 -363
  143. package/dist/libs/crud-sharding/ShardingCrudPro.js +0 -675
  144. package/dist/libs/crud-sharding/ShardingRouter.d.ts +0 -69
  145. package/dist/libs/crud-sharding/ShardingRouter.js +0 -377
  146. package/dist/models/StandardColumns.d.ts +0 -71
  147. package/dist/models/StandardColumns.js +0 -28
  148. package/dist/service/curd/CrudProQuick.d.ts +0 -190
  149. package/dist/service/curd/CrudProQuick.js +0 -319
  150. package/dist/service/curd/README.md +0 -1100
  151. package/dist/service/curd/fixSoftDelete.d.ts +0 -20
  152. package/src/libs/crud-pro/README.md +0 -809
  153. package/src/libs/crud-pro/README_FUNC.md +0 -193
  154. package/src/libs/crud-sharding/ROUTING_LOGIC.md +0 -944
  155. package/src/libs/crud-sharding/ShardingCrudPro.ts +0 -835
  156. package/src/libs/crud-sharding/ShardingRouter.ts +0 -512
  157. package/src/models/StandardColumns.ts +0 -76
  158. package/src/service/curd/CrudProQuick.ts +0 -360
  159. package/src/service/curd/README.md +0 -1100
@@ -27,6 +27,8 @@ const global_middleware_1 = require("./middleware/global.middleware");
27
27
  const forbidden_middleware_1 = require("./middleware/forbidden.middleware");
28
28
  const schedule_1 = require("./schedule");
29
29
  const crypto_utils_1 = require("./libs/utils/crypto-utils");
30
+ const TableMetaCacheRedisSubscriber_1 = require("./service/TableMetaCacheRedisSubscriber");
31
+ const redis_1 = require("@midwayjs/redis");
30
32
  let ContainerLifeCycle = class ContainerLifeCycle {
31
33
  async onConfigLoad() {
32
34
  const config = this.app.getConfig();
@@ -53,6 +55,10 @@ let ContainerLifeCycle = class ContainerLifeCycle {
53
55
  * 让ANONYMOUS_CONTEXT获取app对象
54
56
  */
55
57
  schedule_1.ANONYMOUS_CONTEXT.setApp(this.app);
58
+ /**
59
+ * 初始化表元数据缓存 Redis 广播
60
+ */
61
+ await this.initTableMetaCacheRedis();
56
62
  /**
57
63
  * 启动定时任务
58
64
  */
@@ -63,6 +69,26 @@ let ContainerLifeCycle = class ContainerLifeCycle {
63
69
  // add filter
64
70
  // this.app.useFilter([NotFoundFilter, DefaultErrorFilter]);
65
71
  }
72
+ /**
73
+ * 初始化表元数据缓存的 Redis Pub/Sub 广播
74
+ *
75
+ * - 发布客户端:复用已有的 RedisService 实例
76
+ * - 订阅客户端:通过 duplicate() 创建独立连接
77
+ *
78
+ * 集群部署时,任意节点调用 clearTableMetaCacheWithBroadcast()
79
+ * 会通过 Redis 广播通知所有节点清空本地缓存。
80
+ */
81
+ async initTableMetaCacheRedis() {
82
+ try {
83
+ const redisService = await this.app.getApplicationContext().getAsync(redis_1.RedisService);
84
+ (0, TableMetaCacheRedisSubscriber_1.initTableMetaCachePublishClient)(redisService);
85
+ (0, TableMetaCacheRedisSubscriber_1.initTableMetaCacheSubscriber)(redisService);
86
+ }
87
+ catch (e) {
88
+ // Redis 未配置或不可用时,降级为单节点模式(仅清空本地缓存)
89
+ this.app.getLogger().warn('ContainerLifeCycle ==> initTableMetaCacheRedis Redis不可用,降级为单节点模式:', e.message);
90
+ }
91
+ }
66
92
  async startScheduleOnReady() {
67
93
  const logger = this.app.getLogger();
68
94
  const config = this.app.getConfig();
@@ -33,7 +33,7 @@ export declare class BaseApiController extends BaseService {
33
33
  */
34
34
  protected checkUserActionTimeLimit(actionCode: string, limitSecond?: number): Promise<void>;
35
35
  protected getUserSessionInfo(): import("../../models/userSession").ISessionInfo;
36
- executeSysSQL(executeSql: string, executeSqlArgs: any[]): Promise<any>;
36
+ executeSysSQL(executeSql: string, executeSqlArgs: any[]): Promise<import("../../libs/crud-pro/interfaces").ExecuteSQLResult<Record<string, any>>>;
37
37
  /**
38
38
  * 查询sys表中的SQL语句。sys表的表结构都是标准的。
39
39
  * @param sqlTable
@@ -42,7 +42,6 @@ export declare class BaseApiController extends BaseService {
42
42
  * @protected
43
43
  */
44
44
  protected executeSysSimpleSQL(sqlTable: string, sqlSimpleName: KeysOfSimpleSQL, extParams?: IExecuteSimpleSqlParams): Promise<import("../../libs/crud-pro/models/ExecuteContext").ExecuteContext>;
45
- protected get sysDBUtil(): import("../..").CrudProQuick;
46
45
  private addAccountBasicInfoCfgModel;
47
46
  private addWorkbenchBasicInfoCfgModel;
48
47
  protected decodeBodyBySession<T>(body: any): Promise<any>;
@@ -89,10 +89,6 @@ let BaseApiController = class BaseApiController extends BaseService_1.BaseServic
89
89
  }
90
90
  return await this.curdMixService.executeCrudByCfg(body, cfgModel);
91
91
  }
92
- get sysDBUtil() {
93
- const { SystemDbName, SystemDbType } = global_config_1.GLOBAL_STATIC_CONFIG.getConfig();
94
- return this.curdMixService.getBbUtil(SystemDbName, SystemDbType);
95
- }
96
92
  addAccountBasicInfoCfgModel(cfgModel) {
97
93
  let columnsRelation = cfgModel.columnsRelation;
98
94
  if (!columnsRelation) {
@@ -106,7 +106,7 @@ let DocGatewayController = class DocGatewayController extends BaseApiController_
106
106
  condition: {
107
107
  doc_lib_id: parseInt(docLibId),
108
108
  doc_category_code: {
109
- $notNull: '',
109
+ $notNull: true,
110
110
  },
111
111
  },
112
112
  }, {
@@ -32,5 +32,11 @@ export declare class HelpersApi {
32
32
  * @param queryData
33
33
  */
34
34
  cryptoAes128CBC(queryData: any): Promise<CommonResult>;
35
+ /**
36
+ * 工具函数: 清空表元数据缓存(集群广播)
37
+ * 清空本节点缓存,并通过 Redis Pub/Sub 广播通知集群中其他节点。
38
+ * 清空后,下次请求会自动从数据库重新加载(懒加载刷新)。
39
+ */
40
+ clearTableMetaCacheApi(): Promise<CommonResult>;
35
41
  private checkLocalPermissionEnv;
36
42
  }
@@ -21,6 +21,7 @@ const functions_1 = require("../libs/utils/functions");
21
21
  const crypto_utils_1 = require("../libs/utils/crypto-utils");
22
22
  const common_dto_1 = require("../libs/utils/common-dto");
23
23
  const SystemPerm_1 = require("../models/SystemPerm");
24
+ const TableMetaCacheRedisSubscriber_1 = require("../service/TableMetaCacheRedisSubscriber");
24
25
  // http://127.0.0.1:7002/ns/api/helpers/getApiScript?prefix=/ns/api/manage
25
26
  // http://127.0.0.1:7002/ns/api/helpers/getApiScript
26
27
  // http://127.0.0.1:7002/ns/api/helpers/getApiEnv
@@ -124,6 +125,18 @@ let HelpersApi = class HelpersApi {
124
125
  isEqual: input === decrypted,
125
126
  });
126
127
  }
128
+ /**
129
+ * 工具函数: 清空表元数据缓存(集群广播)
130
+ * 清空本节点缓存,并通过 Redis Pub/Sub 广播通知集群中其他节点。
131
+ * 清空后,下次请求会自动从数据库重新加载(懒加载刷新)。
132
+ */
133
+ async clearTableMetaCacheApi() {
134
+ const stats = (0, TableMetaCacheRedisSubscriber_1.clearTableMetaCacheWithBroadcast)();
135
+ return common_dto_1.CommonResult.successRes({
136
+ message: '表元数据缓存已清空(已广播集群)',
137
+ beforeClear: stats,
138
+ });
139
+ }
127
140
  checkLocalPermissionEnv() {
128
141
  //是否是开发者
129
142
  const isDevelopUser = () => {
@@ -181,6 +194,12 @@ __decorate([
181
194
  __metadata("design:paramtypes", [Object]),
182
195
  __metadata("design:returntype", Promise)
183
196
  ], HelpersApi.prototype, "cryptoAes128CBC", null);
197
+ __decorate([
198
+ (0, core_1.Get)('/clearTableMetaCache'),
199
+ __metadata("design:type", Function),
200
+ __metadata("design:paramtypes", []),
201
+ __metadata("design:returntype", Promise)
202
+ ], HelpersApi.prototype, "clearTableMetaCacheApi", null);
184
203
  HelpersApi = __decorate([
185
204
  (0, core_1.Controller)('/ns/api/helpers')
186
205
  ], HelpersApi);
@@ -40,7 +40,8 @@ let FlowConfigManageApi = class FlowConfigManageApi extends BaseApiController_1.
40
40
  }
41
41
  async updateFlowConfig() {
42
42
  const body = this.ctx.request.body;
43
- const { flow_code, flow_version } = body.condition;
43
+ const flow_code = String(body.condition.flow_code);
44
+ const flow_version = Number(body.condition.flow_version);
44
45
  await this.flowConfigService.remove_cache_flow_config_one(flow_code, flow_version);
45
46
  return this.executeSysSimpleSQL(FlowModel_1.FLOW_TABLES.flow_config, keys_1.KeysOfSimpleSQL.SIMPLE_UPDATE, {
46
47
  enableSoftDelete: true,
@@ -53,7 +54,8 @@ let FlowConfigManageApi = class FlowConfigManageApi extends BaseApiController_1.
53
54
  }
54
55
  async deleteFlowConfig() {
55
56
  const body = this.ctx.request.body;
56
- const { flow_code, flow_version } = body.condition;
57
+ const flow_code = String(body.condition.flow_code);
58
+ const flow_version = Number(body.condition.flow_version);
57
59
  await this.flowConfigService.remove_cache_flow_config_one(flow_code, flow_version);
58
60
  return this.executeSysSimpleSQL(FlowModel_1.FLOW_TABLES.flow_config, keys_1.KeysOfSimpleSQL.SIMPLE_DELETE, {
59
61
  enableSoftDelete: true,
@@ -55,7 +55,12 @@ let SysConfigMangeApi = class SysConfigMangeApi extends BaseApiController_1.Base
55
55
  if (!id) {
56
56
  return common_dto_1.CommonResult.errorRes('id不能为空');
57
57
  }
58
- const sysConfig = await this.curdMixService.getBbUtil(SystemDbName, SystemDbType).getUniqueOne({ condition: body.condition }, SystemTables_1.SystemTables.sys_configs);
58
+ const sysConfigRes = await this.curdMixService.getQuickCrud({
59
+ sqlDatabase: SystemDbName,
60
+ sqlDbType: SystemDbType,
61
+ sqlTable: SystemTables_1.SystemTables.sys_configs,
62
+ }).findOne({ condition: body.condition });
63
+ const sysConfig = sysConfigRes.row;
59
64
  if (!sysConfig) {
60
65
  return common_dto_1.CommonResult.errorRes('配置项不存在');
61
66
  }
@@ -50,9 +50,14 @@ let UserAccountManageApi = class UserAccountManageApi extends BaseApiController_
50
50
  if (!id) {
51
51
  return common_dto_1.CommonResult.errorRes('id不能为空');
52
52
  }
53
- const userAccountInfo = await this.curdMixService.getBbUtil(SystemDbName, SystemDbType).getUniqueOne({
53
+ const userAccountInfoRes = await this.curdMixService.getQuickCrud({
54
+ sqlDatabase: SystemDbName,
55
+ sqlDbType: SystemDbType,
56
+ sqlTable: SystemTables_1.SystemTables.sys_user_account,
57
+ }).findUniqueOne({
54
58
  condition: body.condition
55
- }, SystemTables_1.SystemTables.sys_user_account);
59
+ });
60
+ const userAccountInfo = userAccountInfoRes.row;
56
61
  if (!userAccountInfo) {
57
62
  return common_dto_1.CommonResult.errorRes('用户信息不存在');
58
63
  }
package/dist/index.d.ts CHANGED
@@ -70,7 +70,7 @@ export * from './service/curd/CurdMixByWorkbenchService';
70
70
  export * from './service/curd/CurdMixService';
71
71
  export * from './service/curd/CurdMixUtils';
72
72
  export * from './service/curd/CurdProService';
73
- export * from './service/curd/CrudProQuick';
73
+ export * from './libs/crud-pro-quick';
74
74
  export * from './service/flow/FlowConfigService';
75
75
  export * from './service/flow/FlowInstanceService';
76
76
  export * from './service/flow/FlowInstanceCrudService';
@@ -87,7 +87,6 @@ export * from './models/contextLogger';
87
87
  export * from './models/devops';
88
88
  export * from './models/SystemTables';
89
89
  export * from './models/AsyncTaskModel';
90
- export * from './models/StandardColumns';
91
90
  export * from './schedule/index';
92
91
  export * from './libs/utils/common-dto';
93
92
  export * from './libs/utils/crypto-utils';
@@ -110,4 +109,5 @@ export * from './libs/crud-pro/models/RequestCfgModel';
110
109
  export * from './libs/crud-pro/models/SqlSegArg';
111
110
  export * from './libs/crud-pro/models/ResModel';
112
111
  export * from './libs/crud-sharding/index';
112
+ export * from './libs/crud-pro-quick/index';
113
113
  export * from './libs/global-config/global-config';
package/dist/index.js CHANGED
@@ -88,7 +88,7 @@ __exportStar(require("./service/curd/CurdMixByWorkbenchService"), exports);
88
88
  __exportStar(require("./service/curd/CurdMixService"), exports);
89
89
  __exportStar(require("./service/curd/CurdMixUtils"), exports);
90
90
  __exportStar(require("./service/curd/CurdProService"), exports);
91
- __exportStar(require("./service/curd/CrudProQuick"), exports);
91
+ __exportStar(require("./libs/crud-pro-quick"), exports);
92
92
  __exportStar(require("./service/flow/FlowConfigService"), exports);
93
93
  __exportStar(require("./service/flow/FlowInstanceService"), exports);
94
94
  __exportStar(require("./service/flow/FlowInstanceCrudService"), exports);
@@ -105,7 +105,6 @@ __exportStar(require("./models/contextLogger"), exports);
105
105
  __exportStar(require("./models/devops"), exports);
106
106
  __exportStar(require("./models/SystemTables"), exports);
107
107
  __exportStar(require("./models/AsyncTaskModel"), exports);
108
- __exportStar(require("./models/StandardColumns"), exports);
109
108
  __exportStar(require("./schedule/index"), exports);
110
109
  __exportStar(require("./libs/utils/common-dto"), exports);
111
110
  __exportStar(require("./libs/utils/crypto-utils"), exports);
@@ -128,4 +127,5 @@ __exportStar(require("./libs/crud-pro/models/RequestCfgModel"), exports);
128
127
  __exportStar(require("./libs/crud-pro/models/SqlSegArg"), exports);
129
128
  __exportStar(require("./libs/crud-pro/models/ResModel"), exports);
130
129
  __exportStar(require("./libs/crud-sharding/index"), exports);
130
+ __exportStar(require("./libs/crud-pro-quick/index"), exports);
131
131
  __exportStar(require("./libs/global-config/global-config"), exports);
@@ -1,21 +1,36 @@
1
- import { ICrudProCfg, ILogger, IRequestCfgModel, IRequestModel, ISqlCfgModel, ITableListResult, ITableNamesOptions, ITableNamesQuery, IVisitor } from './interfaces';
1
+ import { ICrudProCfg, ILogger, IRequestCfgModel, IRequestModel, ISqlCfgModel, ITableListResult, ITableMetaQuery, ITableNamesOptions, ITableNamesQuery, IVisitor, ExecuteSQLResult } from './interfaces';
2
2
  import { ExecuteContext } from './models/ExecuteContext';
3
3
  import { Transaction } from './models/Transaction';
4
4
  import { IExecuteContextFunc } from './models/ExecuteContextFunc';
5
5
  declare class CrudPro {
6
6
  private readonly executeContext;
7
7
  private readonly serviceHub;
8
+ /** 标记是否已被使用(防止重复使用导致状态污染) */
9
+ private _isUsed;
10
+ /** 标记是否正在执行中(防止并发调用) */
11
+ private _isExecuting;
8
12
  constructor();
13
+ /**
14
+ * 检查是否可以开始执行
15
+ * @throws 如果已使用或正在执行中则抛出异常
16
+ */
17
+ private checkAndMarkExecuting;
18
+ /**
19
+ * 标记执行完成
20
+ */
21
+ private markExecutionComplete;
9
22
  set transaction(transaction: Transaction);
10
23
  set logger(logger: ILogger);
11
24
  set visitor(visitor: IVisitor);
25
+ getVisitor(): IVisitor;
12
26
  set contextFunc(contextFunc: IExecuteContextFunc);
13
27
  set contextCfg(contextCfg: ICrudProCfg);
14
28
  /**
15
29
  * 直接执行一个SQL
16
30
  * @param sqlCfgModel
31
+ * @returns 返回未被包装的数据库原始结果(根据 resPicker 配置返回不同类型,无 {code, data, message} 包装层)
17
32
  */
18
- executeSQL(sqlCfgModel: ISqlCfgModel): Promise<any>;
33
+ executeSQL(sqlCfgModel: ISqlCfgModel): Promise<ExecuteSQLResult>;
19
34
  /**
20
35
  * 从DB中读取配置
21
36
  * @param reqJson
@@ -28,8 +43,24 @@ declare class CrudPro {
28
43
  * @param cfgJson
29
44
  */
30
45
  executeCrudByCfg(reqJson: IRequestModel, cfgJson: IRequestCfgModel): Promise<ExecuteContext>;
46
+ /**
47
+ * 内部执行方法(不含检查逻辑,供内部调用)
48
+ * @param reqJson
49
+ * @param cfgJson
50
+ */
51
+ private executeCrudByCfgInternal;
31
52
  getCachedCfgByMethod(method: string, isEnableCache: boolean): Promise<IRequestCfgModel>;
32
53
  getAllTableInfos(query: ITableNamesQuery, options?: ITableNamesOptions): Promise<ITableListResult>;
54
+ /**
55
+ * 获取表的主键列名列表
56
+ *
57
+ * 复用 CrudProTableMetaService 的 getTableMeta 缓存,
58
+ * 从 columnDetails 中筛选 isPrimaryKey 的列。
59
+ *
60
+ * @param query 表元数据查询参数
61
+ * @returns 主键列名数组
62
+ */
63
+ getPrimaryKeyColumns(query: ITableMetaQuery): Promise<string[]>;
33
64
  /**
34
65
  * 如果是 INSERT/UPDATE 操作(sqlSimpleName 模式),根据真实表结构过滤 reqModel.data 中的字段
35
66
  * 避免传入不存在的字段导致 SQL 执行报错
@@ -38,6 +69,16 @@ declare class CrudPro {
38
69
  * @param cfgModel 配置模型
39
70
  */
40
71
  private filterDataByTableMetaIfNeeded;
72
+ /**
73
+ * 校验特定操作的必填参数
74
+ *
75
+ * - insertOrUpdate 和 update:condition 和 data 均为必填
76
+ * - insertOnDuplicateUpdate 和 insert:只有data 为必填
77
+ * @param reqModel 请求模型
78
+ * @param cfgModel 配置模型
79
+ * @throws CommonException 如果缺少必填参数
80
+ */
81
+ private validateParamsIfNeeded;
41
82
  /**
42
83
  * 判断 sqlSimpleName 是否为 INSERT/UPDATE 类型
43
84
  * @param sqlSimpleName 简单 SQL 名称
@@ -45,12 +86,19 @@ declare class CrudPro {
45
86
  */
46
87
  private isSimpleInsertOrUpdateType;
47
88
  /**
48
- * 根据表结构字段类型,自动转换数据格式
89
+ * 根据表结构字段类型,自动转换 data 数据格式
49
90
  * 例如:PostgreSQL 的 ARRAY 类型字段,需要将 JSON 数组转为 PG 数组字面量格式
50
91
  * @param reqModel 请求模型
51
92
  * @param cfgModel 配置模型
52
93
  */
53
94
  private convertDataFieldTypeIfNeeded;
95
+ /**
96
+ * 查询时:根据表结构字段类型,自动转换 condition 数据格式
97
+ * 防止数据库隐式类型转换导致索引失效(如 WHERE int_col = '123' 导致索引无法命中)
98
+ * @param reqModel 请求模型
99
+ * @param cfgModel 配置模型
100
+ */
101
+ private convertConditionTypeIfNeeded;
54
102
  private executeSQLList;
55
103
  private parseRunSqlException;
56
104
  private afterExecuteSQLList;
@@ -10,9 +10,35 @@ const MixinUtils_1 = require("./utils/MixinUtils");
10
10
  const keys_1 = require("./models/keys");
11
11
  class CrudPro {
12
12
  constructor() {
13
+ /** 标记是否已被使用(防止重复使用导致状态污染) */
14
+ this._isUsed = false;
15
+ /** 标记是否正在执行中(防止并发调用) */
16
+ this._isExecuting = false;
13
17
  this.executeContext = new ExecuteContext_1.ExecuteContext();
14
18
  this.serviceHub = new CurdProServiceHub_1.CurdProServiceHub(this.executeContext);
15
19
  }
20
+ /**
21
+ * 检查是否可以开始执行
22
+ * @throws 如果已使用或正在执行中则抛出异常
23
+ */
24
+ checkAndMarkExecuting() {
25
+ if (this._isUsed) {
26
+ throw new Error('[CrudPro] 此实例已被使用,不能重复使用。' +
27
+ '每次操作请创建新的 CrudPro 实例,可通过 curdProService.getCrudPro() 或工厂函数获取。');
28
+ }
29
+ if (this._isExecuting) {
30
+ throw new Error('[CrudPro] 此实例正在执行中,不能并发调用。' +
31
+ '请等待当前操作完成后再进行下一次调用,或创建新的实例。');
32
+ }
33
+ this._isExecuting = true;
34
+ }
35
+ /**
36
+ * 标记执行完成
37
+ */
38
+ markExecutionComplete() {
39
+ this._isExecuting = false;
40
+ this._isUsed = true;
41
+ }
16
42
  // 必填
17
43
  set transaction(transaction) {
18
44
  this.executeContext.setTransaction(transaction);
@@ -25,6 +51,10 @@ class CrudPro {
25
51
  set visitor(visitor) {
26
52
  this.executeContext.setVisitor(visitor);
27
53
  }
54
+ // 必填
55
+ getVisitor() {
56
+ return this.executeContext.getVisitor();
57
+ }
28
58
  set contextFunc(contextFunc) {
29
59
  contextFunc.setExecuteContext(this.executeContext);
30
60
  this.executeContext.contextFunc = contextFunc;
@@ -35,8 +65,10 @@ class CrudPro {
35
65
  /**
36
66
  * 直接执行一个SQL
37
67
  * @param sqlCfgModel
68
+ * @returns 返回未被包装的数据库原始结果(根据 resPicker 配置返回不同类型,无 {code, data, message} 包装层)
38
69
  */
39
70
  async executeSQL(sqlCfgModel) {
71
+ this.checkAndMarkExecuting();
40
72
  const RES_NAME = 'executeResult';
41
73
  const sqlCfgModel2 = {
42
74
  resName: RES_NAME,
@@ -53,8 +85,13 @@ class CrudPro {
53
85
  sqlDatabase: sqlCfgModel.sqlDatabase,
54
86
  sqlCfgList: [sqlCfgModel2],
55
87
  };
56
- const ss = await this.executeCrudByCfg({}, cfgModel);
57
- return ss.getResModelItem(RES_NAME);
88
+ try {
89
+ const ss = await this.executeCrudByCfgInternal({}, cfgModel);
90
+ return ss.getResModelItem(RES_NAME);
91
+ }
92
+ finally {
93
+ this.markExecutionComplete();
94
+ }
58
95
  }
59
96
  /**
60
97
  * 从DB中读取配置
@@ -74,6 +111,20 @@ class CrudPro {
74
111
  * @param cfgJson
75
112
  */
76
113
  async executeCrudByCfg(reqJson, cfgJson) {
114
+ this.checkAndMarkExecuting();
115
+ try {
116
+ return await this.executeCrudByCfgInternal(reqJson, cfgJson);
117
+ }
118
+ finally {
119
+ this.markExecutionComplete();
120
+ }
121
+ }
122
+ /**
123
+ * 内部执行方法(不含检查逻辑,供内部调用)
124
+ * @param reqJson
125
+ * @param cfgJson
126
+ */
127
+ async executeCrudByCfgInternal(reqJson, cfgJson) {
77
128
  const logger = this.executeContext.getLogger();
78
129
  logger.info('CurdPro executeCrudByCfg', cfgJson);
79
130
  // 在执行之前可以根据业务需要修改需要执行的内容。
@@ -87,10 +138,14 @@ class CrudPro {
87
138
  const cfgModel = new RequestCfgModel_1.RequestCfgModel(cfgJson);
88
139
  exeCtx.setReqModel(reqModel);
89
140
  exeCtx.setCfgModel(cfgModel);
141
+ // insertOrUpdate 参数校验
142
+ this.validateParamsIfNeeded(reqModel, cfgModel);
90
143
  // 如果是 sqlSimpleName模式的 update/insert,则需要将 reqJson.data 部分根据真实的表结构进行过滤
91
144
  await this.filterDataByTableMetaIfNeeded(reqModel, cfgModel);
92
- // 根据表结构字段类型,自动转换数据格式(如 PostgreSQL ARRAY 字段)
145
+ //插入和更新时: 根据表结构字段类型,自动转换 data 数据格式(如 PostgreSQL ARRAY 字段)
93
146
  await this.convertDataFieldTypeIfNeeded(reqModel, cfgModel);
147
+ //查询时:根据表结构字段类型,自动转换 condition 数据格式(防止数据库隐式类型转换导致索引失效)
148
+ await this.convertConditionTypeIfNeeded(reqModel, cfgModel);
94
149
  // 参数校验
95
150
  this.serviceHub.validateDataType(cfgModel, reqModel);
96
151
  this.serviceHub.validateByAllow(cfgModel, reqModel);
@@ -124,6 +179,18 @@ class CrudPro {
124
179
  async getAllTableInfos(query, options) {
125
180
  return this.serviceHub.getAllTableInfos(query, options);
126
181
  }
182
+ /**
183
+ * 获取表的主键列名列表
184
+ *
185
+ * 复用 CrudProTableMetaService 的 getTableMeta 缓存,
186
+ * 从 columnDetails 中筛选 isPrimaryKey 的列。
187
+ *
188
+ * @param query 表元数据查询参数
189
+ * @returns 主键列名数组
190
+ */
191
+ async getPrimaryKeyColumns(query) {
192
+ return this.serviceHub.getPrimaryKeyColumns(query);
193
+ }
127
194
  /**
128
195
  * 如果是 INSERT/UPDATE 操作(sqlSimpleName 模式),根据真实表结构过滤 reqModel.data 中的字段
129
196
  * 避免传入不存在的字段导致 SQL 执行报错
@@ -168,6 +235,37 @@ class CrudPro {
168
235
  // 直接修改 reqModel.data,只保留表中存在的字段
169
236
  reqModel.data = filteredData;
170
237
  }
238
+ /**
239
+ * 校验特定操作的必填参数
240
+ *
241
+ * - insertOrUpdate 和 update:condition 和 data 均为必填
242
+ * - insertOnDuplicateUpdate 和 insert:只有data 为必填
243
+ * @param reqModel 请求模型
244
+ * @param cfgModel 配置模型
245
+ * @throws CommonException 如果缺少必填参数
246
+ */
247
+ validateParamsIfNeeded(reqModel, cfgModel) {
248
+ // insertOrUpdate 和 update:condition 和 data 均为必填
249
+ if (cfgModel.sqlSimpleName === keys_1.KeysOfSimpleSQL.SIMPLE_INSERT_OR_UPDATE ||
250
+ cfgModel.sqlSimpleName === keys_1.KeysOfSimpleSQL.SIMPLE_UPDATE) {
251
+ if (!reqModel.condition || Object.keys(reqModel.condition).length === 0) {
252
+ throw new exceptions_1.CommonException(exceptions_1.Exceptions.INSERT_OR_UPDATE_CONDITION_EMPTY, '[CrudPro] insertOrUpdate/update 操作的 condition 不能为空。' +
253
+ 'condition 用于判断记录是否存在或定位更新目标。');
254
+ }
255
+ if (!reqModel.data || Object.keys(reqModel.data).length === 0) {
256
+ throw new exceptions_1.CommonException(exceptions_1.Exceptions.INSERT_OR_UPDATE_DATA_EMPTY, '[CrudPro] insertOrUpdate/update 操作的 data 不能为空。' +
257
+ 'data 用于指定插入或更新的内容。');
258
+ }
259
+ }
260
+ // insertOnDuplicateUpdate 和 insert:只有 data 为必填
261
+ if (cfgModel.sqlSimpleName === keys_1.KeysOfSimpleSQL.SIMPLE_INSERT_ON_DUPLICATE_UPDATE ||
262
+ cfgModel.sqlSimpleName === keys_1.KeysOfSimpleSQL.SIMPLE_INSERT) {
263
+ if (!reqModel.data || Object.keys(reqModel.data).length === 0) {
264
+ throw new exceptions_1.CommonException(exceptions_1.Exceptions.INSERT_OR_DUPLICATE_UPDATE_DATA_EMPTY, '[CrudPro] insert/insertOnDuplicateUpdate 操作的 data 不能为空。' +
265
+ 'data 用于指定插入或更新的内容。');
266
+ }
267
+ }
268
+ }
171
269
  /**
172
270
  * 判断 sqlSimpleName 是否为 INSERT/UPDATE 类型
173
271
  * @param sqlSimpleName 简单 SQL 名称
@@ -183,7 +281,7 @@ class CrudPro {
183
281
  return insertOrUpdateTypes.includes(sqlSimpleName);
184
282
  }
185
283
  /**
186
- * 根据表结构字段类型,自动转换数据格式
284
+ * 根据表结构字段类型,自动转换 data 数据格式
187
285
  * 例如:PostgreSQL 的 ARRAY 类型字段,需要将 JSON 数组转为 PG 数组字面量格式
188
286
  * @param reqModel 请求模型
189
287
  * @param cfgModel 配置模型
@@ -191,6 +289,15 @@ class CrudPro {
191
289
  async convertDataFieldTypeIfNeeded(reqModel, cfgModel) {
192
290
  await this.serviceHub.convertDataTypeByTableMeta(reqModel, cfgModel);
193
291
  }
292
+ /**
293
+ * 查询时:根据表结构字段类型,自动转换 condition 数据格式
294
+ * 防止数据库隐式类型转换导致索引失效(如 WHERE int_col = '123' 导致索引无法命中)
295
+ * @param reqModel 请求模型
296
+ * @param cfgModel 配置模型
297
+ */
298
+ async convertConditionTypeIfNeeded(reqModel, cfgModel) {
299
+ await this.serviceHub.convertConditionTypeByTableMeta(reqModel, cfgModel);
300
+ }
194
301
  async executeSQLList() {
195
302
  try {
196
303
  await this.serviceHub.executeSqlCfgModels();
@@ -56,6 +56,12 @@ export declare enum Exceptions {
56
56
  DATA_GET_DATA_EMPTY_ON_INSERT_KEYS = "DATA_GET_DATA_EMPTY_ON_INSERT_KEYS",
57
57
  DATA_GET_DATA_EMPTY_ON_INSERT_VALUES = "DATA_GET_DATA_EMPTY_ON_INSERT_VALUES",
58
58
  BATCH_INSERT_KEYS_MISMATCH = "BATCH_INSERT_KEYS_MISMATCH",
59
+ /**
60
+ * insertOrUpdate 参数缺失
61
+ */
62
+ INSERT_OR_UPDATE_CONDITION_EMPTY = "INSERT_OR_UPDATE_CONDITION_EMPTY",
63
+ INSERT_OR_UPDATE_DATA_EMPTY = "INSERT_OR_UPDATE_DATA_EMPTY",
64
+ INSERT_OR_DUPLICATE_UPDATE_DATA_EMPTY = "INSERT_ON_DUPLICATE_UPDATE_DATA_EMPTY",
59
65
  /**
60
66
  * 请求的Method字段为空
61
67
  */
@@ -79,6 +85,7 @@ export declare enum Exceptions {
79
85
  RUN_PICK_ERR_VISITOR_FIELD_NULL = "RUN_PICK_ERR_VISITOR_FIELD_NULL",
80
86
  RUN_EXECUTE_VALIDATE = "RUN_EXECUTE_VALIDATE",
81
87
  RUN_FUNCTION_NOT_FOUND = "RUN_FUNCTION_NOT_FOUND",
88
+ MORE_THAN_ONE_RECORDS_FOUND = "MORE_THAN_ONE_RECORDS_FOUND",
82
89
  /**
83
90
  * 参数校验错误
84
91
  */
@@ -60,6 +60,12 @@ var Exceptions;
60
60
  Exceptions["DATA_GET_DATA_EMPTY_ON_INSERT_KEYS"] = "DATA_GET_DATA_EMPTY_ON_INSERT_KEYS";
61
61
  Exceptions["DATA_GET_DATA_EMPTY_ON_INSERT_VALUES"] = "DATA_GET_DATA_EMPTY_ON_INSERT_VALUES";
62
62
  Exceptions["BATCH_INSERT_KEYS_MISMATCH"] = "BATCH_INSERT_KEYS_MISMATCH";
63
+ /**
64
+ * insertOrUpdate 参数缺失
65
+ */
66
+ Exceptions["INSERT_OR_UPDATE_CONDITION_EMPTY"] = "INSERT_OR_UPDATE_CONDITION_EMPTY";
67
+ Exceptions["INSERT_OR_UPDATE_DATA_EMPTY"] = "INSERT_OR_UPDATE_DATA_EMPTY";
68
+ Exceptions["INSERT_OR_DUPLICATE_UPDATE_DATA_EMPTY"] = "INSERT_ON_DUPLICATE_UPDATE_DATA_EMPTY";
63
69
  /**
64
70
  * 请求的Method字段为空
65
71
  */
@@ -83,6 +89,7 @@ var Exceptions;
83
89
  Exceptions["RUN_PICK_ERR_VISITOR_FIELD_NULL"] = "RUN_PICK_ERR_VISITOR_FIELD_NULL";
84
90
  Exceptions["RUN_EXECUTE_VALIDATE"] = "RUN_EXECUTE_VALIDATE";
85
91
  Exceptions["RUN_FUNCTION_NOT_FOUND"] = "RUN_FUNCTION_NOT_FOUND";
92
+ Exceptions["MORE_THAN_ONE_RECORDS_FOUND"] = "MORE_THAN_ONE_RECORDS_FOUND";
86
93
  /**
87
94
  * 参数校验错误
88
95
  */