# Event listener

Even though everything is already working properly, we could argue in favor of another approach. The service is where the logic is stored, therefore it can get bloated quickly if not enough care is taken. With this in mind, we may try to relocate some logic for better organization.

TypeORM has a feature called **Subscriber**. It is a class that allows to create **Entity Listeners**, which are methods that "listen" for specific events in an entity's lifecycle. To better understand this, we can think like the following: I want that, when a <mark style="color:blue;">`user`</mark> is about to be created, or updated (in this case, his <mark style="color:blue;">`password`</mark>), then his password should be hashed. There are two listeners that listen to these events: <mark style="color:blue;">`beforeInsert()`</mark> and <mark style="color:blue;">`beforeUpdate()`</mark>. Then, let's get to work.

Create the file <mark style="color:purple;">users</mark>/<mark style="color:purple;">subscribers</mark>/<mark style="color:purple;">users.subscriber</mark>. Below you can find how should be its basic skeleton, in order to listen to users' events. You'll also need to add it to <mark style="color:blue;">`providers`</mark> in the <mark style="color:blue;">`UsersModule`</mark>.

```typescript
@EventSubscriber()
export class UsersSubscriber implements EntitySubscriberInterface<User> {
  constructor(private readonly dataSource: DataSource) {
    dataSource.subscribers.push(this);
  }

  listenTo() {
    return User;
  }
}
```

Now, we should inject, in the <mark style="color:blue;">constructor</mark>, the <mark style="color:blue;">`HashingService`</mark>.

After that, we can proceed to the <mark style="color:blue;">`beforeInsert()`</mark> listener. Notice that it has as parameter the <mark style="color:blue;">`event`</mark>. We then extract the <mark style="color:blue;">`entity`</mark> related to the <mark style="color:blue;">`event`</mark> to perform the desired operation.

```typescript
async beforeInsert(event: InsertEvent<User>) {
  const { entity: user } = event;

  user.password = await this.hashingService.hash(user.password);
}
```

In the <mark style="color:blue;">`beforeUpdate()`</mark> listener, the process is very similar. We just also check if the field of the entity being updated is different from the field of the entity already in the database. We do this because, as the <mark style="color:blue;">`preload()`</mark> method is used to update, in case a password is not sent, then it will have the value present in the database before the entity is updated.

```typescript
async beforeUpdate(event: UpdateEvent<User>) {
  const { entity, databaseEntity: databaseUser } = event;
  const user = entity as User;

  if (user.password !== databaseUser.password) {
    user.password = await this.hashingService.hash(user.password);
  }
}
```

With this, we have relocated this logic from the service and alleviated its burden. Just don't forget to actually remove that logic from the service.

<mark style="color:green;">**Commit**</mark> - Using event listeners to hash password
