Basic CRUD operations with NestJs, TypeScript, Fastify & MongoDB
Tags: mongodb, nestjs, typescript, fastify
Published: 2023-08-18 17:49:09

Fastify is a web framework for building efficient and high-performance web applications and APIs in Node.js. It is designed to be lightweight and focused on speed, making it particularly suitable for applications that require low latency and high throughput. Fastify was developed to address some of the shortcomings of existing Node.js frameworks in terms of performance and simplicity.

Let’s go

Create your NestJs project

```
npx nest new project-name
```
Our project name is : fastify-mongo-crud and we’ll use yarn but you can choose any other package manager listed.


![package manager choice](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xvqix0uz5qcxvokyi6q3.png)

Add the Fastify package with this command

```
yarn add @nestjs/platform-fastify
```

By default , when you create a new Nestjs project, Nest install “@nestjs/platform-express” package (see the image below),

![Platform express](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sl6mu01gfv5bz325qqyj.png)

Because we’ll use Fastify we dont need this express platform anymore.

Create a nest resource with

```
npx nest generate resource articles --no-spec
```
then select REST API

![Rest API](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uaxufgelwtscscjgnmuh.png)

Nest will ask you i f you want to generate CRUD entry points : Type ‘n’ to say no.

![n](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dw42u8sb9efevgy2eke0.png)

Great! now as we already know, the default framework is Express, we need to change it to Fastify.

In the root of the project, pass the code bellow into main.ts file

```
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { FastifyAdapter,NestFastifyApplication} from '@nestjs/platform-fastify';

async function bootstrap() {
  const app = await NestFactory.create<NestFastifyApplication>(AppModule, new FastifyAdapter());
  await app.listen(3000);
}
bootstrap();
```

PS: If you have the following issue :

`Type 'NestFastifyApplication<RawServerDefault>' does not satisfy the constraint 'INestApplication'.`

Perhaps there is a compatibility versions issue of both `@nestjs/platform-fastify` and `NestJS core packages`, so run

```
yarn upgrade-interactive --latest
```
to update the dependencies to their last stable versions.

Once you’ve done with that, install mongoDb to the project

```
yarn add @nestjs/mongoose mongoose
```
Once the mongoose package is installed, we need to import the MongooseModule into the root AppModule. At this stage, your app.module.ts should be like :

```
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ArticlesModule } from './articles/articles.module';
import { MongooseModule } from '@nestjs/mongoose';


@Module({
  imports: [ MongooseModule.forRoot('mongodb://mongO_uri'), ArticlesModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
```

Do not forget to replace the `mongodb://mongO_uri` by a real mongoDb uri.

Create our article schema in `src/article/schema/article.schema.ts` :

```
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument } from 'mongoose';

export type ArticleDocument = HydratedDocument<Article>;

@Schema()
export class Article {
  @Prop()
  title: string;

  @Prop()
  slug: string;
  
  @Prop()
  content: string;  
}

export const ArticleSchema = SchemaFactory.createForClass(Article);
```

Import the MongooseModule, Article and ArticleSchema in your article.module.ts file

```
import { Module } from '@nestjs/common';
import { ArticlesService } from './articles.service';
import { ArticlesController } from './articles.controller';
import { MongooseModule } from '@nestjs/mongoose';
import { Article, ArticleSchema } from './schema/article.schema';

@Module({
  imports:[MongooseModule.forFeature([{ name: Article.name, schema: ArticleSchema }])],
  controllers: [ArticlesController],
  providers: [ArticlesService]
})
export class ArticlesModule {}
```

It’s time to run the project to see if everything works properly.

Run it with `yarn start dev`

If not and if you got this error:

```
const stringWidth = require('string-width');
Error [ERR_REQUIRE_ESM]: require() of ES Module
```
Just delete the node-module file and install all the dependencies again.

Great! MongoDb and Fastify added and set up successfully


![clean console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rr1tyko636wjy70xxdzj.png)

Let’s create our services now in order to post and get data from the database.

`src/articles/articles.service.ts`

```
import { Injectable } from '@nestjs/common';
import { Article } from './schema/article.schema';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';

@Injectable()
export class ArticlesService {
    constructor(@InjectModel(Article.name) private readonly articleModel: Model<Article>){}

    async postArticle( body: Article):Promise<Article> {
        const create = new this.articleModel(body)
        return create.save()
    }
    
    async getArticles(){
        return this.articleModel.find().exec()
    }
}
```

`postArticle()` is here for creating new article and save it to the mongoDb database and `getArticles()` for getting all the articles from the database

Once we created all the services we want, let’s create the controller:

`src/articles/articles.controller.ts`

```
import { Body, Controller, Get, Post } from '@nestjs/common';
import { ArticlesService } from './articles.service';
import { Article } from './schema/article.schema';

@Controller('articles')
export class ArticlesController {
  constructor(private readonly articlesService: ArticlesService) {}

  @Post('create')
  postArticle( @Body() body : Article ){
    return this.articlesService.postArticle(body);
  }

   @Get('get-articles')
   getArticles(){
    return this.articlesService.getArticles();
   }
}
```

For each function, we defined the request type (POST or GET only for this example), the pathname and the necessary parameters.

Great! now let’s open postman to see if we can post and get with our simple Fastify api implementation.

`localhost:3000/articles/get-articles` result :

![Get result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f71k6is7tuxb205wyvle.png)

`localhost:3000/articles/create` result :


![Post result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9mehsjdta96496lnvv6o.png)

Congratulation, we’ve delved into the world of basic CRUD operations, leveraging the power of NestJs, TypeScript, Fastify, and MongoDB. By mastering these fundamental techniques, you’ve laid a strong foundation for creating robust applications. As you continue to explore and refine your skills, remember that the journey of a developer is an ongoing evolution.

For more about Fastify 👉🏾 : https://fastify.dev/

You can find the whole project on Github 👇🏾 : https://github.com/laetitiaouelle/fastify-mongo-crud

Follow me there :

https://linkedin.com/in/laetitia-christelle-ouelle-89373121b/

https://twitter.com/OuelleLaetitia

https://dev.to/ouelle

Happy coding ! 😏