Personal Catalogue: React, Express & MongoDB — Chapter 3, Exercise 1 ===================================================================== TASK Build all five routes (POST, GET list, GET one, PUT, DELETE) into a real routes/items.js file, mount it in server.js, and confirm all five work against a running MongoDB instance using curl or a REST client. SOLUTION routes/items.js: const express = require('express'); const router = express.Router(); const { Item } = require('../models/Item'); const Book = require('../models/Book'); const Cd = require('../models/Cd'); const Dvd = require('../models/Dvd'); const Bluray = require('../models/Bluray'); const MODEL_MAP = { Book, Cd, Dvd, Bluray }; router.post('/', async (req, res) => { const Model = MODEL_MAP[req.body.itemType]; if (!Model) { return res.status(400).json({ error: `Unknown itemType: ${req.body.itemType}` }); } try { const item = await Model.create(req.body); res.status(201).json(item); } catch (err) { if (err.name === 'ValidationError') { return res.status(400).json({ error: err.message }); } res.status(500).json({ error: 'Server error' }); } }); router.get('/', async (req, res) => { const items = await Item.find().lean(); res.json(items); }); router.get('/:id', async (req, res) => { const item = await Item.findById(req.params.id).lean(); if (!item) return res.status(404).json({ error: 'Item not found' }); res.json(item); }); router.put('/:id', async (req, res) => { const existing = await Item.findById(req.params.id); if (!existing) return res.status(404).json({ error: 'Item not found' }); const Model = MODEL_MAP[existing.itemType]; try { const updated = await Model.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true, }).lean(); res.json(updated); } catch (err) { if (err.name === 'ValidationError') { return res.status(400).json({ error: err.message }); } res.status(500).json({ error: 'Server error' }); } }); router.delete('/:id', async (req, res) => { const deleted = await Item.findByIdAndDelete(req.params.id); if (!deleted) return res.status(404).json({ error: 'Item not found' }); res.status(204).send(); }); module.exports = router; server.js (addition, after mongoose.connect): const itemsRouter = require('./routes/items'); app.use('/api/items', itemsRouter); Testing all five with curl, in order: curl -X POST http://localhost:4000/api/items \ -H "Content-Type: application/json" \ -d '{"itemType":"Cd","title":"OK Computer","artist":"Radiohead"}' curl http://localhost:4000/api/items curl http://localhost:4000/api/items/ curl -X PUT http://localhost:4000/api/items/ \ -H "Content-Type: application/json" \ -d '{"notes":"On vinyl"}' curl -X DELETE http://localhost:4000/api/items/ Run with: npx nodemon server.js (in one terminal), then the five curl commands above (in another) Output (in order): a real 201-created Cd document with a genuine _id; the same document appearing in the GET list; the same document returned by the single-item GET; the updated document with "notes":"On vinyl" after the PUT; and a 204 No Content response from the DELETE, confirmed by a final GET /api/items returning one fewer item than before. WHY THIS WORKS AS AN ANSWER ---------------------------- It builds all five routes with the real dynamic-dispatch logic create and update both need, keeps delete deliberately simple per the chapter's own finding, and proves every route actually works against a live database with real requests and real observed responses rather than just reciting the route definitions.