@nest-omni/core 4.1.3-2 → 4.1.3-4

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 (235) hide show
  1. package/audit/audit.module.d.ts +10 -0
  2. package/audit/audit.module.js +15 -0
  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 +8 -0
  6. package/audit/decorators/audit-controller.decorator.js +9 -0
  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 +8 -0
  10. package/audit/decorators/entity-audit.decorator.js +9 -0
  11. package/audit/dto/audit-log-query.dto.d.ts +3 -0
  12. package/audit/dto/audit-log-query.dto.js +3 -0
  13. package/audit/dto/begin-transaction.dto.d.ts +3 -0
  14. package/audit/dto/begin-transaction.dto.js +3 -0
  15. package/audit/dto/compare-entities.dto.d.ts +3 -0
  16. package/audit/dto/compare-entities.dto.js +3 -0
  17. package/audit/dto/pre-check-restore.dto.d.ts +3 -0
  18. package/audit/dto/pre-check-restore.dto.js +3 -0
  19. package/audit/dto/restore-entity.dto.d.ts +3 -0
  20. package/audit/dto/restore-entity.dto.js +3 -0
  21. package/audit/entities/entity-audit-log.entity.d.ts +3 -0
  22. package/audit/entities/entity-audit-log.entity.js +3 -0
  23. package/audit/entities/entity-transaction.entity.d.ts +3 -0
  24. package/audit/entities/entity-transaction.entity.js +3 -0
  25. package/audit/entities/manual-operation-log.entity.d.ts +4 -0
  26. package/audit/entities/manual-operation-log.entity.js +4 -0
  27. package/audit/entities/operation-template.entity.d.ts +4 -0
  28. package/audit/entities/operation-template.entity.js +4 -0
  29. package/audit/enums/audit.enums.d.ts +17 -2
  30. package/audit/enums/audit.enums.js +15 -0
  31. package/audit/index.js +10 -0
  32. package/audit/interceptors/audit.interceptor.d.ts +15 -0
  33. package/audit/interceptors/audit.interceptor.js +23 -1
  34. package/audit/interfaces/audit.interfaces.d.ts +42 -0
  35. package/audit/services/audit-context.service.d.ts +15 -0
  36. package/audit/services/audit-context.service.js +15 -0
  37. package/audit/services/audit-strategy.service.d.ts +6 -0
  38. package/audit/services/audit-strategy.service.js +13 -0
  39. package/audit/services/entity-audit.service.d.ts +57 -0
  40. package/audit/services/entity-audit.service.js +91 -0
  41. package/audit/services/manual-audit-log.service.d.ts +124 -0
  42. package/audit/services/manual-audit-log.service.js +138 -0
  43. package/audit/services/multi-database.service.d.ts +12 -0
  44. package/audit/services/multi-database.service.js +12 -0
  45. package/audit/services/operation-description.service.d.ts +59 -0
  46. package/audit/services/operation-description.service.js +76 -2
  47. package/audit/services/transaction-audit.service.d.ts +30 -0
  48. package/audit/services/transaction-audit.service.js +47 -0
  49. package/audit/subscribers/entity-audit.subscriber.d.ts +15 -0
  50. package/audit/subscribers/entity-audit.subscriber.js +29 -1
  51. package/cache/cache-metrics.service.d.ts +67 -0
  52. package/cache/cache-metrics.service.js +68 -4
  53. package/cache/cache-serialization.service.d.ts +31 -0
  54. package/cache/cache-serialization.service.js +25 -0
  55. package/cache/cache.constants.d.ts +9 -0
  56. package/cache/cache.constants.js +9 -0
  57. package/cache/cache.health.d.ts +26 -0
  58. package/cache/cache.health.js +30 -0
  59. package/cache/cache.module.d.ts +86 -0
  60. package/cache/cache.module.js +71 -0
  61. package/cache/cache.service.d.ts +140 -0
  62. package/cache/cache.service.js +157 -0
  63. package/cache/cache.warmup.service.d.ts +39 -0
  64. package/cache/cache.warmup.service.js +32 -0
  65. package/cache/decorators/cache-evict.decorator.d.ts +47 -0
  66. package/cache/decorators/cache-evict.decorator.js +56 -0
  67. package/cache/decorators/cache-put.decorator.d.ts +34 -0
  68. package/cache/decorators/cache-put.decorator.js +39 -0
  69. package/cache/decorators/cacheable.decorator.d.ts +40 -0
  70. package/cache/decorators/cacheable.decorator.js +55 -0
  71. package/cache/dependencies/callback.dependency.d.ts +33 -0
  72. package/cache/dependencies/callback.dependency.js +39 -1
  73. package/cache/dependencies/chain.dependency.d.ts +28 -0
  74. package/cache/dependencies/chain.dependency.js +34 -0
  75. package/cache/dependencies/db.dependency.d.ts +45 -0
  76. package/cache/dependencies/db.dependency.js +48 -1
  77. package/cache/dependencies/file.dependency.d.ts +32 -0
  78. package/cache/dependencies/file.dependency.js +34 -0
  79. package/cache/dependencies/tag.dependency.d.ts +36 -0
  80. package/cache/dependencies/tag.dependency.js +36 -0
  81. package/cache/dependencies/time.dependency.d.ts +43 -0
  82. package/cache/dependencies/time.dependency.js +43 -0
  83. package/cache/examples/basic-usage.d.ts +15 -0
  84. package/cache/examples/basic-usage.js +62 -8
  85. package/cache/index.js +9 -0
  86. package/cache/interfaces/cache-dependency.interface.d.ts +53 -0
  87. package/cache/interfaces/cache-options.interface.d.ts +81 -0
  88. package/cache/interfaces/cache-options.interface.js +6 -0
  89. package/cache/interfaces/cache-provider.interface.d.ts +78 -0
  90. package/cache/providers/base-cache.provider.d.ts +14 -0
  91. package/cache/providers/base-cache.provider.js +16 -0
  92. package/cache/providers/cls-cache.provider.d.ts +20 -0
  93. package/cache/providers/cls-cache.provider.js +28 -0
  94. package/cache/providers/memory-cache.provider.d.ts +23 -0
  95. package/cache/providers/memory-cache.provider.js +26 -0
  96. package/cache/providers/redis-cache.provider.d.ts +26 -0
  97. package/cache/providers/redis-cache.provider.js +29 -0
  98. package/cache/utils/dependency-manager.util.d.ts +52 -0
  99. package/cache/utils/dependency-manager.util.js +59 -0
  100. package/cache/utils/key-generator.util.d.ts +42 -0
  101. package/cache/utils/key-generator.util.js +53 -1
  102. package/common/abstract.entity.d.ts +14 -0
  103. package/common/abstract.entity.js +14 -0
  104. package/common/boilerplate.polyfill.d.ts +142 -0
  105. package/common/boilerplate.polyfill.js +17 -0
  106. package/common/dto/dto-container.d.ts +16 -0
  107. package/common/dto/dto-container.js +20 -0
  108. package/common/dto/dto-decorators.d.ts +18 -0
  109. package/common/dto/dto-decorators.js +14 -0
  110. package/common/dto/dto-extensions.d.ts +11 -0
  111. package/common/dto/dto-extensions.js +9 -0
  112. package/common/dto/dto-service-accessor.d.ts +17 -0
  113. package/common/dto/dto-service-accessor.js +18 -0
  114. package/common/dto/dto-transformer.d.ts +12 -0
  115. package/common/dto/dto-transformer.js +9 -0
  116. package/common/dto/index.js +2 -0
  117. package/common/examples/paginate-and-map.example.d.ts +6 -0
  118. package/common/examples/paginate-and-map.example.js +26 -0
  119. package/common/utils.d.ts +15 -0
  120. package/common/utils.js +15 -0
  121. package/constants/language-code.js +1 -0
  122. package/decorators/field.decorators.js +8 -1
  123. package/decorators/property.decorators.js +1 -0
  124. package/decorators/public-route.decorator.js +1 -0
  125. package/decorators/transform.decorators.d.ts +27 -0
  126. package/decorators/transform.decorators.js +29 -0
  127. package/decorators/translate.decorator.js +1 -0
  128. package/decorators/user.decorator.js +1 -0
  129. package/decorators/validator.decorators.d.ts +8 -18
  130. package/decorators/validator.decorators.js +22 -190
  131. package/filters/constraint-errors.js +1 -0
  132. package/helpers/common.helper.d.ts +13 -0
  133. package/helpers/common.helper.js +13 -0
  134. package/http-client/config/http-client.config.d.ts +15 -0
  135. package/http-client/config/http-client.config.js +25 -9
  136. package/http-client/decorators/http-client.decorators.d.ts +63 -0
  137. package/http-client/decorators/http-client.decorators.js +71 -3
  138. package/http-client/entities/http-log.entity.d.ts +229 -0
  139. package/http-client/entities/http-log.entity.js +6 -1
  140. package/http-client/errors/http-client.errors.d.ts +57 -0
  141. package/http-client/errors/http-client.errors.js +58 -0
  142. package/http-client/examples/advanced-usage.example.d.ts +41 -0
  143. package/http-client/examples/advanced-usage.example.js +68 -24
  144. package/http-client/examples/auth-with-waiting-lock.example.d.ts +31 -0
  145. package/http-client/examples/auth-with-waiting-lock.example.js +52 -5
  146. package/http-client/examples/basic-usage.example.d.ts +60 -0
  147. package/http-client/examples/basic-usage.example.js +60 -0
  148. package/http-client/examples/multi-api-configuration.example.d.ts +60 -0
  149. package/http-client/examples/multi-api-configuration.example.js +76 -5
  150. package/http-client/http-client.module.d.ts +13 -0
  151. package/http-client/http-client.module.js +19 -0
  152. package/http-client/index.js +8 -0
  153. package/http-client/interfaces/api-client-config.interface.d.ts +125 -0
  154. package/http-client/interfaces/api-client-config.interface.js +3 -0
  155. package/http-client/interfaces/http-client-config.interface.d.ts +60 -0
  156. package/http-client/services/api-client-registry.service.d.ts +57 -0
  157. package/http-client/services/api-client-registry.service.js +84 -1
  158. package/http-client/services/cache.service.d.ts +52 -0
  159. package/http-client/services/cache.service.js +72 -3
  160. package/http-client/services/circuit-breaker.service.d.ts +46 -0
  161. package/http-client/services/circuit-breaker.service.js +52 -0
  162. package/http-client/services/http-client.service.d.ts +67 -0
  163. package/http-client/services/http-client.service.js +105 -4
  164. package/http-client/services/http-log-query.service.d.ts +83 -0
  165. package/http-client/services/http-log-query.service.js +122 -1
  166. package/http-client/services/http-replay.service.d.ts +101 -0
  167. package/http-client/services/http-replay.service.js +86 -0
  168. package/http-client/services/log-cleanup.service.d.ts +63 -0
  169. package/http-client/services/log-cleanup.service.js +54 -2
  170. package/http-client/services/logging.service.d.ts +40 -0
  171. package/http-client/services/logging.service.js +53 -0
  172. package/http-client/utils/call-stack-extractor.util.d.ts +37 -0
  173. package/http-client/utils/call-stack-extractor.util.js +48 -0
  174. package/http-client/utils/context-extractor.util.d.ts +49 -0
  175. package/http-client/utils/context-extractor.util.js +52 -0
  176. package/http-client/utils/curl-generator.util.d.ts +21 -0
  177. package/http-client/utils/curl-generator.util.js +44 -3
  178. package/http-client/utils/request-id.util.d.ts +18 -0
  179. package/http-client/utils/request-id.util.js +20 -0
  180. package/http-client/utils/retry-recorder.util.d.ts +42 -0
  181. package/http-client/utils/retry-recorder.util.js +44 -0
  182. package/index.js +8 -0
  183. package/interceptors/translation-interceptor.service.js +5 -0
  184. package/package.json +1 -1
  185. package/providers/context.provider.js +2 -0
  186. package/providers/generator.provider.d.ts +4 -0
  187. package/providers/generator.provider.js +4 -0
  188. package/redis-lock/examples/lock-strategy.examples.d.ts +89 -0
  189. package/redis-lock/examples/lock-strategy.examples.js +130 -15
  190. package/redis-lock/index.js +3 -0
  191. package/redis-lock/redis-lock.decorator.d.ts +101 -0
  192. package/redis-lock/redis-lock.decorator.js +120 -0
  193. package/redis-lock/redis-lock.module.d.ts +60 -0
  194. package/redis-lock/redis-lock.module.js +46 -0
  195. package/redis-lock/redis-lock.service.d.ts +251 -0
  196. package/redis-lock/redis-lock.service.js +219 -3
  197. package/setup/bootstrap.setup.js +20 -0
  198. package/setup/mode.setup.d.ts +44 -0
  199. package/setup/mode.setup.js +44 -0
  200. package/setup/schedule.decorator.d.ts +226 -0
  201. package/setup/schedule.decorator.js +214 -1
  202. package/setup/worker.decorator.d.ts +86 -0
  203. package/setup/worker.decorator.js +88 -0
  204. package/shared/serviceRegistryModule.js +5 -1
  205. package/shared/services/api-config.service.d.ts +3 -0
  206. package/shared/services/api-config.service.js +20 -9
  207. package/validator-json/decorators.d.ts +17 -0
  208. package/validator-json/decorators.js +17 -2
  209. package/validator-json/default.d.ts +6 -0
  210. package/validator-json/default.js +30 -2
  211. package/validator-json/defaultConverters.js +1 -0
  212. package/validator-json/options.d.ts +23 -0
  213. package/validators/common-validators.d.ts +143 -0
  214. package/validators/common-validators.js +249 -0
  215. package/validators/custom-validate.examples.d.ts +23 -0
  216. package/validators/custom-validate.examples.js +78 -6
  217. package/validators/custom-validate.validator.d.ts +107 -0
  218. package/validators/custom-validate.validator.js +84 -0
  219. package/validators/index.d.ts +1 -0
  220. package/validators/index.js +1 -0
  221. package/validators/is-exists.validator.d.ts +11 -0
  222. package/validators/is-exists.validator.js +22 -0
  223. package/validators/is-unique.validator.d.ts +11 -0
  224. package/validators/is-unique.validator.js +31 -3
  225. package/validators/skip-empty.validator.d.ts +5 -0
  226. package/validators/skip-empty.validator.js +5 -0
  227. package/vault/interfaces/vault-options.interface.d.ts +9 -0
  228. package/vault/vault-config.loader.d.ts +30 -0
  229. package/vault/vault-config.loader.js +48 -1
  230. package/vault/vault-config.service.d.ts +53 -0
  231. package/vault/vault-config.service.js +57 -0
  232. package/vault/vault.module.d.ts +4 -0
  233. package/vault/vault.module.js +4 -0
  234. package/decorators/examples/validation-decorators.example.d.ts +0 -69
  235. package/decorators/examples/validation-decorators.example.js +0 -331
@@ -0,0 +1,249 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.AtLeastOneFieldConstraint = void 0;
10
+ exports.IsPassword = IsPassword;
11
+ exports.IsPhoneNumber = IsPhoneNumber;
12
+ exports.IsTmpKey = IsTmpKey;
13
+ exports.IsUndefinable = IsUndefinable;
14
+ exports.IsEmptyable = IsEmptyable;
15
+ exports.IsNullable = IsNullable;
16
+ exports.IsHttpUrl = IsHttpUrl;
17
+ exports.AtLeastOneField = AtLeastOneField;
18
+ const class_validator_1 = require("class-validator");
19
+ const lodash_1 = require("lodash");
20
+ const nestjs_i18n_1 = require("nestjs-i18n");
21
+ /**
22
+ * 验证密码格式(只允许字母、数字和特定特殊字符)
23
+ *
24
+ * @param validationOptions 验证选项
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * class UserDto {
29
+ * @IsPassword({ message: 'Invalid password format' })
30
+ * password: string;
31
+ * }
32
+ * ```
33
+ */
34
+ function IsPassword(validationOptions) {
35
+ return (object, propertyName) => {
36
+ (0, class_validator_1.registerDecorator)({
37
+ propertyName,
38
+ name: 'isPassword',
39
+ target: object.constructor,
40
+ constraints: [],
41
+ options: validationOptions,
42
+ validator: {
43
+ validate(value) {
44
+ return /^[\d!#$%&*@A-Z^a-z]*$/.test(value);
45
+ },
46
+ },
47
+ });
48
+ };
49
+ }
50
+ /**
51
+ * 验证手机号码(支持指定国家/地区)
52
+ *
53
+ * @param validationOptions 验证选项,可以指定 region
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * class ContactDto {
58
+ * @IsPhoneNumber({ region: 'CN' })
59
+ * phone: string;
60
+ * }
61
+ * ```
62
+ */
63
+ function IsPhoneNumber(validationOptions) {
64
+ return (0, class_validator_1.IsPhoneNumber)(validationOptions === null || validationOptions === void 0 ? void 0 : validationOptions.region, Object.assign({ message: 'error.phoneNumber' }, validationOptions));
65
+ }
66
+ /**
67
+ * 验证临时文件路径(必须以 tmp/ 开头)
68
+ *
69
+ * @param validationOptions 验证选项
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * class FileDto {
74
+ * @IsTmpKey()
75
+ * filePath: string; // 必须是 'tmp/...'
76
+ * }
77
+ * ```
78
+ */
79
+ function IsTmpKey(validationOptions) {
80
+ return (object, propertyName) => {
81
+ (0, class_validator_1.registerDecorator)({
82
+ propertyName,
83
+ name: 'tmpKey',
84
+ target: object.constructor,
85
+ options: validationOptions,
86
+ validator: {
87
+ validate(value) {
88
+ return (0, lodash_1.isString)(value) && /^tmp\//.test(value);
89
+ },
90
+ defaultMessage() {
91
+ return 'error.invalidTmpKey';
92
+ },
93
+ },
94
+ });
95
+ };
96
+ }
97
+ /**
98
+ * 允许字段为 undefined,如果不是 undefined 才执行其他验证
99
+ *
100
+ * @param options 验证选项
101
+ *
102
+ * @example
103
+ * ```typescript
104
+ * class UserDto {
105
+ * @IsUndefinable()
106
+ * @IsString()
107
+ * nickname?: string; // undefined 或字符串
108
+ * }
109
+ * ```
110
+ */
111
+ function IsUndefinable(options) {
112
+ return (0, class_validator_1.ValidateIf)((obj, value) => value !== undefined, options);
113
+ }
114
+ /**
115
+ * 允许字段为空值(null、undefined 或空字符串),如果不为空才执行其他验证
116
+ *
117
+ * @param options 验证选项
118
+ *
119
+ * @example
120
+ * ```typescript
121
+ * class UserDto {
122
+ * @IsEmptyable()
123
+ * @IsEmail()
124
+ * email?: string; // 可以为空,或者必须是有效邮箱
125
+ * }
126
+ * ```
127
+ */
128
+ function IsEmptyable(options) {
129
+ return (0, class_validator_1.ValidateIf)((obj, value) => !(value === null ||
130
+ value === undefined ||
131
+ ((0, lodash_1.isString)(value) && value.trim() === '')), options);
132
+ }
133
+ /**
134
+ * 允许字段为 null,如果不是 null 才执行其他验证
135
+ *
136
+ * @param options 验证选项
137
+ *
138
+ * @example
139
+ * ```typescript
140
+ * class UserDto {
141
+ * @IsNullable()
142
+ * @IsNumber()
143
+ * age?: number | null; // null 或数字
144
+ * }
145
+ * ```
146
+ */
147
+ function IsNullable(options) {
148
+ return (0, class_validator_1.ValidateIf)((obj, value) => value !== null, options);
149
+ }
150
+ /**
151
+ * 验证 HTTP/HTTPS URL
152
+ *
153
+ * @param validationOptions 验证选项
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * class WebsiteDto {
158
+ * @IsHttpUrl({ message: 'Invalid URL' })
159
+ * url: string;
160
+ * }
161
+ * ```
162
+ */
163
+ function IsHttpUrl(validationOptions) {
164
+ return function (object, propertyName) {
165
+ (0, class_validator_1.registerDecorator)({
166
+ name: 'isHttpUrl',
167
+ target: object.constructor,
168
+ propertyName: propertyName,
169
+ options: validationOptions,
170
+ validator: {
171
+ validate(value) {
172
+ const httpUrlPattern = /^(https?:\/\/)/i;
173
+ return typeof value === 'string' && httpUrlPattern.test(value);
174
+ },
175
+ defaultMessage() {
176
+ return 'URL must start with http:// or https://';
177
+ },
178
+ },
179
+ });
180
+ };
181
+ }
182
+ /**
183
+ * Validator constraint for AtLeastOneField decorator
184
+ */
185
+ let AtLeastOneFieldConstraint = class AtLeastOneFieldConstraint {
186
+ validate(value, args) {
187
+ const object = args.object;
188
+ const [requiredProperties] = args.constraints;
189
+ // Check if at least one property has a value
190
+ return requiredProperties.some((property) => {
191
+ const propValue = object[property];
192
+ return (propValue !== null &&
193
+ propValue !== undefined &&
194
+ propValue !== '' &&
195
+ !(Array.isArray(propValue) && propValue.length === 0));
196
+ });
197
+ }
198
+ defaultMessage(args) {
199
+ const [requiredProperties] = args.constraints;
200
+ return `At least one of the following fields must be provided: ${requiredProperties.join(', ')}`;
201
+ }
202
+ };
203
+ exports.AtLeastOneFieldConstraint = AtLeastOneFieldConstraint;
204
+ exports.AtLeastOneFieldConstraint = AtLeastOneFieldConstraint = __decorate([
205
+ (0, class_validator_1.ValidatorConstraint)({ name: 'atLeastOneField', async: false })
206
+ ], AtLeastOneFieldConstraint);
207
+ /**
208
+ * 验证至少提供指定字段中的一个
209
+ *
210
+ * @param properties 要检查的属性名数组
211
+ * @param validationOptions 验证选项
212
+ *
213
+ * @example
214
+ * ```typescript
215
+ * class ContactDto {
216
+ * @AtLeastOneField(['email', 'phone'], {
217
+ * message: 'Either email or phone must be provided'
218
+ * })
219
+ * email?: string;
220
+ *
221
+ * phone?: string;
222
+ * }
223
+ * ```
224
+ *
225
+ * @example
226
+ * 使用虚拟字段(推荐用于类级别验证):
227
+ * ```typescript
228
+ * class ContactDto {
229
+ * @AtLeastOneField(['email', 'phone'])
230
+ * _atLeastOne: any; // 虚拟字段用于验证
231
+ *
232
+ * email?: string;
233
+ * phone?: string;
234
+ * }
235
+ * ```
236
+ */
237
+ function AtLeastOneField(properties, validationOptions) {
238
+ return function (object, propertyName) {
239
+ (0, class_validator_1.registerDecorator)({
240
+ target: object.constructor,
241
+ propertyName: propertyName,
242
+ options: Object.assign({ message: (0, nestjs_i18n_1.i18nValidationMessage)('validation.AT_LEAST_ONE_FIELD', {
243
+ properties: properties.join(', '),
244
+ }) }, validationOptions),
245
+ constraints: [properties],
246
+ validator: AtLeastOneFieldConstraint,
247
+ });
248
+ };
249
+ }
@@ -1,3 +1,8 @@
1
+ /**
2
+ * @CustomValidate 使用示例
3
+ *
4
+ * 这个文件包含了各种使用场景的示例代码
5
+ */
1
6
  import { Repository } from 'typeorm';
2
7
  import { ValidationContext } from '../validators/custom-validate.validator';
3
8
  export declare class Example1_InlineValidation {
@@ -16,9 +21,21 @@ export declare class Example2_EntityMethod {
16
21
  export declare class ExampleValidationService {
17
22
  private readonly userRepository;
18
23
  constructor(userRepository: Repository<any>);
24
+ /**
25
+ * 检查用户名是否可用
26
+ */
19
27
  usernameAvailable(username: string): Promise<boolean>;
28
+ /**
29
+ * 检查邮箱格式
30
+ */
20
31
  validateEmail(email: string): boolean;
32
+ /**
33
+ * 检查数值范围(带额外参数)
34
+ */
21
35
  checkRange(value: number, context: ValidationContext, min: number, max: number): boolean;
36
+ /**
37
+ * 复杂的业务验证
38
+ */
22
39
  validateBusinessRule(value: any, context: ValidationContext): Promise<boolean>;
23
40
  }
24
41
  export declare class Example3_ServiceValidation {
@@ -53,7 +70,13 @@ export declare class Example7_DynamicMessage {
53
70
  discount: number;
54
71
  }
55
72
  export declare class ThirdPartyValidationService {
73
+ /**
74
+ * 验证地址是否真实存在
75
+ */
56
76
  validateAddress(address: string): Promise<boolean>;
77
+ /**
78
+ * 验证税号是否有效
79
+ */
57
80
  validateTaxId(taxId: string, context: ValidationContext): Promise<boolean>;
58
81
  }
59
82
  export declare class Example8_ThirdPartyAPI {
@@ -1,4 +1,9 @@
1
1
  "use strict";
2
+ /**
3
+ * @CustomValidate 使用示例
4
+ *
5
+ * 这个文件包含了各种使用场景的示例代码
6
+ */
2
7
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
8
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
9
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -26,6 +31,14 @@ const common_1 = require("@nestjs/common");
26
31
  const typeorm_1 = require("@nestjs/typeorm");
27
32
  const typeorm_2 = require("typeorm");
28
33
  const custom_validate_validator_1 = require("../validators/custom-validate.validator");
34
+ // ============================================================================
35
+ // Mock Entity(需要在使用前定义)
36
+ // ============================================================================
37
+ class UserEntity {
38
+ }
39
+ // ============================================================================
40
+ // 示例 1: 内联函数验证
41
+ // ============================================================================
29
42
  class Example1_InlineValidation {
30
43
  }
31
44
  exports.Example1_InlineValidation = Example1_InlineValidation;
@@ -42,15 +55,21 @@ __decorate([
42
55
  ], Example1_InlineValidation.prototype, "code", void 0);
43
56
  __decorate([
44
57
  (0, custom_validate_validator_1.CustomValidate)((value, context) => {
58
+ // 可以访问其他属性
45
59
  const minValue = context.object.minPrice || 0;
46
60
  return value > minValue;
47
61
  }, { message: '最大价格必须大于最小价格' }),
48
62
  __metadata("design:type", Number)
49
63
  ], Example1_InlineValidation.prototype, "maxPrice", void 0);
64
+ // ============================================================================
65
+ // 示例 2: Entity 方法验证
66
+ // ============================================================================
50
67
  class Example2_EntityMethod {
68
+ // 同步验证方法
51
69
  validateVersion(value) {
52
70
  return /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.test(value);
53
71
  }
72
+ // 异步验证方法(可访问 this)
54
73
  checkDates(value, context) {
55
74
  return __awaiter(this, void 0, void 0, function* () {
56
75
  return value >= this.createdAt;
@@ -68,10 +87,17 @@ __decorate([
68
87
  (0, custom_validate_validator_1.CustomValidate)('checkDates'),
69
88
  __metadata("design:type", Date)
70
89
  ], Example2_EntityMethod.prototype, "publishedAt", void 0);
90
+ // ============================================================================
91
+ // 示例 3: Service 验��
92
+ // ============================================================================
93
+ // 验证 Service
71
94
  let ExampleValidationService = class ExampleValidationService {
72
95
  constructor(userRepository) {
73
96
  this.userRepository = userRepository;
74
97
  }
98
+ /**
99
+ * 检查用户名是否可用
100
+ */
75
101
  usernameAvailable(username) {
76
102
  return __awaiter(this, void 0, void 0, function* () {
77
103
  const count = yield this.userRepository.count({
@@ -80,14 +106,24 @@ let ExampleValidationService = class ExampleValidationService {
80
106
  return count === 0;
81
107
  });
82
108
  }
109
+ /**
110
+ * 检查邮箱格式
111
+ */
83
112
  validateEmail(email) {
84
113
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
85
114
  }
115
+ /**
116
+ * 检查数值范围(带额外参数)
117
+ */
86
118
  checkRange(value, context, min, max) {
87
119
  return value >= min && value <= max;
88
120
  }
121
+ /**
122
+ * 复杂的业务验证
123
+ */
89
124
  validateBusinessRule(value, context) {
90
125
  return __awaiter(this, void 0, void 0, function* () {
126
+ // 复杂的业务逻辑
91
127
  const user = yield this.userRepository.findOne({
92
128
  where: { id: context.object.userId },
93
129
  relations: ['profile', 'permissions']
@@ -95,6 +131,7 @@ let ExampleValidationService = class ExampleValidationService {
95
131
  if (!user) {
96
132
  return false;
97
133
  }
134
+ // 可以访问关联数据进行复杂验证
98
135
  return user.profile.isVerified && user.permissions.length > 0;
99
136
  });
100
137
  }
@@ -105,6 +142,7 @@ exports.ExampleValidationService = ExampleValidationService = __decorate([
105
142
  __param(0, (0, typeorm_1.InjectRepository)(UserEntity)),
106
143
  __metadata("design:paramtypes", [typeorm_2.Repository])
107
144
  ], ExampleValidationService);
145
+ // 使用 Service 验证
108
146
  class Example3_ServiceValidation {
109
147
  }
110
148
  exports.Example3_ServiceValidation = Example3_ServiceValidation;
@@ -124,6 +162,9 @@ __decorate([
124
162
  (0, custom_validate_validator_1.CustomValidate)([ExampleValidationService, 'validateBusinessRule'], { message: '业务规则验证失败' }),
125
163
  __metadata("design:type", String)
126
164
  ], Example3_ServiceValidation.prototype, "businessField", void 0);
165
+ // ============================================================================
166
+ // 示例 4: 延迟引用(解决循环依赖)
167
+ // ============================================================================
127
168
  class Example4_LazyReference {
128
169
  }
129
170
  exports.Example4_LazyReference = Example4_LazyReference;
@@ -131,14 +172,19 @@ __decorate([
131
172
  (0, custom_validate_validator_1.CustomValidate)([() => ExampleValidationService, 'usernameAvailable'], { message: '用户名已存在' }),
132
173
  __metadata("design:type", String)
133
174
  ], Example4_LazyReference.prototype, "username", void 0);
175
+ // ============================================================================
176
+ // 示例 5: 复杂验证场景
177
+ // ============================================================================
134
178
  class Example5_ComplexValidation {
135
179
  }
136
180
  exports.Example5_ComplexValidation = Example5_ComplexValidation;
137
181
  __decorate([
138
182
  (0, custom_validate_validator_1.CustomValidate)((value, context) => __awaiter(void 0, void 0, void 0, function* () {
183
+ // 条件1:长度检查
139
184
  if (value.length < 8) {
140
185
  return false;
141
186
  }
187
+ // 条件2:复杂度检查
142
188
  const hasUpperCase = /[A-Z]/.test(value);
143
189
  const hasLowerCase = /[a-z]/.test(value);
144
190
  const hasNumber = /\d/.test(value);
@@ -146,6 +192,7 @@ __decorate([
146
192
  if (!(hasUpperCase && hasLowerCase && hasNumber && hasSpecial)) {
147
193
  return false;
148
194
  }
195
+ // 条件3���异步检查(是否在弱密码列表中)
149
196
  const response = yield fetch(`/api/check-weak-password`, {
150
197
  method: 'POST',
151
198
  body: JSON.stringify({ password: value }),
@@ -164,13 +211,17 @@ __decorate([
164
211
  ], Example5_ComplexValidation.prototype, "confirmPassword", void 0);
165
212
  __decorate([
166
213
  (0, custom_validate_validator_1.CustomValidate)((value, context) => {
214
+ // 只有当 requiresApproval 为 true 时才验证 approverId
167
215
  if (context.object.requiresApproval) {
168
216
  return value && value.length > 0;
169
217
  }
170
- return true;
218
+ return true; // 不需要审批时,总是通过
171
219
  }, { message: '需要审批时必须指定审批人' }),
172
220
  __metadata("design:type", String)
173
221
  ], Example5_ComplexValidation.prototype, "approverId", void 0);
222
+ // ============================================================================
223
+ // 示例 6: 文件验证
224
+ // ============================================================================
174
225
  let FileValidationService = class FileValidationService {
175
226
  constructor() {
176
227
  this.allowedMimeTypes = [
@@ -179,7 +230,7 @@ let FileValidationService = class FileValidationService {
179
230
  'image/gif',
180
231
  'application/pdf'
181
232
  ];
182
- this.maxFileSize = 5 * 1024 * 1024;
233
+ this.maxFileSize = 5 * 1024 * 1024; // 5MB
183
234
  }
184
235
  checkFileType(mimeType) {
185
236
  return this.allowedMimeTypes.includes(mimeType);
@@ -190,6 +241,8 @@ let FileValidationService = class FileValidationService {
190
241
  }
191
242
  checkFileHash(hash) {
192
243
  return __awaiter(this, void 0, void 0, function* () {
244
+ // 检查文件是否已存在(防重复上传)
245
+ // 实际实现:查询数据库
193
246
  return true;
194
247
  });
195
248
  }
@@ -206,13 +259,17 @@ __decorate([
206
259
  __metadata("design:type", String)
207
260
  ], Example6_FileUpload.prototype, "mimeType", void 0);
208
261
  __decorate([
209
- (0, custom_validate_validator_1.CustomValidate)([FileValidationService, 'checkFileSize', 10 * 1024 * 1024], { message: '文件大小不能超过 10MB' }),
262
+ (0, custom_validate_validator_1.CustomValidate)([FileValidationService, 'checkFileSize', 10 * 1024 * 1024], // 10MB
263
+ { message: '文件大小不能超过 10MB' }),
210
264
  __metadata("design:type", Number)
211
265
  ], Example6_FileUpload.prototype, "size", void 0);
212
266
  __decorate([
213
267
  (0, custom_validate_validator_1.CustomValidate)([FileValidationService, 'checkFileHash'], { message: '文件已存在' }),
214
268
  __metadata("design:type", String)
215
269
  ], Example6_FileUpload.prototype, "hash", void 0);
270
+ // ============================================================================
271
+ // 示例 7: 动态错误消息
272
+ // ============================================================================
216
273
  class Example7_DynamicMessage {
217
274
  }
218
275
  exports.Example7_DynamicMessage = Example7_DynamicMessage;
@@ -231,7 +288,13 @@ __decorate([
231
288
  }),
232
289
  __metadata("design:type", Number)
233
290
  ], Example7_DynamicMessage.prototype, "discount", void 0);
291
+ // ============================================================================
292
+ // 示例 8: 使用第三方 API 验证
293
+ // ============================================================================
234
294
  let ThirdPartyValidationService = class ThirdPartyValidationService {
295
+ /**
296
+ * 验证地址是否真实存在
297
+ */
235
298
  validateAddress(address) {
236
299
  return __awaiter(this, void 0, void 0, function* () {
237
300
  try {
@@ -245,6 +308,9 @@ let ThirdPartyValidationService = class ThirdPartyValidationService {
245
308
  }
246
309
  });
247
310
  }
311
+ /**
312
+ * 验证税号是否有效
313
+ */
248
314
  validateTaxId(taxId, context) {
249
315
  return __awaiter(this, void 0, void 0, function* () {
250
316
  try {
@@ -278,28 +344,36 @@ __decorate([
278
344
  (0, custom_validate_validator_1.CustomValidate)([ThirdPartyValidationService, 'validateTaxId'], { message: '税号无效' }),
279
345
  __metadata("design:type", String)
280
346
  ], Example8_ThirdPartyAPI.prototype, "taxId", void 0);
347
+ // ============================================================================
348
+ // 示例 9: 性能优化 - 缓存
349
+ // ============================================================================
281
350
  let CachedValidationService = class CachedValidationService {
282
351
  constructor() {
283
352
  this.cache = new Map();
284
- this.cacheTTL = 5 * 60 * 1000;
353
+ this.cacheTTL = 5 * 60 * 1000; // 5分钟
285
354
  }
286
355
  expensiveValidation(value) {
287
356
  return __awaiter(this, void 0, void 0, function* () {
288
357
  const now = Date.now();
358
+ // 检查缓存
289
359
  const cached = this.cache.get(value);
290
360
  if (cached && (now - cached.timestamp) < this.cacheTTL) {
291
361
  console.log(`[Cache Hit] Value: ${value}`);
292
362
  return cached.result;
293
363
  }
364
+ // 执行昂贵的验证
294
365
  console.log(`[Cache Miss] Performing validation for: ${value}`);
295
366
  const result = yield this.doExpensiveCheck(value);
367
+ // 更新缓存
296
368
  this.cache.set(value, { result, timestamp: now });
369
+ // 清理过期缓存
297
370
  this.cleanExpiredCache();
298
371
  return result;
299
372
  });
300
373
  }
301
374
  doExpensiveCheck(value) {
302
375
  return __awaiter(this, void 0, void 0, function* () {
376
+ // 模拟耗时操作(数据库查询、外部 API 等)
303
377
  yield new Promise(resolve => setTimeout(resolve, 1000));
304
378
  return true;
305
379
  });
@@ -324,5 +398,3 @@ __decorate([
324
398
  (0, custom_validate_validator_1.CustomValidate)([CachedValidationService, 'expensiveValidation'], { message: '验证失败' }),
325
399
  __metadata("design:type", String)
326
400
  ], Example9_CachedValidation.prototype, "field", void 0);
327
- class UserEntity {
328
- }
@@ -1,26 +1,133 @@
1
1
  import type { ValidationArguments, ValidationOptions, ValidatorConstraintInterface } from 'class-validator';
2
2
  import { ModuleRef } from '@nestjs/core';
3
+ /**
4
+ * 验证上下文,传递给验证函数
5
+ */
3
6
  export interface ValidationContext {
7
+ /** 当前验证的值 */
4
8
  value: any;
9
+ /** 当前对象实例 */
5
10
  object: any;
11
+ /** 属性名 */
6
12
  property: string;
13
+ /** 约束参数(包含验证函数和额外参数) */
7
14
  constraints: any[];
15
+ /** 类名 */
8
16
  targetName: string;
17
+ /** 所有验证参数(原始 ValidationArguments) */
9
18
  args: ValidationArguments;
10
19
  }
20
+ /**
21
+ * 验证函数类型
22
+ * @param value 当前验证的值
23
+ * @param context 验证上下文
24
+ * @param extraArgs 额外参数(可选)
25
+ * @returns boolean 或 Promise<boolean>
26
+ */
11
27
  export type ValidatorFunction = (value: any, context: ValidationContext, ...extraArgs: any[]) => boolean | Promise<boolean>;
28
+ /**
29
+ * 验证约束类型
30
+ *
31
+ * 支持以下几种形式:
32
+ * 1. 直接函数:(value, context) => boolean
33
+ * 2. Entity 方法名:'methodName'
34
+ * 3. Service + 方法名:[ServiceClass, 'methodName']
35
+ * 4. 延迟引用 Service:[() => ServiceClass, 'methodName']
36
+ * 5. 带额外参数:[ServiceClass, 'methodName', arg1, arg2, ...]
37
+ */
12
38
  export type ValidationConstraint = ValidatorFunction | string | [Function | (() => Function), string, ...any[]];
39
+ /**
40
+ * 装饰器选项
41
+ */
13
42
  export interface CustomValidateOptions extends ValidationOptions {
43
+ /** 错误消息(支持字符串、函数、i18n key) */
14
44
  message?: string | ((args: ValidationArguments) => string);
45
+ /** 是否异步(可选,会自动检测) */
15
46
  async?: boolean;
16
47
  }
17
48
  export declare class CustomValidateValidator implements ValidatorConstraintInterface {
18
49
  private readonly moduleRef;
19
50
  constructor(moduleRef: ModuleRef);
51
+ /**
52
+ * 验证入口
53
+ */
20
54
  validate(value: any, args: ValidationArguments): Promise<boolean>;
55
+ /**
56
+ * 调用内联函数
57
+ */
21
58
  private callFunction;
59
+ /**
60
+ * 调用 Entity 方法
61
+ */
22
62
  private callEntityMethod;
63
+ /**
64
+ * 调用 Service 方法
65
+ */
23
66
  private callServiceMethod;
67
+ /**
68
+ * 默认错误消息
69
+ */
24
70
  defaultMessage(args: ValidationArguments): string;
25
71
  }
72
+ /**
73
+ * @CustomValidate 装饰器
74
+ *
75
+ * 支持多种验证方式的灵活验证装饰器
76
+ *
77
+ * @example
78
+ * // 1. 内联函数(同步)
79
+ * @CustomValidate(
80
+ * (value) => value > 0,
81
+ * { message: '价格必须大于0' }
82
+ * )
83
+ * price: number;
84
+ *
85
+ * @example
86
+ * // 2. 内联函数(异步)
87
+ * @CustomValidate(
88
+ * async (value, context) => {
89
+ * const response = await fetch(`/api/check/${value}`);
90
+ * return response.ok;
91
+ * }
92
+ * )
93
+ * username: string;
94
+ *
95
+ * @example
96
+ * // 3. Entity 方法
97
+ * @CustomValidate('validateVersion')
98
+ * version: string;
99
+ *
100
+ * validateVersion(value: string): boolean {
101
+ * return /^\d+\.\d+\.\d+$/.test(value);
102
+ * }
103
+ *
104
+ * @example
105
+ * // 4. Service 方法
106
+ * @CustomValidate([UserValidationService, 'checkUsername'])
107
+ * username: string;
108
+ *
109
+ * @example
110
+ * // 5. 延迟引用(解决循环依赖)
111
+ * @CustomValidate([() => UserValidationService, 'checkUsername'])
112
+ * username: string;
113
+ *
114
+ * @example
115
+ * // 6. 带额外参数
116
+ * @CustomValidate(
117
+ * [ValidationService, 'checkRange', 0, 100],
118
+ * { message: '价格必须在 0-100 之间' }
119
+ * )
120
+ * price: number;
121
+ *
122
+ * @example
123
+ * // 7. 使用 i18n
124
+ * @CustomValidate(
125
+ * (value) => value.length >= 6,
126
+ * { message: 'validation.PASSWORD_TOO_SHORT' }
127
+ * )
128
+ * password: string;
129
+ *
130
+ * @param constraint 验证约束(函数、方法名、或 [Service, 方法名])
131
+ * @param validationOptions 验证选项
132
+ */
26
133
  export declare function CustomValidate(constraint: ValidationConstraint, validationOptions?: CustomValidateOptions): PropertyDecorator;