@nest-omni/core 4.1.3-1 → 4.1.3-11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/audit/audit.module.d.ts +10 -0
  2. package/audit/audit.module.js +39 -1
  3. package/audit/controllers/audit.controller.d.ts +24 -0
  4. package/audit/controllers/audit.controller.js +24 -0
  5. package/audit/decorators/audit-controller.decorator.d.ts +9 -1
  6. package/audit/decorators/audit-controller.decorator.js +11 -2
  7. package/audit/decorators/audit-operation.decorator.d.ts +45 -0
  8. package/audit/decorators/audit-operation.decorator.js +49 -0
  9. package/audit/decorators/entity-audit.decorator.d.ts +76 -1
  10. package/audit/decorators/entity-audit.decorator.js +135 -3
  11. package/audit/decorators/index.d.ts +1 -0
  12. package/audit/decorators/index.js +1 -0
  13. package/audit/dto/audit-log-query.dto.d.ts +3 -0
  14. package/audit/dto/audit-log-query.dto.js +3 -0
  15. package/audit/dto/begin-transaction.dto.d.ts +3 -0
  16. package/audit/dto/begin-transaction.dto.js +3 -0
  17. package/audit/dto/compare-entities.dto.d.ts +3 -0
  18. package/audit/dto/compare-entities.dto.js +3 -0
  19. package/audit/dto/pre-check-restore.dto.d.ts +3 -0
  20. package/audit/dto/pre-check-restore.dto.js +3 -0
  21. package/audit/dto/restore-entity.dto.d.ts +3 -0
  22. package/audit/dto/restore-entity.dto.js +3 -0
  23. package/audit/entities/entity-audit-log.entity.d.ts +8 -0
  24. package/audit/entities/entity-audit-log.entity.js +33 -1
  25. package/audit/entities/entity-transaction.entity.d.ts +10 -0
  26. package/audit/entities/entity-transaction.entity.js +33 -1
  27. package/audit/entities/index.d.ts +2 -0
  28. package/audit/entities/index.js +2 -0
  29. package/audit/entities/manual-operation-log.entity.d.ts +4 -0
  30. package/audit/entities/manual-operation-log.entity.js +4 -0
  31. package/audit/entities/operation-template.entity.d.ts +4 -0
  32. package/audit/entities/operation-template.entity.js +4 -0
  33. package/audit/enums/audit.enums.d.ts +45 -5
  34. package/audit/enums/audit.enums.js +47 -4
  35. package/audit/index.d.ts +3 -1
  36. package/audit/index.js +30 -1
  37. package/audit/interceptors/audit.interceptor.d.ts +15 -0
  38. package/audit/interceptors/audit.interceptor.js +23 -1
  39. package/audit/interfaces/audit.interfaces.d.ts +182 -2
  40. package/audit/services/audit-context.service.d.ts +15 -0
  41. package/audit/services/audit-context.service.js +15 -0
  42. package/audit/services/audit-strategy.service.d.ts +6 -0
  43. package/audit/services/audit-strategy.service.js +13 -0
  44. package/audit/services/entity-audit.service.d.ts +129 -3
  45. package/audit/services/entity-audit.service.js +301 -6
  46. package/audit/services/index.d.ts +2 -0
  47. package/audit/services/index.js +2 -0
  48. package/audit/services/manual-audit-log.service.d.ts +124 -0
  49. package/audit/services/manual-audit-log.service.js +138 -0
  50. package/audit/services/multi-database.service.d.ts +12 -0
  51. package/audit/services/multi-database.service.js +12 -0
  52. package/audit/services/operation-description.service.d.ts +59 -0
  53. package/audit/services/operation-description.service.js +76 -2
  54. package/audit/services/transaction-audit.service.d.ts +30 -0
  55. package/audit/services/transaction-audit.service.js +47 -0
  56. package/audit/subscribers/entity-audit.subscriber.d.ts +15 -0
  57. package/audit/subscribers/entity-audit.subscriber.js +29 -1
  58. package/cache/cache-metrics.service.d.ts +67 -0
  59. package/cache/cache-metrics.service.js +68 -4
  60. package/cache/cache-serialization.service.d.ts +31 -0
  61. package/cache/cache-serialization.service.js +25 -0
  62. package/cache/cache.constants.d.ts +9 -0
  63. package/cache/cache.constants.js +9 -0
  64. package/cache/cache.health.d.ts +26 -0
  65. package/cache/cache.health.js +30 -0
  66. package/cache/cache.module.d.ts +86 -0
  67. package/cache/cache.module.js +71 -0
  68. package/cache/cache.service.d.ts +140 -0
  69. package/cache/cache.service.js +157 -0
  70. package/cache/cache.warmup.service.d.ts +39 -0
  71. package/cache/cache.warmup.service.js +32 -0
  72. package/cache/decorators/cache-evict.decorator.d.ts +47 -0
  73. package/cache/decorators/cache-evict.decorator.js +56 -0
  74. package/cache/decorators/cache-put.decorator.d.ts +34 -0
  75. package/cache/decorators/cache-put.decorator.js +39 -0
  76. package/cache/decorators/cacheable.decorator.d.ts +40 -0
  77. package/cache/decorators/cacheable.decorator.js +55 -0
  78. package/cache/dependencies/callback.dependency.d.ts +33 -0
  79. package/cache/dependencies/callback.dependency.js +39 -1
  80. package/cache/dependencies/chain.dependency.d.ts +28 -0
  81. package/cache/dependencies/chain.dependency.js +34 -0
  82. package/cache/dependencies/db.dependency.d.ts +45 -0
  83. package/cache/dependencies/db.dependency.js +48 -1
  84. package/cache/dependencies/file.dependency.d.ts +32 -0
  85. package/cache/dependencies/file.dependency.js +34 -0
  86. package/cache/dependencies/tag.dependency.d.ts +36 -0
  87. package/cache/dependencies/tag.dependency.js +36 -0
  88. package/cache/dependencies/time.dependency.d.ts +43 -0
  89. package/cache/dependencies/time.dependency.js +43 -0
  90. package/cache/examples/basic-usage.d.ts +15 -0
  91. package/cache/examples/basic-usage.js +62 -8
  92. package/cache/index.js +9 -0
  93. package/cache/interfaces/cache-dependency.interface.d.ts +53 -0
  94. package/cache/interfaces/cache-options.interface.d.ts +81 -0
  95. package/cache/interfaces/cache-options.interface.js +6 -0
  96. package/cache/interfaces/cache-provider.interface.d.ts +78 -0
  97. package/cache/providers/base-cache.provider.d.ts +14 -0
  98. package/cache/providers/base-cache.provider.js +16 -0
  99. package/cache/providers/cls-cache.provider.d.ts +20 -0
  100. package/cache/providers/cls-cache.provider.js +28 -0
  101. package/cache/providers/memory-cache.provider.d.ts +23 -0
  102. package/cache/providers/memory-cache.provider.js +26 -0
  103. package/cache/providers/redis-cache.provider.d.ts +26 -0
  104. package/cache/providers/redis-cache.provider.js +29 -0
  105. package/cache/utils/dependency-manager.util.d.ts +52 -0
  106. package/cache/utils/dependency-manager.util.js +59 -0
  107. package/cache/utils/key-generator.util.d.ts +42 -0
  108. package/cache/utils/key-generator.util.js +53 -1
  109. package/common/abstract.entity.d.ts +14 -0
  110. package/common/abstract.entity.js +14 -0
  111. package/common/boilerplate.polyfill.d.ts +142 -4
  112. package/common/boilerplate.polyfill.js +24 -100
  113. package/common/dto/dto-container.d.ts +16 -0
  114. package/common/dto/dto-container.js +20 -0
  115. package/common/dto/dto-decorators.d.ts +18 -0
  116. package/common/dto/dto-decorators.js +14 -0
  117. package/common/dto/dto-extensions.d.ts +11 -0
  118. package/common/dto/dto-extensions.js +9 -0
  119. package/common/dto/dto-service-accessor.d.ts +17 -0
  120. package/common/dto/dto-service-accessor.js +18 -0
  121. package/common/dto/dto-transformer.d.ts +12 -0
  122. package/common/dto/dto-transformer.js +9 -0
  123. package/common/dto/index.js +2 -0
  124. package/common/examples/paginate-and-map.example.d.ts +6 -0
  125. package/common/examples/paginate-and-map.example.js +26 -0
  126. package/common/utils.d.ts +15 -0
  127. package/common/utils.js +15 -0
  128. package/constants/language-code.js +1 -0
  129. package/decorators/field.decorators.js +8 -1
  130. package/decorators/property.decorators.js +1 -0
  131. package/decorators/public-route.decorator.js +1 -0
  132. package/decorators/transform.decorators.d.ts +27 -0
  133. package/decorators/transform.decorators.js +29 -0
  134. package/decorators/translate.decorator.js +1 -0
  135. package/decorators/user.decorator.js +1 -0
  136. package/decorators/validator.decorators.d.ts +8 -18
  137. package/decorators/validator.decorators.js +22 -190
  138. package/filters/constraint-errors.js +1 -0
  139. package/helpers/common.helper.d.ts +13 -0
  140. package/helpers/common.helper.js +13 -0
  141. package/http-client/config/http-client.config.d.ts +15 -0
  142. package/http-client/config/http-client.config.js +25 -9
  143. package/http-client/decorators/http-client.decorators.d.ts +63 -0
  144. package/http-client/decorators/http-client.decorators.js +71 -3
  145. package/http-client/entities/http-log.entity.d.ts +229 -0
  146. package/http-client/entities/http-log.entity.js +6 -1
  147. package/http-client/errors/http-client.errors.d.ts +57 -0
  148. package/http-client/errors/http-client.errors.js +58 -0
  149. package/http-client/examples/advanced-usage.example.d.ts +41 -0
  150. package/http-client/examples/advanced-usage.example.js +68 -24
  151. package/http-client/examples/auth-with-waiting-lock.example.d.ts +31 -0
  152. package/http-client/examples/auth-with-waiting-lock.example.js +52 -5
  153. package/http-client/examples/basic-usage.example.d.ts +60 -0
  154. package/http-client/examples/basic-usage.example.js +60 -0
  155. package/http-client/examples/multi-api-configuration.example.d.ts +60 -0
  156. package/http-client/examples/multi-api-configuration.example.js +76 -5
  157. package/http-client/http-client.module.d.ts +13 -0
  158. package/http-client/http-client.module.js +20 -5
  159. package/http-client/index.js +8 -0
  160. package/http-client/interfaces/api-client-config.interface.d.ts +125 -0
  161. package/http-client/interfaces/api-client-config.interface.js +3 -0
  162. package/http-client/interfaces/http-client-config.interface.d.ts +60 -0
  163. package/http-client/services/api-client-registry.service.d.ts +57 -0
  164. package/http-client/services/api-client-registry.service.js +84 -1
  165. package/http-client/services/cache.service.d.ts +52 -0
  166. package/http-client/services/cache.service.js +72 -3
  167. package/http-client/services/circuit-breaker.service.d.ts +46 -0
  168. package/http-client/services/circuit-breaker.service.js +52 -0
  169. package/http-client/services/http-client.service.d.ts +67 -0
  170. package/http-client/services/http-client.service.js +105 -4
  171. package/http-client/services/http-log-query.service.d.ts +83 -0
  172. package/http-client/services/http-log-query.service.js +122 -1
  173. package/http-client/services/http-replay.service.d.ts +101 -0
  174. package/http-client/services/http-replay.service.js +86 -0
  175. package/http-client/services/log-cleanup.service.d.ts +63 -0
  176. package/http-client/services/log-cleanup.service.js +54 -2
  177. package/http-client/services/logging.service.d.ts +40 -0
  178. package/http-client/services/logging.service.js +53 -0
  179. package/http-client/utils/call-stack-extractor.util.d.ts +37 -0
  180. package/http-client/utils/call-stack-extractor.util.js +48 -0
  181. package/http-client/utils/context-extractor.util.d.ts +49 -0
  182. package/http-client/utils/context-extractor.util.js +52 -0
  183. package/http-client/utils/curl-generator.util.d.ts +21 -0
  184. package/http-client/utils/curl-generator.util.js +44 -3
  185. package/http-client/utils/request-id.util.d.ts +18 -0
  186. package/http-client/utils/request-id.util.js +20 -0
  187. package/http-client/utils/retry-recorder.util.d.ts +42 -0
  188. package/http-client/utils/retry-recorder.util.js +44 -0
  189. package/i18n/en_US/validation.json +2 -1
  190. package/i18n/zh_CN/validation.json +2 -1
  191. package/index.js +8 -0
  192. package/interceptors/translation-interceptor.service.js +5 -0
  193. package/package.json +1 -1
  194. package/providers/context.provider.js +2 -0
  195. package/providers/generator.provider.d.ts +4 -0
  196. package/providers/generator.provider.js +4 -0
  197. package/redis-lock/comprehensive-lock-cleanup.service.d.ts +94 -0
  198. package/redis-lock/comprehensive-lock-cleanup.service.js +253 -0
  199. package/redis-lock/examples/lock-strategy.examples.d.ts +89 -0
  200. package/redis-lock/examples/lock-strategy.examples.js +130 -15
  201. package/redis-lock/index.d.ts +2 -0
  202. package/redis-lock/index.js +8 -1
  203. package/redis-lock/lock-heartbeat.service.d.ts +78 -0
  204. package/redis-lock/lock-heartbeat.service.js +222 -0
  205. package/redis-lock/redis-lock.decorator.d.ts +101 -0
  206. package/redis-lock/redis-lock.decorator.js +120 -0
  207. package/redis-lock/redis-lock.module.d.ts +66 -0
  208. package/redis-lock/redis-lock.module.js +175 -70
  209. package/redis-lock/redis-lock.service.d.ts +278 -0
  210. package/redis-lock/redis-lock.service.js +282 -12
  211. package/setup/bootstrap.setup.js +20 -0
  212. package/setup/mode.setup.d.ts +44 -0
  213. package/setup/mode.setup.js +44 -0
  214. package/setup/schedule.decorator.d.ts +227 -0
  215. package/setup/schedule.decorator.js +235 -12
  216. package/setup/worker.decorator.d.ts +86 -0
  217. package/setup/worker.decorator.js +88 -0
  218. package/shared/serviceRegistryModule.js +27 -14
  219. package/shared/services/api-config.service.d.ts +3 -0
  220. package/shared/services/api-config.service.js +20 -9
  221. package/validator-json/decorators.d.ts +17 -0
  222. package/validator-json/decorators.js +17 -2
  223. package/validator-json/default.d.ts +6 -0
  224. package/validator-json/default.js +30 -2
  225. package/validator-json/defaultConverters.js +1 -0
  226. package/validator-json/options.d.ts +23 -0
  227. package/validators/common-validators.d.ts +143 -0
  228. package/validators/common-validators.js +249 -0
  229. package/validators/custom-validate.examples.d.ts +96 -0
  230. package/validators/custom-validate.examples.js +400 -0
  231. package/validators/custom-validate.validator.d.ts +134 -0
  232. package/validators/custom-validate.validator.js +214 -0
  233. package/validators/index.d.ts +2 -0
  234. package/validators/index.js +2 -0
  235. package/validators/is-exists.validator.d.ts +18 -4
  236. package/validators/is-exists.validator.js +67 -6
  237. package/validators/is-unique.validator.d.ts +32 -5
  238. package/validators/is-unique.validator.js +99 -17
  239. package/validators/skip-empty.validator.d.ts +5 -0
  240. package/validators/skip-empty.validator.js +5 -0
  241. package/vault/interfaces/vault-options.interface.d.ts +9 -0
  242. package/vault/vault-config.loader.d.ts +30 -0
  243. package/vault/vault-config.loader.js +48 -1
  244. package/vault/vault-config.service.d.ts +53 -0
  245. package/vault/vault-config.service.js +57 -0
  246. package/vault/vault.module.d.ts +4 -0
  247. package/vault/vault.module.js +4 -0
  248. package/decorators/examples/validation-decorators.example.d.ts +0 -69
  249. package/decorators/examples/validation-decorators.example.js +0 -331
@@ -0,0 +1,214 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
12
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
13
+ return new (P || (P = Promise))(function (resolve, reject) {
14
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
15
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
16
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
17
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
18
+ });
19
+ };
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.CustomValidateValidator = void 0;
22
+ exports.CustomValidate = CustomValidate;
23
+ const class_validator_1 = require("class-validator");
24
+ const common_1 = require("@nestjs/common");
25
+ const core_1 = require("@nestjs/core");
26
+ const nestjs_i18n_1 = require("nestjs-i18n");
27
+ let CustomValidateValidator = class CustomValidateValidator {
28
+ constructor(moduleRef) {
29
+ this.moduleRef = moduleRef;
30
+ }
31
+ /**
32
+ * 验证入口
33
+ */
34
+ validate(value, args) {
35
+ return __awaiter(this, void 0, void 0, function* () {
36
+ const [constraint, ...extraArgs] = args.constraints;
37
+ const context = {
38
+ value,
39
+ object: args.object,
40
+ property: args.property,
41
+ constraints: args.constraints,
42
+ targetName: args.targetName,
43
+ args,
44
+ };
45
+ try {
46
+ // 1. 如果是函数,直接调用
47
+ if (typeof constraint === 'function') {
48
+ return yield this.callFunction(constraint, value, context, extraArgs);
49
+ }
50
+ // 2. 如果是字符串,调用 Entity 方法
51
+ if (typeof constraint === 'string') {
52
+ return yield this.callEntityMethod(args.object, constraint, value, context, extraArgs);
53
+ }
54
+ // 3. 如果是数组,调用 Service 方法
55
+ if (Array.isArray(constraint)) {
56
+ return yield this.callServiceMethod(constraint, value, context);
57
+ }
58
+ throw new Error(`[@CustomValidate] Invalid constraint type for property "${args.property}". ` +
59
+ `Expected: function, string, or array. Got: ${typeof constraint}`);
60
+ }
61
+ catch (error) {
62
+ // 验证函数执行出错,记录详细错误信息
63
+ console.error(`[@CustomValidate] Validation error for property "${args.property}":`, error);
64
+ throw error;
65
+ }
66
+ });
67
+ }
68
+ /**
69
+ * 调用内联函数
70
+ */
71
+ callFunction(fn, value, context, extraArgs) {
72
+ return __awaiter(this, void 0, void 0, function* () {
73
+ const result = fn(value, context, ...extraArgs);
74
+ return result instanceof Promise ? yield result : result;
75
+ });
76
+ }
77
+ /**
78
+ * 调用 Entity 方法
79
+ */
80
+ callEntityMethod(entity, methodName, value, context, extraArgs) {
81
+ return __awaiter(this, void 0, void 0, function* () {
82
+ if (!entity || typeof entity[methodName] !== 'function') {
83
+ throw new Error(`[@CustomValidate] Method "${methodName}" not found on entity "${context.targetName}". ` +
84
+ `Make sure the method exists and is accessible.`);
85
+ }
86
+ const result = entity[methodName](value, context, ...extraArgs);
87
+ return result instanceof Promise ? yield result : result;
88
+ });
89
+ }
90
+ /**
91
+ * 调用 Service 方法
92
+ */
93
+ callServiceMethod(constraint, value, context) {
94
+ return __awaiter(this, void 0, void 0, function* () {
95
+ let [serviceClass, methodName, ...extraArgs] = constraint;
96
+ // 验证参数
97
+ if (!serviceClass || !methodName) {
98
+ throw new Error(`[@CustomValidate] Invalid service constraint format. ` +
99
+ `Expected: [ServiceClass, 'methodName'] or [() => ServiceClass, 'methodName']`);
100
+ }
101
+ // 解析延迟引用(解决循环依赖)
102
+ if (typeof serviceClass === 'function' && !serviceClass.prototype) {
103
+ serviceClass = serviceClass();
104
+ }
105
+ if (!serviceClass) {
106
+ throw new Error(`[@CustomValidate] Service class is undefined. ` +
107
+ `This may be caused by circular dependencies. ` +
108
+ `Consider using lazy reference: [() => ServiceClass, 'methodName']`);
109
+ }
110
+ // 通过依赖注入获取 service 实例
111
+ let service;
112
+ try {
113
+ service = this.moduleRef.get(serviceClass, { strict: false });
114
+ }
115
+ catch (error) {
116
+ throw new Error(`[@CustomValidate] Failed to resolve service "${serviceClass.name}". ` +
117
+ `Make sure the service is registered as a provider in a NestJS module. ` +
118
+ `Error: ${error.message}`);
119
+ }
120
+ if (!service || typeof service[methodName] !== 'function') {
121
+ throw new Error(`[@CustomValidate] Method "${methodName}" not found on service "${serviceClass.name}". ` +
122
+ `Available methods: ${Object.getOwnPropertyNames(Object.getPrototypeOf(service)).join(', ')}`);
123
+ }
124
+ const result = service[methodName](value, context, ...extraArgs);
125
+ return result instanceof Promise ? yield result : result;
126
+ });
127
+ }
128
+ /**
129
+ * 默认错误消息
130
+ */
131
+ defaultMessage(args) {
132
+ // 优先使用 i18n
133
+ return (0, nestjs_i18n_1.i18nValidationMessage)('validation.CUSTOM_VALIDATE')(args);
134
+ }
135
+ };
136
+ exports.CustomValidateValidator = CustomValidateValidator;
137
+ exports.CustomValidateValidator = CustomValidateValidator = __decorate([
138
+ (0, common_1.Injectable)(),
139
+ (0, class_validator_1.ValidatorConstraint)({ name: 'customValidate', async: true }),
140
+ __metadata("design:paramtypes", [core_1.ModuleRef])
141
+ ], CustomValidateValidator);
142
+ /**
143
+ * @CustomValidate 装饰器
144
+ *
145
+ * 支持多种验证方式的灵活验证装饰器
146
+ *
147
+ * @example
148
+ *
149
+ * // 1. 内联函数(同步)
150
+ * @CustomValidate(
151
+ * (value) => value > 0,
152
+ * { message: '价格必须大于0' }
153
+ * )
154
+ * price: number;
155
+ *
156
+ * @example
157
+ * // 2. 内联函数(异步)
158
+ * @CustomValidate(
159
+ * async (value, context) => {
160
+ * const response = await fetch(`/api/check/${value}`);
161
+ * return response.ok;
162
+ * }
163
+ * )
164
+ * username: string;
165
+ *
166
+ * @example
167
+ * // 3. Entity 方法
168
+ * @CustomValidate('validateVersion')
169
+ * version: string;
170
+ *
171
+ * validateVersion(value: string): boolean {
172
+ * return /^\d+\.\d+\.\d+$/.test(value);
173
+ * }
174
+ *
175
+ * @example
176
+ * // 4. Service 方法
177
+ * @CustomValidate([UserValidationService, 'checkUsername'])
178
+ * username: string;
179
+ *
180
+ * @example
181
+ * // 5. 延迟引用(解决循环依赖)
182
+ * @CustomValidate([() => UserValidationService, 'checkUsername'])
183
+ * username: string;
184
+ *
185
+ * @example
186
+ * // 6. 带额外参数
187
+ * @CustomValidate(
188
+ * [ValidationService, 'checkRange', 0, 100],
189
+ * { message: '价格必须在 0-100 之间' }
190
+ * )
191
+ * price: number;
192
+ *
193
+ * @example
194
+ * // 7. 使用 i18n
195
+ * @CustomValidate(
196
+ * (value) => value.length >= 6,
197
+ * { message: 'validation.PASSWORD_TOO_SHORT' }
198
+ * )
199
+ * password: string;
200
+ *
201
+ * @param constraint 验证约束(函数、方法名、或 [Service, 方法名])
202
+ * @param validationOptions 验证选项
203
+ */
204
+ function CustomValidate(constraint, validationOptions) {
205
+ return (object, propertyName) => {
206
+ (0, class_validator_1.registerDecorator)({
207
+ target: object.constructor,
208
+ propertyName,
209
+ options: validationOptions,
210
+ constraints: [constraint],
211
+ validator: CustomValidateValidator,
212
+ });
213
+ };
214
+ }
@@ -4,3 +4,5 @@ export * from './file-mimetype.validator';
4
4
  export * from './is-exists.validator';
