Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Readify Bookstore API

A REST API portfolio project for managing books and authors. It demonstrates resource-oriented HTTP endpoints, JSON request validation, SQLite relationships, consistent error responses, OpenAPI documentation and request tracing.

Project status

The API runs locally and supports the documented book lifecycle. It is not currently deployed to a public environment, so all examples below use http://localhost:3000.

Key features

  • Create, list, retrieve, replace, update and delete books
  • List the authors seeded into the local database
  • Enforce author relationships and unique ISBN values with SQLite
  • Validate JSON bodies and reject unknown fields
  • Return consistent error codes, messages and request IDs
  • Publish interactive OpenAPI documentation through Swagger UI
  • Log request IDs, response status codes and request duration
  • Include a Postman collection for exploring the local endpoints

Technology stack

  • Node.js 22
  • Express 5
  • SQLite
  • OpenAPI 3.0 and Swagger UI
  • Postman and Newman

API endpoints

Method Endpoint Purpose Success status
GET /health Check service health 200
GET /authors List authors 200
GET /books List books 200
POST /books Create a book 201
GET /books/{id} Retrieve a book 200
PUT /books/{id} Replace a book's editable fields 200
PATCH /books/{id} Update selected book fields 200
DELETE /books/{id} Delete a book 204

Interactive documentation is available at /api-docs after the server starts. The source specification is in docs/openapi.yaml.

Installation

Requirements:

  • Node.js 22 or later
  • npm
git clone https://github.com/macrovise/bookstore-api.git
cd bookstore-api
npm ci
cp .env.example .env
npm start

The API starts on http://localhost:3000 by default. The SQLite database is created in data/bookstore.db on first start and is excluded from Git.

Configuration

The only supported environment variable is:

Variable Default Purpose
PORT 3000 HTTP port used by the local server

The committed .env.example contains no credentials.

Example request

Create a book using an existing author_id from GET /authors:

POST /books
Content-Type: application/json
{
  "title": "1984",
  "isbn": "9780451524935",
  "price": 9.99,
  "published_year": 1949,
  "author_id": 1
}

Example 201 Created response:

{
  "data": {
    "id": 1,
    "title": "1984",
    "isbn": "9780451524935",
    "price": 9.99,
    "published_year": 1949,
    "author_id": 1,
    "author": {
      "id": 1,
      "name": "George Orwell"
    },
    "created_at": "2026-07-26 20:00:00",
    "updated_at": "2026-07-26 20:00:00"
  }
}

Error handling

Invalid input returns a structured response with an application error code and the request ID used in logs:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The request contains invalid fields.",
    "request_id": "04675389-9f9b-4e67-9c05-8a43139a7315",
    "details": {
      "price": "Price must be 0 or greater."
    }
  }
}

Expected client error statuses include:

  • 400 for invalid JSON, IDs, fields or relationships
  • 404 for an unknown route or book
  • 409 for a duplicate ISBN

Postman and Newman collection

The local collection and environment are stored in:

Start the API in one terminal, then run the current collection in another:

npm run test:postman

The current collection is a work in progress. It contains CRUD requests, but it does not yet include assertion scripts or reliable response-variable hand-off between requests. A Newman run can therefore complete even when individual requests return unexpected statuses. It is useful for manual exploration, but it must not be described as automated test coverage.

Repository structure

bookstore-api/
|-- data/                    # Local SQLite database location
|-- docs/openapi.yaml        # OpenAPI specification
|-- postman/                 # Collection and local environment
|-- src/
|   |-- database/            # Connection and schema initialisation
|   |-- middleware/          # Validation, logging and error handling
|   |-- routes/              # Book and author endpoints
|   |-- utils/               # Application error type
|   |-- app.js               # Express application
|   `-- server.js            # Service entry point
|-- .env.example
|-- package.json
`-- README.md

Design decisions and edge cases

  • PUT requires the complete editable book representation; PATCH accepts only changed fields.
  • Unknown request fields are rejected instead of silently ignored.
  • ISBN values are unique.
  • Author IDs must reference an existing author.
  • Book IDs must be positive integers.
  • Successful collection responses include both data and count.

Future improvements

  • Complete response-variable hand-off and add assertion scripts to the Postman collection
  • Add isolated unit and integration tests
  • Add pagination and filtering to GET /books
  • Add authentication and role-based authorisation
  • Deploy to a verified public environment

Author

Trevor Kirton - GitHub | LinkedIn

About

Node.js, Express and SQLite REST API demonstrating CRUD operations, JSON validation, OpenAPI documentation and Postman/Newman workflows.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages