Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Quick Start

**Common commands:**
- `npm run dev` — Run server with file-watching during development
- `npm start` — Run the server once
- `npm test` — Run all tests (Node.js built-in test runner)
- `npm run lint` — Run ESLint

**Run a single test:**
```
node --test tests/update-user.test.js
```

## Architecture

This is a small Express API (starter template for course projects) with three layers:

**1. Server (`server.js`)**
- Creates Express app, registers middleware (JSON parsing), mounts route handlers
- Exports `app` so tests can import it; only starts listening when run directly

**2. Routes (`routes/`)**
- `routes/users.js` — User resource: GET /users (list), GET /users/:id (fetch), POST /users (create), PUT /users/:id (update — to be implemented)
- `routes/health.js` — Health check endpoint
- Each route validates input (return 400 for missing fields) and handles missing resources (return 404)

**3. Data Store (`db/store.js`)**
- In-memory data store (not persisted; resets on restart)
- All data access goes through the store module
- Exports: `getAllUsers()`, `getUserById(id)`, `createUser({ name, email })`, and `updateUser(id, { name, email })` (to be implemented)

## Current Project: Implement PUT /users/:id

**What to build:**
- Add a `PUT /users/:id` endpoint to update an existing user
- Validate that both `name` and `email` are provided in the request body (return 400 if missing)
- Return 404 if the user doesn't exist
- Return 200 with the updated user object on success
- Follow the existing pattern: route handler calls a store function

**Tests:** `tests/update-user.test.js` defines the requirements. Run tests as you build; they'll turn green when the endpoint is correct.

**Related files to touch:**
- `routes/users.js` — Add the PUT route handler
- `db/store.js` — Add the `updateUser(id, { name, email })` function (update the user in-place, return the updated user)

## Testing

- Tests use Node.js built-in `test` module (no external test framework)
- `supertest` for HTTP request/response assertions
- Tests import `app` from `server.js`, so server doesn't start listening during test runs
- Each test file runs independently

## Code Style

- ESLint rules in `.eslintrc.json` — unused parameters matching `_`, `req`, `res`, `next` are OK
- No strict linting — warnings are fine, aim to avoid errors

## Environment

- `.env.example` shows the shape of environment config
- PORT defaults to 3000 if not set
- Create `.env` from `.env.example` to override defaults locally
17 changes: 17 additions & 0 deletions NOTES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Implementation Notes: PUT /users/:id

## Plan

The approved plan specified adding a `PUT /users/:id` endpoint by modifying two files: `db/store.js` to add an `updateUser` function, and `routes/users.js` to add the route handler with validation and not-found handling. The plan correctly identified that validation should reject missing and invalid (non-string, empty/whitespace) fields with a 400 response, and return 404 for non-existent users. I did not edit the plan before approving it — it was clear and complete as written.

## Model Choice

I chose Claude Haiku 4.5 because the task was well-scoped with clear, concrete test requirements and straightforward implementation following existing code patterns. The small size and speed of Haiku made it ideal for a feature of this scope, and it proved sufficient to complete the work correctly on the first try.

## Commit Split

I split the work into three commits: (1) add the `updateUser` store function, (2) add the `PUT /:id` route handler, and (3) add CLAUDE.md and NOTES.md documentation. The first two commits separate data access (store layer) from HTTP handling (routes layer), making each change's responsibility clear and independently reviewable. The documentation commit is a natural standalone piece that should be reviewed separately.

## Review

The review confirmed that validation correctly rejects missing, non-string, and empty/whitespace values, covering the "missing or invalid" requirement. It verified that 404 and 400 error responses match the expected codes and existing error message patterns. The implementation follows the same validation-before-store pattern as POST `/users`, and all three update-user tests pass with no regressions in other endpoints. No linting errors were introduced.
14 changes: 13 additions & 1 deletion db/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,16 @@ function createUser({ name, email }) {
return user;
}

module.exports = { getAllUsers, getUserById, createUser };
function updateUser(id, { name, email }) {
const user = users.find((user) => user.id === id);

if (!user) {
return null;
}

user.name = name;
user.email = email;
return user;
}

module.exports = { getAllUsers, getUserById, createUser, updateUser };
18 changes: 18 additions & 0 deletions routes/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,22 @@ router.post("/", (req, res) => {
res.status(201).json(user);
});

// PUT /users/:id — update an existing user; name and email are required
router.put("/:id", (req, res) => {
const id = Number(req.params.id);
const { name, email } = req.body;

if (typeof name !== "string" || !name.trim() || typeof email !== "string" || !email.trim()) {
return res.status(400).json({ error: "name and email are required" });
}

const user = store.updateUser(id, { name, email });

if (!user) {
return res.status(404).json({ error: "User not found" });
}

res.json(user);
});

module.exports = router;