Closed markoj3s closed 1 month ago
CC @NoNameProvided
Just "driving past" but saw this when I went to search for "performance" (somehow).
I think it's meant for the backend, but definitely on the "user-data facing" side. I wouldn't consider that frontend.
I think the main niche this library is used for is handling incoming data (e.g. from users, API consumers, etc), which might come in as JSON, then need to be transformed to a class form (and then either validated with class-validator or with something else). So using it more for DTOs would be expected. It's probably expected your DB data is already validated or typesafe (SQL, Mongoose), or is being accessed as JSON (plain MongoDB driver) in which case you can use class-transformer + class-validator anyway.
(A less opinionated equivalent might be Zod. In other languages, there is a similar split in responsibilities with e.g. Java and Kotlin, where you might have one library handling serialisation of DTOs (e.g. Kotlinx Serialization, Jackson), and then another library (e.g. Spring Data) handling the ORM models. This handles roughly the same niche as Kotlinx, but without the AOT compilation benefits).
Basically, taking unknown, plain objects, and turning them into something richer with methods, state, or encapsulation as required.
Re getters and setters, makes sense that you can't use plainToInstance
to populate something with a getter, you would need a corresponding setter. The other way should work though, e.g. instanceToPlain or instanceToInstance. The getter has to be accessible from the "left hand side" of the operation basically.
I guess you can approach this in a number of ways and potentially make this quite complicated, like the below:
export class UserDTO {
@Transform(({ value, obj }) => value ?? obj.screenName.split(" ")[0])
firstName: string;
@Transform(({ value, obj }) => value ?? obj.screenName.split(" ")[1])
lastName: string;
@Expose()
get screenName() {
return `${user.firstName} {user.lastName}`;
}
}
export function fromUser(user: UserModel): UserDTO {
return plainToInstance(UserDTO, {
firstName: user.firstName,
lastName: user.lastName,
screenName: `${user.firstName} {user.lastName}`;
});
}
@ceigey thank you for your detailed answer, I aggree. This library can be used at the backend or frontend, where you find it suitable. If you have good tests you should be fine.
Although, if you want class-transformer
to work nicely with an ORM, you will have to write some custom Transformers as the integration with other libraries is out of the scope of this library and will not implement anything related to any ORM.
Closing as answered. If you have any questions left feel free to comment on this issue.
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Basically, back-end code usually manipulates ORM objects and transforms them to return suitable data to the clients. However,
class-transformer
does not seem to work well with ORM objects (at least not withSequelize
models' instances); also,plainToInstance
does not seem to include in the transformed object fields defined in getters like:So at first glance it feels more suitable to simply work as follows in the back-end:
However, it seems to work well with front-end code which receives json objects.
So I was wondering if I was doing something wrong, or if this library is indeed thought for the front-end rather than the back-end?