This is my Book Library API project for Manchester Codes as part of the Backend module.
The main purpose of this project is to:
- Learn how to take user stories and turn them into requirements.
- Expand my knowledge of database design.
- Learn how to use Sequelize to perform SQL queries.
- Get real world practice with documentation by figuring out how to implement validation on models.
- Create, read, update and delete readers, authors, genres and books.
- Associate books with their authors.
- Associate books with their genres.
- Search for books based on author, or genre.
- The readers password is never returned to the users of the API.
- Node JS - JavaScript runtime environment
- Express - to set up the server and manage routes and responses
- Helmet - to add some security middleware to Express
- MySQL2 - to work with the MySQL database engine
- Sequelize - to work with MySQL using a JavaScript ORM
- Faker - to generate fake data used for testing
- Mocha - testing framework of choice for this project
- Chai - testing assertion library used to provide the testing framework (in this case Mocha) with assertions
- SuperTest - HTTP assertion library used to test HTTP servers
- Dotenv - to store environment variables
- Nodemon - to run the
npm run start:dev
script, allowing for hot reloading - ES Lint - to analyze the code for style guide problems
- Prettier - to format code and keep styling consistent
- Pull down a MySQL image from DockerHub
docker pull bbatm9/music_library_mysql
- more info: DockerHub
- Set up the container
docker run -d -p <OUTSIDE_PORT>:<INSIDE_PORT> --name <NAME> -e MYSQL_ROOT_PASSWORD=<PASSWORD> <IMAGE_NAME>
- Clone this repo
- e.g.
git clone https://github.com/invertostew/book-library-api.git
- e.g.
- Change into the repo directory
cd book-library-api
(or the directory you specified the repo to be cloned into)
- Install the dependencies from
package-lock.json
npm install
- Create an
.env
and.env.test
file in the project roottouch .env && touch .env.test
- Add the following to both
.env
and.env.test
, switching out the<VALUE>
as necessaryDB_HOST=<YOUR_DB_HOST>
DB_USER=<YOUR_DB_USER>
DB_PASSWORD=<YOUR_DB_PASSWORD>
DB_PORT=<YOUR_DB_PORT>
(as specified in thedocker run
command)DB_NAME=<YOUR_DB_NAME>
APP_PORT=<YOUR_APP_PORT>
(optional, will default to 4000)- IMPORTANT: Ensure
DB_NAME
is different in.env
than it is in.env.test
, the database in.env.test
will be dropped each time.
- To start the production server:
npm start
- To start the development server:
npm run start:dev
HTTP Verb | Route | Required Fields |
---|---|---|
GET | /readers | |
POST | /readers | name , email , password |
GET | /readers/:id | |
PATCH | /readers/:id | |
DELETE | /readers/:id |
// Endpoint: POST /readers
{
"name": "First Last",
"email": "[email protected]",
"password": "VerySecurePassword"
}
// Endpoint: PATCH /readers/1
{
"name": "First Last Updated!"
}
name
(required)- must be provided
email
(required)- must be provided
- must be an email address
password
(required)- must be provided
- must be more than 8 characters
- must be less than 64 characters
HTTP Verb | Route | Required Fields |
---|---|---|
GET | /authors | |
POST | /authors | author |
GET | /authors/:id | |
PATCH | /authors/:id | |
DELETE | /authors/:id |
// Endpoint: POST /authors
{
"author": "First Last"
}
// Endpoint: PATCH /authors/1
{
"author": "First Last Updated!"
}
author
(required)- must be provided
- must be unique
HTTP Verb | Route | Required Fields |
---|---|---|
GET | /genres | |
POST | /genres | genre |
GET | /genres/:id | |
PATCH | /genres/:id | |
DELETE | /genres/:id |
// Endpoint: POST /genres
{
"genre": "Sci-Fy"
}
// Endpoint: PATCH /genres/1
{
"genre": "Sci-Fi"
}
genre
(required)- must be provided
- must be unique
HTTP Verb | Route | Required Fields | Optional Fields |
---|---|---|---|
GET | /books | ||
POST | /books | title , AuthorId |
ISBN , ReaderId , GenreId |
GET | /books/:id | ||
PATCH | /books/:id | ||
DELETE | /books/:id |
// Endpoint: POST /books
{
"title": "Book Title",
"ISBN": 1234567890,
"ReaderId": 1,
"AuthorId": 1,
"GenreId": 1
}
// Endpoint: PATCH /books/1
{
"title": "New Book Title",
"ISBN": 1234567890123
}
title
(required)- must be provided
ISBN
(optional)- must be between 10 and 13 characters to match ISBN-10 or ISBN-13
- must be unique
ReaderId
(optional)- must be a valid
ReaderId
if provided
- must be a valid
AuthorId
(required)- must be a valid
AuthorId
- must be a valid
GenreId
(optional)- must be a valid
GenreId
if provided
- must be a valid
Built using a TDD approach. Tests have been split out into unit tests and integration tests. Where possible tests where written as failing tests first, and then built out as per the tests, and later refactored and tested again. At some points it was necessary to spike, in which case I would delete the code, write the test and then re-implement the code.
All tests are located inside of the ./src/__tests__
directory.
If you wish to run the tests for yourself, you can install Faker, Mocha, Chai and SuperTest by running npm install
and from there you can run the tests by running npm test
.
I also used Insomnia to send requests to my RESTful API endpoints as documented above.
- I would like to condense down the CRUD tests in the future to use the CRUD helper functions where possible to make tests more DRY.