# Core Repository

{% hint style="info" %}
This is an abstract class and is used as a base for other modules.
{% endhint %}

### Imports

{% tabs %}
{% tab title="Contract" %}

```typescript
import { CoreRepositoryContract } from 'niro-health';
```

{% endtab %}

{% tab title="Interface" %}

```typescript
import type { ICoreRepositoryContract } from 'niro-health';
```

{% endtab %}
{% endtabs %}

### Method of Use

To implement this class, you will need an create entity.

{% code title="entities/index.ts" %}

```typescript
import { CoreEntityContract } from 'niro-health';

export class User extends CoreEntityContract {
  username: string;
  email: string;
  password: string;

  constructor(data: Partial<User>) {
    super(data);
    this.username = data?.username;
    this.email = data?.email;
    this.password = data?.password;
  }
}
```

{% endcode %}

You will need an implementation for the database.

{% code title="contracts/index.ts" overflow="wrap" %}

```typescript
import { CoreDatabaseContract } from 'niro-health';
import type { User } from './entities';

export abstract class UserDatabaseContract extends CoreDatabaseContract<User> {
  abstract findByEmail(email: string): Promise<User | null>;
}
```

{% endcode %}

Let's create an in-memory bank by implementing our contract.

{% code title="db/memory.ts" %}

```typescript
import type { INestApplication } from '@nestjs/common';
import type { ISimilarityFilterService, SimilarityFilterType as Type } from 'niro-health';
import type { User } from './entities';

import { UserDatabaseContract } from './contracts';

import * as _ from 'lodash';

export class UserMemoryDB extends UserDatacbaseContract {
  private readonly _similarityFilterService: ISimilarityFilterService;

  constructor(
    protected readonly app: INestApplication,
    private users: User[] = [],
  ) {
    super(app);
    this._similarityFilterService = this.app.get<ISimilarityFilterService>(
      'ISimilarityFilterService',
    );
  }

  async create(data: User): Promise<User> {
    this.users.push(data);

    return data;
  }

  async findAll(limit?: number, offset?: number): Promise<User[]> {
    return this.users.slice(offset || 0, limit || this.users.length);
  }

  async findOne(id: number | string): Promise<User | null> {
    return this.users.find((user) => user.id === id);
  }

  async findBy(filter: Partial<User>, similarity?: Type): Promise<User[]> {
    return this.users.filter((key) =>
      this._similarityFilterService.execute<User>(
        filter,
        key as User,
        similarity || 'full',
      ),
    ) as User[];
  }

  async findByEmail(email: string): Promise<User | null> {
    const hash = this.hashText(email);

    return this.users.find((user) => user.hash.email === hash);
  }

  async update(id: number | string, newData: User): Promise<User | null> {
    this.users = this.users.map((user) =>
      user.id === id ? { ...user, ..._.omitBy(newData, _.isNil) } : user,
    ) as User[];

    return await this.findOne(id);
  }

  async delete(id: number | string): Promise<boolean> {
    this.users = this.users.filter((user) => user.id !== id);

    return true;
  }
}
```

{% endcode %}

### Create UseCases

To implement creating, updating, and deleting users, we should create use cases to make code maintenance and organization easier.

{% code title="usecases/create.ts" %}

```typescript
import type { INestApplication } from '@nestjs/common';
import type { CreateUserDto } from './users/dto/create';
import { UserRepository } from './users/repositories';
import { UserDatabaseContract } from './users/contracts';
import { User } from './users/entities';

export class CreateUser {
  static async execute(
    user: CreateUserDto,
    database: UserDatabaseContract,
    app: INestApplication,
  ) {
    const repository = new UserRepository(database, app);
    const entity = new User({ id: database.generateUUID() });

    entity.username = user.username;
    entity.email = user.email;
    entity.password = user.password;

    return await repository.create(entity);
  }
}
```

{% endcode %}

### Create Factories

Now we can implement a factory to group our use cases with our database implementations.

{% code title="factories/create.ts" %}

```typescript
import type { INestApplication } from '@nestjs/common';
import type { CreateUserDto } from './users/dto/create';
import { CreateUser } from './users/usecases/create';
import { UserMemoryDB } from './users/db/memory';

export class CreateUserFactory {
  static async run(user: CreateUserDto, app: INestApplication) {
    const database = new UserMemoryDB(app);
    return await CreateUser.execute(user, database, app);
  }
}
```

{% endcode %}

Our implementation is complete.

### Methods

<table><thead><tr><th width="266.3333333333333">Method</th><th width="124" align="center">Scope</th><th>Description</th></tr></thead><tbody><tr><td><code>beforeSave</code></td><td align="center"><code>abstract</code></td><td><code>This method is called before saving data to the database.</code></td></tr><tr><td><code>beforeUpdate</code></td><td align="center"><code>abstract</code></td><td><code>This method is called before updating data in the database.</code></td></tr><tr><td><code>create</code></td><td align="center"><code>abstract</code></td><td><code>This method is called for create new data in the database.</code></td></tr><tr><td><code>update</code></td><td align="center"><code>abstract</code></td><td><code>This method is called for update data in the database.</code></td></tr><tr><td><code>delete</code></td><td align="center"><code>abstract</code></td><td><code>This method is called for delete data in the database.</code></td></tr><tr><td><code>findById</code></td><td align="center"><code>abstract</code></td><td><code>This method is called for find data by id in the database.</code></td></tr><tr><td><code>findAll</code></td><td align="center"><code>abstract</code></td><td><code>This method is called for find all data in the database.</code></td></tr><tr><td><code>findBy</code></td><td align="center"><code>abstract</code></td><td><code>This method is called for find data by filter in the database.</code></td></tr></tbody></table>
