TypeORM repositories

Concrete repository implementation extending RepositoryBase.

Concrete repositories live in src/infra/repositories and implement the abstract contracts defined in the domain.

typescript
@Injectable()
export class PersonRepository
  extends RepositoryBase<Person>
  implements IPersonRepository
{
  constructor(@Inject(DATA_SOURCE_PROVIDER_TOKEN) dataSource: DataSource) {
    super(dataSource, Person);
  }

  findMany(query: PersonQueryDto): Promise<ListResponse<Person>> {
    return this.repository
      .findAndCount({
        where: { name: query.name ? Like(`%${query.name}%`) : undefined },
        order: query.generateOrderBy(),
        skip: query.skip(),
        take: query.limit,
      })
      .then(([items, count]) => ({
        items,
        count,
      }));
  }

  findById(id: number): Promise<Person | null> {
    return this.repository.findOne({ where: { id } });
  }
}

Common operations (save, delete) are already in the base class:

typescript
export class RepositoryBase<T extends ObjectLiteral> {
  protected readonly repository: Repository<T>;

  constructor(
    protected readonly dataSource: DataSource,
    protected readonly entity: EntityTarget<T>,
  ) {
    this.repository = this.dataSource.getRepository<T>(entity);
  }

  save(entity: T) {
    return this.repository.save(entity);
  }

  async delete(entity: T) {
    await this.repository.remove(entity);
  }
}

Specific methods (findMany, findById, etc.) are implemented in the concrete class.

typescript
@Module({
  imports: [DatabaseModule],
  providers: [{ provide: IPersonRepository, useClass: PersonRepository }],
  exports: [DatabaseModule, IPersonRepository],
})
export class RepositoryModule {}

Thanks to invalidWhereValuesBehavior.undefined: 'ignore' on the DataSource, undefined properties in where are ignored by TypeORM — useful for optional filters like name:

typescript
where: { name: query.name ? Like(`%${query.name}%`) : undefined }
  1. Extend RepositoryBase<YourEntity>.
  2. Implement the domain abstract class.
  3. Inject DATA_SOURCE_PROVIDER_TOKEN in the constructor.
  4. Register the provider in RepositoryModule.

Beyond repositories, InfraModule exports shared services:

Contract Use
ICacheService Data cache (Redis or memory)
IRedLockService Distributed CronJob lock
ILoggingService Error reporting in ErrorsFilter

Cache guide: Cache (Redis).

Koala Nest

A facilitator for building NestJS APIs with DDD architecture. Code copied into your repository — readable, adaptable, and under your control.

Creator

igordrangel.com.br

Design, back-end, and product strategy.

Quick Commands

Global CLI and scripts in the generated project

  • bun install -g @koalarx/nest
  • kl-nest new
  • kl-nest add cache
  • bun run migration:run # CRUD template
  • kl-nest --help
© 2026 Koala NestBuilt for NestJS developers and AI-assisted workflows.