dede
dede

Reputation: 2663

NestJS / TypeORM: Custom repository method is not accessible in service

New to NestJS and TypeORM, and the similar questions on SO didn't solve my problem.

I have a custom TypeORM repository in NestJS using it in service, but it fails with error: TypeError: this.tenantRepository.createTenant is not a function.

tenants.module.ts:

import { TenantRepository } from './tenant.repository';

@Module({
  imports: [
    TypeOrmModule.forFeature([TenantRepository]),
  ],
  controllers: [TenantsController],
  providers: [TenantsService],

})
export class TenantsModule { }

tenant.repository.ts:

// ...
import { TenantEntity } from './entities/tenant.entity';

@EntityRepository(TenantEntity)
export class TenantRepository extends Repository<TenantEntity>{

    async createTenant(createTenantDto: CreateTenantDto): Promise<TenantEntity> {
        const { name, email } = createTenantDto;

        const newTenant = new TenantEntity()
        newTenant.name = name;
        newTenant.email = email;
        await newTenant.save()

        return newTenant;
    }
}

And here's where the error is triggered (tenants.service.ts)

// ...
import { TenantEntity } from './entities/tenant.entity';
import { TenantRepository } from './tenant.repository';

@Injectable()
export class TenantsService {

  constructor(
    @InjectRepository(TenantRepository)
    private tenantRepository: TenantRepository
  ) { }

  async createTenant(createTenantDto: CreateTenantDto): Promise<TenantEntity> {
    return await this.tenantRepository.createTenant(createTenantDto); // <-- ERROR

  }
}

I can inject entity in service and use it for simple CRUD, but I want to separate concerns and use the repository pattern. This is a POST endpoint and the error is only after submission from Swagger. Also, VS Code autocomplete is suggesting createTenant after typing this.tenantRepository Where am I going wrong?

Upvotes: 0

Views: 1780

Answers (1)

Mostafa Fakhraei
Mostafa Fakhraei

Reputation: 3687

EntityRepository decorator was deprecated, and as far as I know, you need to define a custom class that extends Repository and decorate it with @Injectable. Hence, you need to have some changes as follows:

tenant.repository.ts:

import { Injectable } from '@nestjs/common';
import { DataSource, Repository } from 'typeorm';

@Injectable()
export class TenantRepository extends Repository<TenantEntity>{

  constructor(private dataSource: DataSource) {
    super(TenantEntity, dataSource.createEntityManager());
  }

  async createTenant(createTenantDto: CreateTenantDto): Promise<TenantEntity> {
    const { name, email } = createTenantDto;

    const newTenant = this.create({ name, email });
    await this.save(newTenant);

    return newTenant;
  }
}

tenants.module.ts:

import { TenantRepository } from './tenant.repository';

@Module({
  imports: [
    TypeOrmModule.forFeature([TenantRepository]),
  ],
  controllers: [TenantsController],
  providers: [TenantsService, TenantRepository],

})
export class TenantsModule { }

tenants.service.ts:

import { TenantEntity } from './entities/tenant.entity';
import { TenantRepository } from './tenant.repository';

@Injectable()
export class TenantsService {

  constructor(
    private tenantRepository: TenantRepository
  ) { }

  async createTenant(createTenantDto: CreateTenantDto): Promise<TenantEntity> {
    return await this.tenantRepository.createTenant(createTenantDto);
  }
}

You also have access to built-in typeorm methods like save, create, find, etc. since the custom repository is derived from Repository class.

Upvotes: 3

Related Questions