Implementing the Repository Pattern with TypeScript and Node.js
The repository pattern is a design pattern that abstracts data storage, allowing for the decoupling of data access logic from business logic. This leads to a more maintainable, flexible, and scalable codebase.
Benefits of the Repository Pattern
- Enforces the dependency inversion principle
- Allows for separate testing of business logic and data access logic
- Keeps code structured and organized
- Reduces code duplication and enhances maintainability
Implementing the Repository Pattern with TypeScript and Node.js
In this example, we’ll use the Nest framework and Objection.js, an ORM built on top of Knex. We’ll create a PostRepository
that encapsulates data access logic for posts.
Step 1: Create a New Nest App
Create a new Nest app using the Nest CLI:
bash
npx @nestjs/cli new my-nest-app
Step 2: Set Up the Database
Install the required dependencies:
bash
npm install --save @nestjs/objection objection knex pg
Set up the database connection in app.module.ts
:
“`typescript
import { Module } from ‘@nestjs/common’;
import { AppController } from ‘./app.controller’;
import { AppService } from ‘./app.service’;
import { ObjectionModule } from ‘@nestjs/objection’;
import { knexConfig } from ‘./knex.config’;
@Module({
imports: [
ObjectionModule.forRoot(knexConfig),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
“`
Step 3: Create a Post Model and Migration
Create a post.model.ts
file:
“`typescript
import { Model } from ‘objection’;
export class Post extends Model {
id: number;
title: string;
content: string;
}
typescript
Create a migration for the posts table:
import { Migration } from ‘@nestjs/objection’;
export class PostMigration implements Migration {
async up(knex: Knex): Promise
await knex.schema.createTableIfNotExists(‘posts’, (table) => {
table.increments(‘id’).primary();
table.string(‘title’);
table.text(‘content’);
});
}
async down(knex: Knex): Promise
await knex.schema.dropTableIfExists(‘posts’);
}
}
“`
Step 4: Implement the Repository Pattern
Create a post.repository.ts
file:
“`typescript
import { Injectable } from ‘@nestjs/common’;
import { InjectRepository } from ‘@nestjs/objection’;
import { Post } from ‘./post.model’;
@Injectable()
export class PostRepository {
constructor(private readonly postModel: typeof Post) {}
async findAll(): Promise async findOne(id: number): Promise async create(post: Post): Promise async update(id: number, post: Post): Promise async delete(id: number): Promise Inject the @Controller(‘posts’) @Get()
return this.postModel.query().findById(id);
}
return this.postModel.query().insert(post);
}
return this.postModel.query().updateAndFetchById(id, post);
}
await this.postModel.query().deleteById(id);
}
}
“`
Using the RepositoryPostRepository
into a service or controller:
“`typescript
import { Controller, Get } from ‘@nestjs/common’;
import { PostRepository } from ‘./post.repository’;
export class PostController {
constructor(private readonly postRepository: PostRepository) {}
async findAll(): Promise