Files
bonpin-student-api-mw600/README.md
T
adrianbonpin 45e4de3557 Add Student Management mini system
Express + MySQL CRUD API for student records, with a plain HTML frontend.

- Single-file backend (server.js) with 5 CRUD routes
- Proper HTTP status codes and a consistent error envelope
- 8-digit ids: 2-digit year + per-year 6-digit counter (e.g. 26000001),
  allocated under a MySQL advisory lock so concurrent inserts cannot collide
- student_db.sql schema and seed data
- .env for credentials; only .env.example is committed
2026-09-28 18:58:42 +08:00

83 lines
2.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Student Management System (MW600)
A mini system for managing student records, built with **Express** and **MySQL**.
Backend is a single file (`server.js`) exposing a CRUD API; the frontend is a
plain HTML page (`index.html`) served from the same server.
## Requirements
- Node.js 20.6+ (uses `process.loadEnvFile`)
- A running MySQL server
## Setup
```sh
npm install
cp .env.example .env # then fill in your MySQL credentials
npm run db:push # creates the database and imports student_db.sql
npm start
```
Open http://localhost:3000
`npm run db:push` creates the `student_db` database and imports the schema and
seed data from `student_db.sql`. It is safe to re-run — the script drops and
recreates the `students` table.
## Database
`student_db.sql` holds the schema and seed rows for a single table:
| Column | Type | Notes |
| ------------ | ------------ | ---------------------------- |
| `id` | `INT` | Primary key, assigned by app |
| `name` | `VARCHAR(100)` | Required |
| `course` | `VARCHAR(50)` | Required |
| `year_level` | `INT` | Required, 1–6 |
### ID format
Ids are **8 digits**: a 2-digit year followed by a 6-digit counter that resets
each year.
```
26 000001 -> first student added in 2026
26 000002 -> second student added in 2026
27 000001 -> first student added in 2027
```
The counter is per year, so ids never collide across years. Because MySQL cannot
generate this pattern, `id` has no `AUTO_INCREMENT` — the application assigns it.
Allocation is guarded by a MySQL advisory lock (`GET_LOCK`) so simultaneous
requests cannot receive the same id.
## API
| Method | Path | Response |
| -------- | -------------------- | -------------------------------------------- |
| `GET` | `/api/students` | `200` list of students |
| `GET` | `/api/students/:id` | `200` student, `400` bad id, `404` not found |
| `POST` | `/api/students` | `201` created, `400` invalid, `415` not JSON |
| `PUT` | `/api/students/:id` | `200` updated, `400` invalid, `404` not found |
| `DELETE` | `/api/students/:id` | `204` deleted, `404` not found |
Errors use one envelope:
```json
{ "error": { "code": "VALIDATION_ERROR", "message": "...", "details": [] } }
```
## Configuration
All connection settings live in `.env` (not committed):
| Variable | Default |
| ------------- | ------------- |
| `DB_HOST` | `127.0.0.1` |
| `DB_PORT` | `3306` |
| `DB_USER` | `root` |
| `DB_PASSWORD` | *required* |
| `DB_NAME` | `student_db` |
| `PORT` | `3000` |