An order management REST API with authentication, role-based access control, and MongoDB persistence. It exposes endpoints for:
- Auth – register/login, issue JWTs
- Products – admin-only create/update, public list
- Orders – customers create/list/pay/cancel orders
- Users – admin-only user listing
Built with Node.js, Express 5, TypeScript, and Mongoose.
Swagger doc for test in the browser: https://order-service-t77z.onrender.com/docs/
-
Prerequisites
- Node.js: v20+ recommended
- Package manager:
pnpm(project usespnpm-lock.yaml) - MongoDB: running locally or accessible via connection string
-
Clone and install
git clone <your-fork-or-repo-url> order-service
cd order-service
pnpm install- Build the project
pnpm run build- Start the server
By default the compiled server entrypoint is dist/server.js:
node dist/server.jsThe API will listen on http://localhost:<PORT> (defaults to 3000).
Environment variables are loaded via dotenv in src/config/env.ts. The following variables are required/recommended:
-
Required
MONGO_URI: MongoDB connection string
Example:mongodb://localhost:27017/order_serviceJWT_SECRET: Secret key used to sign JWT access tokens
-
Optional
PORT: HTTP port to run the server on
Default:3000NODE_ENV:development|production
Default:developmentAPI_URL: External base URL for the API
Default:http://localhost:3000JWT_EXPIRES_IN: Token lifetime, e.g.1h,7d
Default:1h
-
Example
.env
NODE_ENV=development
PORT=3000
API_URL=http://localhost:3000
MONGO_URI=mongodb://localhost:27017/order_service
JWT_SECRET=super-secret-change-me
JWT_EXPIRES_IN=1hCreate a .env file at the project root before running the server or scripts.
This project uses MongoDB + Mongoose. There is no formal migration tool configured; schemas are defined via Mongoose models under src/models.
-
Database connection
- Configured in
src/config/db.tsusingMONGO_URI.
- Configured in
-
Seeding products
There is a seed script at src/scripts/seed.ts which:
- Connects to MongoDB
- Clears the
productscollection - Inserts a fixed list of sample products (mice, keyboards, etc.)
Run the seed script:
pnpm run seedUnder the hood this will:
- Compile TypeScript (
tsc) - Run
node dist/scripts/seed.js
Make sure:
- The project is built without errors.
MONGO_URIis correctly set in your.env.
- Build once:
pnpm run build- Start server:
node dist/server.jsThe service will:
- Connect to MongoDB.
- Expose health check at
GET /health. - Expose REST endpoints under
/auth,/products,/orders,/users. - Expose Swagger docs under
/docs.
Note: For local development you can also use
ts-node/nodemonif you wire custom scripts, but for this task the build‑then‑run flow above is sufficient.
- GET
/health
curl -i https://order-service-t77z.onrender.com/health- POST
/auth/register - Body:
curl -i -X POST https://order-service-t77z.onrender.com/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "customer@example.com",
"password": "Password123",
"role": "customer"
}'For an admin user, set "role": "admin".
- POST
/auth/login
curl -i -X POST https://order-service-t77z.onrender.com/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "customer@example.com",
"password": "Password123"
}'The response includes a token field (JWT). Use this token in subsequent requests:
Authorization: Bearer <token>
- GET
/products
curl -i https://order-service-t77z.onrender.com/products- POST
/products
curl -i -X POST https://order-service-t77z.onrender.com/products \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <admin-token>" \
-d '{
"name": "New Gadget",
"price": 1999,
"stock": 25
}'- PATCH
/products/:id
curl -i -X PATCH https://order-service-t77z.onrender.com/products/<productId> \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <admin-token>" \
-d '{
"price": 2499,
"stock": 40
}'- POST
/orders
curl -i -X POST https://order-service-t77z.onrender.com/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"items": [
{ "productId": "<productId>", "quantity": 2 },
{ "productId": "<otherProductId>", "quantity": 1 }
]
}'- GET
/orders
curl -i https://order-service-t77z.onrender.com/orders \
-H "Authorization: Bearer <token>"- POST
/orders/:id/pay
curl -i -X POST https://order-service-t77z.onrender.com/orders/<orderId>/pay \
-H "Authorization: Bearer <token>"- POST
/orders/:id/cancel
curl -i -X POST https://order-service-t77z.onrender.com/orders/<orderId>/cancel \
-H "Authorization: Bearer <token>"- GET
/users
curl -i https://order-service-t77z.onrender.com/users \
-H "Authorization: Bearer <admin-token>"The service is wired with swagger-jsdoc and swagger-ui-express. OpenAPI annotations live in the route files (e.g. src/routes/auth.routes.ts, src/routes/order.routes.ts, etc) and are aggregated in the Swagger configuration.
- View documentation UI:
open https://order-service-t77z.onrender.com/docsThis provides an interactive UI for exploring and testing all endpoints.
-
Architecture
- Layered structure:
controllers/: Express route handlers (request/response orchestration).services/: Business logic (auth, orders, products, users).repositories/: Data access layer over Mongoose models.models/: Mongoose schemas and models.middleware/: Cross-cutting concerns (auth, validation, error handling, rate limiting, role checks).
- Separation of concerns keeps controllers thin and business logic testable.
- Layered structure:
-
Authentication & Authorization
- JWT-based auth (see
auth.middleware.tsandutils/jwt.ts). - Role-based access control via
requireRolemiddleware:- Customers can create/list/pay/cancel their own orders.
- Admins can manage products and list all users.
- JWT-based auth (see
-
Validation & Error Handling
- Zod schemas validate payloads (
validation/*.schema.ts). - Central
error.middleware.tsnormalizes API error responses. rateLimit.middleware.tslimits sensitive endpoints (e.g. auth) to mitigate brute-force.
- Zod schemas validate payloads (
-
Persistence
- MongoDB via Mongoose models (
user.model.ts,product.model.ts,order.model.ts). - Order items reference products and store quantities and pricing data for consistency.
- MongoDB via Mongoose models (
-
Observability & DX
morgan+ customloggerprovide structured request logs.- TypeScript configuration (
tsconfig.json) and linting (eslint.config.mts) encourage a consistent, safe codebase.