Skip to content

Commit 3c58b0f

Browse files
committed
class-transformer @Transform() decorators copying is implemented
1 parent 231a798 commit 3c58b0f

File tree

2 files changed

+71
-2
lines changed

2 files changed

+71
-2
lines changed

src/api-property-ref.decorator.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,14 @@ import { DECORATORS } from '@nestjs/swagger/dist/constants';
33
import { ApiPropertyOptions } from '@nestjs/swagger';
44
import { createApiPropertyDecorator } from '@nestjs/swagger/dist/decorators/api-property.decorator';
55

6-
import { defaultMetadataStorage, TypeMetadata, ExposeMetadata, ExcludeMetadata } from './@import-fix/class-transformer';
6+
import {
7+
defaultMetadataStorage,
8+
ExcludeMetadata,
9+
ExposeMetadata,
10+
TransformationType,
11+
TransformMetadata,
12+
TypeMetadata,
13+
} from './@import-fix/class-transformer';
714
import { getMetadataStorage, ValidationMetadata } from './@import-fix/class-validator';
815
import { AnyObject, isClass, Type } from './utils';
916

@@ -213,6 +220,20 @@ export class ApiPropertyRefDecorator {
213220
const copy: ExcludeMetadata = { ...excludeOnClass, target: this.classProto.constructor, propertyName: undefined };
214221
storage.addExcludeMetadata(copy);
215222
}
223+
224+
const transformMetadataCopyCb = (meta: TransformMetadata) => {
225+
const copy: TransformMetadata = { ...meta, target: this.classProto.constructor, propertyName: this.propertyKey };
226+
storage.addTransformMetadata(copy);
227+
};
228+
// Notice: CLASS_TO_CLASS transformers is not tested, but should work.
229+
// I don't understand what they do and how to use them. So I don't know how to test them and don't.
230+
_.values(TransformationType).forEach(transformationTypeValue =>
231+
storage.findTransformMetadatas(
232+
EntityConstructor,
233+
this.normalizedEntityPropertyKey,
234+
transformationTypeValue as TransformationType,
235+
).forEach(transformMetadataCopyCb),
236+
);
216237
}
217238

218239
}

src/integration.spec.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Body, Controller, INestApplication, Module, Post } from '@nestjs/common';
22
import { Test } from '@nestjs/testing';
33

4-
import { classToPlain, Exclude, Expose, plainToClass, Type } from 'class-transformer';
4+
import { classToPlain, Exclude, Expose, plainToClass, Transform, Type } from 'class-transformer';
55
import { IsInt, IsString, Max, Min, validate } from 'class-validator';
66
import { ApiProperty, DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
77
import { ReferenceObject, SchemaObject } from '@nestjs/swagger/dist/interfaces/open-api-spec.interface';
@@ -350,6 +350,54 @@ describe('Integration tests', () => {
350350
expect(raw).toEqual({ name: ins.name });
351351
});
352352
}); // END @Expose() & @Exclude() together
353+
354+
describe(`@${ Transform.name }() decorators`, () => {
355+
describe('Copying @Transform() decorators from an Entity to a DTO.', () => {
356+
it('Should copy PLAIN_TO_CLASS decorators', () => {
357+
// arrange
358+
const date = new Date();
359+
class User {
360+
@Transform(({ value }) => new Date(value))
361+
public createdAt!: Date;
362+
}
363+
@ApiEntityRef(User)
364+
class UserCreateDto {
365+
@ApiPropertyRef()
366+
public createdAt!: Date;
367+
}
368+
const raw = { createdAt: date.toISOString() };
369+
370+
// act
371+
const ins = plainToClass(UserCreateDto, raw);
372+
373+
// assert
374+
expect(ins.createdAt).toBeInstanceOf(Date);
375+
expect(ins.createdAt.toISOString()).toEqual(date.toISOString());
376+
});
377+
378+
it('Should copy CLASS_TO_PLAIN decorators', () => {
379+
// arrange
380+
const date = new Date();
381+
class User {
382+
@Transform(({ value }) => (value as Date).toISOString(), { toPlainOnly: true })
383+
public createdAt!: Date;
384+
}
385+
@ApiEntityRef(User)
386+
class UserCreateDto {
387+
@ApiPropertyRef()
388+
public createdAt!: Date;
389+
}
390+
const ins = new UserCreateDto();
391+
ins.createdAt = date;
392+
393+
// act
394+
const raw = classToPlain(ins);
395+
396+
// assert
397+
expect(raw).toEqual({ createdAt: date.toISOString() });
398+
});
399+
});
400+
}); // END @${ Transform.name }() decorators
353401
});
354402
});
355403
});

0 commit comments

Comments
 (0)