All Articles

Mongoose to TypeORM - What is the equivalent of pre-save in TypeORM?

I have a code where I create a user and hash the password before saving.

userSchema.pre('save', async function(next) {
  const user = this;
  if (user.isModified('password')) {
    user.password = await brcrypt.hash(user.password, BCRYPT_HASH_ROUND);
  }
  next();
});

The userSchema could be any data model but the interesting part here is the pre('save'), ...

Lately, I’ve been playing around with Nestjs to use for my next project and I was trying to implement a user management with it.

Here’s my code when adding a new user

import { Repository, EntityRepository } from 'typeorm';
import { User } from './user.entity';
import { UserCredentialsDto } from './dto/user-credentials.dto';
import * as bcrypt from 'bcryptjs';
const BCRYPT_HASH_ROUND = 8;

@EntityRepository(User)
export class UserRepository extends Repository<User> {
  async add(userCredentialsDTO: UserCredentialsDto): Promise<any> {
    const { email, password } = userCredentialsDTO;
    const user = new User();
    user.email = email;
    user.password = await bcrypt.hash(this.password, BCRYPT_HASH_ROUND);
    try {
       return await user.save();
    } catch (e) {
      if (e.code === '23505') {
        throw new Error('Email already exists');
      }
    }
  }
}

In my code, I’m hashing the password explicity before executing the user.save() method. I want what I have in mongoose where I tapped in the pre-save event and hash the password from there.

To do this, I just need to use @BeforeInsert listener on my user entity like this

import {
  BaseEntity,
  Entity,
  PrimaryGeneratedColumn,
  Column,
  BeforeInsert,
} from 'typeorm';
import * as bcrypt from 'bcryptjs';
const BCRYPT_HASH_ROUND = 8;

@Entity()
export class User extends BaseEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({ unique: true, length: 256 })
  email: string;

  @Column()
  password: string;

  @BeforeInsert()
  async beforeInsert() {
    this.password = await bcrypt.hash(this.password, BCRYPT_HASH_ROUND);
  }
  // imagine more code below
  ....

Another benefit with this approach would be that the UserRepository doesn’t need to know anything about bcryptjs!

#TodayILearned