Logo

dev-resources.site

for different kinds of informations.

3. Building a Common Repository for Nest.js Microservices

Published at
11/7/2023
Categories
mongodb
nestjs
typeorm
typescript
Author
techjayvee
Categories
4 categories in total
mongodb
open
nestjs
open
typeorm
open
typescript
open
Author
10 person written this
techjayvee
open
3. Building a Common Repository for Nest.js Microservices

Introduction:

In a microservices architecture, maintaining consistent CRUD functionality across different services can be challenging. To address this, we can create an abstract repository in Nest.js that provides common database operations. In this tutorial, we'll walk you through creating an abstract schema and an abstract repository that your microservices can extend, thus saving you from duplicating code.

Prerequisites:

  • Basic knowledge of Nest.js
  • Mongoose for MongoDB

Part 1: Creating the Abstract Schema

In the first part, we will create an abstract schema that will serve as the foundation for other schemas in your microservices.

let's create it inside libs/common/src/database just run the following command in your terminal:

touch libs/common/src/database/abstract.schema.ts

populate it with the following codes:

import { Prop, Schema } from '@nestjs/mongoose';
import { SchemaTypes } from 'mongoose';
import { ObjectId } from 'mongoose';

@Schema()
export class AbstractDocument {
  @Prop({ type: SchemaTypes.ObjectId })
  _id: ObjectId;
}

Enter fullscreen mode Exit fullscreen mode

In this code:

We define an abstract class AbstractDocument with a property _id, which is of type ObjectId.
The @Schema() decorator comes from Nest.js Mongoose.
The ObjectId type is imported from Mongoose.

Part 2: Building the Abstract Repository

Now, let's create the abstract repository that all other repositories in your microservices will extend.

let's create it inside libs/common/src/database just run the following command in your terminal:

touch libs/common/src/database/abstract.repository.ts

populate it with the following codes:

import { Model, Types, FilterQuery, UpdateQuery } from 'mongoose';
import { Logger, NotFoundException } from '@nestjs/common';
import { AbstractDocument } from './abstract.schema';

export abstract class AbstractRepository<TDocument extends AbstractDocument> {
  protected readonly logger: Logger;

  constructor(protected readonly model: Model<TDocument>) {
    this.logger = new Logger(model.modelName);
  }

  async create(document: Omit<TDocument, '_id'>): Promise<TDocument> {
    const createdDocument = new this.model({
      ...document,
      _id: new Types.ObjectId(),
    });

    const savedDocument = await createdDocument.save();
    return savedDocument.toJSON() as unknown as TDocument;
  }

  async findOne(filterQuery: FilterQuery<TDocument>): Promise<TDocument> {
    const document = (await this.model
      .findOne(filterQuery)
      .lean(true)) as TDocument;
    if (!document) {
      this.logger.warn(
        `Document not found with filter query: ${JSON.stringify(filterQuery)}`,
      );
      throw new NotFoundException('The document was not found');
    }
    return document;
  }

  async findOneAndUpdate(
    filterQuery: FilterQuery<TDocument>,
    update: UpdateQuery<TDocument>,
  ): Promise<TDocument> {
    const document = (await this.model
      .findOneAndUpdate(filterQuery, update, { new: true })
      .lean(true)) as TDocument;
    if (!document) {
      this.logger.warn(
        `Document not found with filter query: ${JSON.stringify(filterQuery)}`,
      );
      throw new NotFoundException('The document was not found');
    }
    return document;
  }

  async find(filterQuery: FilterQuery<TDocument>): Promise<TDocument[]> {
    const documents = (await this.model
      .find(filterQuery)
      .lean(true)) as TDocument[];
    return documents;
  }
  FilterQuery;
  async findOneAndDelete(
    filterQuery: FilterQuery<TDocument>,
  ): Promise<TDocument> {
    const document = (await this.model
      .findOneAndDelete(filterQuery)
      .lean(true)) as TDocument;
    if (!document) {
      this.logger.warn(
        `Document not found with filter query: ${JSON.stringify(filterQuery)}`,
      );
      throw new NotFoundException('The document was not found');
    }
    return document;
  }
}

Enter fullscreen mode Exit fullscreen mode

In this code:

We define an abstract class AbstractRepository with a generic type TDocument that extends Document.

The repository provides common CRUD functionality, such as create, findOne, findOneAndUpdate, find, and findOneAndDelete.

We utilize the lean(true) method to retrieve plain JavaScript objects, reducing the overhead of Mongoose's hydrated documents.

don't forget to open your libs/common/src/database/index.ts
and export the two newly created files
your index.ts should look like this

export * from './database.module';
export * from './abstract.schema';
export * from './abstract.repository';

Enter fullscreen mode Exit fullscreen mode

Conclusion:

By creating an abstract schema and an abstract repository, you can ensure consistent CRUD operations across your Nest.js microservices. This approach simplifies your codebase, reduces duplication, and provides a common foundation for your services.

Extend the AbstractRepository in your custom repositories to benefit from its built-in CRUD functionality, and you'll have a robust architecture for your microservices.

typeorm Article's
30 articles in total
Favicon
Creating Typescript app with decorator-based dependency injection 💉
Favicon
ORM and Migrating/Adding Data to MySql Database from MongoDb using TypeOrm in javaScript
Favicon
🌟 NestJS + Databases: Making Snake Case Seamless!🐍
Favicon
NestJS TypeORM and Multi-Tenancy
Favicon
Nx + TypeORM + NestJS + Migrations
Favicon
Handling TypeORM migrations in Electron apps
Favicon
How to manage multiple environments with dotenv and Databases config in NestJS
Favicon
Sveltekit + TypeScript + TypeORM + ESM
Favicon
Using TypeORM with TSX: A Smoother Development Experience
Favicon
Prisma or TypeORM ?
Favicon
Mock TypeORM Package
Favicon
Connecting a Serverless PostgreSQL Database (Neon) to NestJS Using the Config Service
Favicon
NestJS and TypeORM — Efficient Schema-Level Multi-Tenancy with Auto Generated Migrations: A DX Approach
Favicon
Getting Started with NestJS and TypeORM: A Beginner's Guide
Favicon
Migration - Module query with TypeORM version 0.3.x
Favicon
Double bind the foreign key to avoid unnecessary JOIN in TypeORM
Favicon
Handling Migrations on NestJS with TypeORM
Favicon
match all conditions in the first array and at least one condition for the second array typeorm
Favicon
Taming cross-service database transactions in NestJS with AsyncLocalStorage
Favicon
Announcing Version 2.0 of nestjs-DbValidator
Favicon
Optimizing SQL Queries by 23x!!!
Favicon
Building my own PostgresGUI with TypeORM+TypeGraphQl class generaion
Favicon
TypeORM | Query Builder
Favicon
NestJs에서 TypeORM을 사용하여 MySQL 연동, 2024-01-25
Favicon
Defining Custom Many-to-many Relationship in NestJS TypeORM.
Favicon
4. Building an Abstract Repository
Favicon
3. Building a Common Repository for Nest.js Microservices
Favicon
TypeORM - remove children with orphanedRowAction
Favicon
Migrating NestJS project with TypeORM to Prisma
Favicon
Authentication part 2 using NestJS

Featured ones: