Skip to content

TheSamadAzeez/nexus-backend

Repository files navigation

Nexus E-commerce Backend API

NestJS TypeScript PostgreSQL Redis Drizzle Docker

A production-ready e-commerce backend API built with modern technologies, featuring JWT authentication, role-based access control, Redis caching, rate limiting, and comprehensive Swagger documentation.


πŸ“‘ Table of Contents


✨ Features

Feature Description
πŸ” JWT Authentication Secure authentication with access + refresh token strategy
πŸ‘₯ Role-Based Access Control Admin and User roles with granular permissions
πŸ“¦ Product Management Full CRUD with cursor-based pagination and advanced filtering
πŸ›’ Shopping Cart Add, update, remove items with real-time stock validation
πŸ“‹ Order Management Create orders from cart, view order history
πŸ’³ Checkout Flow Mock payment processing for demonstration
⚑ Redis Caching Lightning-fast responses with intelligent cache invalidation
πŸ›‘οΈ Rate Limiting Multi-tier request throttling for API protection
πŸ“– API Documentation Interactive Swagger/OpenAPI documentation

πŸ›  Tech Stack & Architecture Decisions

Why NestJS?

NestJS was chosen as the framework for several compelling reasons:

  • TypeScript-first: Full type safety out of the box, reducing runtime errors
  • Modular Architecture: Clean separation of concerns with modules, controllers, and services
  • Dependency Injection: Built-in DI container for testable, maintainable code
  • Decorator-based: Familiar patterns for developers coming from Angular or Java/Spring
  • Rich Ecosystem: First-class support for OpenAPI, validation, caching, and more

Why Drizzle ORM?

I chose Drizzle ORM over alternatives like Prisma or TypeORM for the following reasons:

Aspect Drizzle Advantage
Type Safety SQL-like syntax with full TypeScript inference - you write SQL, get type safety
Performance Lightweight with zero dependencies, minimal runtime overhead
Flexibility Direct SQL when needed, no "magic" - what you write is what runs
Bundle Size Significantly smaller than Prisma (~7KB vs ~300KB)
No Code Generation Schema-as-code approach - no prisma generate step needed
Drizzle Studio Built-in visual database browser (pnpm db:studio)

Why PostgreSQL?

  • ACID Compliance: Reliable transactions for e-commerce operations
  • JSON Support: Native JSONB for flexible data structures
  • Scalability: Handles high-volume concurrent operations
  • Ecosystem: Excellent tooling and community support

Why Redis for Caching?

  • Speed: In-memory data store with sub-millisecond latency
  • Persistence: Optional data persistence for cache survival
  • TTL Support: Automatic cache expiration management
  • Production Ready: Battle-tested in high-traffic applications

πŸ“‹ Prerequisites

Before you begin, ensure you have the following installed:

  • Node.js v18.0.0 or higher (Download)
  • pnpm v8.0.0 or higher (npm install -g pnpm)
  • Docker & Docker Compose (Download)
  • Git for version control

πŸš€ Complete Setup Guide

Follow these steps to get the project running locally:

Step 1: Clone the Repository

git clone https://github.com/TheSamadAzeez/nexus-backend.git
cd nexus-backend

Step 2: Install Dependencies

pnpm install

Step 3: Configure Environment Variables

Create your environment file from the template:

cp .env.example .env

Edit the .env file with your preferred settings (see Environment Variables section).

Step 4: Start Docker Services

This starts PostgreSQL and Redis containers:

docker-compose up -d

Verify containers are running:

docker-compose ps

You should see both nexus-postgres and nexus-redis with status Up.

Step 5: Push Database Schema

Apply the database schema to PostgreSQL:

pnpm db:push

Step 6: Seed the Database (Recommended)

Populate the database with sample data including test users and products:

pnpm db:seed

This creates:

  • Admin User: admin@nexus.com / admin123
  • Test User: user@nexus.com / user123
  • 33 Sample Products across categories: Electronics, Footwear, Clothing, Accessories, Watches, Gaming

To create your own admin user account:

pnpm db:create-admin

For more info on creating an admin user, see the Creating Admin Users section below.

Step 7: Start the Development Server

pnpm start:dev

The API will be available at http://localhost:3000

Step 8: Access API Documentation

Open your browser and navigate to:

http://localhost:3000/api

πŸŽ‰ You're all set! The Swagger UI provides interactive documentation for all endpoints.


πŸ”§ Environment Variables

Create a .env file in the project root with the following variables:

# Database Configuration
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_USER=admin
POSTGRES_PASSWORD=admin
POSTGRES_DB=nexus

# Redis Configuration
REDIS_HOST=localhost
REDIS_PORT=6379

# JWT Configuration
JWT_SECRET=your-super-secret-jwt-key-change-in-production
JWT_EXPIRES_IN=15m
JWT_REFRESH_SECRET=your-super-secret-refresh-key-change-in-production
JWT_REFRESH_EXPIRES_IN=7d

# Application Configuration
PORT=3000
NODE_ENV=development

Environment Variable Details

Variable Description Default Required
POSTGRES_HOST PostgreSQL server hostname localhost Yes
POSTGRES_PORT PostgreSQL server port 5432 Yes
POSTGRES_USER Database username admin Yes
POSTGRES_PASSWORD Database password admin Yes
POSTGRES_DB Database name nexus Yes
REDIS_HOST Redis server hostname localhost Yes
REDIS_PORT Redis server port 6379 Yes
JWT_SECRET Secret key for access tokens - Yes
JWT_EXPIRES_IN Access token expiration time 15m Yes
JWT_REFRESH_SECRET Secret key for refresh tokens - Yes
JWT_REFRESH_EXPIRES_IN Refresh token expiration time 7d Yes
PORT Server port 3000 No
NODE_ENV Environment mode development No

⚠️ Security Note: Always use strong, unique secrets in production. Never commit .env files to version control.


πŸ—„οΈ Database Management

Viewing the Database (Drizzle Studio)

Drizzle comes with a built-in visual database browser. To explore your data:

pnpm db:studio

This opens Drizzle Studio in your browser at https://local.drizzle.studio where you can:

  • Browse all tables and their data
  • Execute queries
  • View and edit records
  • Understand table relationships

Database Schema

The database consists of the following tables:

Table Description
users User accounts with roles (ADMIN, USER)
products Product catalog with categories
carts User shopping carts
cart_items Items in shopping carts
orders Order records
order_items Items in orders

Pushing Schema Changes

After modifying schemas in src/database/schemas/, apply changes:

pnpm db:push

Re-seeding the Database

To reset and re-seed the database:

# Drop and recreate schema (use with caution!)
docker-compose down -v
docker-compose up -d
pnpm db:push
pnpm db:seed

πŸ‘¨β€πŸ’Ό Creating Admin Users

⚠️ IMPORTANT: This is an interactive CLI command that runs in your terminal!

To create additional admin users, use the built-in CLI script:

pnpm db:create-admin

What to Expect

The script will interactively prompt you for:

πŸ” Create Admin User

========================================
Email: newadmin@example.com
Name: John Admin
Password (min 8 characters): ********
Confirm Password: ********

⏳ Creating admin user...

βœ… Admin user created successfully!
========================================
ID:    550e8400-e29b-41d4-a716-446655440000
Email: newadmin@example.com
Name:  John Admin
Role:  ADMIN
========================================

πŸŽ‰ Done!

Validation Rules

  • Email: Must be a valid email format
  • Name: Required, cannot be empty
  • Password: Minimum 8 characters
  • Confirmation: Passwords must match

Use Cases

  • Creating initial admin accounts in production
  • Adding new team members with admin privileges
  • Recovering admin access without database manipulation

πŸ“– API Documentation

Swagger/OpenAPI

Once the server is running, comprehensive API documentation is available at:

http://localhost:3000/api

Features:

  • Interactive endpoint testing
  • Request/response schemas
  • Authentication support (JWT Bearer)
  • Model definitions

Testing with Swagger UI

  1. Navigate to http://localhost:3000/api
  2. Click "Authorize" button
  3. Login via /auth/login endpoint to get a token
  4. Paste the accessToken in the authorization field
  5. Test authenticated endpoints

⚑ Caching Strategy

How Caching Works

The API uses Redis as a caching layer via @nestjs/cache-manager with cache-manager-ioredis-yet.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      Request Flow                           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                             β”‚
β”‚   Request  ──►  Cache Check  ──►  Cache Hit? ──► Response   β”‚
β”‚                     β”‚                  β”‚                    β”‚
β”‚                     β”‚ No               β”‚ Yes                β”‚
β”‚                     β–Ό                  β”‚                    β”‚
β”‚               Database Query           β”‚                    β”‚
β”‚                     β”‚                  β”‚                    β”‚
β”‚                     β–Ό                  β”‚                    β”‚
β”‚               Store in Cache β—„β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β”‚
β”‚                     β”‚                                       β”‚
β”‚                     β–Ό                                       β”‚
β”‚                 Response                                    β”‚
β”‚                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Configuration

Located in src/app.module.ts:

CacheModule.registerAsync({
  isGlobal: true,
  useFactory: async (configService: ConfigService) => ({
    store: await redisStore({
      host: configService.get('REDIS_HOST', 'localhost'),
      port: configService.get('REDIS_PORT', 6379),
    }),
    ttl: 60000, // 60 seconds default TTL
  }),
}),

Cache Behavior

Aspect Value
Store Redis
Default TTL 60 seconds
Scope Global (available to all modules)
Connection Automatic via environment variables

Why Redis for Caching?

  • Performance: Sub-millisecond read/write operations
  • Shared Cache: All server instances share the same cache (horizontal scaling ready)
  • Persistence: Cache survives server restarts (if configured)
  • TTL Management: Automatic expiration handling

πŸ›‘οΈ Rate Limiting

How Rate Limiting Works

The API implements multi-tier rate limiting using @nestjs/throttler to protect against abuse:

Rate Limit Tiers

Tier Time Window Max Requests Purpose
Short 1 second 3 requests Prevents rapid-fire requests
Medium 10 seconds 20 requests Limits burst traffic
Long 60 seconds 100 requests Overall usage cap

Implementation

// src/app.module.ts
ThrottlerModule.forRoot([
  {
    name: 'short',
    ttl: 1000,     // 1 second
    limit: 3,
  },
  {
    name: 'medium',
    ttl: 10000,    // 10 seconds
    limit: 20,
  },
  {
    name: 'long',
    ttl: 60000,    // 60 seconds
    limit: 100,
  },
]),

Response on Rate Limit Exceeded

When you exceed the rate limit, you'll receive:

{
  "statusCode": 429,
  "message": "ThrottlerException: Too Many Requests"
}

Rate Limit Headers

Responses include headers showing your current rate limit status:

  • X-RateLimit-Limit: Maximum requests allowed
  • X-RateLimit-Remaining: Requests remaining in current window
  • X-RateLimit-Reset: Time until the limit resets

πŸ“ Project Structure

nexus-backend/
β”œβ”€β”€ πŸ“ src/
β”‚   β”œβ”€β”€ πŸ“ auth/              # Authentication module
β”‚   β”‚   β”œβ”€β”€ dto/              # Data transfer objects
β”‚   β”‚   β”œβ”€β”€ guards/           # JWT & Roles guards
β”‚   β”‚   β”œβ”€β”€ strategies/       # Passport JWT strategy
β”‚   β”‚   └── auth.service.ts   # Auth business logic
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“ users/             # User management module
β”‚   β”‚   β”œβ”€β”€ dto/
β”‚   β”‚   └── users.service.ts
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“ products/          # Product catalog module
β”‚   β”‚   β”œβ”€β”€ dto/              # Create, Update, Query DTOs
β”‚   β”‚   └── products.service.ts
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“ cart/              # Shopping cart module
β”‚   β”‚   β”œβ”€β”€ dto/
β”‚   β”‚   └── cart.service.ts
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“ orders/            # Order management module
β”‚   β”‚   β”œβ”€β”€ dto/
β”‚   β”‚   └── orders.service.ts
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“ checkout/          # Payment processing module
β”‚   β”‚   └── checkout.service.ts
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“ common/            # Shared utilities
β”‚   β”‚   β”œβ”€β”€ decorators/       # Custom decorators (@Public, @Roles)
β”‚   β”‚   β”œβ”€β”€ filters/          # Exception filters
β”‚   β”‚   └── interceptors/     # Logging interceptor
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“ database/          # Database layer
β”‚   β”‚   β”œβ”€β”€ schemas/          # Drizzle table schemas
β”‚   β”‚   β”œβ”€β”€ database.module.ts
β”‚   β”‚   └── drizzle.service.ts
β”‚   β”‚
β”‚   β”œβ”€β”€ app.module.ts         # Root module
β”‚   └── main.ts               # Application entry point
β”‚
β”œβ”€β”€ πŸ“ scripts/
β”‚   └── create-admin.ts       # Admin user creation CLI
β”‚
β”œβ”€β”€ πŸ“„ seed.ts                # Database seeding script
β”œβ”€β”€ πŸ“„ docker-compose.yml     # Docker services config
β”œβ”€β”€ πŸ“„ drizzle.config.ts      # Drizzle configuration
β”œβ”€β”€ πŸ“„ .env.example           # Environment template
└── πŸ“„ package.json           # Dependencies & scripts

πŸ“‘ API Endpoints Reference

Authentication

Method Endpoint Description Access
POST /auth/register Register new user Public
POST /auth/login Login & get tokens Public
POST /auth/logout Logout user Authenticated

Products

Method Endpoint Description Access
GET /products List products (cursor-paginated) Public
GET /products/:id Get product by ID Public
GET /products/categories Get all categories Public
POST /products Create product Admin
PATCH /products/:id Update product Admin
DELETE /products/:id Delete product Admin

Product Query Parameters

Parameter Type Description
cursor string Pagination cursor (product ID)
limit number Results per page (default: 10)
category string Filter by category
search string Search in product name
minPrice number Minimum price filter
maxPrice number Maximum price filter

Cart

Method Endpoint Description Access
GET /cart Get user's cart Authenticated
POST /cart/items Add item to cart Authenticated
PATCH /cart/items/:id Update item quantity Authenticated
DELETE /cart/items/:id Remove item from cart Authenticated
DELETE /cart Clear entire cart Authenticated

Orders

Method Endpoint Description Access
POST /orders Create order from cart Authenticated
GET /orders Get order history Authenticated
GET /orders/:id Get order details Authenticated

Checkout

Method Endpoint Description Access
POST /checkout/pay Process payment (mock) Authenticated

πŸ”§ Scripts Reference

# Development
pnpm start:dev     # Start development server with hot reload
pnpm start:debug   # Start with debugger attached

# Production
pnpm build         # Build for production
pnpm start:prod    # Run production build

# Database
pnpm db:push       # Push schema changes to database
pnpm db:seed       # Seed database with sample data
pnpm db:studio     # Open Drizzle Studio (visual DB browser)
pnpm db:create-admin  # Create new admin user (interactive)

# Code Quality
pnpm lint          # Run ESLint
pnpm format        # Format code with Prettier

# Testing
pnpm test          # Run unit tests
pnpm test:watch    # Run tests in watch mode
pnpm test:cov      # Generate test coverage report
pnpm test:e2e      # Run end-to-end tests

πŸ“¦ Submission & Deployment

Repository

GitHub: https://github.com/TheSamadAzeez/nexus-backend

What's Included

Item Status Description
πŸ“– API Documentation (Swagger) βœ… Available at /api endpoint
πŸ“„ README with Setup Instructions βœ… This document
πŸ”§ Sample .env File βœ… .env.example included
πŸ—„οΈ Database Schema/Migrations βœ… Drizzle schemas in src/database/schemas/

Docker Services

The application uses Docker Compose for local development:

Service Container Name Port Purpose
PostgreSQL nexus-postgres 5432 Primary database
Redis nexus-redis 6379 Caching layer

Quick Access URLs

Resource URL
API Server http://localhost:3000
Swagger Documentation http://localhost:3000/api
Drizzle Studio https://local.drizzle.studio

πŸ“ Default Test Credentials

After running pnpm db:seed, the following users are available:

Email Password Role
admin@nexus.com admin123 ADMIN
user@nexus.com user123 USER

🀝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.


Built with ❀️ using NestJS, Drizzle ORM, PostgreSQL, and Redis

About

No description or website provided.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors