Skip to content

Commit 02a5c3a

Browse files
Merge pull request #10 from numericgraphics/feature/08_add-seeder
Add seeder
2 parents 6c2774f + 1eaa464 commit 02a5c3a

File tree

7 files changed

+582
-122
lines changed

7 files changed

+582
-122
lines changed

README.md

Lines changed: 233 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,234 @@
11
# speed-puzzle-backend
2-
backend project
2+
3+
Backend API for the **Speed Puzzle** app.
4+
5+
- **Language**: TypeScript
6+
- **Framework**: Express (Node.js)
7+
- **Database**: MongoDB
8+
- **Data model**
9+
- `users`: `{ _id, userName, password(hashed), createdAt, updatedAt }`
10+
- `scores`: `{ _id, userId (ref users._id), value, createdAt }`
11+
12+
---
13+
14+
## Tech stack
15+
16+
- Express (REST API)
17+
- MongoDB Node.js driver
18+
- TypeScript + `tsx` (watch/dev runner)
19+
- `dotenv` for env vars
20+
- `bcryptjs` for password hashing
21+
- `@faker-js/faker` for seed data
22+
23+
---
24+
25+
## Project structure
26+
27+
```text
28+
src/
29+
constants/events.ts
30+
controllers/Global.ts
31+
services/
32+
MongoDB.ts
33+
Users.ts
34+
Scores.ts
35+
index.ts
36+
scripts/
37+
seed.ts
38+
```
39+
40+
> Note: The seeder populates 15 users with 1–3 scores each (200–500).
41+
42+
---
43+
44+
## Setup
45+
46+
1. **Install**
47+
48+
```bash
49+
npm install
50+
```
51+
52+
2. **Environment** — create a `.env` at the project root:
53+
54+
```bash
55+
MONGODB_URI="mongodb://localhost:27017"
56+
API_PORT=3000
57+
```
58+
59+
3. **Run**
60+
61+
```bash
62+
# dev (watch)
63+
npm run dev
64+
65+
# prod
66+
npm run build
67+
npm start
68+
```
69+
70+
4. **Seed demo data**
71+
72+
```bash
73+
# inserts 15 users with 1–3 scores each (values 200–500)
74+
npm run seed
75+
76+
# wipe & reseed
77+
npm run seed -- --reset
78+
```
79+
80+
---
81+
82+
## REST API
83+
84+
**Base URL:** `http://localhost:3000`
85+
86+
### GET `/`
87+
88+
Health check.
89+
90+
```
91+
200 OK → "<h1>Hello world</h1>"
92+
```
93+
94+
---
95+
96+
### POST `/adduser`
97+
98+
Create a user aligned with the mobile schema (optionally with an initial score).
99+
100+
**Body**
101+
102+
```json
103+
{
104+
"userName": "Ada Lovelace",
105+
"password": "SeedUser#2025",
106+
"score": 420
107+
}
108+
```
109+
110+
**Responses**
111+
112+
- `200 OK` → array of users (public fields only)
113+
- `409 Conflict` → "User Already Exist."
114+
115+
**cURL**
116+
117+
```bash
118+
curl -s -X POST http://localhost:3000/adduser \
119+
-H 'content-type: application/json' \
120+
-d '{"userName":"Ada Lovelace","password":"SeedUser#2025","score":420}' | jq .
121+
```
122+
123+
---
124+
125+
### POST `/users/:userName/scores`
126+
127+
Add a score for an existing user.
128+
129+
**Body**
130+
131+
```json
132+
{ "value": 451 }
133+
```
134+
135+
**Responses**
136+
137+
- `201 Created``{ "userId": "<ObjectId>", "value": 451 }`
138+
- `400 Bad Request` if `value` is not a number
139+
- `409 Conflict` if rejected by the acceptance rule
140+
141+
**cURL**
142+
143+
```bash
144+
curl -s -X POST 'http://localhost:3000/users/Ada%20Lovelace/scores' \
145+
-H 'content-type: application/json' \
146+
-d '{"value":451}' | jq .
147+
```
148+
149+
---
150+
151+
### POST `/score`
152+
153+
Check a raw score against the global minimum across all scores. **Does not persist**.
154+
155+
**Body**
156+
157+
```json
158+
{ "score": 300 }
159+
```
160+
161+
**Responses**
162+
163+
- `200 OK` if accepted
164+
- `409 Conflict` if rejected
165+
166+
**cURL**
167+
168+
```bash
169+
curl -i -X POST http://localhost:3000/score \
170+
-H 'content-type: application/json' \
171+
-d '{"score":300}'
172+
```
173+
174+
---
175+
176+
### GET `/users`
177+
178+
List all users (public fields only).
179+
180+
**Response (example)**
181+
182+
```json
183+
[
184+
{
185+
"_id": "665e...",
186+
"userName": "Ava Johnson",
187+
"createdAt": 1720000000000,
188+
"updatedAt": 1720000000000
189+
}
190+
]
191+
```
192+
193+
**cURL**
194+
195+
```bash
196+
curl -s http://localhost:3000/users | jq .
197+
```
198+
199+
---
200+
201+
### GET `/scores/top?limit=10`
202+
203+
Top `limit` scores (default 10). Each item returns `{ score, user }`.
204+
205+
**Response (example)**
206+
207+
```json
208+
[
209+
{
210+
"score": 497,
211+
"user": { "_id": "665e...", "userName": "Noah Smith", "createdAt": 172..., "updatedAt": 172... }
212+
}
213+
]
214+
```
215+
216+
**cURL**
217+
218+
```bash
219+
curl -s 'http://localhost:3000/scores/top?limit=5' | jq .
220+
```
221+
222+
---
223+
224+
## Notes
225+
226+
- Passwords are hashed with `bcryptjs` (10 rounds).
227+
- Seeding uses Faker’s `person.fullName()` to generate human names.
228+
- `tsx` provides fast TypeScript execution with watch mode for development.
229+
230+
---
231+
232+
## License
233+
234+
MIT

0 commit comments

Comments
 (0)