We will be building an API for the purpose of accessing application data programmatically. The intention here is to mimick the building of a real world backend service (such as reddit) which should provide this information to the front end architecture.
Your database will be PSQL, and you will interact with it using node-postgres.
You will need to create two .env files for your project: .env.test and .env.development. Into each, add PGDATABASE=<database_name_here>, with the correct database name for that environment (see /db/setup.sql for the database names). Double check that these .env files are .gitignored.
You have also been provided with a db folder with some data, a setup.sql file and a seeds folder. You should also take a minute to familiarise yourself with the npm scripts you have been provided.
The job of index.js in each the data folders is to export out all the data from that folder, currently stored in separate files. This is so that, when you need access to the data elsewhere, you can write one convenient require statement - to the index file, rather than having to require each file individually. Think of it like a index of a book - a place to refer to! Make sure the index file exports an object with values of the data from that folder with the keys:
categoryDatareviewDatauserDatacommentData
You will need to create your tables and write your seed function to insert the data into your database.
In order to both create the tables and seed your data, you will need the connection to your database. You can find this in the provided connection.js.
You should have separate tables for categories, reviews, users and comments. Make sure to consider the order in which you create your tables. You should think about whether you require any constraints on your table columns (e.g. 'NOT NULL')
Each category should have:
slugfield which is a unique string that acts as the table's primary keydescriptionfield which is a string giving a brief description of a given category
Each user should have:
usernamewhich is the primary key & uniqueavatar_urlname
Each review should have:
review_idwhich is the primary keytitlereview_bodydesignerreview_img_urldefaults tohttps://images.pexels.com/photos/163064/play-stone-network-networked-interactive-163064.jpegvotesdefaults to 0categoryfield which references the slug in the categories tableownerfield that references a user's primary key (username)created_atdefaults to the current timestamp
Each comment should have:
comment_idwhich is the primary keyauthorfield that references a user's primary key (username)review_idfield that references an review's primary keyvotesdefaults to 0created_atdefaults to the current timestampbody
You need to complete the provided seed function to insert the appropriate data into your database.
- Use proper project configuration from the offset, being sure to treat development and test environments differently.
- Test each route as you go, checking both successful requests and the variety of errors you could expect to encounter See the error-handling file here for ideas of errors that will need to be considered.
- After taking the happy path when testing a route, think about how a client could make it go wrong. Add a test for that situation, then error handling to deal with it gracefully.
Work through building endpoints in the following order:
This is a summary of all the endpoints. More detail about each endpoint is further down this document.
Essential endpoints
GET /api/categories
GET /api/reviews/:review_id
PATCH /api/reviews/:review_id
GET /api/reviews
GET /api/reviews/:review_id/comments
POST /api/reviews/:review_id/comments
DELETE /api/comments/:comment_id
GET /apiHosting and README time!
Next endpoints to work through
GET /api/users
GET /api/users/:username
PATCH /api/comments/:comment_idAll of your endpoints should send the responses specified below in an object, with a key name of what it is that being sent. E.g.
{
"categories": [
{
"description": "Abstact games that involve little luck",
"slug": "Euro games"
},
{
"description": "Players attempt to uncover each other's hidden role",
"slug": "Social deduction"
},
{
"description": "Games involving physical skill",
"slug": "Dexterity"
}
]
}Responds with:
- an array of category objects, each of which should have the following properties:
slugdescription
Responds with:
-
a review object, which should have the following properties:
ownerwhich is theusernamefrom the users tabletitlereview_idreview_bodydesignerreview_img_urlcategorycreated_atvotescomment_countwhich is the total count of all the comments with this review_id - you should make use of queries to the database in order to achieve this
Request body accepts:
-
an object in the form
{ inc_votes: newVote }newVotewill indicate how much thevotesproperty in the database should be updated by
e.g.
{ inc_votes : 1 }would increment the current review's vote property by 1{ inc_votes : -100 }would decrement the current review's vote property by 100
Responds with:
- the updated review
Responds with:
- an
reviewsarray of review objects, each of which should have the following properties:ownerwhich is theusernamefrom the users tabletitlereview_idcategoryreview_img_urlcreated_atvotescomment_countwhich is the total count of all the comments with this review_id - you should make use of queries to the database in order to achieve this
Should accept queries:
sort_by, which sorts the reviews by any valid column (defaults to date)order, which can be set toascordescfor ascending or descending (defaults to descending)category, which filters the reviews by the category value specified in the query
Responds with:
- an array of comments for the given
review_idof which each comment should have the following properties:comment_idvotescreated_atauthorwhich is theusernamefrom the users tablebody
Request body accepts:
- an object with the following properties:
usernamebody
Responds with:
- the posted comment
Should:
- delete the given comment by
comment_id
Responds with:
- status 204 and no content
Responds with:
- JSON describing all the available endpoints on your API
- If you have already hosted your app at this point, remember to push up to
herokuyour updated code - If you haven't already hosted your app, now is the time! Follow the instructions in hosting.md
- Write your README, including the following information:
- Link to hosted version
- Write a summary of what the project is
- Provide clear instructions of how to clone, install dependencies, seed local database, and run tests
- Include information about how to create the two
.envfiles - Specify minimum versions of
Node.jsandPostgresneeded to run the project
Remember that this README is targetted at people who will come to your repo (potentially from your CV or portfolio website) and want to see what you have created, and try it out for themselves(not just to look at your code!). So it is really important to include a link to the hosted version, as well as implement the above GET /api endpoint so that it is clear what your api does.
Responds with:
- an array of objects, each object should have the following property:
username
Responds with:
- a user object which should have the following properties:
usernameavatar_urlname
Request body accepts:
-
an object in the form
{ inc_votes: newVote }newVotewill indicate how much thevotesproperty in the database should be updated by
e.g.
{ inc_votes : 1 }would increment the current comment's vote property by 1{ inc_votes : -1 }would decrement the current comment's vote property by 1
Responds with:
- the updated comment
To make sure that an API can handle large amounts of data, it is often necessary to use pagination. Head over to Google, and you will notice that the search results are broken down into pages. It would not be feasible to serve up all the results of a search in one go. The same is true of websites / apps like Facebook or Twitter (except they hide this by making requests for the next page in the background, when we scroll to the bottom of the browser). We can implement this functionality on our
/api/reviewsand/api/commentsendpoints.
- Should accepts the following queries:
limit, which limits the number of responses (defaults to 10)p, stands for page which specifies the page at which to start (calculated using limit)
- add a
total_countproperty, displaying the total number of reviews (this should display the total number of reviews with any filters applied, discounting the limit)
Should accept the following queries:
limit, which limits the number of responses (defaults to 10)p, stands for page which specifies the page at which to start (calculated using limit)
Request body accepts:
-
an object with the following properties:
ownerwhich is theusernamefrom the users tabletitlereview_bodydesignercategorywhich is acategoryfrom the categories table
Responds with:
- the newly added review, with all the above properties as well as:
review_idvotescreated_atcomment_count
Request body accepts:
- an object in the form:
{
"slug": "category name here",
"description": "description here"
}Responds with:
- a category object containing the newly added category
Should:
- delete the given review by review_id
Respond with:
- status 204 and no content