Skip to content

raza-bukhari/ecommerce-app

Repository files navigation

NestJS E-Commerce API

Production-ready e-commerce REST API built with NestJS, TypeScript, TypeORM, and PostgreSQL.

This project implements a modular backend for a typical online store, including authentication, users, categories, products, inventory, cart, wishlist, orders, addresses, reviews, coupons, shipping, and admin analytics.

Tech Stack

  • Framework: NestJS 11
  • Language: TypeScript with strict mode
  • ORM: TypeORM
  • Database: PostgreSQL
  • Auth: JWT access token + refresh token
  • Validation: class-validator + class-transformer
  • Config: @nestjs/config
  • Password hashing: bcrypt
  • API docs: @nestjs/swagger

Features

  • Modular NestJS architecture
  • Global request validation
  • Global exception filter
  • Global response envelope
  • JWT authentication
  • Role-based authorization for admin routes
  • Swagger documentation
  • Product catalog with variants and images
  • Inventory management
  • Cart and wishlist flows
  • Order creation and cancellation
  • Address management
  • Product reviews with purchase validation
  • Coupon validation and admin coupon management
  • Shipping estimation and tracking
  • Admin dashboard statistics

Project Structure

src/
├── main.ts
├── app.module.ts
├── app.controller.ts
├── app.service.ts
├── common/
│   ├── decorators/
│   ├── enums/
│   ├── filters/
│   ├── guards/
│   ├── interceptors/
│   ├── interfaces/
│   ├── pipes/
│   └── utils/
├── config/
│   └── database.config.ts
└── modules/
    ├── admin/
    ├── addresses/
    ├── auth/
    ├── cart/
    ├── categories/
    ├── coupons/
    ├── inventory/
    ├── orders/
    ├── products/
    ├── reviews/
    ├── shipping/
    ├── users/
    └── wishlist/

Global API Behavior

Base prefix:

/api/v1

Swagger UI:

/api/docs

Success response shape:

{
  "success": true,
  "data": {},
  "message": "Request completed successfully"
}

Error response shape:

{
  "success": false,
  "statusCode": 400,
  "message": "Validation failed",
  "errors": [],
  "path": "/api/v1/example",
  "timestamp": "2026-04-11T00:00:00.000Z"
}

Validation behavior:

  • whitelist: true
  • forbidNonWhitelisted: true
  • transform: true

Authentication and Authorization

JWT

  • Access token is used in the Authorization: Bearer <token> header
  • Refresh token is stored hashed on the user record
  • Email verification is required before login

Roles

Supported roles:

  • ADMIN
  • CUSTOMER

Admin endpoints use:

@UseGuards(JwtAuthGuard, RolesGuard)
@Roles(Role.ADMIN)

For fully admin-only controllers such as inventory and admin, guards are applied at class level.

Environment Variables

Use .env.example as the template.

PORT=3000
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USER=postgres
DATABASE_PASSWORD=secret
DATABASE_NAME=ecommerce_db
DATABASE_SYNCHRONIZE=false
DATABASE_LOGGING=false
JWT_ACCESS_SECRET=access_secret
JWT_REFRESH_SECRET=refresh_secret
JWT_ACCESS_EXPIRY=15m
JWT_REFRESH_EXPIRY=7d
BCRYPT_ROUNDS=10

Notes:

  • DATABASE_SYNCHRONIZE=true is useful for local development against an empty database
  • keep DATABASE_SYNCHRONIZE=false for production
  • if port 3000 is already in use locally, set PORT=3001

Local Setup

  1. Install dependencies:
npm install
  1. Create .env from .env.example

  2. Start PostgreSQL and make sure the configured database exists

  3. Run the API:

npm run start:dev
  1. Open Swagger:
http://localhost:3000/api/docs

If you changed PORT, adjust the Swagger URL accordingly.

Scripts

  • npm run build - compile the project
  • npm run start - start the app
  • npm run start:dev - start in watch mode
  • npm run start:prod - run compiled build
  • npm test - run unit tests
  • npm run test:e2e - run e2e smoke tests
  • npm run test:cov - run coverage
  • npm run lint - run eslint

Database Notes

The app is configured for PostgreSQL via TypeORM with autoLoadEntities: true.

Important local notes:

  • this project expects a reachable PostgreSQL server
  • if you reuse an existing shared database, schema sync can collide with unrelated tables
  • prefer using a dedicated database such as ecommerce_db for this project

Main Business Areas

Auth

  • register user
  • verify email
  • login and issue tokens
  • refresh token rotation
  • forgot/reset password
  • logout

Catalog

  • categories
  • products
  • variants
  • product images
  • featured and search endpoints

Commerce

  • cart
  • wishlist
  • orders
  • coupons
  • shipping estimates

Customer Data

  • profile management
  • addresses
  • reviews

Admin

  • user management
  • inventory management
  • coupon management
  • order administration
  • revenue and dashboard analytics

API Endpoint Reference

Access labels:

  • Public = no token required
  • JWT = authenticated user required
  • Admin = authenticated ADMIN user required

Health

Method Path Access Description
GET /api/v1/health Public Health check

Auth

Method Path Access Description
POST /api/v1/auth/register Public Register a customer
POST /api/v1/auth/login Public Login and receive access/refresh tokens
POST /api/v1/auth/logout JWT Logout current user
POST /api/v1/auth/refresh-token Public Refresh token pair
POST /api/v1/auth/forgot-password Public Start password reset flow
POST /api/v1/auth/reset-password Public Reset password using token
POST /api/v1/auth/verify-email Public Verify email address

