Skip to content

IronPTSolutions/express-books-api

Repository files navigation

Express Books API

REST API built with Node.js and Express, refactored to follow the MVC (Model-View-Controller) architectural pattern.

Project structure

express-books-api/
├── index.js                    # Entry point: app setup, middleware, server start
├── books.json                  # In-memory data store (resets on restart)
├── config/
│   └── routes.config.js        # Route definitions — maps URLs to controller actions
├── controllers/
│   └── book.controller.js      # Request/response logic for the Book resource
└── models/
    └── book.model.js           # Data access and business logic for books

MVC architecture

MVC separates an application into three distinct responsibilities. Each layer has one job and communicates only with the layer directly below it.

Request → Router → Controller → Model → (data)
                       ↓
                    Response

Model (models/book.model.js)

The model is the only layer that knows about the data. It contains:

  • The Joi validation schema that enforces required fields on creation.
  • All data access methods (find, findById, create, findByIdAndUpdate, findByIdAndDelete) — modelled after the Mongoose API so the transition to a real database is straightforward.

The model never imports Express or touches req/res.

Controller (controllers/book.controller.js)

The controller sits between the router and the model. It:

  1. Reads data from the incoming request (req.params, req.query, req.body).
  2. Calls the appropriate model method.
  3. Sends the HTTP response (res.json(...), res.status(...)).

Controllers contain no business logic — if you find yourself filtering an array inside a controller, that code belongs in the model.

Router / Config (config/routes.config.js)

The router maps each HTTP method + URL pattern to a controller action. It does nothing else.

Centralising routes here means index.js stays clean and new resource routers can be added with a single app.use(...) line.

Entry point (index.js)

Bootstraps Express, registers global middleware (express.json()), mounts the router, and starts the server. Nothing else lives here.


Setup

npm install
npm run dev

The server starts on http://localhost:8000.


Endpoints

Method URL Description
GET /api/books Return all books
GET /api/books?genre=sci-fi Filter by genre
GET /api/books?sort=year Sort by year (ascending)
GET /api/books?genre=sci-fi&sort=year Filter + sort combined
GET /api/books/:id Return a single book by id
POST /api/books Create a new book
PUT /api/books/:id Partially update a book
DELETE /api/books/:id Delete a book

POST / PUT body

{
  "title": "Refactoring",
  "author": "Martin Fowler",
  "genre": "programming",
  "year": 1999
}

All fields except available are required on creation. available defaults to undefined when omitted.


HTTP status codes

Status When
200 Successful GET, PUT
204 Successful DELETE (no body)
400 Validation error on POST (missing or wrong field type)
404 Book id not found

Notes

  • The books array is in-memory only — all changes reset when the server restarts.
  • Validation uses Joi. The schema lives in the model, not the controller.
  • node --watch (Node 18+) provides hot-reload without nodemon.
  • Method names (find, findById, findByIdAndUpdate, findByIdAndDelete) intentionally mirror the Mongoose API to ease the migration to MongoDB later.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors