Files
bonpin-adrian-movie-api/README.md
T

3.6 KiB
Raw Blame History

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

npm install
npm start          # node server.js

Open http://localhost:3000.

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:

{ "error": "Title is required.", "fields": { "title": "Title is required.", "year": "Year is required." } }

Examples

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

[
  { "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

{ "id": 4, "title": "Inception", "genre": "science fiction", "year": 2010 }

POST /api/movies with {} → 400

{
  "error": "Title is required.",
  "fields": {
    "title": "Title is required.",
    "genre": "Genre is required.",
    "year": "Year is required."
  }
}

GET /api/movies/abc → 400

{ "error": "ID must be a whole number, like 1." }

GET /api/movies/99 → 404

{ "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. 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.