Skip to content

Repository files navigation

🛒 E-Commerce API

A robust, scalable RESTful API for a full-featured e-commerce platform, built with NestJS, TypeORM, and PostgreSQL. Provides complete backend services including authentication, product management, shopping cart, order processing, Stripe payments, reviews, favourites, coupons, and more.

📖 Live Swagger Docs


📋 Table of Contents


✨ Features

FeatureDescription
🔐 AuthenticationRegister, login, logout, and token refresh with JWT + Passport.js
🔑 Password ManagementForgot password, reset via email OTP, and authenticated password change
👥 User ManagementProfile view/update, admin user listing, role-based access (User, Manager, Admin)
📦 ProductsFull CRUD with image upload (Cloudinary), pagination, filtering by category/price/search
🗂️ CategoriesCreate, list, update, and delete product categories
🛒 CartAdd/remove/update items, view cart — all scoped to the authenticated user
📋 OrdersPlace orders from cart, view order history, filter by status, cancel orders
💳 Stripe PaymentsCreate payment intents for orders, Stripe webhook for payment confirmation
ReviewsCreate, read, update, and delete product reviews with pagination
❤️ FavouritesAdd/remove products to a personal wishlist
🎟️ CouponsAdmin-managed discount coupons with CRUD operations
📧 Email ServiceTransactional emails (password reset) via Nodemailer
☁️ Image HostingCloudinary integration for product image upload and CDN delivery
📖 API DocsAuto-generated interactive Swagger/OpenAPI documentation
ValidationRequest body validation with class-validator and DTO whitelisting
🐳 DockerDockerfile and docker-compose for containerized deployment with PostgreSQL

🛠️ Tech Stack

TechnologyVersionPurpose
NestJS10.xProgressive Node.js framework
TypeORM0.3.xORM for PostgreSQL
PostgreSQLLatestRelational database
Passport.jsAuthentication middleware
JWTToken-based auth (access + refresh tokens)
Swagger/OpenAPI7.xInteractive API documentation
Stripe16.xPayment processing + webhooks
Cloudinary2.xImage upload and CDN
Nodemailer6.xEmail delivery
class-validator0.14.xDTO validation
bcrypt5.xPassword hashing
DockerContainerization

🏛️ Architecture

The API follows NestJS's modular architecture. Each domain feature is a self-contained module with its own controller, service, DTOs, entities, and guards.

 ┌─────────────────────┐
│ Client / Frontend │
└──────────┬──────────┘
│ HTTP
┌──────────▼──────────┐
│ NestJS Application │
│ (Global Prefix: │
│ /api/v1) │
├─────────────────────┤
│ Middleware │
│ ┌─ CORS │
│ ├─ ValidationPipe │
│ └─ ClassSerializer │
├─────────────────────┤
│ Modules │
│ ┌── Auth + JWT │
│ ├── User │
│ ├── Products │
│ ├── Categories │
│ ├── Cart │
│ ├── Order │
│ ├── Payment (Stripe)│
│ ├── Review │
│ ├── Favourite │
│ ├── Coupons │
│ ├── Cloudinary │
│ └── Email │
└──────────┬──────────┘
│
┌─────────────────┼─────────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼───────┐ ┌───────▼──────┐
│ PostgreSQL │ │ Cloudinary │ │ Stripe │
│ (TypeORM) │ │ (Images) │ │ (Payments) │
└─────────────┘ └──────────────┘ └──────────────┘

📁 Project Structure

