npm package: @nestlize/repository
Description: Abstract repository and other database tools for Nest and Sequelize.js ORM
Author: Kiril Yakymchuk
Latest version: 0.1.13

# 🧱 Abstract Sequelize Repository for NestJS

Abstract repository pattern implementation for Sequelize ORM in NestJS projects.

- [Quick start](#-quick-start)
- [Purpose](#-purpose)
- [Methods](#-irepository-methods)
- [Configuration](#-irepositoryoptions)

Supports:

* ✅ Custom DTO typing or Sequelize creation attributes
* ✅ Custom error handling
* ✅ Soft delete support (`paranoid: true`)
* ✅ Pagination
* ✅ Optional UUID auto-generation
* ✅ Injected logger
* ✅ Simplified transaction handling

---

## 📦 Installation

```bash
npm install @nestlize/repository
# or
yarn add @nestlize/repository
# or
pnpm add @nestlize/repository
```

---

## 🧠 Purpose

This package provides a reusable and extensible base repository class that works with `sequelize-typescript`. It reduces repetitive CRUD logic while keeping full flexibility for different entity needs.

---

## 🔧 Features

| Feature               | Description                                                        |
|-----------------------|--------------------------------------------------------------------|
| ✅ Abstract class      | Extend `AbstractRepository` for each model                         |
| ✅ Generic typing      | Supports custom DTOs or defaults to Sequelize `CreationAttributes` |
| ✅ Soft delete         | Supports `paranoid` models with `force` option                     |
| ✅ Transaction utility | `repository.transaction()` for scoped logic                        |
| ✅ Logger injection    | Optional NestJS logger for better traceability                     |
| ✅ Flexible options    | Configure `logger`, `autoGenerateId`, etc.                         |

---

## 🛠️ IRepositoryOptions

Configuration options for the abstract repository:

| Option           | Type                     | Default                 | Description                                           |
|------------------|--------------------------|-------------------------|-------------------------------------------------------|
| `logger`         | `Logger`                 | `NestJS default Logger` | Optional NestJS logger instance for internal logging  |

---

## 🛠️ IRepository Methods

All methods return Promises.

| Method                                         | Parameters                                                                                                                                          | Description                                     | 
|------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------|
| `create(dto, options?)`                        | `dto: CreationAttributes<TModel>`, `options?: CreateOptions<TModel>`                                                                                | Creates a new record                            |  
| `insert(dto, options?)`                        | Same as `create`                                                                                                                                    | Alias for `create`                              |  
| `insertMany(dtos, options?)`                   | `dtos: CreationAttributes<TModel>[]`, `options?: BulkCreateOptions<Attributes<TModel>>`                                                             | Creates multiple records                        |   
| `findByPk(primaryKey, options?)`               | `primaryKey: string \| number`, `options?: Omit<FindOptions, 'where'>`                                                                              | Find record by primary key                      |   
| `findOne(query?, options?)`                    | `query?: WhereOptions`, `options?: Omit<FindOptions, 'where'>`                                                                                      | Find single record by query                     |   
| `findAll(query?, options?)`                    | `query?: WhereOptions`, `options?: Omit<FindOptions, 'where'>`                                                                                      | Find all matching records                       |   
| `findAllPaginated(options?)`                   | `limit?: number`, `offset?: number`, `page?: number`, `query?: WhereOptions`, `options?: Omit<FindAndCountOptions, 'where' \| 'offset' \| 'limit'>` | Find paginated records and total count          |
| `updateByPk(primaryKey, dto, options?)`        | `primaryKey: string \| number`, `dto: Partial<Attributes<TModel>>`, `options?: SaveOptions`                                                         | Update record by primary key                    |
| `deleteByPk(primaryKey, options?)`             | `primaryKey: string \| number`, `options?: InstanceDestroyOptions`                                                                                  | Delete (soft/hard) record by primary key        |
| `restoreByPk(primaryKey, options?)`            | `primaryKey: string \| number`, `options?: InstanceRestoreOptions`                                                                                  | Restore previously soft-deleted record          |
| `transaction(runInTransaction)`                | `(transaction: Transaction) => Promise<R>`                                                                                                          | Execute callback within a Sequelize transaction |
| `calculateOffset(limit: number, page: number)` | `limit: number, page: number`                                                                                                                       | Calculate offset for page pagination            |

---

## 🚀 Quick Start

### 1. Define a model

[`BaseModel`](src/base.model.ts) extends from sequelize `Model` class adding timestamps

```ts
import { BaseModel } from '@nestlize/repository'

@Table({ tableName: 'users', paranoid: true })
export class User extends BaseModel<User> {
  @PrimaryKey
  @Default(DataType.UUIDV4)
  @Column
  user_id: string;

  @Column
  name: string;

  @Column
  email: string;
}
```

---

### 2. Create repository

```ts
import { AbstractRepository } from '@nestlize/repository';

@Injectable()
export class UserRepository extends AbstractRepository<User> {
  constructor(@InjectModel(User) userModel: typeof User) {
    super(userModel);
  }
}
```

---

### 3. Use in your service

```ts
@Injectable()
export class UserService {
  constructor(private readonly users: UserRepository) {}

  async createUser(dto: CreateUserDto) {
    return this.users.create(dto);
  }

  async getUsers() {
    return this.users.findAll();
  }

  async updateUser(id: string, update: YourUpdateType) {
    return this.users.updateByPk(id, update);
  }
}
```

---

## ⚙️ Options

You can pass options when instantiating:

```ts
{
  logger: new MyCustomLogger('MyRepo'), // optional
}
```

---

## 💡 Transaction usage

```ts
await repo.transaction(async (transaction) => {
  await repo.insert(data, { transaction });
  await transaction.commit();
});
```

---

## 🏗️ Advanced Use

* Override methods like `create()` or `updateByPk()` to apply custom hooks or validation.
* Extend with filters, scopes, or relations as needed.

---

## 📜 License

MIT © Kiril Yakymchuk

---