Skip to content

Commit

Permalink
Merge pull request #1523 from riquena969/fix/intersection-type-decora…
Browse files Browse the repository at this point in the history
…tors

fix: resolve decorator stacking issue with intersection type usage
  • Loading branch information
kamilmysliwiec authored Nov 8, 2024
2 parents 596a73c + 52a46d9 commit ecafa8e
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 3 deletions.
2 changes: 1 addition & 1 deletion lib/intersection-type.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export function IntersectionType<T extends Type[]>(...classRefs: T) {

classRefs.forEach((classRef) => {
inheritValidationMetadata(classRef, IntersectionClassType);
inheritTransformationMetadata(classRef, IntersectionClassType);
inheritTransformationMetadata(classRef, IntersectionClassType, undefined, false);
});

const intersectedNames = classRefs.reduce((prev, ref) => prev + ref.name, '');
Expand Down
5 changes: 4 additions & 1 deletion lib/type-helpers.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export function inheritTransformationMetadata(
parentClass: Type<any>,
targetClass: Function,
isPropertyInherited?: (key: string) => boolean,
stackDecorators = true
) {
if (!isClassTransformerAvailable()) {
return;
Expand All @@ -112,6 +113,7 @@ export function inheritTransformationMetadata(
parentClass,
targetClass,
isPropertyInherited,
stackDecorators
),
);
} catch (err) {
Expand All @@ -127,6 +129,7 @@ function inheritTransformerMetadata(
parentClass: Type<any>,
targetClass: Function,
isPropertyInherited?: (key: string) => boolean,
stackDecorators = true,
) {
let classTransformer: any;
try {
Expand Down Expand Up @@ -169,7 +172,7 @@ function inheritTransformerMetadata(

[existingRules, targetMetadataEntries].forEach((entries) => {
for (const [valueKey, value] of entries) {
if (mergeMap.has(valueKey)) {
if (mergeMap.has(valueKey) && stackDecorators) {
const parentValue = mergeMap.get(valueKey);

if (Array.isArray(parentValue)) {
Expand Down
22 changes: 21 additions & 1 deletion tests/intersection-type.helper.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ describe('IntersectionType', () => {
@Transform(({ value }) => value + '_transformed')
@MinLength(10)
password!: string;

@Transform(({ value }) => value + '_transformed')
@MinLength(15)
repeatedProperty = 'repeatedPropertyValue';
}

class ClassB {
Expand All @@ -20,6 +24,10 @@ describe('IntersectionType', () => {
@Transform(({ value }) => value + '_transformed')
@MinLength(5)
lastName!: string;

@Transform(({ value }) => value + '_transformed')
@IsString()
repeatedProperty = 'repeatedPropertyValue';
}

class UpdateUserDto extends IntersectionType(ClassA, ClassB) {}
Expand All @@ -32,22 +40,29 @@ describe('IntersectionType', () => {
expect(validationKeys).toEqual([
'login',
'password',
'repeatedProperty',
'firstName',
'lastName',
'repeatedProperty',
]);
});

describe('when object does not fulfil validation rules', () => {
it('"validate" should return validation errors', async () => {
const updateDto = new UpdateUserDto();
updateDto.password = '1234567';
updateDto.repeatedProperty = '014-characters';

const validationErrors = await validate(updateDto);

expect(validationErrors.length).toEqual(2);
expect(validationErrors.length).toEqual(3);
expect(validationErrors[0].constraints).toEqual({
minLength: 'password must be longer than or equal to 10 characters',
});
expect(validationErrors[1].constraints).toEqual({
minLength: 'repeatedProperty must be longer than or equal to 15 characters',
});
expect(validationErrors[2].constraints).toEqual({
minLength: 'lastName must be longer than or equal to 5 characters',
});
});
Expand All @@ -59,6 +74,7 @@ describe('IntersectionType', () => {
updateDto.firstName = 'firstNameTest';
updateDto.lastName = 'lastNameTest';
updateDto.login = 'mylogintesttest';
updateDto.repeatedProperty = 'repeatedPropertyTestValue';

const validationErrors = await validate(updateDto);
expect(validationErrors.length).toEqual(0);
Expand All @@ -70,14 +86,18 @@ describe('IntersectionType', () => {
it('should inherit transformer metadata', () => {
const password = '1234567891011';
const lastName = 'lastNameTest';
const repeatedProperty = 'repeatedPropertyTestValue';

const updateDto = new UpdateUserDto();
updateDto.password = password;
updateDto.lastName = lastName;
updateDto.repeatedProperty = repeatedProperty;

const transformedDto = instanceToInstance(updateDto);

expect(transformedDto.lastName).toEqual(lastName + '_transformed');
expect(transformedDto.password).toEqual(password + '_transformed');
expect(transformedDto.repeatedProperty).toEqual(repeatedProperty + '_transformed');
});
});

Expand Down

0 comments on commit ecafa8e

Please sign in to comment.