Skip to content
PanchalKeyur0806Public

About

A BookStore REST API built to manage bookstore operations through structured HTTP endpoints. Designed to handle book data and CRUD operations, this project demonstrates backend development, API design, request handling, and data management, providing a foundation for integrating bookstore functionality into web applications.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

📚 BookStore API – Node.js Backend

A production-grade, eCommerce-style backend built with Node.js, Express, and MongoDB, designed using the MVC architecture. It features authentication, multi-provider email verification (Nodemailer & Resend), Stripe payments & webhooks, order processing, in-memory Redis caching (15-minute TTL), BullMQ background queues, Cloudinary media storage, and comprehensive analytics — ideal for developers building scalable, real-world applications.


📄 API Documentation

  • 🌐 Interactive Redoc API Documentation: Served locally at http://localhost:8002/ (built with OpenAPI 3.1 & Redoc)
  • 📎 Postman API Documentation: View Postman Documentation
  • 📜 OpenAPI Specifications: Multi-file OpenAPI 3.1 definitions located in /docs (openapi.yaml, admin.yaml, auth.yaml, book.yaml, cart.yaml, order.yaml, review.yaml, user.yaml, wishlist.yaml, schema.yaml)
  • 🛠️ CLI Documentation Commands:
    • npm run doc:bundle – Bundles modular YAML specs into docs/bundle/openapi.yaml
    • npm run doc:build – Builds standalone HTML documentation to docs/apidoc.html

🚀 Features

🔐 Authentication & Security

  • ✅ JWT-based User & Admin Authentication
  • ✅ Multi-Provider Email OTP Verification (Nodemailer Gmail SMTP & Resend API with 1-minute expiration window)
  • ✅ Automatic Admin Account Seeding on Server Startup (seeds/initilizeAdmin.js)
  • ✅ Role-Based Access Control (RBAC) with Self-Protection Guards
  • ✅ Account Activation & Suspension Management (/admin/activateUser, /admin/deactivateUser)
  • ✅ Role Modification & Promotion/Demotion (/admin/change-role)
  • ✅ Multi-tier API Rate Limiting (Read, Mutation, Auth, General)
  • ✅ Input & Parameter Validation (validateUser, validateId)
  • ✅ Secure Environment-based Configuration
  • ✅ Centralized Error Handling & Operational Exceptions

📚 Book Management

  • ✅ Complete CRUD Operations for Books
  • ✅ Book Review & Rating System with Dynamic Recalculation
  • ✅ Wishlist Management
  • ✅ Advanced Filtering, Search, Sorting & Pagination
  • ✅ Soft-deletion preserving historical order records

🛒 Cart & Orders

  • ✅ Shopping Cart Management with Redis Caching (15-minute TTL)
  • ✅ Complete Order Management & Stripe Checkout Sessions
  • ✅ Real-time Inventory Reservation & Restocking
  • ✅ 7-Day Refund Window Policy & Automated Stripe Refunds
  • ✅ BullMQ Queue System for Background Order & Email Processing

💳 Payments & Invoices

  • ✅ Stripe Payment Integration (Checkout Sessions & Webhooks)
  • ✅ Payment Status Tracking (pending, paid, refunded, failed)
  • ✅ Automated PDF Invoice Generation

📊 Admin Dashboard & Analytics

  • ✅ Admin Dashboard with Key Business Metrics
  • ✅ Sales & Revenue Analytics (Daily, Weekly, Monthly, Yearly)
  • ✅ Order Analytics & Order Growth Tracking
  • ✅ Average Order Value (AOV) Analytics
  • ✅ Book Performance, Sales & Revenue Analytics
  • ✅ Inventory & Stock Analytics (Low-stock & Dead stock detection)
  • ✅ Category-wise Sales & Revenue Trends
  • ✅ Book Rating Distribution Analytics
  • ✅ Customer Analytics & Top Spenders
  • ✅ Payment Analytics (Stripe status volume & rates)

