Add user management, API testing tools, and fix database connection issues
- Added user routes (CRUD operations) for managing users - Created Postman collection for API testing - Added HTML test page for interactive API testing - Fixed UUID handling for species_id and breed_id - Added user validation for listings and locations - Improved error handling and validation - Added static file serving for test page - Updated server configuration with all routes
This commit is contained in:
parent
9f6f7a0bab
commit
b3899dc14d
|
|
@ -0,0 +1,637 @@
|
||||||
|
{
|
||||||
|
"info": {
|
||||||
|
"_postman_id": "buysellservice-api-collection",
|
||||||
|
"name": "BuySellService API",
|
||||||
|
"description": "Complete API collection for Livestock Marketplace - BuySellService",
|
||||||
|
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
||||||
|
},
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "Users",
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "Create User",
|
||||||
|
"request": {
|
||||||
|
"method": "POST",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"id\": \"aaf295cb-a19e-4179-a2df-31c0c64ea9f4\",\n \"name\": \"Test User\",\n \"phone_number\": \"+919876543210\",\n \"avatar_url\": null,\n \"language\": \"en\",\n \"timezone\": \"Asia/Kolkata\",\n \"country_code\": \"+91\"\n}"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/users",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"users"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Create a new user. You can provide a specific UUID or let the system generate one."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Get All Users",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/users?limit=100&offset=0",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"users"
|
||||||
|
],
|
||||||
|
"query": [
|
||||||
|
{
|
||||||
|
"key": "limit",
|
||||||
|
"value": "100"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "offset",
|
||||||
|
"value": "0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Get a list of all users"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Get User by ID",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/users/:userId",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"users",
|
||||||
|
":userId"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "userId",
|
||||||
|
"value": "aaf295cb-a19e-4179-a2df-31c0c64ea9f4"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Get a single user by UUID"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Update User",
|
||||||
|
"request": {
|
||||||
|
"method": "PUT",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"name\": \"Updated User Name\",\n \"phone_number\": \"+919876543210\"\n}"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/users/:userId",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"users",
|
||||||
|
":userId"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "userId",
|
||||||
|
"value": "aaf295cb-a19e-4179-a2df-31c0c64ea9f4"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Update user information"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Listings",
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "Get All Listings",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/listings?status=active&limit=20&offset=0",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"listings"
|
||||||
|
],
|
||||||
|
"query": [
|
||||||
|
{
|
||||||
|
"key": "status",
|
||||||
|
"value": "active"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "limit",
|
||||||
|
"value": "20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "offset",
|
||||||
|
"value": "0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Get all active listings"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Get Listing by ID",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/listings/:listingId",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"listings",
|
||||||
|
":listingId"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "listingId",
|
||||||
|
"value": "your-listing-uuid-here"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Get a single listing with full details"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Create Listing",
|
||||||
|
"request": {
|
||||||
|
"method": "POST",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"seller_id\": \"aaf295cb-a19e-4179-a2df-31c0c64ea9f4\",\n \"title\": \"High-yield Gir cow for sale\",\n \"price\": 55000,\n \"currency\": \"INR\",\n \"is_negotiable\": true,\n \"listing_type\": \"sale\",\n \"animal\": {\n \"species_id\": \"your-species-uuid\",\n \"breed_id\": \"your-breed-uuid\",\n \"sex\": \"F\",\n \"age_months\": 36,\n \"weight_kg\": 450,\n \"color_markings\": \"Brown with white patches\",\n \"quantity\": 1,\n \"purpose\": \"dairy\",\n \"health_status\": \"healthy\",\n \"vaccinated\": true,\n \"dewormed\": true,\n \"pregnancy_status\": \"pregnant\",\n \"milk_yield_litre_per_day\": 15,\n \"ear_tag_no\": \"TAG-12345\",\n \"description\": \"Calm nature, easy to handle.\"\n },\n \"media\": [\n {\n \"media_url\": \"https://cdn.app.com/listings/abc1.jpg\",\n \"media_type\": \"image\",\n \"is_primary\": true,\n \"sort_order\": 1\n }\n ]\n}"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/listings",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"listings"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Create a new listing with animal details"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Update Listing",
|
||||||
|
"request": {
|
||||||
|
"method": "PUT",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"title\": \"Updated title\",\n \"price\": 52000,\n \"status\": \"active\"\n}"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/listings/:listingId",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"listings",
|
||||||
|
":listingId"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "listingId",
|
||||||
|
"value": "your-listing-uuid-here"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Update listing information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Search Listings",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/listings/search?q=cow&limit=20&offset=0",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"listings",
|
||||||
|
"search"
|
||||||
|
],
|
||||||
|
"query": [
|
||||||
|
{
|
||||||
|
"key": "q",
|
||||||
|
"value": "cow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "limit",
|
||||||
|
"value": "20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "offset",
|
||||||
|
"value": "0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Search listings by text query"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Near Me Search",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/listings/near-me?lat=18.5204&lng=73.8567&radius_meters=100000&limit=20",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"listings",
|
||||||
|
"near-me"
|
||||||
|
],
|
||||||
|
"query": [
|
||||||
|
{
|
||||||
|
"key": "lat",
|
||||||
|
"value": "18.5204"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "lng",
|
||||||
|
"value": "73.8567"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "radius_meters",
|
||||||
|
"value": "100000"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "limit",
|
||||||
|
"value": "20"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Find listings near a specific location"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Get Species",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/listings/species",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"listings",
|
||||||
|
"species"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Get all available species"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Get Breeds",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/listings/breeds?species_id=your-species-uuid",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"listings",
|
||||||
|
"breeds"
|
||||||
|
],
|
||||||
|
"query": [
|
||||||
|
{
|
||||||
|
"key": "species_id",
|
||||||
|
"value": "your-species-uuid",
|
||||||
|
"description": "Optional: Filter breeds by species"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Get all available breeds (optionally filtered by species)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Locations",
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "Create Location",
|
||||||
|
"request": {
|
||||||
|
"method": "POST",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"user_id\": \"aaf295cb-a19e-4179-a2df-31c0c64ea9f4\",\n \"lat\": 18.15,\n \"lng\": 74.5833,\n \"country\": \"India\",\n \"state\": \"Maharashtra\",\n \"district\": \"Pune\",\n \"city_village\": \"Baramati\",\n \"pincode\": \"413102\",\n \"location_type\": \"farm\",\n \"is_saved_address\": true,\n \"source_type\": \"manual\",\n \"source_confidence\": \"high\"\n}"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/locations",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"locations"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Create a new location. user_id is optional for captured locations but required for saved addresses."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Get User Locations",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/locations/user/:userId",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"locations",
|
||||||
|
"user",
|
||||||
|
":userId"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "userId",
|
||||||
|
"value": "aaf295cb-a19e-4179-a2df-31c0c64ea9f4"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Get all locations for a specific user"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Get Location by ID",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/locations/:locationId",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"locations",
|
||||||
|
":locationId"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "locationId",
|
||||||
|
"value": "your-location-uuid-here"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Get a single location by ID"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Update Location",
|
||||||
|
"request": {
|
||||||
|
"method": "PUT",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"city_village\": \"Updated City Name\",\n \"pincode\": \"413103\"\n}"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/locations/:locationId",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"locations",
|
||||||
|
":locationId"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "locationId",
|
||||||
|
"value": "your-location-uuid-here"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Update location information"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Chat",
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "Create/Get Conversation",
|
||||||
|
"request": {
|
||||||
|
"method": "POST",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"buyer_id\": \"buyer-uuid-here\",\n \"seller_id\": \"seller-uuid-here\"\n}"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/chat/conversations",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"chat",
|
||||||
|
"conversations"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Create a new conversation or get existing one between buyer and seller"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Get User Conversations",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/chat/conversations/user/:userId",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"chat",
|
||||||
|
"conversations",
|
||||||
|
"user",
|
||||||
|
":userId"
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "userId",
|
||||||
|
"value": "aaf295cb-a19e-4179-a2df-31c0c64ea9f4"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Get all conversations for a specific user"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Get Messages",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/chat/conversations/:conversationId/messages?limit=50&offset=0",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"chat",
|
||||||
|
"conversations",
|
||||||
|
":conversationId",
|
||||||
|
"messages"
|
||||||
|
],
|
||||||
|
"query": [
|
||||||
|
{
|
||||||
|
"key": "limit",
|
||||||
|
"value": "50"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "offset",
|
||||||
|
"value": "0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "conversationId",
|
||||||
|
"value": "your-conversation-uuid-here"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Get messages for a conversation"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Send Message",
|
||||||
|
"request": {
|
||||||
|
"method": "POST",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"conversation_id\": \"conversation-uuid-here\",\n \"sender_id\": \"sender-uuid-here\",\n \"receiver_id\": \"receiver-uuid-here\",\n \"content\": \"Hello, I'm interested in your listing.\",\n \"message_type\": \"text\"\n}"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:3200/chat/messages",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "3200",
|
||||||
|
"path": [
|
||||||
|
"chat",
|
||||||
|
"messages"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Send a message in a conversation"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "baseUrl",
|
||||||
|
"value": "http://localhost:3200",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,143 @@
|
||||||
|
# Postman Testing Guide for BuySellService API
|
||||||
|
|
||||||
|
## 📥 How to Import the Collection
|
||||||
|
|
||||||
|
1. **Open Postman**
|
||||||
|
2. Click **Import** button (top left)
|
||||||
|
3. Select **File** tab
|
||||||
|
4. Choose `BuySellService_API.postman_collection.json`
|
||||||
|
5. Click **Import**
|
||||||
|
|
||||||
|
The collection will appear in your Postman sidebar with all endpoints organized by category.
|
||||||
|
|
||||||
|
## 🚀 Quick Start Testing
|
||||||
|
|
||||||
|
### Step 1: Create a User (Required First Step)
|
||||||
|
|
||||||
|
Before creating listings or locations, you need to create a user:
|
||||||
|
|
||||||
|
1. Go to **Users** → **Create User**
|
||||||
|
2. The request body is pre-filled with the UUID from your error: `aaf295cb-a19e-4179-a2df-31c0c64ea9f4`
|
||||||
|
3. Click **Send**
|
||||||
|
4. You should get a 201 response with the created user
|
||||||
|
|
||||||
|
**Request Body:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "aaf295cb-a19e-4179-a2df-31c0c64ea9f4",
|
||||||
|
"name": "Test User",
|
||||||
|
"phone_number": "+919876543210",
|
||||||
|
"avatar_url": null,
|
||||||
|
"language": "en",
|
||||||
|
"timezone": "Asia/Kolkata",
|
||||||
|
"country_code": "+91"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Get Species and Breeds
|
||||||
|
|
||||||
|
Before creating a listing, you need to know the UUIDs of species and breeds:
|
||||||
|
|
||||||
|
1. Go to **Listings** → **Get Species**
|
||||||
|
2. Click **Send** - This will show you all available species with their UUIDs
|
||||||
|
3. Copy a species UUID
|
||||||
|
4. Go to **Listings** → **Get Breeds**
|
||||||
|
5. Add the species UUID as a query parameter: `?species_id=your-species-uuid`
|
||||||
|
6. Click **Send** - This will show breeds for that species
|
||||||
|
7. Copy a breed UUID
|
||||||
|
|
||||||
|
### Step 3: Create a Location (Optional)
|
||||||
|
|
||||||
|
1. Go to **Locations** → **Create Location**
|
||||||
|
2. Update the `user_id` in the request body to your user UUID
|
||||||
|
3. Modify other fields as needed
|
||||||
|
4. Click **Send**
|
||||||
|
|
||||||
|
### Step 4: Create a Listing
|
||||||
|
|
||||||
|
1. Go to **Listings** → **Create Listing**
|
||||||
|
2. Update the request body:
|
||||||
|
- `seller_id`: Use your user UUID
|
||||||
|
- `species_id`: Use the species UUID from Step 2
|
||||||
|
- `breed_id`: Use the breed UUID from Step 2
|
||||||
|
3. Click **Send**
|
||||||
|
|
||||||
|
## 📋 Endpoint Categories
|
||||||
|
|
||||||
|
### 👤 Users
|
||||||
|
- **Create User** - Create a new user (with optional UUID)
|
||||||
|
- **Get All Users** - List all users
|
||||||
|
- **Get User by ID** - Get specific user details
|
||||||
|
- **Update User** - Update user information
|
||||||
|
|
||||||
|
### 📋 Listings
|
||||||
|
- **Get All Listings** - List all active listings
|
||||||
|
- **Get Listing by ID** - Get specific listing with full details
|
||||||
|
- **Create Listing** - Create a new listing with animal details
|
||||||
|
- **Update Listing** - Update listing information
|
||||||
|
- **Search Listings** - Search by text query
|
||||||
|
- **Near Me Search** - Find listings near coordinates
|
||||||
|
- **Get Species** - Get all available species
|
||||||
|
- **Get Breeds** - Get all breeds (optionally filtered by species)
|
||||||
|
|
||||||
|
### 📍 Locations
|
||||||
|
- **Create Location** - Create a location (user_id optional for captured locations)
|
||||||
|
- **Get User Locations** - Get all locations for a user
|
||||||
|
- **Get Location by ID** - Get specific location
|
||||||
|
- **Update Location** - Update location information
|
||||||
|
|
||||||
|
### 💬 Chat
|
||||||
|
- **Create/Get Conversation** - Create or get existing conversation
|
||||||
|
- **Get User Conversations** - Get all conversations for a user
|
||||||
|
- **Get Messages** - Get messages in a conversation
|
||||||
|
- **Send Message** - Send a message
|
||||||
|
|
||||||
|
## 🔧 Important Notes
|
||||||
|
|
||||||
|
### UUIDs Required
|
||||||
|
- All IDs in this API are **UUIDs**, not integers
|
||||||
|
- Make sure to use valid UUID format: `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
|
||||||
|
|
||||||
|
### User ID Requirements
|
||||||
|
- **For Listings**: `seller_id` must exist in users table
|
||||||
|
- **For Locations**:
|
||||||
|
- `user_id` is **optional** if `is_saved_address = false` (captured location)
|
||||||
|
- `user_id` is **required** if `is_saved_address = true` (saved address)
|
||||||
|
|
||||||
|
### Testing Order
|
||||||
|
1. ✅ Create User first
|
||||||
|
2. ✅ Get Species and Breeds
|
||||||
|
3. ✅ Create Location (optional)
|
||||||
|
4. ✅ Create Listing
|
||||||
|
|
||||||
|
## 🐛 Common Errors
|
||||||
|
|
||||||
|
### "User does not exist"
|
||||||
|
- **Solution**: Create the user first using the **Create User** endpoint
|
||||||
|
|
||||||
|
### "Invalid input syntax for type uuid"
|
||||||
|
- **Solution**: Make sure you're using UUIDs, not integers. Check species_id and breed_id are UUIDs.
|
||||||
|
|
||||||
|
### "Foreign key constraint violation"
|
||||||
|
- **Solution**: Ensure all referenced IDs (user_id, species_id, breed_id) exist in their respective tables
|
||||||
|
|
||||||
|
## 💡 Tips
|
||||||
|
|
||||||
|
1. **Use Environment Variables**: Create a Postman environment with:
|
||||||
|
- `baseUrl`: `http://localhost:3200`
|
||||||
|
- `userId`: Your user UUID
|
||||||
|
- `speciesId`: A species UUID
|
||||||
|
- `breedId`: A breed UUID
|
||||||
|
|
||||||
|
2. **Save Responses**: After creating resources, save the returned UUIDs for use in other requests
|
||||||
|
|
||||||
|
3. **Test in Order**: Follow the testing order above to avoid foreign key errors
|
||||||
|
|
||||||
|
4. **Check Server**: Make sure your server is running on port 3200 before testing
|
||||||
|
|
||||||
|
## 🔗 Base URL
|
||||||
|
|
||||||
|
All endpoints use: `http://localhost:3200`
|
||||||
|
|
||||||
|
If your server runs on a different port, update the base URL in the collection variables.
|
||||||
|
|
||||||
|
|
@ -5,7 +5,9 @@
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"start": "node server.js",
|
||||||
|
"dev": "node server.js"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -20,6 +20,20 @@ const createNewLocation = async (client, userId, locationData) => {
|
||||||
pincode,
|
pincode,
|
||||||
} = locationData;
|
} = locationData;
|
||||||
|
|
||||||
|
// Validate user exists if this is a saved address
|
||||||
|
let finalUserId = userId;
|
||||||
|
if (is_saved_address && userId) {
|
||||||
|
const userCheck = await client.query("SELECT id FROM users WHERE id = $1 AND deleted = FALSE", [userId]);
|
||||||
|
if (userCheck.rows.length === 0) {
|
||||||
|
throw new Error(`User with id ${userId} does not exist. Cannot create saved address for non-existent user.`);
|
||||||
|
}
|
||||||
|
} else if (!is_saved_address) {
|
||||||
|
// For captured locations (not saved addresses), user_id can be NULL
|
||||||
|
finalUserId = null;
|
||||||
|
} else if (is_saved_address && !userId) {
|
||||||
|
throw new Error("user_id is required when is_saved_address is true");
|
||||||
|
}
|
||||||
|
|
||||||
// 1. Insert into locations (Merged Table)
|
// 1. Insert into locations (Merged Table)
|
||||||
const insertLocationQuery = `
|
const insertLocationQuery = `
|
||||||
INSERT INTO locations (
|
INSERT INTO locations (
|
||||||
|
|
@ -31,7 +45,7 @@ const createNewLocation = async (client, userId, locationData) => {
|
||||||
RETURNING id
|
RETURNING id
|
||||||
`;
|
`;
|
||||||
const locationValues = [
|
const locationValues = [
|
||||||
userId,
|
finalUserId,
|
||||||
lat,
|
lat,
|
||||||
lng,
|
lng,
|
||||||
source_type || "manual",
|
source_type || "manual",
|
||||||
|
|
@ -266,6 +280,18 @@ router.post("/", async (req, res) => {
|
||||||
media // Array of { media_url, media_type, is_primary, sort_order }
|
media // Array of { media_url, media_type, is_primary, sort_order }
|
||||||
} = req.body;
|
} = req.body;
|
||||||
|
|
||||||
|
// Validate seller exists
|
||||||
|
if (seller_id) {
|
||||||
|
const sellerCheck = await client.query("SELECT id FROM users WHERE id = $1 AND deleted = FALSE", [seller_id]);
|
||||||
|
if (sellerCheck.rows.length === 0) {
|
||||||
|
await client.query("ROLLBACK");
|
||||||
|
return res.status(400).json({ error: `Seller with id ${seller_id} does not exist. Please create the user first.` });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await client.query("ROLLBACK");
|
||||||
|
return res.status(400).json({ error: "seller_id is required" });
|
||||||
|
}
|
||||||
|
|
||||||
let final_location_id = animal?.location_id;
|
let final_location_id = animal?.location_id;
|
||||||
|
|
||||||
// 1. Create Location (if needed)
|
// 1. Create Location (if needed)
|
||||||
|
|
@ -531,11 +557,32 @@ router.delete("/:id", async (req, res) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Get the list of species
|
||||||
|
router.get("/species", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const queryText = "SELECT * FROM species WHERE deleted = FALSE ORDER BY name";
|
||||||
|
const result = await pool.query(queryText);
|
||||||
|
res.json(result.rows);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error fetching species:", err);
|
||||||
|
res.status(500).json({ error: "Internal server error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Get the list of breeds
|
// Get the list of breeds
|
||||||
router.get("/breeds", async (req, res) => {
|
router.get("/breeds", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const queryText = "SELECT * FROM breeds";
|
const { species_id } = req.query;
|
||||||
const result = await pool.query(queryText);
|
let queryText = "SELECT * FROM breeds WHERE deleted = FALSE";
|
||||||
|
const queryParams = [];
|
||||||
|
|
||||||
|
if (species_id) {
|
||||||
|
queryText += " AND species_id = $1";
|
||||||
|
queryParams.push(species_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
queryText += " ORDER BY name";
|
||||||
|
const result = await pool.query(queryText, queryParams);
|
||||||
res.json(result.rows);
|
res.json(result.rows);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Error fetching breeds:", err);
|
console.error("Error fetching breeds:", err);
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,26 @@ router.post("/", async (req, res) => {
|
||||||
pincode,
|
pincode,
|
||||||
} = req.body;
|
} = req.body;
|
||||||
|
|
||||||
|
// Validate user exists if this is a saved address
|
||||||
|
let finalUserId = user_id;
|
||||||
|
if (is_saved_address && user_id) {
|
||||||
|
const userCheck = await client.query("SELECT id FROM users WHERE id = $1 AND deleted = FALSE", [user_id]);
|
||||||
|
if (userCheck.rows.length === 0) {
|
||||||
|
await client.query("ROLLBACK");
|
||||||
|
return res.status(400).json({
|
||||||
|
error: `User with id ${user_id} does not exist. Cannot create saved address for non-existent user.`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (!is_saved_address) {
|
||||||
|
// For captured locations (not saved addresses), user_id can be NULL
|
||||||
|
finalUserId = null;
|
||||||
|
} else if (is_saved_address && !user_id) {
|
||||||
|
await client.query("ROLLBACK");
|
||||||
|
return res.status(400).json({
|
||||||
|
error: "user_id is required when is_saved_address is true"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 1. Insert into locations
|
// 1. Insert into locations
|
||||||
const insertLocationQuery = `
|
const insertLocationQuery = `
|
||||||
INSERT INTO locations (
|
INSERT INTO locations (
|
||||||
|
|
@ -35,7 +55,7 @@ router.post("/", async (req, res) => {
|
||||||
RETURNING *
|
RETURNING *
|
||||||
`;
|
`;
|
||||||
const locationValues = [
|
const locationValues = [
|
||||||
user_id,
|
finalUserId,
|
||||||
lat,
|
lat,
|
||||||
lng,
|
lng,
|
||||||
source_type || "manual",
|
source_type || "manual",
|
||||||
|
|
@ -59,7 +79,15 @@ router.post("/", async (req, res) => {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await client.query("ROLLBACK");
|
await client.query("ROLLBACK");
|
||||||
console.error("Error creating location:", err);
|
console.error("Error creating location:", err);
|
||||||
res.status(500).json({ error: "Internal server error" });
|
|
||||||
|
// Provide more specific error messages
|
||||||
|
if (err.code === '23503') { // Foreign key violation
|
||||||
|
return res.status(400).json({
|
||||||
|
error: `Foreign key constraint violation: ${err.detail || 'The provided user_id does not exist in the users table.'}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(500).json({ error: err.message || "Internal server error" });
|
||||||
} finally {
|
} finally {
|
||||||
client.release();
|
client.release();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,169 @@
|
||||||
|
import express from "express";
|
||||||
|
import pool from "../db/pool.js";
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
// 1. CREATE User
|
||||||
|
router.post("/", async (req, res) => {
|
||||||
|
const client = await pool.connect();
|
||||||
|
try {
|
||||||
|
await client.query("BEGIN");
|
||||||
|
|
||||||
|
const {
|
||||||
|
id, // Optional: if provided, use this UUID; otherwise generate one
|
||||||
|
name,
|
||||||
|
phone_number,
|
||||||
|
avatar_url,
|
||||||
|
language,
|
||||||
|
timezone,
|
||||||
|
country_code = "+91",
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
// If id is provided, use it; otherwise let the database generate one
|
||||||
|
const insertUserQuery = id
|
||||||
|
? `
|
||||||
|
INSERT INTO users (id, name, phone_number, avatar_url, language, timezone, country_code)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||||
|
RETURNING *
|
||||||
|
`
|
||||||
|
: `
|
||||||
|
INSERT INTO users (name, phone_number, avatar_url, language, timezone, country_code)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6)
|
||||||
|
RETURNING *
|
||||||
|
`;
|
||||||
|
|
||||||
|
const userValues = id
|
||||||
|
? [id, name, phone_number, avatar_url, language, timezone, country_code]
|
||||||
|
: [name, phone_number, avatar_url, language, timezone, country_code];
|
||||||
|
|
||||||
|
const userResult = await client.query(insertUserQuery, userValues);
|
||||||
|
|
||||||
|
await client.query("COMMIT");
|
||||||
|
|
||||||
|
res.status(201).json(userResult.rows[0]);
|
||||||
|
} catch (err) {
|
||||||
|
await client.query("ROLLBACK");
|
||||||
|
console.error("Error creating user:", err);
|
||||||
|
|
||||||
|
if (err.code === "23505") {
|
||||||
|
// Unique constraint violation
|
||||||
|
return res.status(400).json({
|
||||||
|
error: err.detail || "A user with this phone number or ID already exists",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err.code === "23503") {
|
||||||
|
// Foreign key violation
|
||||||
|
return res.status(400).json({
|
||||||
|
error: err.detail || "Foreign key constraint violation",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(500).json({ error: err.message || "Internal server error" });
|
||||||
|
} finally {
|
||||||
|
client.release();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. GET All Users
|
||||||
|
router.get("/", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { limit = 100, offset = 0 } = req.query;
|
||||||
|
const queryText = `
|
||||||
|
SELECT id, name, phone_number, avatar_url, language, timezone, country_code,
|
||||||
|
is_active, created_at, updated_at
|
||||||
|
FROM users
|
||||||
|
WHERE deleted = FALSE
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
LIMIT $1 OFFSET $2
|
||||||
|
`;
|
||||||
|
const result = await pool.query(queryText, [limit, offset]);
|
||||||
|
res.json(result.rows);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error fetching users:", err);
|
||||||
|
res.status(500).json({ error: "Internal server error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3. GET Single User
|
||||||
|
router.get("/:id", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { id } = req.params;
|
||||||
|
const queryText = `
|
||||||
|
SELECT id, name, phone_number, avatar_url, language, timezone, country_code,
|
||||||
|
is_active, created_at, updated_at
|
||||||
|
FROM users
|
||||||
|
WHERE id = $1 AND deleted = FALSE
|
||||||
|
`;
|
||||||
|
const result = await pool.query(queryText, [id]);
|
||||||
|
|
||||||
|
if (result.rows.length === 0) {
|
||||||
|
return res.status(404).json({ error: "User not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json(result.rows[0]);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error fetching user:", err);
|
||||||
|
res.status(500).json({ error: "Internal server error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 4. UPDATE User
|
||||||
|
router.put("/:id", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { id } = req.params;
|
||||||
|
const { name, phone_number, avatar_url, language, timezone, country_code, is_active } = req.body;
|
||||||
|
|
||||||
|
const updateQuery = `
|
||||||
|
UPDATE users
|
||||||
|
SET name = COALESCE($1, name),
|
||||||
|
phone_number = COALESCE($2, phone_number),
|
||||||
|
avatar_url = COALESCE($3, avatar_url),
|
||||||
|
language = COALESCE($4, language),
|
||||||
|
timezone = COALESCE($5, timezone),
|
||||||
|
country_code = COALESCE($6, country_code),
|
||||||
|
is_active = COALESCE($7, is_active)
|
||||||
|
WHERE id = $8 AND deleted = FALSE
|
||||||
|
RETURNING *
|
||||||
|
`;
|
||||||
|
|
||||||
|
const values = [name, phone_number, avatar_url, language, timezone, country_code, is_active, id];
|
||||||
|
|
||||||
|
const result = await pool.query(updateQuery, values);
|
||||||
|
|
||||||
|
if (result.rows.length === 0) {
|
||||||
|
return res.status(404).json({ error: "User not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json(result.rows[0]);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error updating user:", err);
|
||||||
|
res.status(500).json({ error: "Internal server error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 5. DELETE User (Soft Delete)
|
||||||
|
router.delete("/:id", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { id } = req.params;
|
||||||
|
const queryText = `
|
||||||
|
UPDATE users
|
||||||
|
SET deleted = TRUE
|
||||||
|
WHERE id = $1
|
||||||
|
RETURNING id
|
||||||
|
`;
|
||||||
|
const result = await pool.query(queryText, [id]);
|
||||||
|
|
||||||
|
if (result.rows.length === 0) {
|
||||||
|
return res.status(404).json({ error: "User not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json({ message: "User deleted successfully" });
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error deleting user:", err);
|
||||||
|
res.status(500).json({ error: "Internal server error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
|
|
||||||
23
server.js
23
server.js
|
|
@ -1,24 +1,31 @@
|
||||||
import express from "express";
|
import express from "express";
|
||||||
import cors from "cors";
|
import cors from "cors";
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
import { dirname, join } from 'path';
|
||||||
|
import http from "http";
|
||||||
|
import listingRoutes from "./routes/listingRoutes.js";
|
||||||
|
import locationRoutes from "./routes/locationRoutes.js";
|
||||||
|
import chatRoutes from "./routes/chatRoutes.js";
|
||||||
|
import userRoutes from "./routes/userRoutes.js";
|
||||||
|
import { initSocket } from "./socket.js";
|
||||||
|
import { startExpirationJob } from "./jobs/expirationJob.js";
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
|
|
||||||
|
// Serve static files from public directory
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = dirname(__filename);
|
||||||
|
app.use(express.static(join(__dirname, 'public')));
|
||||||
|
|
||||||
const PORT = process.env.PORT || 3200;
|
const PORT = process.env.PORT || 3200;
|
||||||
|
|
||||||
// Add routes here
|
// Add routes here
|
||||||
import listingRoutes from "./routes/listingRoutes.js";
|
|
||||||
import locationRoutes from "./routes/locationRoutes.js";
|
|
||||||
import chatRoutes from "./routes/chatRoutes.js";
|
|
||||||
|
|
||||||
|
|
||||||
app.use("/listings", listingRoutes);
|
app.use("/listings", listingRoutes);
|
||||||
app.use("/locations", locationRoutes);
|
app.use("/locations", locationRoutes);
|
||||||
app.use("/chat", chatRoutes);
|
app.use("/chat", chatRoutes);
|
||||||
import http from "http";
|
app.use("/users", userRoutes);
|
||||||
import { initSocket } from "./socket.js";
|
|
||||||
import { startExpirationJob } from "./jobs/expirationJob.js";
|
|
||||||
|
|
||||||
const server = http.createServer(app);
|
const server = http.createServer(app);
|
||||||
initSocket(server);
|
initSocket(server);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue