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
76 changes: 76 additions & 0 deletions NOTES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Notes

## Plan

Задача — реалізувати `PUT /users/:id` так, щоб пройшли всі три сценарії з
`tests/update-user.test.js`: успішне оновлення існуючого користувача (200 з
оновленими полями), 404 для неіснуючого id, 400 при відсутньому полі в тілі
запиту.

Перед написанням коду я дослідила структуру репозиторію (`server.js` →
`routes/users.js` → `db/store.js`, in-memory масив користувачів) і побачила,
що `GET /`, `GET /:id` та `POST /` вже задають чіткий конвенційний стиль:
парсинг id через `Number(req.params.id)`, валідація `{ name, email }` через
перевірку на falsy зі status 400, і 404 з `{ error: "User not found" }` при
відсутньому користувачі. Затверджений план складався з двох кроків:

1. Додати в `db/store.js` функцію `updateUser(id, { name, email })`, яка
шукає користувача через існуючий `getUserById`, за наявності — мутує
`name`/`email` і повертає оновленого користувача, інакше повертає
`undefined`.
2. Додати в `routes/users.js` роут `router.put("/:id", ...)`, який спершу
валідує тіло запиту (400, якщо `name` або `email` відсутні — ще до
пошуку користувача, щоб цей сценарій спрацьовував навіть для існуючого
id), потім викликає `store.updateUser` і повертає 404 або 200 з
оновленим користувачем.

Під час реалізації від затвердженого плану не відхилялись — код вийшов
практично один в один з планом, без додаткових правок логіки.

## Model choice

Я працювала з Claude Sonnet 5 в Claude Code. Для дослідження кодової бази
використала окремого Explore-агента (щоб зібрати повний контекст: тест,
існуючі роути, стор, конвенції) — це дозволило спланувати зміну без здогадок
про формат помилок чи структуру відповіді. Саму реалізацію (дві невеликі,
шаблонні зміни за наявним патерном) писала напряму, без окремого
planning-агента, оскільки задача була достатньо простою і однозначною після
дослідження.

## Commits

Зміну розділила на два окремі, логічно незалежні коміти:

1. `Add updateUser helper to in-memory store` — зміна в `db/store.js`
(шар даних).
2. `Add PUT /users/:id endpoint` — зміна в `routes/users.js` (шар роутів),
яка використовує щойно доданий helper.

Такий поділ відображає межу шарів у самому проєкті (`db/` vs `routes/`) і
робить кожен коміт самодостатнім для рев'ю: перший коміт можна перевірити
ізольовано як просте розширення стору за наявним патерном (`createUser`,
`getUserById`), другий — як інтеграцію цього helper-а в HTTP-шар з
валідацією та обробкою помилок.

Окремо: спершу я випадково закомітила обидві зміни прямо в `main` і встигла
запушити це у форк. Після зауваження користувача я перенесла обидва коміти
на нову гілку `feature/update-user-endpoint`, відкотила `origin/main`
force-push-ом назад до попереднього стану і вже з фічної гілки відкрила PR.

## Review

Я запускала `/code-review` (рівень medium) на diff з обох комітів. Рев'ю
пройшлось по коду рядок за рядком, перевірило not-found-шлях (включно з
нечисловим id, який через `Number()` перетворюється на `NaN` і коректно не
матчиться жодному id), порядок валідації відносно пошуку користувача, форму
відповіді (узгоджена з `GET`/`POST`), а також можливі спрощення/дублювання.
Явних багів чи проблем рев'ю не знайшло — реалізація визнана мінімальним і
точним віддзеркаленням наявних патернів (`POST /users` для валідації,
`GET /:id` для 404). Окремо я звернула увагу на дрібні межові випадки, які
не покриті тестами і залишені навмисно (без змін), бо вони узгоджені з
поведінкою вже наявного `POST /users`: рядки з самих пробілів (`" "`)
проходять перевірку на falsy, а типи `name`/`email` не валідуються — це не
регресія, а той самий рівень строгості, що вже був у коді.

`npm test` та `npm run lint` пройшли успішно для обох комітів (окрім двох
тестів у `notes.test.js`, які до появи цього файлу очікувано падали).
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 = getUserById(id);

if (!user) {
return undefined;
}

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 { name, email } = req.body;

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

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

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

res.json(user);
});

module.exports = router;