Skip to content

NGalletly/BoroughBooks-BE

Repository files navigation

BoroughBooks-BE

Requirements

  • Node v22.14.0

Getting Started:

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'

Creating Test and Development Databases:

To create Databases navigate to the db folder and run:

psql -f setup-dbs.sql

Seeding the Database:

To seed the Database use the commands:

npm run test-seed
npm run seed-dev

Local development

After creating databases and seeding please run

npm start

Note: Server will be running on http://localhost:9000/api

Display tables

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

Production ( Supabase )

  1. Request the .env.production connection string from a team member — never commit this to GitHub
  2. Create a .env.production file in the root with:
DATABASE_URL=your_supabase_transaction_pooler_url
SSL=true

Endpoints

Example endpoints:

GET Requests

  • /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
        }
      ]
    }

Post Requests:

  • /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
      }
    }

Patch Requests:

  • /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 }

DELETE Requests:

  • /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.

About

The Backend for our radical digital bookshelf.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages