A REST API for managing Suppliers and their Inventory Products in a minimal dropshipping setup, built with TypeScript, Express.js, TypeORM, and MySQL.
- Supplier Management: Create, list, and retrieve suppliers with analytics
- Product Management: Create, list, retrieve, and update product stock
- Custom Validation: Custom validation classes for data integrity
- Category Filtering: Filter products by category (ELECTRONICS, FASHION, HOME, OTHER)
- Analytics: Supplier-level analytics (total products, total stock)
- Error Handling: Comprehensive error handling with proper HTTP status codes
- Language: TypeScript
- Framework: Express.js
- Database: MySQL
- ORM: TypeORM
- Validation: Custom validation classes
- Environment: Node.js
id(Primary Key, Auto Increment)name(String, required, min 2 chars)email(Unique, must be valid)phone(10 digits, starts with 7-9)country(String, not empty)created_at(timestamp)
id(Primary Key, Auto Increment)supplier_id(FK → Supplier)title(String, required, max 100 chars)price(Decimal, > 0)stock_quantity(Integer, >= 0)category(Enum: ELECTRONICS, FASHION, HOME, OTHER)created_at(timestamp)
- Node.js (v18 or higher)
- MySQL server running
- npm or yarn package manager
```bash git clone cd WellFound-Task npm install ```
Create a `.env` file in the project root: ```env PORT=8000 DB_HOST=localhost DB_PORT=3306 DB_USER=root DB_PASS=your_mysql_password DB_NAME=synegrow CORS_ORIGIN=* NODE_ENV=development ```
-
Create the MySQL database: ```sql CREATE DATABASE synegrow; ```
-
The application will automatically create tables when you start it (synchronize: true in development).
```bash
npm run build
npm run dev
npm start ```
The server will start on `http://localhost:8000\`
Create a new supplier.
Request Body: ```json { "name": "Tech Supplier", "email": "[email protected]", "phone": "9876543210", "country": "India" } ```
cURL Example: ```bash curl -X POST http://localhost:8000/api/suppliers \ -H "Content-Type: application/json" \ -d '{ "name": "Tech Supplier", "email": "[email protected]", "phone": "9876543210", "country": "India" }' ```
List all suppliers with analytics.
cURL Example: ```bash curl http://localhost:8000/api/suppliers ```
Get supplier details with products and analytics.
cURL Example: ```bash curl http://localhost:8000/api/suppliers/1 ```
Create a new product.
Request Body: ```json { "supplier_id": 1, "title": "Gaming Laptop", "price": 1299.99, "stock_quantity": 5, "category": "ELECTRONICS" } ```
cURL Example: ```bash curl -X POST http://localhost:8000/api/products \ -H "Content-Type: application/json" \ -d '{ "supplier_id": 1, "title": "Gaming Laptop", "price": 1299.99, "stock_quantity": 5, "category": "ELECTRONICS" }' ```
List all products with optional category filter.
cURL Examples: ```bash
curl http://localhost:8000/api/products
curl "http://localhost:8000/api/products?category=FASHION" ```
Get product details.
cURL Example: ```bash curl http://localhost:8000/api/products/1 ```
Update product stock quantity.
Request Body: ```json { "stock_quantity": 15 } ```
cURL Example: ```bash curl -X PATCH http://localhost:8000/api/products/1 \ -H "Content-Type: application/json" \ -d '{ "stock_quantity": 15 }' ```
Create a Postman environment with:
- `baseUrl`: `http://localhost:8000\`
-
Create Supplier
- Method: POST
- URL: `{{baseUrl}}/api/suppliers`
- Body: Raw JSON ```json { "name": "Electronics Hub", "email": "[email protected]", "phone": "9123456789", "country": "India" } ```
-
Create Product
- Method: POST
- URL: `{{baseUrl}}/api/products`
- Body: Raw JSON ```json { "supplier_id": 1, "title": "Wireless Headphones", "price": 99.99, "stock_quantity": 20, "category": "ELECTRONICS" } ```
-
Filter Products by Category
- Method: GET
- URL: `{{baseUrl}}/api/products?category=FASHION`
- name: Required, string, minimum 2 characters
- email: Required, valid email format, unique
- phone: Required, exactly 10 digits, starts with 7, 8, or 9
- country: Required, non-empty string
- supplier_id: Required, positive integer, must reference existing supplier
- title: Required, non-empty string, maximum 100 characters
- price: Required, positive number
- stock_quantity: Required, non-negative integer
- category: Required, must be one of: ELECTRONICS, FASHION, HOME, OTHER
All validation errors return HTTP 400 with details: ```json { "statusCode": 400, "message": "Validation failed", "success": false, "errors": [ "Name must be at least 2 characters long", "Email must be valid" ] } ```
Not found errors return HTTP 404: ```json { "statusCode": 404, "message": "Supplier not found", "success": false, "errors": [] } ```
``` src/ ├── entities/ # TypeORM entities │ ├── Supplier.ts │ └── Product.ts ├── validators/ # Custom validation classes │ ├── SupplierValidator.ts │ └── ProductValidator.ts ├── controllers/ # Route controllers │ ├── supplier.controllers.ts │ └── product.controllers.ts ├── routes/ # Express routes │ ├── supplier.routes.ts │ └── product.routes.ts ├── utils/ # Utility classes │ ├── ApiError.ts │ ├── ApiResponse.ts │ └── asyncHandler.ts ├── migrations/ # TypeORM migrations ├── data-source.ts # TypeORM configuration ├── app.ts # Express app setup └── index.ts # Application entry point ```
- Reusable: Validation logic separated into dedicated classes
- Comprehensive: Validates data types, formats, and business rules
- Error Aggregation: Collects all validation errors and returns them together
- Separation of Concerns: Controllers, validators, and entities are separate
- Error Handling: Centralized error handling with custom ApiError class
- Response Format: Consistent API response format with ApiResponse class
- Easy to Add Fields: Add new fields to entities and update validators
- New Entities: Follow the same pattern for new entities
- Middleware Support: Ready for authentication, logging, etc.
- Create/update entity in `src/entities/`
- Create/update validator in `src/validators/`
- Create controller in `src/controllers/`
- Create routes in `src/routes/`
- Register routes in `src/app.ts`
```bash
npm run migration:generate
npm run migration:run
npm run migration:revert ```
This project is licensed under the ISC License.
Parikshit Jaiswal
Submission Date: September 11, 2025
Deadline: September 14, 2025 by 7:00 PM