5
5
  export * from './is-unique.validator';
6
6
  export * from './same-as.validator';
7
+ export * from './custom-validate.validator';
8
+ export * from './common-validators';
@@ -20,3 +20,5 @@ __exportStar(require("./file-mimetype.validator"), exports);
20
20
  __exportStar(require("./is-exists.validator"), exports);
21
21
  __exportStar(require("./is-unique.validator"), exports);
22
22
  __exportStar(require("./same-as.validator"), exports);
23
+ __exportStar(require("./custom-validate.validator"), exports);
24
+ __exportStar(require("./common-validators"), exports);
@@ -1,14 +1,28 @@
1
1
  import type { ValidationArguments, ValidationOptions, ValidatorConstraintInterface } from 'class-validator';
2
2
  import type { EntitySchema, FindOptionsWhere, ObjectType } from 'typeorm';
3
- import { DataSource } from 'typeorm';
3
+ import { TransactionHost } from '@nestjs-cls/transactional';
4
+ import { TransactionalAdapterTypeOrm } from '@nestjs-cls/transactional-adapter-typeorm';
4
5
  export declare class IsExistsValidator implements ValidatorConstraintInterface {
5
- private readonly dataSource;
6
- constructor(dataSource: DataSource);
6
+ private readonly transactionHost;
7
+ constructor(transactionHost: TransactionHost<TransactionalAdapterTypeOrm>);
8
+ /**
9
+ * 解析 Entity 引用,支持多种形式:
10
+ * 1. Entity 类直接引用
11
+ * 2. 延迟函数 () => Entity
12
+ * 3. 字符串名称 "EntityName"
13
+ * 4. undefined (从属性名自动推断)
14
+ */
15
+ private resolveEntity;
16
+ /**
17
+ * 从属性名推断 Entity 名称
18
+ * 例如:appId -> App, userId -> User
19
+ */
20
+ private inferEntityNameFromProperty;
7
21
  validate<E>(value: string, args: IExistsValidationArguments<E>): Promise<boolean>;
8
22
  defaultMessage(args: ValidationArguments): string;
9
23
  }