Users

Method Path Access Description
GET /api/v1/users/me JWT Get current user profile
PUT /api/v1/users/me JWT Update current user profile
DELETE /api/v1/users/me JWT Delete current user account
GET /api/v1/users Admin Get all users
GET /api/v1/users/:id Admin Get user by id
PATCH /api/v1/users/:id/role Admin Update user role
DELETE /api/v1/users/:id Admin Delete user by id

Categories

Method Path Access Description
GET /api/v1/categories Public Get all categories
GET /api/v1/categories/:id Public Get category by id
GET /api/v1/categories/:id/products Public Get products in category
POST /api/v1/categories Admin Create category
PUT /api/v1/categories/:id Admin Update category
DELETE /api/v1/categories/:id Admin Delete category

Products

Method Path Access Description
GET /api/v1/products Public Get paginated products
GET /api/v1/products/featured Public Get featured products
GET /api/v1/products/new-arrivals Public Get new arrivals
GET /api/v1/products/search?q= Public Search products
GET /api/v1/products/slug/:slug Public Get product by slug
GET /api/v1/products/:id Public Get product by id
GET /api/v1/products/:id/variants Public Get product variants
POST /api/v1/products Admin Create product
PUT /api/v1/products/:id Admin Update product
DELETE /api/v1/products/:id Admin Delete product
POST /api/v1/products/:id/variants Admin Create variant
PUT /api/v1/products/:id/variants/:variantId Admin Update variant
DELETE /api/v1/products/:id/variants/:variantId Admin Delete variant
POST /api/v1/products/:id/images Admin Add product image
DELETE /api/v1/products/:id/images/:imageId Admin Delete product image

Inventory

Method Path Access Description
GET /api/v1/inventory Admin Get all inventory records
GET /api/v1/inventory/low-stock Admin Get low stock products
GET /api/v1/inventory/out-of-stock Admin Get out of stock products
GET /api/v1/inventory/:productId Admin Get product inventory
GET /api/v1/inventory/:productId/variants/:variantId Admin Get variant inventory
PATCH /api/v1/inventory/:productId/adjust Admin Adjust product stock
PATCH /api/v1/inventory/:productId/variants/:variantId/adjust Admin Adjust variant stock

Cart

Method Path Access Description
GET /api/v1/cart JWT Get current cart
POST /api/v1/cart/items JWT Add item to cart
PUT /api/v1/cart/items/:itemId JWT Update cart item quantity
DELETE /api/v1/cart/items/:itemId JWT Remove cart item
DELETE /api/v1/cart JWT Clear cart

Wishlist

Method Path Access Description
GET /api/v1/wishlist JWT Get current wishlist
POST /api/v1/wishlist/items JWT Add product to wishlist
DELETE /api/v1/wishlist/items/:productId JWT Remove product from wishlist

Orders

Method Path Access Description
POST /api/v1/orders JWT Create order from cart
GET /api/v1/orders JWT Get current user orders
GET /api/v1/orders/:id JWT Get current user order by id
POST /api/v1/orders/:id/cancel JWT Cancel current user order
GET /api/v1/orders/:id/invoice JWT Get invoice for order
GET /api/v1/orders/admin/all Admin Get all orders
PATCH /api/v1/orders/:id/status Admin Update order status
GET /api/v1/orders/admin/stats Admin Get order statistics

Addresses

Method Path Access Description
GET /api/v1/addresses JWT Get current user addresses
POST /api/v1/addresses JWT Create address
PUT /api/v1/addresses/:id JWT Update address
DELETE /api/v1/addresses/:id JWT Delete address
PATCH /api/v1/addresses/:id/default JWT Set default address

Reviews

Method Path Access Description
GET /api/v1/products/:productId/reviews Public Get product reviews
POST /api/v1/products/:productId/reviews JWT Create review
PUT /api/v1/products/:productId/reviews/:reviewId JWT Update own review
DELETE /api/v1/products/:productId/reviews/:reviewId JWT Delete own review

Coupons

Method Path Access Description
POST /api/v1/coupons/validate Public Validate coupon code
GET /api/v1/coupons Admin Get all coupons
POST /api/v1/coupons Admin Create coupon
PUT /api/v1/coupons/:id Admin Update coupon
DELETE /api/v1/coupons/:id Admin Delete coupon

Shipping

Method Path Access Description
GET /api/v1/shipping/methods Public Get active shipping methods
POST /api/v1/shipping/estimate JWT Estimate shipping cost
GET /api/v1/shipping/track/:trackingNumber JWT Get mock tracking information

Admin Dashboard

Method Path Access Description
GET /api/v1/admin/stats/overview Admin Get overview metrics
GET /api/v1/admin/stats/revenue?range=daily|weekly|monthly Admin Get grouped revenue data
GET /api/v1/admin/stats/top-products Admin Get top selling products
GET /api/v1/admin/stats/recent-orders Admin Get latest orders

Notes on Current Local Runtime

During local setup in this workspace:

  • the app was successfully started against Dockerized PostgreSQL
  • Swagger was verified at http://localhost:3001/api/docs
  • local .env currently uses port 3001 to avoid a conflict with another container already using 3000

That local override is not required for every environment. Use whatever PORT fits your machine.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages