Abstract repository pattern implementation for Sequelize ORM in NestJS projects.
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
npm install nest-sequelize-repository
# or
yarn add nest-sequelize-repository
# or
pnpm add nest-sequelize-repositoryThis 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.
| 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. |
Configuration options for the abstract repository:
| Option | Type | Default | Description |
|---|---|---|---|
logger |
Logger |
NestJS default Logger |
Optional NestJS logger instance for internal logging |
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, 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 |
@Table({ tableName: 'users', paranoid: true })
export class User extends Model<User> {
@PrimaryKey
@Default(DataType.UUIDV4)
@Column
user_id: string;
@Column
name: string;
@Column
email: string;
}import { AbstractRepository } from 'nest-sequelize-repository';
@Injectable()
export class UserRepository extends AbstractRepository<User> {
constructor(@InjectModel(User) userModel: typeof User) {
super(userModel);
}
}@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);
}
}You can pass options when instantiating:
{
logger: new MyCustomLogger('MyRepo'), // optional
}await repo.transaction(async (transaction) => {
await repo.insert(data, { transaction });
await transaction.commit();
});- Override methods like
create()orupdateByPk()to apply custom hooks or validation. - Extend with filters, scopes, or relations as needed.
MIT Β© Kiril Yakymchuk