This project is a sample implementation of a ecommerce inventory manager API built with Node.js and Express. It demonstrates modern backend development practices, including a layered architecture, dependency injection, Zod for validation, and a robust testing strategy using Vitest.
- Node.js (v18 or higher recommended)
- pnpm (Preferred Node Package Manager)
pnpm install
pnpm dev
pnpm check
pnpm test:watch
A Postman collection for manual testing can be found in the _dev directory.
pnpm install
pnpm check
pnpm test
pnpm build
pnpm start
GET /products: Get all products.POST /products: Create a new product.- Request Body:
{ name: string, description: string, price: number, stock: number }
- Request Body:
POST /products/:id/restock: Restock a product.- Request Body:
{ quantity: number }
- Request Body:
POST /products/:id/sell: Sell a product.- Request Body:
{ quantity: number }
- Request Body:
GET /orders/:id: Get an order by ID.POST /orders: Create a new order.- Request Body:
{ customerId: string, items: [{ productId: string, quantity: number }] }
- Request Body:
GET /customers/:id: Get a customer by ID.POST /customers: Create a new customer.- Request Body:
{ name: string, region: string }
- Request Body:
The application uses a layered architecture with clear separation of concerns: routes, controllers, services, and data access. It implements a simplified CQRS pattern, distinguishing between command (write) and query (read) services.
lowdb serves as a simple JSON database for prototyping. For production, a robust database like MongoDB or PostgreSQL would be essential to support transactions, ensure data consistency, and handle concurrent requests effectively.
Input data is validated using Zod schemas. A single, unified Zod schema acts as a single source of truth for API definitions, facilitating consistent validation and easy generation of API documentation (e.g. via OpenAPI standards). A global error handling middleware translates domain-specific exceptions into consistent HTTP error responses with appropriate status codes.
Key business rules, such as stock validation, are implemented in dedicated service layers. Pricing and discount logic (e.g., regional pricing, volume discounts, seasonal promotions) is encapsulated within a dedicated PricingService in the domain layer. The current pricing and discount logic is simplified for this prototype. Production version would require a more dynamic and configurable system, potentially with a dedicated management interface for prices and discounts.
To evolve this application into a production-ready system, the following key areas require further development:
- Robust Database: Replace
lowdbwith a transactional database like MongoDB or PostgreSQL to ensure data consistency, support atomic operations, and manage race conditions effectively. - Pagination, Filtering, Sorting: Implement comprehensive pagination, filtering, and sorting for list endpoints to handle large datasets efficiently.
- Advanced CQRS: For high-scale, consider a more explicit CQRS setup with separate read/write models and event sourcing.
- Statelessness & Containerization: Ensure the application is stateless for horizontal scaling and containerize it (e.g. with Docker) for automated deployment and orchestration.
- Caching: Implement caching mechanisms (e.g. Redis) for frequently accessed data to reduce database load and improve response times.
- Concurrency Control: Implement robust concurrency control mechanisms (e.g. optimistic/pessimistic locking) for critical operations like stock management.
- Logging & Monitoring: Integrate structured logging with a centralized logging system (e.g. ELK stack) and implement application performance monitoring.
- Idempotency & Retries: Implement idempotency for order creation and other critical operations, along with retry mechanisms, to ensure reliability in distributed systems. For critical operations, consider asynchronous processing using message queues (e.g. RabbitMQ, Kafka).
- API Authentication & Authorization: Secure API access with authentication (e.g. OAuth, JWT, API keys) and implement authorization for administrative endpoints (e.g. product/stock management).
- Rate Limiting: Protect against abuse and ensure fair usage by implementing rate limiting.
- Dedicated Test Database: For integration tests, use a separate, dedicated test database instance rather than in-memory mocking to ensure realistic testing scenarios.
- Expanded Coverage: Further expand unit and integration test coverage, especially for services, middleware, and error handlers.
- Configuration Management: Externalize dynamic configurations (e.g. discount rules, regional pricing multipliers) to a database or dedicated configuration service.
- API Gateway: Introduce an API Gateway for request routing, load balancing, and centralized security.
- Response Validation: Implement Zod schemas for API responses and a middleware to validate outgoing data, ensuring consistency and correctness of API output in a production environment.