# Movie Collection API A simple Movie Collection REST API built with **Node.js + Express**, plus a single-page frontend that talks to it with `fetch()`. A **Movie** is one entry in the collection; the collection is `/api/movies`. Movies are kept in a plain JavaScript array, so **there is no database — records added through the API disappear when the server restarts.** ## Running ```sh npm install npm start # node server.js ``` Open . ```sh npm run dev # node --watch server.js PORT=4000 npm start ``` ## Schema Each movie has four fields: | Field | Type | Notes | | --- | --- | --- | | `id` | integer ≥ 1 | **assigned by the server**, never sent by the client | | `title` | string, 1–120 chars | required, trimmed | | `genre` | string, 1–60 chars | required, trimmed | | `year` | integer, 1888–2100 | required; `"2010"` and `2010` are both accepted | The three request fields are required. Anything missing or blank comes back as a `400` with one message per field. ## Endpoints | Method | Path | Result | | --- | --- | --- | | `GET` | `/api/movies` | all movies → `200` | | `GET` | `/api/movies/:id` | one movie → `200`, or `404` if there is no such id | | `POST` | `/api/movies` | add a movie → `201` with a `Location` header | | `GET` | `/` | the frontend | Errors come back as a message plus the offending fields: ```json { "error": "Title is required.", "fields": { "title": "Title is required.", "year": "Year is required." } } ``` ## Examples ```sh curl http://localhost:3000/api/movies curl http://localhost:3000/api/movies/2 curl -X POST http://localhost:3000/api/movies \ -H 'content-type: application/json' \ -d '{"title":"Inception","genre":"science fiction","year":2010}' ``` `GET /api/movies` → `200` ```json [ { "id": 1, "title": "Interstellar", "genre": "Science Fiction", "year": 2014 }, { "id": 2, "title": "Avengers: Endgame", "genre": "Action", "year": 2019 }, { "id": 3, "title": "Coco", "genre": "Animation", "year": 2017 } ] ``` `POST /api/movies` → `201` · `Location: /api/movies/4` ```json { "id": 4, "title": "Inception", "genre": "science fiction", "year": 2010 } ``` `POST /api/movies` with `{}` → `400` ```json { "error": "Title is required.", "fields": { "title": "Title is required.", "genre": "Genre is required.", "year": "Year is required." } } ``` `GET /api/movies/abc` → `400` ```json { "error": "ID must be a whole number, like 1." } ``` `GET /api/movies/99` → `404` ```json { "error": "No movie with ID 99." } ``` ## Frontend `index.html` is a single file (no build step, no framework) served by the same Express app. It: - displays the movie list in a table, - has a form for adding a movie (title, genre, year), - uses `fetch()` for every call to the API, - refreshes the list after a movie is added. Clicking a row fetches that one movie from `GET /api/movies/:id` and shows it in a detail panel, so all three endpoints are exercised from the UI. ## Files ``` server.js Express app: schemas, in-memory store, routes, error handling index.html the frontend (styles + fetch logic, no dependencies) package.json express + zod ``` ## Project structure notes - **Storage** is `const movies = []` in `server.js`, with a `nextId` counter for the auto-assigned `id`. It is seeded with three movies on startup. - **Validation** uses [zod](https://zod.dev). One schema per shape (`movieDraftSchema` for the request body, `movieSchema` for what is stored and returned), and a small helper turns a failure into the `{ error, fields }` response the frontend renders next to each input. - `node_modules/` is git-ignored.