A Node.js REST API for managing school data with proximity-based sorting functionality. Built with Express.js, MySQL, and featuring geographical distance calculations.
- Add Schools: Add new schools with name, address, and coordinates
- List Schools: Retrieve all schools sorted by proximity to user location
- Data Validation: Comprehensive input validation for all endpoints
- Geographical Sorting: Haversine formula for accurate distance calculations
- Security: Helmet.js for security headers and CORS support
- Logging: Morgan for HTTP request logging
- Error Handling: Comprehensive error handling and validation
- Node.js (v14 or higher)
- MySQL (v8.0 or higher)
- npm or yarn
-
Clone the repository
git clone <repository-url> cd school-management-api
-
Install dependencies
npm install
-
Set up environment variables
cp env.example .env
Edit
.envfile with your database credentials:DB_HOST=localhost DB_USER=root DB_PASSWORD=your_password DB_NAME=school_management DB_PORT=3306 PORT=3000 NODE_ENV=development
-
Create MySQL database
CREATE DATABASE school_management;
-
Start the server
# Development mode with auto-restart npm run dev # Production mode npm start
http://localhost:3000
POST /addSchool
Add a new school to the database.
Request Body:
{
"name": "Delhi Public School",
"address": "123 Main Street, New Delhi, India",
"latitude": 28.7041,
"longitude": 77.1025
}Response:
{
"success": true,
"message": "School added successfully",
"data": {
"id": 1,
"name": "Delhi Public School",
"address": "123 Main Street, New Delhi, India",
"latitude": 28.7041,
"longitude": 77.1025,
"created_at": "2024-01-15T10:30:00.000Z",
"updated_at": "2024-01-15T10:30:00.000Z"
}
}GET /listSchools?latitude=28.7041&longitude=77.1025
Get all schools sorted by proximity to the specified coordinates.
Query Parameters:
latitude(required): User's latitude (-90 to 90)longitude(required): User's longitude (-180 to 180)
Response:
{
"success": true,
"message": "Schools retrieved successfully",
"data": [
{
"id": 1,
"name": "Delhi Public School",
"address": "123 Main Street, New Delhi, India",
"latitude": 28.7041,
"longitude": 77.1025,
"created_at": "2024-01-15T10:30:00.000Z",
"updated_at": "2024-01-15T10:30:00.000Z",
"distance": 0.0
},
{
"id": 2,
"name": "Mumbai International School",
"address": "456 Marine Drive, Mumbai, India",
"latitude": 19.0760,
"longitude": 72.8777,
"created_at": "2024-01-15T10:35:00.000Z",
"updated_at": "2024-01-15T10:35:00.000Z",
"distance": 1156.8
}
],
"total": 2,
"userLocation": {
"latitude": 28.7041,
"longitude": 77.1025
}
}GET /school/:id
Get a specific school by its ID.
Response:
{
"success": true,
"message": "School retrieved successfully",
"data": {
"id": 1,
"name": "Delhi Public School",
"address": "123 Main Street, New Delhi, India",
"latitude": 28.7041,
"longitude": 77.1025,
"created_at": "2024-01-15T10:30:00.000Z",
"updated_at": "2024-01-15T10:30:00.000Z"
}
}GET /health
Check if the API is running.
Response:
{
"success": true,
"message": "School Management API is running",
"timestamp": "2024-01-15T10:30:00.000Z",
"environment": "development"
}- name: Required, 2-255 characters
- address: Required, 5-500 characters
- latitude: Required, float between -90 and 90
- longitude: Required, float between -180 and 180
- latitude: Required, float between -90 and 90
- longitude: Required, float between -180 and 180
CREATE TABLE schools (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
address VARCHAR(500) NOT NULL,
latitude FLOAT NOT NULL,
longitude FLOAT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);The API uses the Haversine formula to calculate geographical distances between coordinates:
const R = 6371; // Earth's radius in kilometers
const dLat = (lat2 - lat1) * Math.PI / 180;
const dLon = (lon2 - lon1) * Math.PI / 180;
const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
Math.sin(dLon/2) * Math.sin(dLon/2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
const distance = R * c;npm run devnpm startNODE_ENV=production
PORT=3000
DB_HOST=your-production-db-host
DB_USER=your-production-db-user
DB_PASSWORD=your-production-db-password
DB_NAME=your-production-db-name
DB_PORT=3306school-management-api/
โโโ config/
โ โโโ database.js # Database configuration
โโโ controllers/
โ โโโ schoolController.js # Business logic
โโโ middleware/
โ โโโ validation.js # Input validation
โโโ routes/
โ โโโ schoolRoutes.js # API routes
โโโ utils/
โ โโโ distanceCalculator.js # Distance calculation utilities
โโโ server.js # Main server file
โโโ package.json # Dependencies
โโโ env.example # Environment variables template
โโโ README.md # Documentation
-
Add School Request:
- Method: POST
- URL:
http://localhost:3000/addSchool - Headers:
Content-Type: application/json - Body:
{ "name": "Test School", "address": "Test Address, Test City", "latitude": 28.7041, "longitude": 77.1025 } -
List Schools Request:
- Method: GET
- URL:
http://localhost:3000/listSchools?latitude=28.7041&longitude=77.1025
# Add a school
curl -X POST http://localhost:3000/addSchool \
-H "Content-Type: application/json" \
-d '{
"name": "Test School",
"address": "Test Address, Test City",
"latitude": 28.7041,
"longitude": 77.1025
}'
# List schools
curl "http://localhost:3000/listSchools?latitude=28.7041&longitude=77.1025"- Helmet.js: Security headers
- CORS: Cross-origin resource sharing
- Input Validation: Comprehensive validation using express-validator
- SQL Injection Protection: Parameterized queries with mysql2
- Error Handling: Secure error responses
The API returns consistent error responses:
{
"success": false,
"message": "Error description",
"errors": [
{
"field": "latitude",
"message": "Latitude must be a valid number between -90 and 90",
"value": "invalid"
}
]
}- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
This project is licensed under the MIT License.
For support, please open an issue in the repository or contact the development team.