⚡ Performance, Caching & Background Processing

  • ✅ Redis In-Memory Caching (15-minute TTL): Cache-aside strategy on Book details, Customer Carts, Orders, and Personal Reviews
  • ✅ BullMQ Distributed Queue System: Background worker processing for orders and automated emails
  • ✅ Multi-Provider Email Dispatching: Seamlessly switch between Gmail SMTP and Resend API (EMAIL_PROVIDER)

🏗️ Architecture & Code Quality

  • ✅ Clean MVC Project Structure
  • ✅ Modular & Maintainable Codebase
  • ✅ Centralized Error Handling (AppError & catchAsync)
  • ✅ Secure Configuration Management with environment validation

📁 Project Structure

BookStore/
├── config/             # Database and Redis client configuration (redisClient.js)
├── controllers/        # Express route controllers (MVC)
│   ├── adminController.js
│   ├── authController.js
│   ├── booksController.js
│   ├── cartController.js
│   ├── errorController.js
│   ├── orderController.js
│   ├── reviewController.js
│   ├── userController.js
│   └── wishlistController.js
├── docs/               # Multi-file OpenAPI 3.1 specifications & Redoc docs
├── middlewares/        # Authentication (protect, restrictTo), rate limiters, validators
├── models/             # Mongoose schemas & models (User, Books, Cart, Order, Review, Wishlist)
├── queues/             # BullMQ queue definitions (emailQueue.js, orderQueue.js)
├── routes/             # Express API route declarations
├── seeds/              # Database seed scripts (initilizeAdmin.js, userSeeds.js, reviewSeeds.js)
├── services/           # External service integrations (Stripe, Cloudinary)
├── utils/              # Helper utilities & email templates
│   ├── validateEnv.js  # Startup environment variable validation & diagnostics
│   ├── sendEmail.js    # Multi-provider email dispatcher (replaces nodemailer.js)
│   ├── AppError.js
│   ├── AppFeatures.js
│   ├── catchAsync.js
│   ├── generateInvoice.js
│   ├── otpGenerator.js
│   └── emailTemplates/ # HTML templates (verification OTP, password reset, order confirmation)
├── workers/            # BullMQ background workers (emailWorker.js, orderWorker.js)
├── .env                # Environment variables
├── package.json
├── server.js           # Main application entry point & Express server
└── README.md

🛠️ Tech Stack

  • Runtime: Node.js 22+
  • Framework: Express.js 5.x
  • Database: MongoDB + Mongoose
  • Authentication: JWT (JSON Web Tokens) + Bcrypt
  • Email: Nodemailer (Gmail SMTP) & Resend API (configurable via EMAIL_PROVIDER)
  • Payments: Stripe (Checkout Sessions & Webhooks)
  • Image Storage: Cloudinary
  • In-Memory Caching: Redis (ioredis, 15-minute TTL cache-aside pattern)
  • Background Jobs: BullMQ + Redis
  • API Documentation: OpenAPI 3.1 + Redocly + Postman
  • Architecture: MVC (Model-View-Controller)

📋 Requirements

Before running the project, make sure you have:

  • Node.js: v22 or higher
  • MongoDB: Local MongoDB instance or MongoDB Atlas cluster
  • Redis: Local Docker container or Redis Cloud instance
  • Docker: (Optional) for running Redis locally
  • Stripe Account: With test API keys and Stripe CLI (for local webhook testing)
  • Cloudinary Account: For book cover image uploads
  • Email Service Provider:
    • Gmail Account with Google App Password (if using EMAIL_PROVIDER=smtp), OR
    • Resend Account with API Key (if using EMAIL_PROVIDER=resend, recommended for cloud platforms like Render)

🛠️ Installation & Setup

1️⃣ Clone the repository

git clone https://github.com/PanchalKeyur0806/BookStore.git
cd BookStore
npm install

2️⃣ Setup Environment Variables

Create a .env file in the root directory and configure the following variables:

# Server Configuration
PORT=8002
NODE_ENV=development
CORS_ORIGIN=*

# MongoDB Database Connection
DB_STRING=mongodb+srv://<username>:<password>@cluster0.kqdlh.mongodb.net/BookStore
# Local alternative: mongodb://localhost:27017/BookStore

# Admin Account Initialization (Automatic on server startup)
ADMIN_EMAIL=admin@bookstore.com
ADMIN_PASSWORD=your_admin_secure_password
ADMIN_NAME=Admin User
ADMIN_PHONE=9999999999

# Redis Configuration (Docker or Cloud Redis)
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_USERNAME=
REDIS_PASSWORD=

# JWT Authentication
JWT_SECRET_KEY=your_super_secret_jwt_key
JWT_EXPIRES=7d

# Email Configuration
# Set to 'smtp' for local Gmail SMTP development
# Set to 'resend' for production / cloud deployment (e.g., Render)
EMAIL_PROVIDER=resend

# Resend Settings (Used when EMAIL_PROVIDER=resend)
RESEND_API_KEY=your_resend_api_key
# Default test sender for domains not yet registered on Resend:
EMAIL_FROM=onboarding@resend.dev
# Production sender once domain is verified on Resend:
EMAIL_FROM_PROD=BookStore <bookstore@yourdomain.com>

# Gmail SMTP Settings (Used when EMAIL_PROVIDER=smtp)
USER_EMAIL=your_email@gmail.com
GMAIL_APP_PASSWORD=your_gmail_app_password

# Stripe Payments & Webhooks
STRIPE_SECRET_KEY=your_stripe_secret_key
STRIPE_WEBHOOK=your_stripe_webhook_signing_secret

# Cloudinary Media Storage
CLOUDINARY_NAME=your_cloudinary_cloud_name
CLOUDINARY_API_KEY=your_cloudinary_api_key
CLOUDINARY_API_SECRET=your_cloudinary_api_secret

📧 Email Provider Setup Guide

The application features a unified email dispatcher (utils/sendEmail.js) supporting both Gmail SMTP and the Resend API. You can switch providers dynamically using EMAIL_PROVIDER in your .env.

Option A: Resend API (Recommended for Cloud & Production)

Cloud hosting platforms (such as Render free tier, Heroku, AWS EC2) often block outbound SMTP ports (25, 465, 587) by default. The Resend integration sends emails over HTTPS API, bypassing port blocks completely.

  1. Create a free account at Resend.com.
  2. Navigate to API Keys and generate an API key.
  3. In .env:
    • Set EMAIL_PROVIDER=resend
    • Set RESEND_API_KEY=re_...
    • For initial testing without a custom domain, use EMAIL_FROM=onboarding@resend.dev.
    • In production with a verified domain, configure EMAIL_FROM_PROD=BookStore <bookstore@yourdomain.com>.

Option B: Gmail SMTP via Nodemailer (Local Development)

  1. Go to your Google Account Settings.
  2. Ensure 2-Step Verification is enabled.
  3. Search for App Passwords and generate a new app password for "BookStore".
  4. In .env:
    • Set EMAIL_PROVIDER=smtp
    • Set USER_EMAIL=your_gmail_address@gmail.com
    • Set GMAIL_APP_PASSWORD=your_16_character_app_password

🛡️ Automatic Admin Account Seeding

On application startup, the server automatically executes initilizeAdmin() from seeds/initilizeAdmin.js:

  • Checks MongoDB for an existing account matching ADMIN_EMAIL.
  • If absent, automatically generates a verified administrator account (role: 'admin', isEmailVerified: true, isActive: true) satisfying all required user schema fields (name, email, password, dateOfBirth, phoneNumber, gender, address).
  • You can also trigger the admin seed script manually from the CLI:
    node seeds/initilizeAdmin.js

⚡ Redis Setup & Caching Architecture

