# 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>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://guilhermesantos.gitbook.io/niro-health/modules/core/core-repository.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