backend/
├── src/
│ ├── main.ts # App bootstrap, CORS, Swagger, global pipes
│ ├── app.module.ts # Root module — imports all feature modules
│ ├── decorator/ # Custom decorators
│ │ ├── GetUser.decorator.ts # Extract user from JWT payload
│ │ ├── role.decorator.ts # @Roles() decorator for RBAC
│ │ └── queryArray.decorator.ts # @ApiQueryArray() for Swagger docs
│ ├── utils/ # Shared utility functions
│ └── modules/
│ ├── auth/ # Authentication & authorization
│ │ ├── auth.controller.ts # POST /register, /login, /refresh, /log-out
│ │ ├── auth.service.ts # Auth business logic, bcrypt, JWT signing
│ │ ├── password.controller.ts # POST /forgot-password, /reset-*-password
│ │ ├── password.service.ts # Password reset flow with email OTP
│ │ ├── dto/ # LoginDto, ForgotPasswordDto, ResetPasswordDto, JwtPayload
│ │ ├── enums/
│ │ │ └── role.enum.ts # Role.USER | Role.MANAGER | Role.ADMIN
│ │ ├── guards/
│ │ │ ├── jwt.guard.ts # Passport JWT guard
│ │ │ └── role.guard.ts # Role-based access guard
│ │ └── strategy/ # Passport JWT strategy
│ │
│ ├── user/ # User management
│ │ ├── user.controller.ts # GET /users, /users/profile, /users/find/:id
│ │ ├── user.service.ts # User CRUD, profile operations
│ │ ├── dto/ # CreateUserDto, UpdateProfileDto
│ │ └── entities/ # User entity (TypeORM)
│ │
│ ├── products/ # Product catalog
│ │ ├── products.controller.ts # CRUD + pagination, filtering, search, image upload
│ │ ├── products.service.ts # Product business logic
│ │ ├── dto/ # CreateProductDto, UpdateProductDto
│ │ └── entities/ # Product entity
│ │
│ ├── categories/ # Product categories
│ │ ├── categories.controller.ts # Full CRUD for categories
│ │ ├── categories.service.ts
│ │ ├── dto/ # CreateCategoryDto, UpdateCategoryDto
│ │ └── entities/ # Category entity
│ │
│ ├── cart/ # Shopping cart
│ │ ├── cart.controller.ts # CRUD — all routes require JWT auth
│ │ ├── cart.service.ts # Cart business logic (user-scoped)
│ │ ├── dto/ # CreateCartDto, UpdateCartItemDto
│ │ └── entities/ # Cart / CartItem entities
│ │
│ ├── order/ # Order processing
│ │ ├── order.controller.ts # Create, list (paginated + status filter), cancel
│ │ ├── order.service.ts # Order workflow, status management
│ │ ├── dto/ # CreateOrderDto, UpdateOrderDto
│ │ ├── entities/ # Order entity
│ │ └── enums/
│ │ └── order-status.enum.ts # inProcess | shipped | cancel | success
│ │
│ ├── payment/ # Stripe payment integration
│ │ ├── payment.controller.ts # POST /payments/create, /payments/webhook
│ │ ├── payment.service.ts # Stripe payment intent creation + webhook handler
│ │ └── payment.module.ts
│ │
│ ├── review/ # Product reviews
│ │ ├── review.controller.ts # CRUD + paginated listing per product
│ │ ├── review.service.ts
│ │ ├── dto/ # CreateReviewDto, UpdateReviewDto
│ │ └── entities/ # Review entity
│ │
│ ├── favourite/ # Wishlist / Favourites
│ │ ├── favourite.controller.ts # Add, list, remove — user-scoped
│ │ ├── favourite.service.ts
│ │ ├── dto/ # CreateFavouriteDto
│ │ └── entities/ # Favourite entity
│ │
│ ├── coupons/ # Discount coupons (Admin only)
│ │ ├── coupons.controller.ts # Full CRUD — Admin role required
│ │ ├── coupons.service.ts
│ │ ├── dto/ # CreateCouponDto, UpdateCouponDto
│ │ └── entities/ # Coupon entity
│ │
│ ├── cloudinary/ # Image upload service
│ │ └── cloudinary.module.ts # Cloudinary SDK configuration
│ │
│ ├── email/ # Email service
│ │ └── ... # Nodemailer transporter (Gmail/SMTP)
│ │
│ ├── jwt/ # Global JWT module
│ │ └── jwt.module.ts # JwtModule.registerAsync (global)
│ │
│ └── DB/ # Database configuration
│ ├── DB.module.ts # TypeOrmModule.forRootAsync
│ ├── data-source.ts # TypeORM DataSource for CLI migrations
│ └── migrations/ # Database migration files
│
├── test/ # E2E tests
├── Dockerfile # Node 20 multi-stage build
├── docker-compose.yml # App + PostgreSQL services
├── .env.example # Environment variable template
├── tsconfig.json
└── package.json

🚀 Getting Started

Prerequisites

  • Node.js ≥ 20
  • pnpm (recommended) or npm
  • PostgreSQL ≥ 14 (or use Docker)
  • A Stripe account (for payment features)
  • A Cloudinary account (for image uploads)
  • A Gmail account or SMTP service (for emails)

Installation

# Clone the repository
git clone https://github.com/DevBassel/e-store-API.git
cd backend
# Install dependencies
pnpm install
# Copy and configure environment variables
cp .env.example .env
# Edit .env with your credentials (see Environment Variables section)# Start in development mode (hot-reload)
pnpm run start:dev

The API server starts on http://localhost:4000 (or your configured PORT). Swagger documentation is available at http://localhost:4000/api.

Seed the Database

Populate the database with sample data using Faker.js:

pnpm run seeding

🔐 Environment Variables

Create a .env file in the project root using .env.example as a template:

# Server ConfigurationPORT=4000HOST=http://localhost:4000NODE_ENV=dev# Options: dev, prod# Database ConfigurationDB_HOST=localhostDB_PORT=5432DB_NAME=e_commerceDB_USERNAME=postgresDB_PASSWORD=rootDB_Sync=true# Auto-sync schema (dev only!)# JWT ConfigurationJWT_KEY=your_jwt_secret_key# Email Configuration (Gmail App Password or SMTP)EMAIL_USER=your_email@gmail.comEMAIL_SK=your_email_app_password# Cloudinary ConfigurationCLOUD_NAME=your_cloudinary_cloud_nameCLOUD_API_KEY=your_cloudinary_api_keyCLOUD_API_SECRET=your_cloudinary_api_secret# Stripe ConfigurationSTRIPE_SK=your_stripe_secret_keySTRIPE_WEEBHOOK_SK=your_stripe_webhook_secret

⚠️Warning: Set DB_Sync=false in production. Use migrations instead.


📖 API Reference

All endpoints are prefixed with /api/v1. Interactive documentation is available via Swagger at /api.

Auth (/api/v1/auth)

MethodEndpointAuthDescription
POST/auth/registerRegister a new user
POST/auth/loginLogin and receive JWT tokens
POST/auth/refreshRefresh access token
POST/auth/log-out🔒Logout (invalidate refresh token)

Password Management (/api/v1/auth)

MethodEndpointAuthDescription
POST/auth/forgot-passwordSend password reset email
POST/auth/reset-forgot-passwordReset password via email token
POST/auth/reset-password🔒Change password (authenticated)

Users (/api/v1/users)

MethodEndpointAuthDescription
GET/users🔒 AdminList all users (paginated)
GET/users/profile🔒Get authenticated user's profile
PATCH/users/profile🔒Update profile
GET/users/find/:userId🔒Find a user by ID

Products (/api/v1/products)

MethodEndpointAuthDescription
POST/products🔒 Admin/ManagerCreate product (multipart/form-data with image)
GET/productsList products (paginated, filterable)
GET/products/:idGet product details
PATCH/products/:id🔒Update product
DELETE/products/:id🔒 Admin/ManagerDelete product

Query Parameters for GET /products:

ParamTypeDefaultDescription
pagenumber1Page number
limitnumber10Items per page
categorystringFilter by category
minnumber0Minimum price
maxnumber1,000,000Maximum price
sstringSearch term

Categories (/api/v1/categories)

MethodEndpointAuthDescription
POST/categoriesCreate a category
GET/categoriesList all categories
GET/categories/:idGet category by ID
PATCH/categories/:idUpdate category
DELETE/categories/:idDelete category

Cart (/api/v1/cart)

MethodEndpointAuthDescription
POST/cart🔒Add item to cart
GET/cart🔒Get user's cart
GET/cart/:id🔒Get specific cart item
PATCH/cart/:id🔒Update cart item quantity
DELETE/cart/:id🔒Remove item from cart

Orders (/api/v1/orders)

MethodEndpointAuthDescription
POST/orders🔒Create order from cart
GET/orders🔒List orders (paginated, status filter)
GET/orders/:id🔒Get order details
GET/orders/me🔒Get current user's orders
PATCH/orders/:id🔒Update order
DELETE/orders/:id🔒Cancel order

Order Statuses: inProcessshippedsuccess | cancel

Payments (/api/v1/payments)

MethodEndpointAuthDescription
POST/payments/create🔒Create Stripe payment intent for an order
POST/payments/webhookStripe webhook endpoint (signature verified)

Reviews (/api/v1/reviews)

MethodEndpointAuthDescription
POST/reviews🔒Create a review
GET/reviews/:productIdList reviews for a product (paginated)
GET/reviews/:id/viewGet single review
PATCH/reviews/:id🔒Update a review
DELETE/reviews/:id🔒Delete a review

Favourites (/api/v1/favourite)

MethodEndpointAuthDescription
POST/favourite🔒Add product to favourites
GET/favourite🔒List user's favourites
GET/favourite/:id🔒Get specific favourite
DELETE/favourite/:id🔒Remove from favourites

Coupons (/api/v1/coupons)

MethodEndpointAuthDescription
POST/coupons🔒 AdminCreate coupon
GET/coupons🔒 AdminList coupons (paginated)
GET/coupons/:id🔒 AdminGet coupon details
PATCH/coupons/:id🔒 AdminUpdate coupon
DELETE/coupons/:id🔒 AdminDelete coupon

🛡️ Authorization & Roles

The API uses a role-based access control (RBAC) system with three roles:

RoleValuePermissions
UseruserDefault role. Can manage own cart, orders, reviews, favourites, and profile
ManagermanagerCan create, update, and delete products
AdminadminFull access — user management, product management, coupon management

Guards applied:

  • JwtGuard — Validates the Bearer JWT token from the Authorization header
  • RoleGuard — Checks the user's role against the @Roles() decorator on the endpoint

🗃️ Database

TypeORM Configuration

The database connection is configured via environment variables and managed by TypeORM:

  • Entities are auto-discovered from each module's entities/ directory
  • Synchronization (DB_Sync=true) auto-creates/updates tables from entities (dev only)
  • Migrations are stored in src/modules/DB/migrations/

Migration Commands

# Generate a migration from entity changes
pnpm run migration:generate -- src/modules/DB/migrations/MigrationName
# Run pending migrations
pnpm run migration:run
# Revert the last migration
pnpm run migration:revert

🐳 Docker

Docker Compose (Recommended)

Spins up the API and PostgreSQL together:

docker-compose up -d

Services:

ServiceImagePort
appBuilt from Dockerfile3000
postgrespostgres:latest5432

Standalone Docker Build

# Build the image
docker build -t e-commerce-api .# Run the container
docker run -p 4000:4000 --env-file .env e-commerce-api

🧪 Testing

# Unit tests
pnpm run test# Watch mode
pnpm run test:watch
# Coverage report
pnpm run test:cov
# E2E tests
pnpm run test:e2e
# Debug tests
pnpm run test:debug

📜 Scripts

ScriptCommandDescription
start:devpnpm run start:devDevelopment server with hot-reload
start:prodpnpm run start:prodProduction server (compiled JS)
buildpnpm run buildCompile TypeScript via NestJS CLI
seedingpnpm run seedingSeed database with sample data
migration:generatepnpm run migration:generateGenerate new migration
migration:runpnpm run migration:runExecute pending migrations
migration:revertpnpm run migration:revertRevert last migration
webhookpnpm run webhookForward Stripe webhooks locally
testpnpm run testRun unit tests
test:e2epnpm run test:e2eRun end-to-end tests
test:covpnpm run test:covGenerate coverage report
lintpnpm run lintLint and auto-fix with ESLint
formatpnpm run formatFormat code with Prettier

📄 License

This project is UNLICENSED — private use only.

Releases

Packages

Used by

Contributors

Languages