🧱 Running Redis via Docker (Local Development)

  1. Make sure Docker Desktop is running.
  2. Run Redis in a detached container:
    docker run -d --name redis -p 6379:6379 redis
  3. Start an existing container:
    docker start redis
  4. Stop the Redis container:
    docker stop redis
  5. Verify container status:
    docker ps

☁️ Using Cloud Redis (e.g., Redis Cloud)

If deploying to production or using Redis Cloud:

  1. Obtain your host, port, username, and password from your Redis Cloud dashboard.
  2. Add them to .env:
    REDIS_HOST=your-redis-cloud-endpoint.redislabs.com
    REDIS_PORT=15497
    REDIS_USERNAME=default
    REDIS_PASSWORD=your_redis_password

🚀 15-Minute Cache-Aside Strategy

The application enforces a 15-minute Time-To-Live (TTL) (EX: 15) across all cached read endpoints to maximize throughput and ensure data freshness:

Resource Route Cache Key TTL Invalidation & Refresh Behavior
Book Details GET /books/:bookId book:{bookId} 15 mins Populated on cache miss; updated in Redis on PATCH /books/:bookId
Customer Cart GET /cart user:{userId}:cart 15 mins Populated on cache miss; resynchronized on POST /cart/add & DELETE /cart/remove/:bookId
Order Details GET /orders/order/:orderId order:{orderId} 15 mins Populated on cache miss; verifies order ownership before caching
Personal Review GET /reviews/:bookId/me user:{id}:book:{bookId} 15 mins Fast cache-aside retrieval of authenticated user's book review

📬 BullMQ Background Queues

Redis also powers the BullMQ distributed queue system:

  • email-queue: Dispatches transactional order notification emails asynchronously in the background.
  • order-processing: Handles asynchronous order queue events and payment reconciliation.

☁️ Cloudinary Setup

  1. Sign up at Cloudinary.
  2. From the dashboard, copy:
    • Cloud Name → CLOUDINARY_NAME
    • API Key → CLOUDINARY_API_KEY
    • API Secret → CLOUDINARY_API_SECRET
  3. Add them to your .env file.

💳 Stripe Setup & Webhooks

  1. Create a Stripe account and enable Test Mode.
  2. Go to Developers > API Keys and copy your Secret Key:
    STRIPE_SECRET_KEY=sk_test_...
  3. Install the Stripe CLI for local webhook testing:
    stripe login
  4. Start webhook forwarding to the local backend:
    stripe listen --forward-to localhost:8002/webhook
  5. Copy the displayed webhook secret (whsec_...) and add it to .env:
    STRIPE_WEBHOOK=whsec_...

▶️ Running the Project

1️⃣ Start Redis

Ensure Redis is running locally (docker start redis) or connected via Redis Cloud.

2️⃣ Start Webhook Forwarding (If testing Stripe payments)

stripe listen --forward-to localhost:8002/webhook

3️⃣ Start Development Server

npm run dev

The server will start on http://localhost:8002 (or your configured PORT).

4️⃣ Validate Environment (Optional verification)

npm run validate:env

5️⃣ API Documentation Scripts

# Bundle modular YAML specs into a single bundle
npm run doc:bundle

# Build standalone Redoc HTML documentation
npm run doc:build

📡 API Endpoints Reference

All endpoints except public catalog browsing and authentication require a valid Bearer JWT token in the Authorization header (Bearer <token>).

🛡️ Admin Endpoints (/admin)

Requires role: 'admin'. Base rate limiter: 30 req/min (getRateLimiter). Mutation endpoints enforce 10 req/min (mutationLimiter).

Method Endpoint Description Key Middlewares & Validations
GET /admin/dashboard Aggregated dashboard statistics (revenue, orders, low stock, users) protect, restrictTo('admin')
GET /admin/getSalesAnalytics Revenue & sales trends grouped by day, week, or month startDate, endDate, groupBy
GET /admin/book/analytics Catalog health (active, inactive, low-stock, best/low selling) Aggregated across Books & Orders
GET /admin/book/deadstock Books with zero sales in the last 30 days (paginated) page, limit
GET /admin/book/performance Detailed book sales, copies sold, and revenue performance page, limit
GET /admin/book/category/revenue Sales count and revenue distribution across all book categories Aggregated across all paid orders
GET /admin/book/category/trend Monthly category sales trends over a specified date range startDate, endDate (max 1 year)
GET /admin/book/rating/distribution Review star rating counts (1 to 5 stars) per book page, limit
GET /admin/order/analytics Total counts per order status and platform cancellation rate Aggregated across Orders
GET /admin/order/order-growth Day-by-day order counts with automated date densification startDate, endDate (max 90 days)
GET /admin/order/avg-order-value Monthly Average Order Value (AOV) and revenue trend startDate, endDate (max 1 year)
GET /admin/customer/analytics Customer growth, top spenders, and returning customer rate startDate, endDate (max 1 year)
GET /admin/payment/analytics Payment volume, amounts, and success/failure rates Aggregated by Stripe payment status
PATCH /admin/activateUser/:userId Reactivate a suspended user account (isActive: true) mutationLimiter, validateId('userId')
PATCH /admin/deactivateUser/:userId Suspend a user account (isActive: false). Guards against self-deactivation & admin suspension. mutationLimiter, validateId('userId'), self & admin guard
PATCH /admin/change-role/:userId Update a user's role (admin or user). Guards against self-role changes. mutationLimiter, validateId('userId'), role enum validation

🔑 Authentication Endpoints (/auth)

Public access with rate limiting.

Method Endpoint Description Key Middlewares & Validations
POST /auth/register Register new account & dispatch 6-digit OTP (1-minute expiry) Input validation, OTP generation, Email dispatch
POST /auth/login Authenticate existing user & issue JWT Email & password check, suspension guard
POST /auth/verifyOtp Verify email using 6-digit OTP within 1-minute window OTP matching, token expiry validation
POST /auth/resendOtp Generate and resend fresh 6-digit verification OTP (1-minute expiry) Email check, OTP cooldown
POST /auth/forgotpassword Initiate password reset with token via email Crypto token generation, Email dispatch
PATCH /auth/resetpassword/:token Reset password using verified reset token Token verification, password hashing

👤 User Endpoints (/users)

Requires authenticated session (protect).

Method Endpoint Description Key Middlewares & Validations
GET /users/me Retrieve profile of the currently logged-in user getRateLimiter (30 req/min)
PATCH /users/updateMe Update profile information and shipping address mutationLimiter (10 req/min), validateUser
GET /users/orders Retrieve authenticated user's order history getRateLimiter
POST /users/favBooks Add a book to user's favorites collection mutationLimiter, book existence check
GET /users/all Admin query: List all users with regex filters and sorting getRateLimiter, restrictTo('admin'), pagination
GET /users/:userId Admin query: Retrieve a user by ObjectId getRateLimiter, validateId('userId'), restrictTo('admin')

📚 Book Endpoints (/books)

Method Endpoint Access Description Key Features
GET /books Public List active books with regex search, sorting, and pagination Regex on title and author, sorting (new, old), pagination
POST /books Admin Create a new book with Cloudinary cover image mutationLimiter, Multer file upload, validateBooks
GET /books/:bookId Public Fetch book details by ID Redis cache-aside lookup (book:{bookId}, 15 min TTL)
PATCH /books/:bookId Admin Update book metadata or replace cover image mutationLimiter, validateId('bookId'), Redis cache synchronized (15 min TTL)
DELETE /books/:bookId Admin Soft-delete a book (isDeleted: true) Preserves historical orders; returns HTTP 204

🛒 Cart Endpoints (/cart)

Method Endpoint Access Description Key Features
GET /cart Customer (user) Retrieve active shopping cart Redis cache-aside lookup (user:{userId}:cart, 15 min TTL)
POST /cart/add Customer (user) Add book to cart with quantity Stock validation, dynamic total recalculation, Redis cache sync (15 min TTL)
DELETE /cart/remove/:bookId Customer (user) Remove book item from cart Price and quantity reconciliation, Redis cache sync (15 min TTL)

💖 Wishlist Endpoints (/wishlist)

Method Endpoint Access Description Key Features
GET /wishlist Customer (user) Retrieve customer's saved wishlist books Populated book catalog details
POST /wishlist/:bookId Customer (user) Add book to wishlist Real-time existence & duplicate prevention
DELETE /wishlist/:bookId Customer (user) Remove book from wishlist Atomic pull update

⭐ Review Endpoints (/reviews & /books/:bookId/review)

Method Endpoint Access Description Key Features
GET /books/:bookId/review Authenticated Get paginated reviews for a specific book Regex query msg, sorting, auto-populated author
POST /books/:bookId/review Customer (user) Create a review and rating (1–5 stars) Auto-recalculates book rating average & quantity
PATCH /books/:bookId/review Customer (user) Update review commentary or rating Verifies book existence; synchronizes rating aggregate
DELETE /books/:bookId/review Customer (user) Delete review and star rating Resynchronizes book score; returns HTTP 204
GET /reviews/all Admin Platform-wide review monitoring Filter by review text regex, sorting, pagination
GET /reviews/:bookId/me Customer (user) Retrieve logged-in user's review for a book Redis cached lookup (user:{id}:book:{bookId}, 15 min TTL)

💳 Order & Payment Endpoints (/orders & /webhook)

Method Endpoint Access Description Key Features
POST /orders/createcheckoutsession Customer (user) Create a Stripe checkout session from cart makeReservation inventory reservation; BullMQ async order generation
GET /orders/refundPayment/:stripePaymentId Customer (user) Request refund for a paid order checkRefundStatus: Enforces 7-day refund window and paid status
GET /orders/all Admin Platform-wide order list with sorting page, limit, sort
GET /orders/order/:orderId Customer / Admin Fetch order details by ID Redis cache (order:{orderId}, 15 min TTL); strictly validates user ownership
GET /orders/success Public Stripe redirect callback handler Redirects to home page
POST /webhook Stripe Raw JSON Stripe webhook listener Handles session completed, expired, refund confirmation, inventory restock

⚠️ Error Handling & Response Architecture

The application implements a centralized error handling system (controllers/errorController.js) distinguishing between operational errors and unexpected programmer errors.

Standard Response Schemas

Successful Response:

{
  "status": "success",
  "message": "Operation completed successfully",
  "data": { ... }
}

Error Response:

{
  "status": "Error",
  "message": "Specific error explanation"
}

HTTP Status Codes:

  • 400 Bad Request: Validation failure (validateUser, validateId), business rule breach (self-deactivation, role constraints, 7-day refund window expiration, inventory shortage).
  • 401 Unauthorized: Missing Bearer token, expired JWT, or invalid signature.
  • 403 Forbidden: Role permission failure (e.g. non-admin accessing admin routes) or unverified email account.
  • 404 Not Found: Entity not found in database or ownership mismatch.
  • 429 Too Many Requests: Client exceeded rate limiting thresholds.
  • 500 Internal Server Error: Unexpected non-operational error.

🔮 Future Improvements

  • 🔍 Improve and optimize pagination, search, and sorting functionality for better performance and scalability.
  • ⚙️ Improve the background worker architecture so workers can be managed automatically with the main application, eliminating the need to start a separate worker process manually during local development.

📧 Contact: panchalkeyur694@gmail.com

About

A BookStore REST API built to manage bookstore operations through structured HTTP endpoints. Designed to handle book data and CRUD operations, this project demonstrates backend development, API design, request handling, and data management, providing a foundation for integrating bookstore functionality into web applications.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages