Maxdola
Maxdola

Reputation: 1650

NestJS class-transformer ignoring Declorators on TypeORM-Entity

I am trying to use classToPlain on a TypeORM-Entity in a NestJS Project and class Transformer just ignores the @Exclude Declorator. Below are some snippets of my code:

user.entity

@Entity()
export class User {
  @Column()
  @Exclude()
  password!: string;
}

export const userToPlain = (user : User) => {
  return classToPlain<User>(user);
}

user.service

  createUser(userDTO : userCreateDTO, role?: RoleType[]) : Promise<User> {
    return new Promise<User>(async (resolve, reject) => 
      this.usersRepository.save(userDTO).then(res => {
        resolve(res);
      }).catch(reject);
    })
  }

users.controller

@Post("/create")
create(@Body() userDto : userCreateDTO, @Req() request: Request, @Res() res: Response) {
      this.userService.createUser(userDto, ["EDITOR"]).then(newUser => {
        res.status(201);
        res.json(userToPlain(newUser));
      })
  })
}

I've neither worked with NestJS, TypeORM, nor class-transformer before, so I really have no clue what's going on.

Upvotes: 0

Views: 1817

Answers (1)

Jay McDoniel
Jay McDoniel

Reputation: 70171

You're injecting @Res() into your route handler. Nest's docs explicitly state that if you use @Res() you are in charge of formatting and sending the response yourself. If you want Nest to handle the response for you, remove @Res() from the route handler, and use @UseInterceptors(ClassSerializationInterceptor) as described in the docs here

Edit 8/3/21 to answer the question

Apologies, I read the question too quickly and didn't notice that you are indeed calling res.send and the userToPlain method yourself.

SO, TypeORM is a little weird with the save method, in that it only returns an object, not a class instance, so there's no metadata to be read in regards to the classToPlain method, and as such, it returns the object as is. You can verify this yourself by logging newUser instanceof User.

What you can do about this is call plainToClass first, so that you get back an actual instance of the User class, that can then be properly serialized in the userToPlain method. You can put this in your useToClass method, or make it a part of the UserService#createUser

Upvotes: 2

Related Questions