10
24
  type ExistsValidationConstraints<E> = [
11
- ObjectType<E> | EntitySchema<E> | string,
25
+ ObjectType<E> | EntitySchema<E> | string | (() => ObjectType<E> | EntitySchema<E> | string),
12
26
  (validationArguments: ValidationArguments) => FindOptionsWhere<E>
13
27
  ];
14
28
  interface IExistsValidationArguments<E> extends ValidationArguments {
@@ -21,18 +21,79 @@ Object.defineProperty(exports, "__esModule", { value: true });
21
21
  exports.IsExistsValidator = void 0;
22
22
  exports.IsExists = IsExists;
23
23
  const class_validator_1 = require("class-validator");
24
- const typeorm_1 = require("typeorm");
25
24
  const nestjs_i18n_1 = require("nestjs-i18n");
26
25
  const common_1 = require("@nestjs/common");
26
+ const transactional_1 = require("@nestjs-cls/transactional");
27
27
  let IsExistsValidator = class IsExistsValidator {
28
- constructor(dataSource) {
29
- this.dataSource = dataSource;
28
+ constructor(transactionHost) {
29
+ this.transactionHost = transactionHost;
30
+ }
31
+ /**
32
+ * 解析 Entity 引用,支持多种形式:
33
+ * 1. Entity 类直接引用
34
+ * 2. 延迟函数 () => Entity
35
+ * 3. 字符串名称 "EntityName"
36
+ * 4. undefined (从属性名自动推断)
37
+ */
38
+ resolveEntity(entityRef, propertyName, object) {
39
+ // 1. 如果是字符串,直接返回(TypeORM 支持字符串)
40
+ if (typeof entityRef === 'string') {
41
+ return entityRef;
42
+ }
43
+ // 2. 如果是函数,需要区分延迟函数和 Entity 类
44
+ if (typeof entityRef === 'function') {
45
+ // 2.1 箭头函数没有 prototype,是延迟函数
46
+ if (!entityRef.prototype) {
47
+ const resolved = entityRef();
48
+ if (resolved)
49
+ return resolved;
50
+ }
51
+ else {
52
+ // 2.2 有 prototype,是 Entity 类或普通构造函数
53
+ // 直接返回
54
+ return entityRef;
55
+ }
56
+ }
57
+ // 3. 如果是 undefined,尝试从属性名推断 Entity
58
+ // 例如:appId -> AppEntity, userId -> UserEntity
59
+ if (!entityRef) {
60
+ const inferredEntityName = this.inferEntityNameFromProperty(propertyName);
61
+ if (inferredEntityName) {
62
+ console.warn(`[IsExists] Entity reference is undefined for property "${propertyName}". ` +
63
+ `This may be caused by circular dependencies. ` +
64
+ `Consider using lazy reference: () => ${inferredEntityName}`);
65
+ // 返回字符串形式的 Entity 名称
66
+ return inferredEntityName;
67
+ }
68
+ }
69
+ throw new Error(`[IsExists] Cannot resolve entity reference for property "${propertyName}". ` +
70
+ `Entity is undefined. This is likely caused by circular dependencies. ` +
71
+ `Please use one of the following solutions:\n` +
72
+ `1. Lazy reference: @IsExists([() => EntityClass, ...])\n` +
73
+ `2. String reference: @IsExists(["EntityName", ...])\n` +
74
+ `3. Break the circular dependency`);
75
+ }
76
+ /**
77
+ * 从属性名推断 Entity 名称
78
+ * 例如:appId -> App, userId -> User
79
+ */
80
+ inferEntityNameFromProperty(propertyName) {
81
+ // 移除常见后缀:Id, Ids, Key, Code
82
+ const name = propertyName.replace(/(Id|Ids|Key|Code)$/, '');
83
+ if (!name)
84
+ return null;
85
+ // 转换为 PascalCase 并添加 Entity 后缀
86
+ const entityName = name.charAt(0).toUpperCase() + name.slice(1) + 'Entity';
87
+ return entityName;
30
88
  }
31
89
  validate(value, args) {
32
90
  return __awaiter(this, void 0, void 0, function* () {
33
- const [entityClass, findCondition] = args.constraints;
91
+ const [entityRef, findCondition] = args.constraints;
92
+ // 解析 Entity 引用
93
+ const entityClass = this.resolveEntity(entityRef, args.property, args.object);
94
+ const repository = this.transactionHost.tx.getRepository(entityClass);
34
95
  args.value = value;
35
- return ((yield this.dataSource.getRepository(entityClass).count({
96
+ return ((yield repository.count({
36
97
  where: findCondition(args),
37
98
  })) > 0);
38
99
  });
@@ -45,7 +106,7 @@ exports.IsExistsValidator = IsExistsValidator;
45
106
  exports.IsExistsValidator = IsExistsValidator = __decorate([
46
107
  (0, common_1.Injectable)(),
47
108
  (0, class_validator_1.ValidatorConstraint)({ name: 'isExists', async: true }),
48
- __metadata("design:paramtypes", [typeorm_1.DataSource])
109
+ __metadata("design:paramtypes", [transactional_1.TransactionHost])
49
110
  ], IsExistsValidator);
50
111
  function IsExists(constraints, validationOptions) {
51
112
  return (object, propertyName) => {
@@ -1,14 +1,41 @@
1
1
  import type { ValidationArguments, ValidationOptions, ValidatorConstraintInterface } from 'class-validator';
2
- import { DataSource, EntitySchema, FindOptionsWhere, ObjectType } from 'typeorm';
2
+ import { EntitySchema, FindOptionsWhere, ObjectType } from 'typeorm';
3
+ import { TransactionHost } from '@nestjs-cls/transactional';
4
+ import { TransactionalAdapterTypeOrm } from '@nestjs-cls/transactional-adapter-typeorm';
3
5
  export declare class IsUniqueValidator implements ValidatorConstraintInterface {
4
- private readonly dataSource;
5
- constructor(dataSource: DataSource);
6
+ private readonly transactionHost;
7
+ constructor(transactionHost: TransactionHost<TransactionalAdapterTypeOrm>);
8
+ /**
9
+ * 解析 Entity 引用,支持多种形式:
10
+ * 1. Entity 类直接引用
11
+ * 2. 延迟函数 () => Entity
12
+ * 3. 字符串名称 "EntityName"
13
+ * 4. undefined (从属性名自动推断)
14
+ */
15
+ private resolveEntity;
16
+ /**
17
+ * 从属性名推断 Entity 名称
18
+ * 例如:appId -> App, userId -> User
19
+ */
20
+ private inferEntityNameFromProperty;
6
21
  validate<E>(value: string, args: IUniqueValidationArguments<E>): Promise<boolean>;
7
22
  defaultMessage(args: ValidationArguments): string;
8
23
  }
24
+ /**
25
+ * IsUnique 配置选项
26
+ */
27
+ export interface IsUniqueOptions {
28
+ /**
29
+ * 手动指定用于判断是否为新建的字段名
30
+ * 适用于视图(View)等没有主键的场景
31
+ * 例如:uniqueKeys: ['id'] 或 uniqueKeys: ['id', 'version']
32
+ */
33
+ uniqueKeys?: string[];
34
+ }
9
35
  type UniqueValidationConstraints<E> = [
10
- ObjectType<E> | EntitySchema<E> | string,
11
- (validationArguments: ValidationArguments) => FindOptionsWhere<E>
36
+ ObjectType<E> | EntitySchema<E> | string | (() => ObjectType<E> | EntitySchema<E> | string),
37
+ (validationArguments: ValidationArguments) => FindOptionsWhere<E>,
38
+ IsUniqueOptions?
12
39
  ];
13
40
  interface IUniqueValidationArguments<E> extends ValidationArguments {
14
41
  constraints: UniqueValidationConstraints<E>;
@@ -21,48 +21,129 @@ Object.defineProperty(exports, "__esModule", { value: true });
21
21
  exports.IsUniqueValidator = void 0;
22
22
  exports.IsUnique = IsUnique;
23
23
  const class_validator_1 = require("class-validator");
24
- const typeorm_1 = require("typeorm");
25
24
  const nestjs_i18n_1 = require("nestjs-i18n");
25
+ const common_1 = require("@nestjs/common");
26
+ const transactional_1 = require("@nestjs-cls/transactional");
26
27
  let IsUniqueValidator = class IsUniqueValidator {
27
- constructor(dataSource) {
28
- this.dataSource = dataSource;
28
+ constructor(transactionHost) {
29
+ this.transactionHost = transactionHost;
30
+ }
31
+ /**
32
+ * 解析 Entity 引用,支持多种形式:
33
+ * 1. Entity 类直接引用
34
+ * 2. 延迟函数 () => Entity
35
+ * 3. 字符串名称 "EntityName"
36
+ * 4. undefined (从属性名自动推断)
37
+ */
38
+ resolveEntity(entityRef, propertyName, object) {
39
+ // 1. 如果是字符串,直接返回(TypeORM 支持字符串)
40
+ if (typeof entityRef === 'string') {
41
+ return entityRef;
42
+ }
43
+ // 2. 如果是函数,需要区分延迟函数和 Entity 类
44
+ if (typeof entityRef === 'function') {
45
+ // 2.1 箭头函数没有 prototype,是延迟函数
46
+ if (!entityRef.prototype) {
47
+ const resolved = entityRef();
48
+ if (resolved)
49
+ return resolved;
50
+ }
51
+ else {
52
+ // 2.2 有 prototype,是 Entity 类或普通构造函数
53
+ // 直接返回
54
+ return entityRef;
55
+ }
56
+ }
57
+ // 3. 如果是 undefined,尝试从属性名推断 Entity
58
+ if (!entityRef) {
59
+ const inferredEntityName = this.inferEntityNameFromProperty(propertyName);
60
+ if (inferredEntityName) {
61
+ console.warn(`[IsUnique] Entity reference is undefined for property "${propertyName}". ` +
62
+ `This may be caused by circular dependencies. ` +
63
+ `Consider using lazy reference: () => ${inferredEntityName}`);
64
+ return inferredEntityName;
65
+ }
66
+ }
67
+ throw new Error(`[IsUnique] Cannot resolve entity reference for property "${propertyName}". ` +
68
+ `Entity is undefined. This is likely caused by circular dependencies. ` +
69
+ `Please use one of the following solutions:\n` +
70
+ `1. Lazy reference: @IsUnique([() => EntityClass, ...])\n` +
71
+ `2. String reference: @IsUnique(["EntityName", ...])\n` +
72
+ `3. Break the circular dependency`);
73
+ }
74
+ /**
75
+ * 从属性名推断 Entity 名称
76
+ * 例如:appId -> App, userId -> User
77
+ */
78
+ inferEntityNameFromProperty(propertyName) {
79
+ const name = propertyName.replace(/(Id|Ids|Key|Code)$/, '');
80
+ if (!name)
81
+ return null;
82
+ const entityName = name.charAt(0).toUpperCase() + name.slice(1) + 'Entity';
83
+ return entityName;
29
84
  }
30
85
  validate(value, args) {
31
86
  return __awaiter(this, void 0, void 0, function* () {
32
- const [entityClass, findCondition] = args.constraints;
87
+ const [entityRef, findCondition, options] = args.constraints;
88
+ // 解析 Entity 引用
89
+ const entityClass = this.resolveEntity(entityRef, args.property, args.object);
90
+ const repository = this.transactionHost.tx.getRepository(entityClass);
33
91
  args.value = value;
34
92
  let exists;
35
93
  const defCon = findCondition(args);
36
- const pkCols = this.dataSource
37
- .getMetadata(entityClass)
38
- .primaryColumns.map((column) => column.propertyName);
39
- const isNew = pkCols.some((pk) => args.object[pk]);
40
- if (!isNew) {
94
+ // 获取用于判断是否为新建的字段
95
+ // 优先级:手动配置的 uniqueKeys > 实体主键
96
+ let pkCols;
97
+ if ((options === null || options === void 0 ? void 0 : options.uniqueKeys) && options.uniqueKeys.length > 0) {
98
+ // 1. 使用手动指定的字段
99
+ pkCols = options.uniqueKeys;
100
+ }
101
+ else {
102
+ // 2. 使用实体的主键
103
+ pkCols = repository.metadata
104
+ .primaryColumns.map((column) => column.propertyName);
105
+ }
106
+ // 如果没有主键也没有 uniqueKeys,使用简化逻辑
107
+ // 查询条件本身表示唯一性,只要存在记录就不允许
108
+ if (pkCols.length === 0) {
109
+ const count = yield repository.count({ where: defCon });
110
+ exists = count < 1;
111
+ return exists;
112
+ }
113
+ // 修复:检查是否为新建记录
114
+ // 如果所有 uniqueKeys/主键都没有值(null/undefined),则为新建
115
+ const isNew = !pkCols.some((pk) => {
116
+ const pkValue = args.object[pk];
117
+ return pkValue !== null && pkValue !== undefined && pkValue !== '';
118
+ });
119
+ if (isNew) {
120
+ // 新建场景:简单检查是否存在相同值的记录
41
121
  exists =
42
- (yield this.dataSource
43
- .getRepository(entityClass)
122
+ (yield repository
44
123
  .count({ where: defCon })) < 1;
45
124
  }
46
125
  else {
47
- const entities = yield this.dataSource
48
- .getRepository(entityClass)
126
+ // 更新场景:需要排除当前记录(通过主键对比)
127
+ const entities = yield repository
49
128
  .createQueryBuilder()
50
129
  .where(defCon)
51
- .select(pkCols)
52
130
  .limit(2)
53
- .execute();
131
+ .getMany();
54
132
  const entityCount = entities.length;
55
133
  if (entityCount === 1) {
134
+ // 只有一条记录,检查是否是当前记录本身
56
135
  const entity = entities[0];
57
136
  const oldPk = {};
58
137
  const newPk = {};
59
- pkCols.map((pk) => {
138
+ pkCols.forEach((pk) => {
60
139
  oldPk[pk] = entity[pk];
61
140
  newPk[pk] = args.object[pk];
62
141
  });
142
+ // 如果主键相同,说明是自己,允许(唯一)
63
143
  exists = JSON.stringify(oldPk) === JSON.stringify(newPk);
64
144
  }
65
145
  else {
146
+ // 0条或多条记录
66
147
  exists = entityCount < 1;
67
148
  }
68
149
  }
@@ -75,8 +156,9 @@ let IsUniqueValidator = class IsUniqueValidator {
75
156
  };
76
157
  exports.IsUniqueValidator = IsUniqueValidator;
77
158
  exports.IsUniqueValidator = IsUniqueValidator = __decorate([
159
+ (0, common_1.Injectable)(),
78
160
  (0, class_validator_1.ValidatorConstraint)({ name: 'isUnique', async: true }),
79
- __metadata("design:paramtypes", [typeorm_1.DataSource])
161
+ __metadata("design:paramtypes", [transactional_1.TransactionHost])
80
162
  ], IsUniqueValidator);
81
163
  function IsUnique(constraints, validationOptions) {
82
164
  return function (object, propertyName) {
@@ -1 +1,6 @@
1
+ /**
2
+ * When the value is emtpy, validation is skipped
3
+ * @param field
4
+ * @constructor
5
+ */
1
6
  export declare function SkipEmpty(field?: string): <TFunction extends Function, Y>(target: TFunction | object, propertyKey?: string | symbol, descriptor?: TypedPropertyDescriptor<Y>) => void;
@@ -5,6 +5,11 @@ const common_1 = require("@nestjs/common");
5
5
  const swagger_1 = require("@nestjs/swagger");
6
6
  const class_validator_1 = require("class-validator");
7
7
  const lodash_1 = require("lodash");
8
+ /**
9
+ * When the value is emtpy, validation is skipped
10
+ * @param field
11
+ * @constructor
12
+ */
8
13
  function SkipEmpty(field) {
9
14
  return (0, common_1.applyDecorators)((0, swagger_1.ApiProperty)({ required: false }), (0, class_validator_1.ValidateIf)((obj, value) => {
10
15
  if (field) {
@@ -1,3 +1,6 @@
1
+ /**
2
+ * Vault 认证选项
3
+ */
1
4
  export interface VaultAuthOptions {
2
5
  token?: string;
3
6
  roleId?: string;
@@ -5,6 +8,9 @@ export interface VaultAuthOptions {
5
8
  k8sRole?: string;
6
9
  k8sServiceAccountToken?: string;
7
10
  }
11
+ /**
12
+ * Vault 配置选项
13
+ */
8
14
  export interface VaultOptions {
9
15
  endpoint: string;
10
16
  auth: VaultAuthOptions;
@@ -16,6 +22,9 @@ export interface VaultOptions {
16
22
  hotReloadInterval?: number;
17
23
  failOnError?: boolean;
18
24
  }
25
+ /**
26
+ * Vault 配置
27
+ */
19
28
  export interface VaultConfig {
20
29
  enabled: boolean;
21
30
  options?: VaultOptions;
@@ -1,13 +1,43 @@
1
+ /**
2
+ * Vault 配置加载器
3
+ * 负责在应用启动时从 Vault 加载配置并注入到 process.env
4
+ * 配置优先级: base.env < 环境.env < Vault
5
+ */
1
6
  export declare class VaultConfigLoader {
2
7
  private static readonly logger;
3
8
  private static vaultClient;
4
9
  private static hotReloadTimer;
10
+ /**
11
+ * 从环境变量构建 Vault 配置
12
+ */
5
13
  private static buildVaultOptions;
14
+ /**
15
+ * 初始化 Vault 客户端并进行认证
16
+ */
6
17
  private static initializeVaultClient;
18
+ /**
19
+ * 从 Vault 读取指定路径的配置
20
+ */
7
21
  private static readSecrets;
22
+ /**
23
+ * 加载 Vault 配置并注入到 process.env
24
+ * 配置优先级: base.env < 环境.env < Vault(Vault 会覆盖之前的配置)
25
+ */
8
26
  static loadVaultConfig(): Promise<void>;
27
+ /**
28
+ * 启动配置热更新
29
+ */
9
30
  private static startHotReload;
31
+ /**
32
+ * 停止热更新
33
+ */
10
34
  static stopHotReload(): void;
35
+ /**
36
+ * 获取 Vault 客户端(用于运行时动态读取)
37
+ */
11
38
  static getVaultClient(): any;
39
+ /**
40
+ * 检查 Vault 是否已连接
41
+ */
12
42
  static isConnected(): boolean;
13
43
  }