Requirements
- Node v22.14.0
Please check package.json for dependencies and run
npm install
Dependencies Installed (manual commands if needed)
Node: npm install
Jest: npm install --save-dev jest
JestSorted: npm install --save-dev jest-sorted
Express: npm install express
Cors: npm install cors
SuperTest: npm install supertest --save-dev
Dotenv: npm install dotenv --save
Nodemon: npm install --save-dev nodemon
PostGres: npm install pg
PostGres Format: npm install pg-format
To start please create your own .env files in root directory:
.env.test.env.development
In these files please connect to the connection.js by placing the following their respective .env.test and env.development files:
PGDATABASE=[YOUR_DATABASE_NAME]
PGDATABASE=[YOUR_DATABASE_NAME]
Once this is done please ensure you have the following in your .gitignore
node_modules/
.env.development
.env.test
.env.*
To check if this is working console.log the ENV variable in connection.js in jest test and in development environment to see it toggle from test to development. const ENV = process.env.NODE_ENV || 'development'
To create Databases navigate to the db folder and run:
psql -f setup-dbs.sql
To seed the Database use the commands:
npm run test-seed
npm run seed-dev
After creating databases and seeding please run
npm start
Note: Server will be running on http://localhost:9000/api
To see scema and display tables in output.txt, write the following command in terminal. Note, ensure you npm run seed-dev before doing this.
psql boroughbooks -c "\dt" -c "SELECT * FROM users;" -c "SELECT _ FROM books;" -c "SELECT _ FROM usersbooks;" -c "SELECT * FROM loans;" -c "SELECT _ FROM wishlist;" -c "SELECT _ FROM user_relationship;" > output.txt && cat output.txt
- Request the
.env.productionconnection string from a team member — never commit this to GitHub - Create a
.env.productionfile in the root with:
DATABASE_URL=your_supabase_transaction_pooler_url
SSL=true
Example endpoints:
-
/api/books
Retrieve an object containing an array of all books, where each book is an object
Example response:{ "books": [ { "isbn": "9780679723394", "title": "Speak, Memory", "authors": "Vladimir Nabokov", "publisher": "Vintage International", "published_date": "1989-07-11T23:00:00.000Z", "description": "A memoir of Nabokov's privileged childhood in pre-revolutionary Russia and his years of European emigration, widely considered one of the finest autobiographies of the twentieth century.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9780679723394&printsec=frontcover&img=1&zoom=1" }, { "isbn": "9781608464456", "title": "Freedom Is a Constant Struggle: Ferguson, Palestine, and the Foundations of a Movement", "authors": "Angela Y. Davis", "publisher": "Haymarket Books", "published_date": "2016-02-01T00:00:00.000Z", "description": "Angela Davis examines the connections between struggles against state violence and oppression throughout history and around the world, arguing that we must build on legacies of resistance to forge a new, more expansive vision of freedom.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9781608464456&printsec=frontcover&img=1&zoom=1" }, { "isbn": "9780374529529", "title": "Memoirs of Hadrian", "authors": "Marguerite Yourcenar", "publisher": "Farrar, Straus and Giroux", "published_date": "2005-03-31T23:00:00.000Z", "description": "A fictional memoir of the Roman Emperor Hadrian, written in the form of a letter to his adopted grandson Marcus Aurelius, meditating on power, love, and the nature of the self.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9780374529529&printsec=frontcover&img=1&zoom=1" }, { "isbn": "9781784870911", "title": "Life and Fate", "authors": "Vasily Grossman", "publisher": "Vintage Classics", "published_date": "2006-05-31T23:00:00.000Z", "description": "Set during the Battle of Stalingrad, this epic novel draws parallels between Nazi and Stalinist totalitarianism and follows the Shaposhnikov family through the brutal crucible of the Second World War.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9781784870911&printsec=frontcover&img=1&zoom=1" }, { "isbn": "9780141189383", "title": "Alone in Berlin", "authors": "Hans Fallada", "publisher": "Penguin Modern Classics", "published_date": "2009-08-26T23:00:00.000Z", "description": "Based on a true story, this novel follows a working-class Berlin couple who begin a secret campaign of resistance against the Nazi regime after the death of their son in the war.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9780141189383&printsec=frontcover&img=1&zoom=1" } ] } -
/api/users
Retrieve an object containing an array of all users, where each user is an object
Example response:{ "users": [ { "username": "gavinHousley", "profile_pic_url": "" }, { "username": "jovaScript", "profile_pic_url": "" }, { "username": "coolSurferDude", "profile_pic_url": "" }, { "username": "nomi", "profile_pic_url": "" }, { "username": "ESerebrianik", "profile_pic_url": "" } ] } -
/api/users/:username
Retrive an object containing an array with a single user object
Example response (username = "jovaScript"):{ "user": [ { "username": "jovaScript", "profile_pic_url": "" } ] } -
/api/users/:username/my-library
Retrieve an object containing all books available to borrow in a single user's library
Example response (username = "nomi"):{ "books": [ { "isbn": "9780441569595", "title": "Neuromancer", "authors": "William Gibson", "publisher": "Ace Books", "published_date": "2000-06-30T23:00:00.000Z", "description": "Case is a washed-up computer criminal hired by a mysterious employer to pull off the ultimate hack. A seminal cyberpunk novel that coined the term 'cyberspace' and shaped modern science fiction.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9780441569595&printsec=frontcover&img=1&zoom=1" }, { "isbn": "9780140154511", "title": "The Earthsea Quartet", "authors": "Ursula K. Le Guin", "publisher": "Penguin Books", "published_date": "1993-01-01T00:00:00.000Z", "description": "Collects the first four books of Le Guin's landmark fantasy series: A Wizard of Earthsea, The Tombs of Atuan, The Farthest Shore, and Tehanu — following the wizard Ged across a vast archipelago world.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9780140154511&printsec=frontcover&img=1&zoom=1" }, { "isbn": "9780441627400", "title": "The Once and Future King", "authors": "T. H. White", "publisher": "Ace Books", "published_date": "1987-04-30T23:00:00.000Z", "description": "A sweeping retelling of the Arthurian legend, from the boyhood education of the Wart by Merlyn to the tragedy of Camelot and the fall of a great king's dream of a just civilization.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9780441627400&printsec=frontcover&img=1&zoom=1" }, { "isbn": "9780618640157", "title": "The Lord of the Rings", "authors": "J. R. R. Tolkien", "publisher": "Mariner Books", "published_date": "2005-09-20T23:00:00.000Z", "description": "The complete single-volume edition of Tolkien's epic fantasy trilogy, following hobbit Frodo Baggins and the Fellowship of the Ring on their quest to destroy the One Ring and defeat the Dark Lord Sauron.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9780618640157&printsec=frontcover&img=1&zoom=1" } ] } -
/api/users/:username/my-library/:isbn
Retrieve an object containing a single book available to borrow in a single user's library
Example response (username = "jovaScript", isbn = "9780679723394"):{ "usersBookByIsbn": [ { "username": "jovaScript", "isbn": "9780679723394", "title": "Speak, Memory", "authors": "Vladimir Nabokov", "publisher": "Vintage International", "published_date": "1989-07-11T23:00:00.000Z", "description": "A memoir of Nabokov's privileged childhood in pre-revolutionary Russia and his years of European emigration, widely considered one of the finest autobiographies of the twentieth century.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9780679723394&printsec=frontcover&img=1&zoom=1" } ] } -
/api/books/:isbn
Retrieve an object containing an array containing an object with a single book object{ "book": [ { "isbn": "9780140154511", "title": "The Earthsea Quartet", "authors": "Ursula K. Le Guin", "publisher": "Penguin Books", "published_date": "1993-01-01T00:00:00.000Z", "description": "Collects the first four books of Le Guin's landmark fantasy series: A Wizard of Earthsea, The Tombs of Atuan, The Farthest Shore, and Tehanu — following the wizard Ged across a vast archipelago world.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9780140154511&printsec=frontcover&img=1&zoom=1" } ] } -
/api/users/:username/friends
Retrieve an object containing an array of all information about thheir profile's friends
Example response (for username = "jovascript"):{ "usersFriends": [ { "user_relationship_id": 1, "origin_username": "jovaScript", "relating_username": "gavinHousley", "friend_status": "accepted", "profile_pic_url": "" }, { "user_relationship_id": 2, "origin_username": "jovaScript", "relating_username": "nomi", "friend_status": "accepted", "profile_pic_url": "" } ] } -
/api/users/:username/loaned
Retrieve an object containing an array where each element is an object storing information about which books have been loaned out by a single user
Example Response (username = "jovaScript"):{ "books": [ { "isbn": "9780441569595", "title": "Neuromancer", "authors": "William Gibson", "publisher": "Ace Books", "published_date": "2000-06-30T23:00:00.000Z", "description": "Case is a washed-up computer criminal hired by a mysterious employer to pull off the ultimate hack. A seminal cyberpunk novel that coined the term 'cyberspace' and shaped modern science fiction.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9780441569595&printsec=frontcover&img=1&zoom=1", "borrower_id": "nomi" } ] } -
/api/users/:username/borrowed
Retrieve an object containing an array where each element is an object storing information about which books have been borrowed by a single user
Example Response (username = "coolSurferDude"):{ "books": [ { "isbn": "9780140154511", "title": "The Earthsea Quartet", "authors": "Ursula K. Le Guin", "publisher": "Penguin Books", "published_date": "1993-01-01T00:00:00.000Z", "description": "Collects the first four books of Le Guin's landmark fantasy series: A Wizard of Earthsea, The Tombs of Atuan, The Farthest Shore, and Tehanu — following the wizard Ged across a vast archipelago world.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9780140154511&printsec=frontcover&img=1&zoom=1", "username": "gavinHousley" }, { "isbn": "9781567923384", "title": "Nox", "authors": "Anne Carson", "publisher": "New Directions", "published_date": "2010-05-17T23:00:00.000Z", "description": "An accordion-fold facsimile of a handmade book, Nox is Anne Carson's elegy for her brother, interweaving a translation of Catullus 101 with photographs, dictionary definitions, and fragments of memory.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9781567923384&printsec=frontcover&img=1&zoom=1", "username": "groovySkaterGirl" } ] } -
/api/users/:username/wish-list
Retrieve an object contianing an array of a user's wish-listed books
Example Response:{ "usersWishList": [ { "isbn": "9780374529529", "username": "jovaScript", "title": "Memoirs of Hadrian", "authors": "Marguerite Yourcenar", "publisher": "Farrar, Straus and Giroux", "published_date": "2005-03-31T23:00:00.000Z", "description": "A fictional memoir of the Roman Emperor Hadrian, written in the form of a letter to his adopted grandson Marcus Aurelius, meditating on power, love, and the nature of the self.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9780374529529&printsec=frontcover&img=1&zoom=1" }, { "isbn": "9780143039945", "username": "jovaScript", "title": "Gravity's Rainbow", "authors": "Thomas Pynchon", "publisher": "Penguin Books", "published_date": "2006-05-29T23:00:00.000Z", "description": "Set in the final months of World War II, this monumental and labyrinthine novel follows dozens of characters across a paranoid landscape shaped by rocket technology, corporate conspiracy, and occult forces.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9780143039945&printsec=frontcover&img=1&zoom=1" }, { "isbn": "9780441627400", "username": "jovaScript", "title": "The Once and Future King", "authors": "T. H. White", "publisher": "Ace Books", "published_date": "1987-04-30T23:00:00.000Z", "description": "A sweeping retelling of the Arthurian legend, from the boyhood education of the Wart by Merlyn to the tragedy of Camelot and the fall of a great king's dream of a just civilization.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9780441627400&printsec=frontcover&img=1&zoom=1" } ] }- /api/conversations
Retrieve an object containing an array of conversations
Example Response:
{ "conversations": [ { "conversation_id": 1, "user1_username": "jovaScript", "user2_username": "nomi", "created_at": "2026-03-18T10:00:00.000Z" }, { "conversation_id": 2, "user1_username": "jovaScript", "user2_username": "coolSurferDude", "created_at": "2026-03-18T11:15:00.000Z" } ] }- /api/conversations/:username
Retrieve an object containing an array of conversations based on username
Example Response:
{ "conversations": [ { "conversation_id": 1, "user1_username": "jovaScript", "user2_username": "nomi", "created_at": "2026-03-18T10:00:00.000Z" } ] }- /api/conversations/:conversation_id/messages
Retrieve an object containing an array of messages based on the conversation id
Example Response:
{ "messages": [ { "message_id": 1, "conversation_id": 1, "sender_username": "jovaScript", "content": "Hey, have you read Midnight library already?", "sent_at": "2026-03-18T10:01:00.000Z", "read_at": "2026-03-18T10:05:00.000Z" }, { "message_id": 2, "conversation_id": 1, "sender_username": "nomi", "content": "Yeah, do you want to borrow it?", "sent_at": "2026-03-18T10:02:00.000Z", "read_at": null } ] } - /api/conversations
-
/api/books
Post a new book to the "books" table.
The request body must be of the the following form:{ "isbn": "9780062316097", "title": "Sapiens: A Brief History of Humankind", "authors": "Yuval Noah Harari", "publisher": "Harper Perennial", "published_date": "2015-02-10", "description": "A sweeping narrative of humanitys creation and evolution.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9780062316097&printsec=frontcover&img=1&zoom=1" }Successful requests give a response with the shape of the following example:
{ "newBook": [ { "isbn": "9780062316097", "title": "Sapiens: A Brief History of Humankind", "authors": "Yuval Noah Harari", "publisher": "Harper Perennial", "published_date": "2015-02-10", "description": "A sweeping narrative of humanitys creation and evolution.", "imagelinks": "https://books.google.com/books/content?vid=ISBN9780062316097&printsec=frontcover&img=1&zoom=1" } ] } -
/api/users/:username/my-library
Post a book to the users-books table associated with their username.
The request body should be of the following form:{ "isbn": "9780140154511" }Successful requests will return a response object with the form:
{ "postedBookToLibrary": [ { "users_book_id": 21, "isbn": "9780140154511", "username": "jovaScript" } ] } -
/api/users/:username/friends
Post a pending friendship between two users. These are "friend requests", and are designed to always initially contain a "pending" value for the friend's status
The request body should be sent with the following shape:{ "relating_username": "coolSurferDude" }where the relating_username is the friend-to-be.
Successful requests will return a response body with the following shape{ "usersNewFriendRequest": [ { "user_relationship_id": 9, "origin_username": "groovySkaterGirl", "relating_username": "coolSurferDude", "friend_status": "pending" } ] } -
/api/conversations
Post a conversation between two users The request body should be sent with the following shape:{ "user1_username": "nomi", "user2_username": "jovaScript" }Will get a 201 with response similar to the below (the date of created_at is taken from postgres)
{ "conversation": { "conversation_id": 1, "user1_username": "nomi", "user2_username": "jovaScript", "created_at": "2026-03-18T15:40:46.341Z" } }- /api/messages
Send a new message in a conversation
Example Request Body:
{ "conversation_id": 1, "sender_username": "nomi", "content": "Hey, are you around?" }{ "message": { "message_id": 1, "conversation_id": 1, "sender_username": "nomi", "content": "Hey, are you around?", "sent_at": "2026-03-18T10:01:00.000Z", "read_at": null } } - /api/messages
-
/api/users/:username/loaned
Patch and update the return status of a loaned book with the loan_id by adding a return date.
Response will be 204 - No content for a successful patch. Here is an example of the object to be sent. Please note the date format.{ "loan_id": 1, "return_date": "2026-03-16T23:00:00.000Z" } -
/api/users/:username/friends
Update the friend status between 2 particular users
The request body should be sent as (as an example):{ "user_relationship_id": 6 }
- /api/users/:username/:ISBN
Successful requests will remove a book by its ISBN from a specified user's library. This removes the record associated with that ISBN and the specified username from the users-books table. - /api/users/:username/friends
Delete a friend from a user's friend list or reject a friend request. - /api/users/:username/wish-list/:isbn
Delete a book from a user's wish list using their username and the isbn of the book they want to delete - /api/users/:username/loaned/:users_book_id
Deletes a loan record, marking a book as returned. This removes the loan entry from the loans table for the specified users_book_id.