Skip to content

Commit 9ef3048

Browse files
authored
Merge pull request #77 from snirs90/feat/transform-plain-to-class
Adding @TransformPlainToClass decorator
2 parents 72e97c5 + 0e11a85 commit 9ef3048

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,7 @@ The `@Transform` decorator is given more arguments to let you configure how you
634634
|--------------------|------------------------------------------|---------------------------------------------|
635635
| `@TransformClassToPlain` | `@TransformClassToPlain({ groups: ["user"] })` | Transform the method return with classToPlain and expose the properties on the class.
636636
| `@TransformClassToClass` | `@TransformClassToClass({ groups: ["user"] })` | Transform the method return with classToClass and expose the properties on the class.
637+
| `@TransformPlainToClass` | `@TransformPlainToClass(User, { groups: ["user"] })` | Transform the method return with plainToClass and expose the properties on the class.
637638

638639
The above decorators accept one optional argument:
639640
ClassTransformOptions - The transform options like groups, version, name

src/decorators.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,21 @@ export function TransformClassToClass(params?: ClassTransformOptions): Function
8888
};
8989
};
9090
}
91+
92+
/**
93+
* Return the class instance only with the exposed properties.
94+
*/
95+
export function TransformPlainToClass(classType: any, params?: ClassTransformOptions): Function {
96+
97+
return function (target: Function, propertyKey: string, descriptor: PropertyDescriptor) {
98+
const classTransformer: ClassTransformer = new ClassTransformer();
99+
const originalMethod = descriptor.value;
100+
101+
descriptor.value = function(...args: any[]) {
102+
const result: any = originalMethod.apply(this, args);
103+
const isPromise = !!result && (typeof result === "object" || typeof result === "function") && typeof result.then === "function";
104+
105+
return isPromise ? result.then((data: any) => classTransformer.plainToClass(classType, data, params)) : classTransformer.plainToClass(classType, result, params);
106+
};
107+
};
108+
}

test/functional/transformer-method.spec.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import "reflect-metadata";
22
import {defaultMetadataStorage} from "../../src/storage";
3-
import {Exclude, Expose, TransformClassToPlain, TransformClassToClass} from "../../src/decorators";
3+
import { Exclude, Expose, TransformClassToPlain, TransformClassToClass, TransformPlainToClass } from "../../src/decorators";
44
import {expect} from "chai";
55

66
describe("transformer methods decorator", () => {
@@ -50,6 +50,49 @@ describe("transformer methods decorator", () => {
5050
expect(result).to.be.instanceof(User);
5151
});
5252

53+
it("should expose non configuration properties and return User instance class instead of plain object", () => {
54+
defaultMetadataStorage.clear();
55+
56+
@Exclude()
57+
class User {
58+
59+
id: number;
60+
61+
@Expose()
62+
firstName: string;
63+
64+
@Expose()
65+
lastName: string;
66+
67+
password: string;
68+
}
69+
70+
class UserController {
71+
72+
@TransformPlainToClass(User)
73+
getUser() {
74+
const user: any = {};
75+
user.firstName = "Snir";
76+
user.lastName = "Segal";
77+
user.password = "imnosuperman";
78+
79+
return user;
80+
}
81+
}
82+
83+
const controller = new UserController();
84+
85+
const result = controller.getUser();
86+
expect(result.password).to.be.undefined;
87+
88+
const user = new User();
89+
user.firstName = "Snir";
90+
user.lastName = "Segal";
91+
92+
expect(result).to.be.eql(user);
93+
expect(result).to.be.instanceof(User);
94+
});
95+
5396
it("should expose non configuration properties", () => {
5497
defaultMetadataStorage.clear();
5598

0 commit comments

Comments
 (0)