NestJs Ecommerce Development Part — II

asif iqubal
2 min readDec 23, 2020

In the part-I of this tutorial series we have created categories module. In this part we will create products module with pagination and sort.

The module and service files are created using nestjs cli.

The schema class has timestamps ‘created_at’ and ‘updated_at’. And also has relationship with category.

import { Prop, Schema, SchemaFactory } from ‘@nestjs/mongoose’;import { Document, Mongoose } from ‘mongoose’;import * as mongoose from ‘mongoose’;import { Category } from ‘src/category/schemas/category.schema’;export type ProductDocument = Product & Document;@Schema({ timestamps: { createdAt: ‘created_at’, updatedAt: ‘updated_at’ } })export class Product {@Prop({ required: true, index: true })name: string;@Prop({ slug: ‘name’, unique: true, index: true })slug: string;@Prop()description: string;@Prop({ type: Number, required: true })price: number;@Prop()image: string;@Prop([String])gallery: string[];@Prop({ type: mongoose.Schema.Types.ObjectId, ref: ‘Category’, index: true })category: Category;}export const ProductSchema = SchemaFactory.createForClass(Product);

The product dto has some validations —

import { IsDecimal, IsMongoId, IsNotEmpty } from “class-validator”;

export class ProductDto {@IsNotEmpty()name: string;slug: string;description: string;@IsNotEmpty()@IsDecimal()price: number;@IsNotEmpty()@IsMongoId() // used to check if input value is ObjectId typecategory: any;}

We also need a pagination and sort dto —


import { IsNotEmpty, IsNumber, IsString } from “class-validator”;
import { Type } from ‘class-transformer’;export class PaginateDto {@IsNotEmpty()@Type(() => Number)@IsNumber()skip: number;@IsNotEmpty()@Type(() => Number)@IsNumber()limit: number;@IsNotEmpty()@Type(() => String)@IsString()sortBy: string;@IsNotEmpty()@Type(() => Number)@IsNumber()sortOrder: number;}

These validations only works if we add global vaidation code in main.ts file. Without that from API value comes as string and cannot be converted so validation fails every time —

app.useGlobalPipes(new ValidationPipe({transform: true,}));

Product service has normal CRUD operations like in category service, some code for pagination is give here —

async findAll(paginateDto: PaginateDto): Promise<any> {const count:number = await this.prodModel.countDocuments().exec();const docs: Product[] = await this.prodModel.find().skip(paginateDto.skip).limit(paginateDto.limit).sort({ [paginateDto.sortBy]: paginateDto.sortOrder }).exec();return { count, docs };}async findAllByCategory(category: any, paginateDto: PaginateDto): Promise<any> {const count:number = await this.prodModel.countDocuments({category}).exec();const docs: Product[] = await this.prodModel.find({category}).skip(paginateDto.skip).limit(paginateDto.limit).sort({ [paginateDto.sortBy]: paginateDto.sortOrder }).exec();return { count, docs };}async findAllByCategorySlug(category: any, paginateDto: PaginateDto): Promise<any> {const cat:any = await this.catServ.findOneBySlug(category);const count:number = await this.prodModel.countDocuments({category: cat._id}).exec();const docs: Product[] = await this.prodModel.find({category: cat._id}).skip(paginateDto.skip).limit(paginateDto.limit).sort({ [paginateDto.sortBy]: paginateDto.sortOrder }).exec();return { count, docs };}

Similarly the controller has same added methods for getting products from category Id and also from category slug —

@Get()async findAll(@Query() paginateSortDto: PaginateDto): Promise<any> {console.log(‘pagin ‘, paginateSortDto);return this.catService.findAll(paginateSortDto);}@Get(‘productsByCategory/:category’)async findAllByCategory(@Param(‘category’) category: string, @Query() paginateSortDto: PaginateDto): Promise<any> {console.log(‘pagin ‘, paginateSortDto, category);return this.catService.findAllByCategory(category, paginateSortDto);}@Get(‘productsByCategorySlug/:category’)async findAllByCategorySlug(@Param(‘category’) category: string, @Query() paginateSortDto: PaginateDto): Promise<any> {console.log(‘pagin ‘, paginateSortDto, category);return this.catService.findAllByCategorySlug(category, paginateSortDto);}

We now have product API s—

{/product, POST}

{/product, GET}

{/product/productsByCategory/:category, GET}

{/product/productsByCategorySlug/:category, GET}

{/product/:id, GET}

{/product/productBySlug/:slug, GET}

{/product/:id, PUT}

{/product/:id, DELETE}

In the next tuorial we will take a look at Auth Module for basic authentication, auth guards, JWT token based access etc..

Github link https://github.com/asif633/nestjs-ecommerce

Thank You.

--

--