A Node.js / Express REST API for an e-commerce backend. It provides authentication, role-based access control, and management for categories, products, shopping carts, and user accounts (registration plus admin-only listing) β backed by MySQL (via Sequelize ORM) with Redis integration.
- Features
- Tech Stack
- Project Structure
- Prerequisites
- Installation
- Environment Configuration
- Database Setup
- Running the Application
- API Reference
- Project Scripts
- Contributing
- License
- JWT Authentication β sign-up, login, logout, and password change with signed access tokens.
- Role-Based Access Control β
Customer,Admin, andSuperAdminroles enforced via middleware. - User Management β registration with automatic cart creation and admin-only user listing.
- Category Management β full CRUD (admin restricted for write operations).
- Product Management β create, read, update, delete, filter, and paginated listing.
- Shopping Cart β update and retrieve a cart by id.
- Redis Integration β a Redis client writes user data to the store on login.
- Input Validation β request payloads validated with Joi.
- Environment Validation β strongly typed config via Envalid.
- Auto Database Bootstrap β the database and default admin are created/seeded on startup.
- Structured Logging & Security β
morganHTTP logging, CORS, and cookie parsing.
| Layer | Technology |
|---|---|
| Runtime | Node.js (>= 22, ESM modules) |
| Framework | Express 5 |
| ORM / DB | Sequelize 6 + MySQL (mysql2) |
| Cache / Redis | redis client (user data written on login) |
| Auth | JSON Web Tokens (jsonwebtoken), bcrypt hashing |
| Validation | Joi, Envalid |
| Middleware | cors, cookie-parser, morgan |
| Testing | Jest, Supertest |
| Formatting | Prettier |
ecommerce/
βββ src/
β βββ index.js # Application entry point (DB sync + bootstrap + listen)
β βββ app.js # Express app, middleware, route mounting
β βββ constants.js
β βββ configs/ # Database & Sequelize configuration
β βββ controllers/ # Request handlers (auth, product, category, cart)
β βββ middlewares/ # JWT auth, role checks, validation
β βββ models/ # Sequelize models (User, Role, Category, Product, Cart)
β βββ routes/ # Express routers
β βββ utils/ # Env, redis, response, helpers, validation, cron
βββ tests/ # Jest test suites (controllers, routes)
βββ .env / .env.sample # Environment configuration
βββ package.json
- Node.js >= 22
- MySQL server (default port
3306) - Redis server (default
redis://localhost:6379) npm(bundled with Node.js)
# 1. Clone the repository
git clone https://github.com/nil2022/ecommerce.git
cd ecommerce
# 2. Install dependencies
npm install
# 3. Configure environment variables
cp .env.sample .env
# then edit .env with your database, redis, and secret valuesCopy .env.sample to .env and adjust the values. All variables are validated at startup
by Envalid, so a missing/invalid value will fail fast.
| Variable | Default | Description |
|---|---|---|
PORT |
9000 |
Port the server listens on |
NODE_ENV |
dev |
Environment (dev, prod, test) |
CORS_ORIGIN |
(empty) | Allowed CORS origin |
CORS_ALLOWED_HEADERS |
(empty) | Comma-separated allowed headers |
ACCESS_TOKEN_SECRET |
secret |
Secret used to sign JWTs |
ACCESS_TOKEN_EXPIRY |
7d |
Access token expiry duration |
DB_HOST |
localhost |
MySQL host |
DB_USER |
root |
MySQL username |
DB_PASSWORD |
root |
MySQL password |
DB_NAME |
ecomm |
MySQL database name |
DB_PORT |
3306 |
MySQL port |
DB_SSL |
false |
Use SSL for the database connection |
REDIS_URL |
redis://localhost:6379 |
Redis connection URL |
SYSTEM_ADMIN_USERID |
john |
System/admin bootstrap user ID |
SYSTEM_ADMIN_PASSWORD |
12345678 |
System/admin bootstrap password |
SYSTEM_ADMIN_EMAIL |
john@email.com |
System/admin bootstrap email |
No manual migrations are required. On startup the application will:
- Create the database (
DB_NAME) if it does not already exist (using the configured DB host/port). - Authenticate the Sequelize connection.
- Synchronize all models (creating tables that do not exist β non-destructive; runs on every startup).
- Seed default data via
initialize()only when a given table is empty:- Roles:
Customer,Admin,SuperAdmin - Category:
Beauty - Product:
MakeUP Kit(cost870, quantity20, under the Beauty category) - System Administrator: created from
SYSTEM_ADMIN_USERID/SYSTEM_ADMIN_PASSWORD/SYSTEM_ADMIN_EMAIL, assigned theSuperAdminrole, with an associated cart.
- Roles:
# Start the server (this triggers the bootstrap above)
npm start# Development mode (hot reload via Node --watch)
npm run dev
# Production start
npm start
# Run the test suite
npm test
# Run tests with coverage
npm run test:covThe server will be available at http://localhost:<PORT> (default 9000).
All routes are mounted under the following base paths:
/auth/category/product/cart
Most endpoints require a valid access token. The token is read from (in order of precedence):
- The
accessTokencookie, or - The
Authorization: Bearer <token>header, or - The
x-access-tokenheader.
Admin-only endpoints additionally require the authenticated user to hold the Admin or
SuperAdmin role.
| Method | Endpoint | Auth | Admin | Description |
|---|---|---|---|---|
POST |
/auth/register |
Register a new user (auto-creates a cart). | ||
POST |
/auth/login |
Authenticate and receive an access token. | ||
GET |
/auth/all-users |
β | Super | List all users (SuperAdmin only). |
PATCH |
/auth/change-password |
β | Change the logged-in user's password. | |
GET |
/auth/logout |
β | Clear the auth cookie / log out. |
Register body
{
"fullName": "John Doe",
"userId": "john",
"email": "john@example.com",
"password": "secret123",
"roles": [1]
}Login body
{ "userId": "john", "password": "secret123" }| Method | Endpoint | Auth | Admin | Description |
|---|---|---|---|---|
POST |
/category/add |
β | β | Create a new category. |
GET |
/category/getAll |
β | List all categories. | |
GET |
/category/getOne |
β | Get a category by query id. |
|
PATCH |
/category/updateOne |
β | β | Update a category. |
DELETE |
/category/deleteOne |
β | β | Delete a category. |
| Method | Endpoint | Auth | Admin | Description |
|---|---|---|---|---|
POST |
/product/add |
β | β | Create a new product. |
GET |
/product/getAll |
β | List all products. | |
GET |
/product/filter |
β | Filter products by query params. | |
GET |
/product/getOne |
β | Get a product by query id. |
|
PATCH |
/product/updateOne |
β | β | Update a product. |
DELETE |
/product/deleteOne |
β | β | Delete a product. |
| Method | Endpoint | Auth | Admin | Description |
|---|---|---|---|---|
PUT |
/cart/:id |
β | Update the cart for user :id. |
|
GET |
/cart/:id |
β | Retrieve the cart for user :id. |
β οΈ Authorization note: These routes only require a valid token; they do not verify that the authenticated user owns the cart identified by:id. Any authenticated user can currently read or modify another user's cart (insecure direct object reference). Enforcing ownership (or admin access) is recommended before production use.
| Script | Command | Purpose |
|---|---|---|
dev |
node --env-file=.env --watch src/index.js |
Run in development with hot reload. |
start |
node --env-file=.env src/index.js |
Run in production. |
test |
jest --verbose --runInBand --detectOpenHandles --forceExit |
Run the Jest test suite. |
test:cov |
cross-env NODE_ENV=test jest --coverage |
Run tests with coverage reporting. |
Contributions are welcome! If you find any issues or have suggestions for improvement, please open an issue or submit a pull request.
- Fork the repository.
- Create a feature branch (
git checkout -b feature/my-feature). - Commit your changes (
git commit -m 'Add my feature'). - Push to the branch (
git push origin feature/my-feature). - Open a pull request.
This project is licensed under the ISC License.