@nest-omni/core 3.1.1-18 → 3.1.1-20
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/cache/cache-serialization.service.d.ts +4 -11
- package/cache/cache-serialization.service.js +29 -124
- package/cache/cache.constants.d.ts +2 -0
- package/cache/cache.constants.js +5 -0
- package/cache/cache.module.d.ts +2 -0
- package/cache/cache.module.js +49 -3
- package/cache/cache.service.d.ts +3 -1
- package/cache/cache.service.js +32 -4
- package/cache/examples/basic-usage.d.ts +58 -0
- package/cache/examples/basic-usage.js +379 -0
- package/cache/index.d.ts +2 -1
- package/cache/index.js +4 -1
- package/common/abstract.entity.d.ts +7 -0
- package/common/abstract.entity.js +12 -0
- package/common/boilerplate.polyfill.d.ts +0 -6
- package/common/dto/page-options.dto.d.ts +0 -3
- package/common/dto/page-options.dto.js +0 -12
- package/common/examples/paginate-and-map.example.d.ts +14 -0
- package/common/examples/paginate-and-map.example.js +158 -0
- package/decorators/examples/validation-decorators.example.d.ts +69 -0
- package/decorators/examples/validation-decorators.example.js +331 -0
- package/decorators/use-dto.decorator.d.ts +1 -0
- package/decorators/use-dto.decorator.js +10 -0
- package/decorators/validator.decorators.d.ts +8 -1
- package/decorators/validator.decorators.js +115 -0
- package/i18n/en_US/validation.json +4 -1
- package/i18n/zh_CN/validation.json +4 -1
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +1 -1
- package/redis-lock/examples/lock-strategy.examples.d.ts +73 -0
- package/redis-lock/examples/lock-strategy.examples.js +387 -0
- package/redis-lock/index.d.ts +2 -2
- package/redis-lock/index.js +4 -1
- package/redis-lock/redis-lock.decorator.d.ts +4 -0
- package/redis-lock/redis-lock.decorator.js +43 -7
- package/redis-lock/redis-lock.service.d.ts +19 -0
- package/redis-lock/redis-lock.service.js +131 -6
- package/setup/index.d.ts +0 -1
- package/setup/index.js +0 -1
- package/shared/serviceRegistryModule.js +2 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
12
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
13
|
+
var m = o[Symbol.asyncIterator], i;
|
|
14
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
15
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
16
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
17
|
+
};
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.basicPaginationExample = basicPaginationExample;
|
|
20
|
+
exports.syncTransformExample = syncTransformExample;
|
|
21
|
+
exports.asyncTransformExample = asyncTransformExample;
|
|
22
|
+
exports.asyncBatchTransformExample = asyncBatchTransformExample;
|
|
23
|
+
exports.complexAsyncTransformExample = complexAsyncTransformExample;
|
|
24
|
+
exports.iterateExample = iterateExample;
|
|
25
|
+
exports.eachBatchSingleExample = eachBatchSingleExample;
|
|
26
|
+
exports.eachBatchGroupExample = eachBatchGroupExample;
|
|
27
|
+
function basicPaginationExample(repository, pageOptions) {
|
|
28
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
29
|
+
const result = yield repository
|
|
30
|
+
.createQueryBuilder('entity')
|
|
31
|
+
.paginateAndMap(pageOptions);
|
|
32
|
+
return result;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function syncTransformExample(repository, pageOptions) {
|
|
36
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
+
const result = yield repository
|
|
38
|
+
.createQueryBuilder('entity')
|
|
39
|
+
.where('entity.isActive = :isActive', { isActive: true })
|
|
40
|
+
.paginateAndMap(pageOptions, {
|
|
41
|
+
transform: (items) => {
|
|
42
|
+
return items.filter(item => item.status === 'approved');
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
return result;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function asyncTransformExample(repository, pageOptions, externalService) {
|
|
49
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
const result = yield repository
|
|
51
|
+
.createQueryBuilder('entity')
|
|
52
|
+
.where('entity.isActive = :isActive', { isActive: true })
|
|
53
|
+
.paginateAndMap(pageOptions, {
|
|
54
|
+
transform: (items) => __awaiter(this, void 0, void 0, function* () {
|
|
55
|
+
const enrichedItems = yield Promise.all(items.map((item) => __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
const additionalData = yield externalService.fetchData(item.id);
|
|
57
|
+
return Object.assign(Object.assign({}, item), { additionalData });
|
|
58
|
+
})));
|
|
59
|
+
return enrichedItems.filter(item => { var _a; return (_a = item.additionalData) === null || _a === void 0 ? void 0 : _a.isValid; });
|
|
60
|
+
}),
|
|
61
|
+
});
|
|
62
|
+
return result;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function asyncBatchTransformExample(repository, pageOptions, batchProcessor) {
|
|
66
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
const result = yield repository
|
|
68
|
+
.createQueryBuilder('entity')
|
|
69
|
+
.leftJoinAndSelect('entity.relations', 'relations')
|
|
70
|
+
.paginateAndMap(pageOptions, {
|
|
71
|
+
dtoOptions: { includeRelations: true },
|
|
72
|
+
transform: (items) => __awaiter(this, void 0, void 0, function* () {
|
|
73
|
+
const processedItems = yield batchProcessor.processBatch(items);
|
|
74
|
+
return processedItems.map(item => (Object.assign(Object.assign({}, item), { processed: true, processedAt: new Date() })));
|
|
75
|
+
}),
|
|
76
|
+
});
|
|
77
|
+
return result;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function complexAsyncTransformExample(repository, pageOptions, services) {
|
|
81
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
82
|
+
const result = yield repository
|
|
83
|
+
.createQueryBuilder('entity')
|
|
84
|
+
.where('entity.createdAt > :date', { date: new Date('2024-01-01') })
|
|
85
|
+
.paginateAndMap(pageOptions, {
|
|
86
|
+
skipCount: false,
|
|
87
|
+
transform: (items) => __awaiter(this, void 0, void 0, function* () {
|
|
88
|
+
const validatedItems = yield Promise.all(items.map((item) => __awaiter(this, void 0, void 0, function* () {
|
|
89
|
+
try {
|
|
90
|
+
const isValid = yield services.validation.validate(item);
|
|
91
|
+
return isValid ? item : null;
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
console.error(`Validation failed for item ${item.id}:`, error);
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
})));
|
|
98
|
+
const validItems = validatedItems.filter(item => item !== null);
|
|
99
|
+
const enrichedItems = yield Promise.all(validItems.map((item) => __awaiter(this, void 0, void 0, function* () {
|
|
100
|
+
const enrichmentData = yield services.enrichment.enrich(item.id);
|
|
101
|
+
return Object.assign(Object.assign({}, item), enrichmentData);
|
|
102
|
+
})));
|
|
103
|
+
const finalItems = yield Promise.all(enrichedItems.map((item) => __awaiter(this, void 0, void 0, function* () {
|
|
104
|
+
const calculatedFields = yield services.calculation.calculate(item);
|
|
105
|
+
return Object.assign(Object.assign({}, item), calculatedFields);
|
|
106
|
+
})));
|
|
107
|
+
return finalItems;
|
|
108
|
+
}),
|
|
109
|
+
});
|
|
110
|
+
return result;
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
function iterateExample(repository, processor) {
|
|
114
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
115
|
+
var _a, e_1, _b, _c;
|
|
116
|
+
const queryBuilder = repository
|
|
117
|
+
.createQueryBuilder('entity')
|
|
118
|
+
.where('entity.needsProcessing = :needsProcessing', { needsProcessing: true });
|
|
119
|
+
try {
|
|
120
|
+
for (var _d = true, _e = __asyncValues(queryBuilder.iterate({ batchSize: 500 })), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
121
|
+
_c = _f.value;
|
|
122
|
+
_d = false;
|
|
123
|
+
const batch = _c;
|
|
124
|
+
console.log(`Processing batch of ${batch.length} entities`);
|
|
125
|
+
yield processor.processBatch(batch);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
129
|
+
finally {
|
|
130
|
+
try {
|
|
131
|
+
if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
|
|
132
|
+
}
|
|
133
|
+
finally { if (e_1) throw e_1.error; }
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
function eachBatchSingleExample(repository, processor) {
|
|
138
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
139
|
+
yield repository
|
|
140
|
+
.createQueryBuilder('entity')
|
|
141
|
+
.where('entity.status = :status', { status: 'pending' })
|
|
142
|
+
.eachBatch((entity) => __awaiter(this, void 0, void 0, function* () {
|
|
143
|
+
console.log(`Processing entity ${entity.id}`);
|
|
144
|
+
yield processor.processOne(entity);
|
|
145
|
+
}), { batchSize: 100, mode: 'single' });
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
function eachBatchGroupExample(repository, processor) {
|
|
149
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
150
|
+
yield repository
|
|
151
|
+
.createQueryBuilder('entity')
|
|
152
|
+
.where('entity.status = :status', { status: 'pending' })
|
|
153
|
+
.eachBatch((batch) => __awaiter(this, void 0, void 0, function* () {
|
|
154
|
+
console.log(`Processing batch of ${batch.length} entities`);
|
|
155
|
+
yield processor.processBatch(batch);
|
|
156
|
+
}), { batchSize: 500, mode: 'batch' });
|
|
157
|
+
});
|
|
158
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export declare class ContactDto {
|
|
2
|
+
email?: string;
|
|
3
|
+
phone?: string;
|
|
4
|
+
wechat?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class SearchDto {
|
|
7
|
+
keyword?: string;
|
|
8
|
+
category?: string;
|
|
9
|
+
tags?: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare class PasswordDto {
|
|
12
|
+
password: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class EmailCheckDto {
|
|
15
|
+
email: string;
|
|
16
|
+
userService?: any;
|
|
17
|
+
}
|
|
18
|
+
export declare class OrderDto {
|
|
19
|
+
orderType: 'standard' | 'express';
|
|
20
|
+
deliveryDate?: Date;
|
|
21
|
+
}
|
|
22
|
+
export declare class DiscountDto {
|
|
23
|
+
discountType: 'percentage' | 'fixed';
|
|
24
|
+
discountValue: number;
|
|
25
|
+
get validatedDiscountValue(): number;
|
|
26
|
+
}
|
|
27
|
+
export declare class UserRegistrationDto {
|
|
28
|
+
username: string;
|
|
29
|
+
password: string;
|
|
30
|
+
confirmPassword: string;
|
|
31
|
+
validatePassword(password: string): boolean;
|
|
32
|
+
validatePasswordMatch(confirmPassword: string): boolean;
|
|
33
|
+
}
|
|
34
|
+
export declare class CreateProductDto {
|
|
35
|
+
name: string;
|
|
36
|
+
sku: string;
|
|
37
|
+
categoryId: string;
|
|
38
|
+
get validatedCategoryId(): string;
|
|
39
|
+
productService?: any;
|
|
40
|
+
categoryService?: any;
|
|
41
|
+
checkSkuUniqueness(sku: string): Promise<boolean>;
|
|
42
|
+
validateCategoryExists(categoryId: string): Promise<boolean>;
|
|
43
|
+
}
|
|
44
|
+
export declare class EmployeeDto {
|
|
45
|
+
name: string;
|
|
46
|
+
personalEmail?: string;
|
|
47
|
+
workEmail?: string;
|
|
48
|
+
phone?: string;
|
|
49
|
+
validatePhoneFormat(phone: string): boolean;
|
|
50
|
+
}
|
|
51
|
+
export declare class PaymentMethodDto {
|
|
52
|
+
paymentType: 'credit_card' | 'bank_transfer' | 'digital_wallet';
|
|
53
|
+
creditCard?: {
|
|
54
|
+
number: string;
|
|
55
|
+
expiryDate: string;
|
|
56
|
+
cvv: string;
|
|
57
|
+
};
|
|
58
|
+
bankAccount?: {
|
|
59
|
+
accountNumber: string;
|
|
60
|
+
routingNumber: string;
|
|
61
|
+
};
|
|
62
|
+
digitalWallet?: {
|
|
63
|
+
provider: string;
|
|
64
|
+
walletId: string;
|
|
65
|
+
};
|
|
66
|
+
validateCreditCard(creditCard: any): boolean;
|
|
67
|
+
validateBankAccount(bankAccount: any): boolean;
|
|
68
|
+
validateDigitalWallet(digitalWallet: any): boolean;
|
|
69
|
+
}
|
|
@@ -0,0 +1,331 @@
|
|
|
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.PaymentMethodDto = exports.EmployeeDto = exports.CreateProductDto = exports.UserRegistrationDto = exports.DiscountDto = exports.OrderDto = exports.EmailCheckDto = exports.PasswordDto = exports.SearchDto = exports.ContactDto = void 0;
|
|
22
|
+
const class_validator_1 = require("class-validator");
|
|
23
|
+
const swagger_1 = require("@nestjs/swagger");
|
|
24
|
+
const validator_decorators_1 = require("../validator.decorators");
|
|
25
|
+
const field_decorators_1 = require("../field.decorators");
|
|
26
|
+
class ContactDto {
|
|
27
|
+
}
|
|
28
|
+
exports.ContactDto = ContactDto;
|
|
29
|
+
__decorate([
|
|
30
|
+
(0, swagger_1.ApiProperty)({ required: false }),
|
|
31
|
+
(0, class_validator_1.IsEmail)(),
|
|
32
|
+
(0, validator_decorators_1.AtLeastOneField)(['email', 'phone', 'wechat']),
|
|
33
|
+
__metadata("design:type", String)
|
|
34
|
+
], ContactDto.prototype, "email", void 0);
|
|
35
|
+
__decorate([
|
|
36
|
+
(0, swagger_1.ApiProperty)({ required: false }),
|
|
37
|
+
(0, class_validator_1.IsString)(),
|
|
38
|
+
__metadata("design:type", String)
|
|
39
|
+
], ContactDto.prototype, "phone", void 0);
|
|
40
|
+
__decorate([
|
|
41
|
+
(0, swagger_1.ApiProperty)({ required: false }),
|
|
42
|
+
(0, class_validator_1.IsString)(),
|
|
43
|
+
__metadata("design:type", String)
|
|
44
|
+
], ContactDto.prototype, "wechat", void 0);
|
|
45
|
+
class SearchDto {
|
|
46
|
+
}
|
|
47
|
+
exports.SearchDto = SearchDto;
|
|
48
|
+
__decorate([
|
|
49
|
+
(0, field_decorators_1.StringFieldOptional)(),
|
|
50
|
+
(0, validator_decorators_1.AtLeastOneField)(['keyword', 'category', 'tags'], {
|
|
51
|
+
message: 'Please provide at least one search criteria: keyword, category, or tags',
|
|
52
|
+
}),
|
|
53
|
+
__metadata("design:type", String)
|
|
54
|
+
], SearchDto.prototype, "keyword", void 0);
|
|
55
|
+
__decorate([
|
|
56
|
+
(0, field_decorators_1.StringFieldOptional)(),
|
|
57
|
+
__metadata("design:type", String)
|
|
58
|
+
], SearchDto.prototype, "category", void 0);
|
|
59
|
+
__decorate([
|
|
60
|
+
(0, field_decorators_1.StringFieldOptional)({ each: true }),
|
|
61
|
+
__metadata("design:type", Array)
|
|
62
|
+
], SearchDto.prototype, "tags", void 0);
|
|
63
|
+
class PasswordDto {
|
|
64
|
+
}
|
|
65
|
+
exports.PasswordDto = PasswordDto;
|
|
66
|
+
__decorate([
|
|
67
|
+
(0, validator_decorators_1.CustomValidation)((value) => {
|
|
68
|
+
if (!value || value.length < 8)
|
|
69
|
+
return false;
|
|
70
|
+
const hasUppercase = /[A-Z]/.test(value);
|
|
71
|
+
const hasLowercase = /[a-z]/.test(value);
|
|
72
|
+
const hasNumber = /[0-9]/.test(value);
|
|
73
|
+
return hasUppercase && hasLowercase && hasNumber;
|
|
74
|
+
}, {
|
|
75
|
+
message: 'Password must be at least 8 characters with uppercase, lowercase, and number',
|
|
76
|
+
}),
|
|
77
|
+
(0, swagger_1.ApiProperty)(),
|
|
78
|
+
__metadata("design:type", String)
|
|
79
|
+
], PasswordDto.prototype, "password", void 0);
|
|
80
|
+
class EmailCheckDto {
|
|
81
|
+
}
|
|
82
|
+
exports.EmailCheckDto = EmailCheckDto;
|
|
83
|
+
__decorate([
|
|
84
|
+
(0, validator_decorators_1.CustomValidation)((value, args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
85
|
+
const userService = args.object.userService;
|
|
86
|
+
if (!userService) {
|
|
87
|
+
console.warn('UserService not found, skipping email check');
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
const exists = yield userService.checkEmailExists(value);
|
|
91
|
+
return !exists;
|
|
92
|
+
}), {
|
|
93
|
+
message: 'Email already exists in the system',
|
|
94
|
+
}),
|
|
95
|
+
(0, class_validator_1.IsEmail)(),
|
|
96
|
+
(0, swagger_1.ApiProperty)(),
|
|
97
|
+
__metadata("design:type", String)
|
|
98
|
+
], EmailCheckDto.prototype, "email", void 0);
|
|
99
|
+
class OrderDto {
|
|
100
|
+
}
|
|
101
|
+
exports.OrderDto = OrderDto;
|
|
102
|
+
__decorate([
|
|
103
|
+
(0, swagger_1.ApiProperty)({ enum: ['standard', 'express'] }),
|
|
104
|
+
(0, class_validator_1.IsString)(),
|
|
105
|
+
__metadata("design:type", String)
|
|
106
|
+
], OrderDto.prototype, "orderType", void 0);
|
|
107
|
+
__decorate([
|
|
108
|
+
(0, validator_decorators_1.CustomValidation)((value, args) => {
|
|
109
|
+
const object = args.object;
|
|
110
|
+
if (object.orderType === 'express') {
|
|
111
|
+
return value !== null && value !== undefined;
|
|
112
|
+
}
|
|
113
|
+
return true;
|
|
114
|
+
}, {
|
|
115
|
+
message: 'Delivery date is required for express orders',
|
|
116
|
+
}),
|
|
117
|
+
(0, swagger_1.ApiProperty)({ required: false }),
|
|
118
|
+
__metadata("design:type", Date)
|
|
119
|
+
], OrderDto.prototype, "deliveryDate", void 0);
|
|
120
|
+
class DiscountDto {
|
|
121
|
+
get validatedDiscountValue() {
|
|
122
|
+
return this.discountValue;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.DiscountDto = DiscountDto;
|
|
126
|
+
__decorate([
|
|
127
|
+
(0, swagger_1.ApiProperty)(),
|
|
128
|
+
__metadata("design:type", String)
|
|
129
|
+
], DiscountDto.prototype, "discountType", void 0);
|
|
130
|
+
__decorate([
|
|
131
|
+
(0, swagger_1.ApiProperty)(),
|
|
132
|
+
__metadata("design:type", Number)
|
|
133
|
+
], DiscountDto.prototype, "discountValue", void 0);
|
|
134
|
+
__decorate([
|
|
135
|
+
(0, validator_decorators_1.CustomValidation)((value, args) => {
|
|
136
|
+
const object = args.object;
|
|
137
|
+
if (object.discountType === 'percentage') {
|
|
138
|
+
return value >= 0 && value <= 100;
|
|
139
|
+
}
|
|
140
|
+
else if (object.discountType === 'fixed') {
|
|
141
|
+
return value > 0;
|
|
142
|
+
}
|
|
143
|
+
return false;
|
|
144
|
+
}, {
|
|
145
|
+
message: 'Invalid discount value for the selected discount type',
|
|
146
|
+
}),
|
|
147
|
+
__metadata("design:type", Object),
|
|
148
|
+
__metadata("design:paramtypes", [])
|
|
149
|
+
], DiscountDto.prototype, "validatedDiscountValue", null);
|
|
150
|
+
class UserRegistrationDto {
|
|
151
|
+
validatePassword(password) {
|
|
152
|
+
if (!password || password.length < 8)
|
|
153
|
+
return false;
|
|
154
|
+
const hasUppercase = /[A-Z]/.test(password);
|
|
155
|
+
const hasLowercase = /[a-z]/.test(password);
|
|
156
|
+
const hasNumber = /[0-9]/.test(password);
|
|
157
|
+
const hasSpecial = /[!@#$%^&*]/.test(password);
|
|
158
|
+
return hasUppercase && hasLowercase && hasNumber && hasSpecial;
|
|
159
|
+
}
|
|
160
|
+
validatePasswordMatch(confirmPassword) {
|
|
161
|
+
return confirmPassword === this.password;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
exports.UserRegistrationDto = UserRegistrationDto;
|
|
165
|
+
__decorate([
|
|
166
|
+
(0, swagger_1.ApiProperty)(),
|
|
167
|
+
(0, class_validator_1.IsString)(),
|
|
168
|
+
__metadata("design:type", String)
|
|
169
|
+
], UserRegistrationDto.prototype, "username", void 0);
|
|
170
|
+
__decorate([
|
|
171
|
+
(0, validator_decorators_1.CustomValidationMethod)('validatePassword', {
|
|
172
|
+
message: 'Password does not meet security requirements',
|
|
173
|
+
}),
|
|
174
|
+
(0, swagger_1.ApiProperty)(),
|
|
175
|
+
__metadata("design:type", String)
|
|
176
|
+
], UserRegistrationDto.prototype, "password", void 0);
|
|
177
|
+
__decorate([
|
|
178
|
+
(0, validator_decorators_1.CustomValidationMethod)('validatePasswordMatch'),
|
|
179
|
+
(0, swagger_1.ApiProperty)(),
|
|
180
|
+
__metadata("design:type", String)
|
|
181
|
+
], UserRegistrationDto.prototype, "confirmPassword", void 0);
|
|
182
|
+
class CreateProductDto {
|
|
183
|
+
get validatedCategoryId() {
|
|
184
|
+
return this.categoryId;
|
|
185
|
+
}
|
|
186
|
+
checkSkuUniqueness(sku) {
|
|
187
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
188
|
+
if (!this.productService) {
|
|
189
|
+
console.warn('ProductService not found');
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
const exists = yield this.productService.skuExists(sku);
|
|
193
|
+
return !exists;
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
validateCategoryExists(categoryId) {
|
|
197
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
198
|
+
if (!this.categoryService) {
|
|
199
|
+
console.warn('CategoryService not found');
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
return yield this.categoryService.exists(categoryId);
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
exports.CreateProductDto = CreateProductDto;
|
|
207
|
+
__decorate([
|
|
208
|
+
(0, swagger_1.ApiProperty)(),
|
|
209
|
+
(0, class_validator_1.IsString)(),
|
|
210
|
+
__metadata("design:type", String)
|
|
211
|
+
], CreateProductDto.prototype, "name", void 0);
|
|
212
|
+
__decorate([
|
|
213
|
+
(0, validator_decorators_1.CustomValidationMethod)('checkSkuUniqueness', {
|
|
214
|
+
message: 'SKU already exists',
|
|
215
|
+
}),
|
|
216
|
+
(0, swagger_1.ApiProperty)(),
|
|
217
|
+
__metadata("design:type", String)
|
|
218
|
+
], CreateProductDto.prototype, "sku", void 0);
|
|
219
|
+
__decorate([
|
|
220
|
+
(0, swagger_1.ApiProperty)(),
|
|
221
|
+
__metadata("design:type", String)
|
|
222
|
+
], CreateProductDto.prototype, "categoryId", void 0);
|
|
223
|
+
__decorate([
|
|
224
|
+
(0, validator_decorators_1.CustomValidationMethod)('validateCategoryExists', {
|
|
225
|
+
message: 'Category does not exist',
|
|
226
|
+
}),
|
|
227
|
+
__metadata("design:type", Object),
|
|
228
|
+
__metadata("design:paramtypes", [])
|
|
229
|
+
], CreateProductDto.prototype, "validatedCategoryId", null);
|
|
230
|
+
class EmployeeDto {
|
|
231
|
+
validatePhoneFormat(phone) {
|
|
232
|
+
if (!phone)
|
|
233
|
+
return true;
|
|
234
|
+
const phoneRegex = /^\+?[1-9]\d{1,14}$/;
|
|
235
|
+
return phoneRegex.test(phone);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
exports.EmployeeDto = EmployeeDto;
|
|
239
|
+
__decorate([
|
|
240
|
+
(0, swagger_1.ApiProperty)(),
|
|
241
|
+
(0, class_validator_1.IsString)(),
|
|
242
|
+
__metadata("design:type", String)
|
|
243
|
+
], EmployeeDto.prototype, "name", void 0);
|
|
244
|
+
__decorate([
|
|
245
|
+
(0, validator_decorators_1.CustomValidation)((value) => {
|
|
246
|
+
const workDomains = ['company.com', 'corp.com'];
|
|
247
|
+
const domain = value === null || value === void 0 ? void 0 : value.split('@')[1];
|
|
248
|
+
return !workDomains.includes(domain);
|
|
249
|
+
}, {
|
|
250
|
+
message: 'Personal email should not be from work domains',
|
|
251
|
+
}),
|
|
252
|
+
(0, class_validator_1.IsEmail)(),
|
|
253
|
+
(0, validator_decorators_1.AtLeastOneField)(['personalEmail', 'workEmail']),
|
|
254
|
+
(0, swagger_1.ApiProperty)({ required: false }),
|
|
255
|
+
__metadata("design:type", String)
|
|
256
|
+
], EmployeeDto.prototype, "personalEmail", void 0);
|
|
257
|
+
__decorate([
|
|
258
|
+
(0, validator_decorators_1.CustomValidation)((value) => {
|
|
259
|
+
const workDomains = ['company.com', 'corp.com'];
|
|
260
|
+
const domain = value === null || value === void 0 ? void 0 : value.split('@')[1];
|
|
261
|
+
return workDomains.includes(domain);
|
|
262
|
+
}, {
|
|
263
|
+
message: 'Work email must be from company domains',
|
|
264
|
+
}),
|
|
265
|
+
(0, class_validator_1.IsEmail)(),
|
|
266
|
+
(0, swagger_1.ApiProperty)({ required: false }),
|
|
267
|
+
__metadata("design:type", String)
|
|
268
|
+
], EmployeeDto.prototype, "workEmail", void 0);
|
|
269
|
+
__decorate([
|
|
270
|
+
(0, validator_decorators_1.CustomValidationMethod)('validatePhoneFormat'),
|
|
271
|
+
(0, swagger_1.ApiProperty)({ required: false }),
|
|
272
|
+
__metadata("design:type", String)
|
|
273
|
+
], EmployeeDto.prototype, "phone", void 0);
|
|
274
|
+
class PaymentMethodDto {
|
|
275
|
+
validateCreditCard(creditCard) {
|
|
276
|
+
var _a;
|
|
277
|
+
if (!creditCard)
|
|
278
|
+
return true;
|
|
279
|
+
const number = (_a = creditCard.number) === null || _a === void 0 ? void 0 : _a.replace(/\s/g, '');
|
|
280
|
+
if (!/^\d{13,19}$/.test(number))
|
|
281
|
+
return false;
|
|
282
|
+
let sum = 0;
|
|
283
|
+
let isEven = false;
|
|
284
|
+
for (let i = number.length - 1; i >= 0; i--) {
|
|
285
|
+
let digit = parseInt(number[i], 10);
|
|
286
|
+
if (isEven) {
|
|
287
|
+
digit *= 2;
|
|
288
|
+
if (digit > 9)
|
|
289
|
+
digit -= 9;
|
|
290
|
+
}
|
|
291
|
+
sum += digit;
|
|
292
|
+
isEven = !isEven;
|
|
293
|
+
}
|
|
294
|
+
return sum % 10 === 0;
|
|
295
|
+
}
|
|
296
|
+
validateBankAccount(bankAccount) {
|
|
297
|
+
if (!bankAccount)
|
|
298
|
+
return true;
|
|
299
|
+
const accountValid = /^\d{8,17}$/.test(bankAccount.accountNumber);
|
|
300
|
+
const routingValid = /^\d{9}$/.test(bankAccount.routingNumber);
|
|
301
|
+
return accountValid && routingValid;
|
|
302
|
+
}
|
|
303
|
+
validateDigitalWallet(digitalWallet) {
|
|
304
|
+
var _a;
|
|
305
|
+
if (!digitalWallet)
|
|
306
|
+
return true;
|
|
307
|
+
const validProviders = ['paypal', 'alipay', 'wechat_pay', 'apple_pay'];
|
|
308
|
+
return validProviders.includes((_a = digitalWallet.provider) === null || _a === void 0 ? void 0 : _a.toLowerCase());
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
exports.PaymentMethodDto = PaymentMethodDto;
|
|
312
|
+
__decorate([
|
|
313
|
+
(0, swagger_1.ApiProperty)(),
|
|
314
|
+
__metadata("design:type", String)
|
|
315
|
+
], PaymentMethodDto.prototype, "paymentType", void 0);
|
|
316
|
+
__decorate([
|
|
317
|
+
(0, validator_decorators_1.CustomValidationMethod)('validateCreditCard'),
|
|
318
|
+
(0, validator_decorators_1.AtLeastOneField)(['creditCard', 'bankAccount', 'digitalWallet']),
|
|
319
|
+
(0, swagger_1.ApiProperty)({ required: false }),
|
|
320
|
+
__metadata("design:type", Object)
|
|
321
|
+
], PaymentMethodDto.prototype, "creditCard", void 0);
|
|
322
|
+
__decorate([
|
|
323
|
+
(0, validator_decorators_1.CustomValidationMethod)('validateBankAccount'),
|
|
324
|
+
(0, swagger_1.ApiProperty)({ required: false }),
|
|
325
|
+
__metadata("design:type", Object)
|
|
326
|
+
], PaymentMethodDto.prototype, "bankAccount", void 0);
|
|
327
|
+
__decorate([
|
|
328
|
+
(0, validator_decorators_1.CustomValidationMethod)('validateDigitalWallet'),
|
|
329
|
+
(0, swagger_1.ApiProperty)({ required: false }),
|
|
330
|
+
__metadata("design:type", Object)
|
|
331
|
+
], PaymentMethodDto.prototype, "digitalWallet", void 0);
|
|
@@ -2,3 +2,4 @@ import type { AbstractEntity } from '../common/abstract.entity';
|
|
|
2
2
|
import type { AbstractDto } from '../common/dto/abstract.dto';
|
|
3
3
|
import type { Constructor } from '../common/types';
|
|
4
4
|
export declare function UseDto(dtoClass: Constructor<AbstractDto, [AbstractEntity, unknown]>): ClassDecorator;
|
|
5
|
+
export declare function UseDto<Entity, Dto extends AbstractDto>(dtoClass: Constructor<Dto, [Entity, unknown?]>): ClassDecorator;
|
|
@@ -4,5 +4,15 @@ exports.UseDto = UseDto;
|
|
|
4
4
|
function UseDto(dtoClass) {
|
|
5
5
|
return (ctor) => {
|
|
6
6
|
ctor.prototype.dtoClass = dtoClass;
|
|
7
|
+
ctor.dtoClass = dtoClass;
|
|
8
|
+
if (!ctor.prototype.toDto) {
|
|
9
|
+
ctor.prototype.toDto = function (options) {
|
|
10
|
+
const DtoClass = this.constructor.dtoClass || dtoClass;
|
|
11
|
+
if (!DtoClass) {
|
|
12
|
+
throw new Error(`You need to use @UseDto on class (${this.constructor.name}) be able to call toDto function`);
|
|
13
|
+
}
|
|
14
|
+
return new DtoClass(this, options);
|
|
15
|
+
};
|
|
16
|
+
}
|
|
7
17
|
};
|
|
8
18
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ValidationOptions } from 'class-validator';
|
|
2
|
-
import { IsPhoneNumber as isPhoneNumber } from 'class-validator';
|
|
2
|
+
import { IsPhoneNumber as isPhoneNumber, ValidationArguments, ValidatorConstraintInterface } from 'class-validator';
|
|
3
3
|
export declare function IsPassword(validationOptions?: ValidationOptions): PropertyDecorator;
|
|
4
4
|
export declare function IsPhoneNumber(validationOptions?: ValidationOptions & {
|
|
5
5
|
region?: Parameters<typeof isPhoneNumber>[0];
|
|
@@ -9,3 +9,10 @@ export declare function IsUndefinable(options?: ValidationOptions): PropertyDeco
|
|
|
9
9
|
export declare function IsEmptyable(options?: ValidationOptions): PropertyDecorator;
|
|
10
10
|
export declare function IsNullable(options?: ValidationOptions): PropertyDecorator;
|
|
11
11
|
export declare function IsHttpUrl(validationOptions?: ValidationOptions): (object: any, propertyName: string) => void;
|
|
12
|
+
export declare class AtLeastOneFieldConstraint implements ValidatorConstraintInterface {
|
|
13
|
+
validate(value: any, args: ValidationArguments): boolean;
|
|
14
|
+
defaultMessage(args: ValidationArguments): string;
|
|
15
|
+
}
|
|
16
|
+
export declare function AtLeastOneField(properties: string[], validationOptions?: ValidationOptions): PropertyDecorator;
|
|
17
|
+
export declare function CustomValidation<T = any>(validationCallback: (value: T, args: ValidationArguments) => boolean | Promise<boolean>, validationOptions?: ValidationOptions): PropertyDecorator;
|
|
18
|
+
export declare function CustomValidationMethod(methodName: string, validationOptions?: ValidationOptions): PropertyDecorator;
|