Creating and Using Custom Repositories in NestJS with TypeORM 0.3

Creating and Using Custom Repositories in NestJS with TypeORM 0.3

NestJS with TypORM

NestJS is a popular framework for building scalable and efficient server-side applications using Node.js. It provides a modular structure for organizing your code and makes it easy to use various libraries and frameworks, such as TypeORM, for managing your database.

In TypeORM 0.2.x, it was easy to create a custom repository and use the @InjectRepository and @EntityRepositoryannotation to inject it into your NestJS service. However, in TypeORM 0.3, the API for creating custom repositories has changed, and the existing approach is no longer valid.

Custom repositories are a way to extend the Repository class provided by TypeORM, which is a class that provides a set of common methods for interacting with a database. Custom repositories allow you to add custom methods or queries to the Repository class, which can be useful if you want to reuse certain queries or add additional functionality.

In this article, we will look at how to create and use custom repositories in NestJS with TypeORM 0.3.

We will start by creating a custom repository interface and implementing it with custom methods. Then, we will inject the custom repository into a NestJS service and use it to access the custom methods. Finally, we will register the custom repository with a NestJS module to make it available for injection.

Creating a custom repository

To create a custom repository in TypeORM 0.3, you need to define an interface that extends the Repository class. This interface should include any custom methods or queries that you want to use in your application.

Here’s an example of a custom repository interface for a User entity:

user.repository.ts

import { Repository } from 'typeorm';
import { User } from './user.entity';

export interface UserRepository extends Repository<User> {
    this: Repository<User>;
    getUsers(): Promise<User[]>;
    getUser(id: number): Promise<User>;
    createUser(user: { firstName: string; lastName: string; isActive: boolean });
}

In this example, we’ve defined a UserRepository interface that extends the Repository class and includes three custom methods: getUsers, getUser, and createUser.

To implement the custom repository interface, you can create an object with the custom methods as its properties. Here’s an example of how to implement the UserRepository interface:

user.repository.ts

...
...
export const customUserRepository: Pick<UserRepository, any> = {
    getUser(this: Repository, id) {
        return this.findOne({ where: { id } });
    },

    getUsers(this: Repository) {
        return this.find();
    },

    createUser(this: Repository, user) {
        return this.save(user);
    },
};

In this example, we’ve defined an object called customUserRepository that has the same properties as the UserRepository interface. Each property is a function that implements the corresponding method from the interface. Notice that we've used the this keyword to refer to the current instance of the Repository class. This allows us to use the Repository class's methods, such as find and save, in our custom methods.

Injecting the custom repository into a NestJS service

To use the custom repository in a NestJS service, you need to inject it using the @InjectRepository decorator and the custom repository interface.

Here’s an example of a NestJS service that injects the UserRepository:

user.service.ts

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';
import { UserRepository } from './user.repository';

@Injectable()
export class UserService {
constructor( @InjectRepository(User) private readonly userRepository: UserRepository, ) {}

async getAll() {
    return await this.userRepository.getUsers();
}

async createUser(): Promise<User> {
    const user: User = this.userRepository.create();
    user.firstName = 'john';
    user.isActive = true;
    user.lastName = 'doe';

    return await this.userRepository.createUser(user);
 }
}

In this example, we’ve injected the UserRepository using the @InjectRepository decorator and the User symbol. We can then use the userRepository property, which is an instance of the UserRepository interface, to access the custom repository methods in our service.

Registering the custom repository with a NestJS module

To use the custom repository in your NestJS application, you need to register it with the module where it will be used.

Here’s an example of how to register the UserRepository with a NestJS module:

user.module.ts

import { Module } from '@nestjs/common';
import {
getDataSourceToken,
getRepositoryToken,
TypeOrmModule,
} from '@nestjs/typeorm';
import { UserController } from './user.controller';
import { UserService } from './user.service';
import { User } from './user.entity';
import { DataSource } from 'typeorm';
import { customUserRepository } from './user.repository';

@Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [UserController],
providers: [
    {
    provide: getRepositoryToken(User),
    inject: [getDataSourceToken()],
    useFactory(datasource: DataSource) {
        return datasource.getRepository(User).extend(customUserRepository);
    },
    },
    UserService,
    ],
})
export class UserModule {}

In this example, we’ve imported the TypeOrmModule and used the forFeature method to register the User entity with the module. This makes the repository for the User entity available for injection into any services or controllers within the module.

We’ve also defined a provider that uses the getRepositoryToken and getDataSourceToken functions to inject the custom repository into the module. The **useFactory** function returns an instance of the **Repository** class for the **User** entity, which we've extended with the **customUserRepository** object. This allows us to use the custom repository methods in our module.

Conclusion

In this article, we’ve looked at how to create and use custom repositories in NestJS with TypeORM 0.3. We’ve defined a custom repository interface, implemented it with custom methods, injected it into a NestJS service, and registered it with a NestJS module.

Custom repositories are a useful way to add custom methods or queries to the Repository class, which can help you reuse code and add additional functionality to your application. By following the steps in this article, you can easily create and use custom repositories in your NestJS applications with TypeORM 0.3.

It’s always appreciated when readers take the time to comment, follow, and share with their friends. If you found this article helpful, please consider supporting me by following me and subscribing to my YouTube channel.

Your support helps me to continue creating and sharing helpful content with the community. Thank you for your support!

Disclaimer*: The NestJS and TypeORM logos are trademarks of their respective brands. The use of these logos in this article is for informational purposes only and does not imply any endorsement or affiliation with the brands.*

Did you find this article valuable?

Support Durgadas Kamath by becoming a sponsor. Any amount is appreciated!