@nest-omni/core 4.1.3-1 → 4.1.3-3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/audit/audit.module.d.ts +10 -0
- package/audit/audit.module.js +15 -0
- package/audit/controllers/audit.controller.d.ts +24 -0
- package/audit/controllers/audit.controller.js +24 -0
- package/audit/decorators/audit-controller.decorator.d.ts +8 -0
- package/audit/decorators/audit-controller.decorator.js +9 -0
- package/audit/decorators/audit-operation.decorator.d.ts +45 -0
- package/audit/decorators/audit-operation.decorator.js +49 -0
- package/audit/decorators/entity-audit.decorator.d.ts +8 -0
- package/audit/decorators/entity-audit.decorator.js +9 -0
- package/audit/dto/audit-log-query.dto.d.ts +3 -0
- package/audit/dto/audit-log-query.dto.js +3 -0
- package/audit/dto/begin-transaction.dto.d.ts +3 -0
- package/audit/dto/begin-transaction.dto.js +3 -0
- package/audit/dto/compare-entities.dto.d.ts +3 -0
- package/audit/dto/compare-entities.dto.js +3 -0
- package/audit/dto/pre-check-restore.dto.d.ts +3 -0
- package/audit/dto/pre-check-restore.dto.js +3 -0
- package/audit/dto/restore-entity.dto.d.ts +3 -0
- package/audit/dto/restore-entity.dto.js +3 -0
- package/audit/entities/entity-audit-log.entity.d.ts +3 -0
- package/audit/entities/entity-audit-log.entity.js +3 -0
- package/audit/entities/entity-transaction.entity.d.ts +3 -0
- package/audit/entities/entity-transaction.entity.js +3 -0
- package/audit/entities/manual-operation-log.entity.d.ts +4 -0
- package/audit/entities/manual-operation-log.entity.js +4 -0
- package/audit/entities/operation-template.entity.d.ts +4 -0
- package/audit/entities/operation-template.entity.js +4 -0
- package/audit/enums/audit.enums.d.ts +17 -2
- package/audit/enums/audit.enums.js +15 -0
- package/audit/index.js +10 -0
- package/audit/interceptors/audit.interceptor.d.ts +15 -0
- package/audit/interceptors/audit.interceptor.js +23 -1
- package/audit/interfaces/audit.interfaces.d.ts +42 -0
- package/audit/services/audit-context.service.d.ts +15 -0
- package/audit/services/audit-context.service.js +15 -0
- package/audit/services/audit-strategy.service.d.ts +6 -0
- package/audit/services/audit-strategy.service.js +13 -0
- package/audit/services/entity-audit.service.d.ts +57 -0
- package/audit/services/entity-audit.service.js +91 -0
- package/audit/services/manual-audit-log.service.d.ts +124 -0
- package/audit/services/manual-audit-log.service.js +138 -0
- package/audit/services/multi-database.service.d.ts +12 -0
- package/audit/services/multi-database.service.js +12 -0
- package/audit/services/operation-description.service.d.ts +59 -0
- package/audit/services/operation-description.service.js +76 -2
- package/audit/services/transaction-audit.service.d.ts +30 -0
- package/audit/services/transaction-audit.service.js +47 -0
- package/audit/subscribers/entity-audit.subscriber.d.ts +15 -0
- package/audit/subscribers/entity-audit.subscriber.js +29 -1
- package/cache/cache-metrics.service.d.ts +67 -0
- package/cache/cache-metrics.service.js +68 -4
- package/cache/cache-serialization.service.d.ts +31 -0
- package/cache/cache-serialization.service.js +25 -0
- package/cache/cache.constants.d.ts +9 -0
- package/cache/cache.constants.js +9 -0
- package/cache/cache.health.d.ts +26 -0
- package/cache/cache.health.js +30 -0
- package/cache/cache.module.d.ts +86 -0
- package/cache/cache.module.js +71 -0
- package/cache/cache.service.d.ts +140 -0
- package/cache/cache.service.js +157 -0
- package/cache/cache.warmup.service.d.ts +39 -0
- package/cache/cache.warmup.service.js +32 -0
- package/cache/decorators/cache-evict.decorator.d.ts +47 -0
- package/cache/decorators/cache-evict.decorator.js +56 -0
- package/cache/decorators/cache-put.decorator.d.ts +34 -0
- package/cache/decorators/cache-put.decorator.js +39 -0
- package/cache/decorators/cacheable.decorator.d.ts +40 -0
- package/cache/decorators/cacheable.decorator.js +55 -0
- package/cache/dependencies/callback.dependency.d.ts +33 -0
- package/cache/dependencies/callback.dependency.js +39 -1
- package/cache/dependencies/chain.dependency.d.ts +28 -0
- package/cache/dependencies/chain.dependency.js +34 -0
- package/cache/dependencies/db.dependency.d.ts +45 -0
- package/cache/dependencies/db.dependency.js +48 -1
- package/cache/dependencies/file.dependency.d.ts +32 -0
- package/cache/dependencies/file.dependency.js +34 -0
- package/cache/dependencies/tag.dependency.d.ts +36 -0
- package/cache/dependencies/tag.dependency.js +36 -0
- package/cache/dependencies/time.dependency.d.ts +43 -0
- package/cache/dependencies/time.dependency.js +43 -0
- package/cache/examples/basic-usage.d.ts +15 -0
- package/cache/examples/basic-usage.js +62 -8
- package/cache/index.js +9 -0
- package/cache/interfaces/cache-dependency.interface.d.ts +53 -0
- package/cache/interfaces/cache-options.interface.d.ts +81 -0
- package/cache/interfaces/cache-options.interface.js +6 -0
- package/cache/interfaces/cache-provider.interface.d.ts +78 -0
- package/cache/providers/base-cache.provider.d.ts +14 -0
- package/cache/providers/base-cache.provider.js +16 -0
- package/cache/providers/cls-cache.provider.d.ts +20 -0
- package/cache/providers/cls-cache.provider.js +28 -0
- package/cache/providers/memory-cache.provider.d.ts +23 -0
- package/cache/providers/memory-cache.provider.js +26 -0
- package/cache/providers/redis-cache.provider.d.ts +26 -0
- package/cache/providers/redis-cache.provider.js +29 -0
- package/cache/utils/dependency-manager.util.d.ts +52 -0
- package/cache/utils/dependency-manager.util.js +59 -0
- package/cache/utils/key-generator.util.d.ts +42 -0
- package/cache/utils/key-generator.util.js +53 -1
- package/common/abstract.entity.d.ts +14 -0
- package/common/abstract.entity.js +14 -0
- package/common/boilerplate.polyfill.d.ts +142 -4
- package/common/boilerplate.polyfill.js +24 -100
- package/common/dto/dto-container.d.ts +16 -0
- package/common/dto/dto-container.js +20 -0
- package/common/dto/dto-decorators.d.ts +18 -0
- package/common/dto/dto-decorators.js +14 -0
- package/common/dto/dto-extensions.d.ts +11 -0
- package/common/dto/dto-extensions.js +9 -0
- package/common/dto/dto-service-accessor.d.ts +17 -0
- package/common/dto/dto-service-accessor.js +18 -0
- package/common/dto/dto-transformer.d.ts +12 -0
- package/common/dto/dto-transformer.js +9 -0
- package/common/dto/index.js +2 -0
- package/common/examples/paginate-and-map.example.d.ts +6 -0
- package/common/examples/paginate-and-map.example.js +26 -0
- package/common/utils.d.ts +15 -0
- package/common/utils.js +15 -0
- package/constants/language-code.js +1 -0
- package/decorators/field.decorators.js +8 -1
- package/decorators/property.decorators.js +1 -0
- package/decorators/public-route.decorator.js +1 -0
- package/decorators/transform.decorators.d.ts +27 -0
- package/decorators/transform.decorators.js +29 -0
- package/decorators/translate.decorator.js +1 -0
- package/decorators/user.decorator.js +1 -0
- package/decorators/validator.decorators.d.ts +8 -18
- package/decorators/validator.decorators.js +22 -190
- package/filters/constraint-errors.js +1 -0
- package/helpers/common.helper.d.ts +13 -0
- package/helpers/common.helper.js +13 -0
- package/http-client/config/http-client.config.d.ts +15 -0
- package/http-client/config/http-client.config.js +25 -9
- package/http-client/decorators/http-client.decorators.d.ts +63 -0
- package/http-client/decorators/http-client.decorators.js +71 -3
- package/http-client/entities/http-log.entity.d.ts +229 -0
- package/http-client/entities/http-log.entity.js +6 -1
- package/http-client/errors/http-client.errors.d.ts +57 -0
- package/http-client/errors/http-client.errors.js +58 -0
- package/http-client/examples/advanced-usage.example.d.ts +41 -0
- package/http-client/examples/advanced-usage.example.js +68 -24
- package/http-client/examples/auth-with-waiting-lock.example.d.ts +31 -0
- package/http-client/examples/auth-with-waiting-lock.example.js +52 -5
- package/http-client/examples/basic-usage.example.d.ts +60 -0
- package/http-client/examples/basic-usage.example.js +60 -0
- package/http-client/examples/multi-api-configuration.example.d.ts +60 -0
- package/http-client/examples/multi-api-configuration.example.js +76 -5
- package/http-client/http-client.module.d.ts +13 -0
- package/http-client/http-client.module.js +19 -0
- package/http-client/index.js +8 -0
- package/http-client/interfaces/api-client-config.interface.d.ts +125 -0
- package/http-client/interfaces/api-client-config.interface.js +3 -0
- package/http-client/interfaces/http-client-config.interface.d.ts +60 -0
- package/http-client/services/api-client-registry.service.d.ts +57 -0
- package/http-client/services/api-client-registry.service.js +84 -1
- package/http-client/services/cache.service.d.ts +52 -0
- package/http-client/services/cache.service.js +72 -3
- package/http-client/services/circuit-breaker.service.d.ts +46 -0
- package/http-client/services/circuit-breaker.service.js +52 -0
- package/http-client/services/http-client.service.d.ts +67 -0
- package/http-client/services/http-client.service.js +105 -4
- package/http-client/services/http-log-query.service.d.ts +83 -0
- package/http-client/services/http-log-query.service.js +122 -1
- package/http-client/services/http-replay.service.d.ts +101 -0
- package/http-client/services/http-replay.service.js +86 -0
- package/http-client/services/log-cleanup.service.d.ts +63 -0
- package/http-client/services/log-cleanup.service.js +54 -2
- package/http-client/services/logging.service.d.ts +40 -0
- package/http-client/services/logging.service.js +53 -0
- package/http-client/utils/call-stack-extractor.util.d.ts +37 -0
- package/http-client/utils/call-stack-extractor.util.js +48 -0
- package/http-client/utils/context-extractor.util.d.ts +49 -0
- package/http-client/utils/context-extractor.util.js +52 -0
- package/http-client/utils/curl-generator.util.d.ts +21 -0
- package/http-client/utils/curl-generator.util.js +44 -3
- package/http-client/utils/request-id.util.d.ts +18 -0
- package/http-client/utils/request-id.util.js +20 -0
- package/http-client/utils/retry-recorder.util.d.ts +42 -0
- package/http-client/utils/retry-recorder.util.js +44 -0
- package/i18n/en_US/validation.json +2 -1
- package/i18n/zh_CN/validation.json +2 -1
- package/index.js +8 -0
- package/interceptors/translation-interceptor.service.js +5 -0
- package/package.json +1 -1
- package/providers/context.provider.js +2 -0
- package/providers/generator.provider.d.ts +4 -0
- package/providers/generator.provider.js +4 -0
- package/redis-lock/examples/lock-strategy.examples.d.ts +89 -0
- package/redis-lock/examples/lock-strategy.examples.js +130 -15
- package/redis-lock/index.js +3 -0
- package/redis-lock/redis-lock.decorator.d.ts +101 -0
- package/redis-lock/redis-lock.decorator.js +120 -0
- package/redis-lock/redis-lock.module.d.ts +60 -0
- package/redis-lock/redis-lock.module.js +46 -0
- package/redis-lock/redis-lock.service.d.ts +251 -0
- package/redis-lock/redis-lock.service.js +219 -3
- package/setup/bootstrap.setup.js +20 -0
- package/setup/mode.setup.d.ts +44 -0
- package/setup/mode.setup.js +44 -0
- package/setup/schedule.decorator.d.ts +226 -0
- package/setup/schedule.decorator.js +214 -1
- package/setup/worker.decorator.d.ts +86 -0
- package/setup/worker.decorator.js +88 -0
- package/shared/serviceRegistryModule.js +9 -1
- package/shared/services/api-config.service.d.ts +3 -0
- package/shared/services/api-config.service.js +20 -9
- package/validator-json/decorators.d.ts +17 -0
- package/validator-json/decorators.js +17 -2
- package/validator-json/default.d.ts +6 -0
- package/validator-json/default.js +30 -2
- package/validator-json/defaultConverters.js +1 -0
- package/validator-json/options.d.ts +23 -0
- package/validators/common-validators.d.ts +143 -0
- package/validators/common-validators.js +249 -0
- package/validators/custom-validate.examples.d.ts +96 -0
- package/validators/custom-validate.examples.js +400 -0
- package/validators/custom-validate.validator.d.ts +133 -0
- package/validators/custom-validate.validator.js +213 -0
- package/validators/index.d.ts +2 -0
- package/validators/index.js +2 -0
- package/validators/is-exists.validator.d.ts +18 -4
- package/validators/is-exists.validator.js +67 -6
- package/validators/is-unique.validator.d.ts +19 -4
- package/validators/is-unique.validator.js +67 -11
- package/validators/skip-empty.validator.d.ts +5 -0
- package/validators/skip-empty.validator.js +5 -0
- package/vault/interfaces/vault-options.interface.d.ts +9 -0
- package/vault/vault-config.loader.d.ts +30 -0
- package/vault/vault-config.loader.js +48 -1
- package/vault/vault-config.service.d.ts +53 -0
- package/vault/vault-config.service.js +57 -0
- package/vault/vault.module.d.ts +4 -0
- package/vault/vault.module.js +4 -0
- package/decorators/examples/validation-decorators.example.d.ts +0 -69
- package/decorators/examples/validation-decorators.example.js +0 -331
|
@@ -0,0 +1,213 @@
|
|
|
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
|
+
* // 1. 内联函数(同步)
|
|
149
|
+
* @CustomValidate(
|
|
150
|
+
* (value) => value > 0,
|
|
151
|
+
* { message: '价格必须大于0' }
|
|
152
|
+
* )
|
|
153
|
+
* price: number;
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* // 2. 内联函数(异步)
|
|
157
|
+
* @CustomValidate(
|
|
158
|
+
* async (value, context) => {
|
|
159
|
+
* const response = await fetch(`/api/check/${value}`);
|
|
160
|
+
* return response.ok;
|
|
161
|
+
* }
|
|
162
|
+
* )
|
|
163
|
+
* username: string;
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* // 3. Entity 方法
|
|
167
|
+
* @CustomValidate('validateVersion')
|
|
168
|
+
* version: string;
|
|
169
|
+
*
|
|
170
|
+
* validateVersion(value: string): boolean {
|
|
171
|
+
* return /^\d+\.\d+\.\d+$/.test(value);
|
|
172
|
+
* }
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* // 4. Service 方法
|
|
176
|
+
* @CustomValidate([UserValidationService, 'checkUsername'])
|
|
177
|
+
* username: string;
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* // 5. 延迟引用(解决循环依赖)
|
|
181
|
+
* @CustomValidate([() => UserValidationService, 'checkUsername'])
|
|
182
|
+
* username: string;
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* // 6. 带额外参数
|
|
186
|
+
* @CustomValidate(
|
|
187
|
+
* [ValidationService, 'checkRange', 0, 100],
|
|
188
|
+
* { message: '价格必须在 0-100 之间' }
|
|
189
|
+
* )
|
|
190
|
+
* price: number;
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* // 7. 使用 i18n
|
|
194
|
+
* @CustomValidate(
|
|
195
|
+
* (value) => value.length >= 6,
|
|
196
|
+
* { message: 'validation.PASSWORD_TOO_SHORT' }
|
|
197
|
+
* )
|
|
198
|
+
* password: string;
|
|
199
|
+
*
|
|
200
|
+
* @param constraint 验证约束(函数、方法名、或 [Service, 方法名])
|
|
201
|
+
* @param validationOptions 验证选项
|
|
202
|
+
*/
|
|
203
|
+
function CustomValidate(constraint, validationOptions) {
|
|
204
|
+
return (object, propertyName) => {
|
|
205
|
+
(0, class_validator_1.registerDecorator)({
|
|
206
|
+
target: object.constructor,
|
|
207
|
+
propertyName,
|
|
208
|
+
options: validationOptions,
|
|
209
|
+
constraints: [constraint],
|
|
210
|
+
validator: CustomValidateValidator,
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
}
|
package/validators/index.d.ts
CHANGED
package/validators/index.js
CHANGED
|
@@ -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 {
|
|
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
|
|
6
|
-
constructor(
|
|
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(
|
|
29
|
-
this.
|
|
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 [
|
|
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
|
|
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", [
|
|
109
|
+
__metadata("design:paramtypes", [transactional_1.TransactionHost])
|
|
49
110
|
], IsExistsValidator);
|
|
50
111
|
function IsExists(constraints, validationOptions) {
|
|
51
112
|
return (object, propertyName) => {
|
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
import type { ValidationArguments, ValidationOptions, ValidatorConstraintInterface } from 'class-validator';
|
|
2
|
-
import {
|
|
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
|
|
5
|
-
constructor(
|
|
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
|
}
|
|
9
24
|
type UniqueValidationConstraints<E> = [
|
|
10
|
-
ObjectType<E> | EntitySchema<E> | string,
|
|
25
|
+
ObjectType<E> | EntitySchema<E> | string | (() => ObjectType<E> | EntitySchema<E> | string),
|
|
11
26
|
(validationArguments: ValidationArguments) => FindOptionsWhere<E>
|
|
12
27
|
];
|
|
13
28
|
interface IUniqueValidationArguments<E> extends ValidationArguments {
|
|
@@ -21,31 +21,86 @@ 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(
|
|
28
|
-
this.
|
|
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 [
|
|
87
|
+
const [entityRef, findCondition] = 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 =
|
|
37
|
-
.getMetadata(entityClass)
|
|
94
|
+
const pkCols = repository.metadata
|
|
38
95
|
.primaryColumns.map((column) => column.propertyName);
|
|
39
96
|
const isNew = pkCols.some((pk) => args.object[pk]);
|
|
40
97
|
if (!isNew) {
|
|
41
98
|
exists =
|
|
42
|
-
(yield
|
|
43
|
-
.getRepository(entityClass)
|
|
99
|
+
(yield repository
|
|
44
100
|
.count({ where: defCon })) < 1;
|
|
45
101
|
}
|
|
46
102
|
else {
|
|
47
|
-
const entities = yield
|
|
48
|
-
.getRepository(entityClass)
|
|
103
|
+
const entities = yield repository
|
|
49
104
|
.createQueryBuilder()
|
|
50
105
|
.where(defCon)
|
|
51
106
|
.select(pkCols)
|
|
@@ -75,8 +130,9 @@ let IsUniqueValidator = class IsUniqueValidator {
|
|
|
75
130
|
};
|
|
76
131
|
exports.IsUniqueValidator = IsUniqueValidator;
|
|
77
132
|
exports.IsUniqueValidator = IsUniqueValidator = __decorate([
|
|
133
|
+
(0, common_1.Injectable)(),
|
|
78
134
|
(0, class_validator_1.ValidatorConstraint)({ name: 'isUnique', async: true }),
|
|
79
|
-
__metadata("design:paramtypes", [
|
|
135
|
+
__metadata("design:paramtypes", [transactional_1.TransactionHost])
|
|
80
136
|
], IsUniqueValidator);
|
|
81
137
|
function IsUnique(constraints, validationOptions) {
|
|
82
138
|
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
|
}
|