Overarching Project
It’s again time to continue with the overarching project. In this part, you’ll focus on building server-side functionality for the “Reddit”-themed overarching project.
We recommend working on the overarching project only after completing all other assignments in this part. For deeper learning, it can also help to take a short break of a few days before starting the project.
The core idea of Reddit is focused on communities and posts. Users can create communities around topics they are interested in, and within those communities, they can create posts to share content or start discussions.
In the fourth step, you will set up an API for creating, reading, listing, and deleting communities. The communities will be stored in a database.
WSD Overarching Project, Step 4
0 / 35 points
In this step, you will implement a set of community-related API using a layered architecture for a small application (Controller -> Repository) and a database to store all relevant information on the server-side. At the end of this step, your server-side application has the following API endpoints that interact directly with the database:
- API for creating a community
- API for deleting the community
- API for retrieving community information from the database.
Database Schema
First, add a new migration file to the database-migrations folder of the project. The migration will be used to create a new table called communities. You can use any name for the migration file (as long as it follows the naming convention of the other migration files). The contents of the migration file should be as follows:
CREATE TABLE communities ( id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name TEXT UNIQUE NOT NULL CHECK (length(name) > 0), description TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);After adding the migration file, run the migration to create the table in the database.
Layered Architecture
Second, since the server-side API will be implemented in a layered architecture here is a small review of each layer’s responsibilities:
-
app.js Acts as the entry point to the application and serves as the route handler that maps routes to controller functions.
-
Controller Layer
- Receives the request and extracts parameters/body
- Calls appropriate methods from the Repository layer
- Returns a JSON-formatted response.
-
Repository Layer
- Handles direct interaction with the database using
sql() - Defines functions for querying, adding, updating, and deleting data
- Handles direct interaction with the database using
Tasks
The task is to implement a set of the following API routes:
-
GET /api/communities Retrieve the communities from the database and return them in an array as a JSON document.
Example JSON:
[{"id": 1,"name": "Developers Hub","description": "A place for developers","created_at": "..."},{"id": 2,"name": "Design Factory","description": "Creative minds meet here","created_at": "..."},{"id": 3,"name": "Startup Workshop","description": "Where ideas become reality","created_at": "..."}] -
GET /api/communities/:communityId Retrieve community data from the database that has its
idmatch:communityId, where:communityIdis a path variable, and return it as JSON:As an example, if a
GETrequest is sent to/api/communities/1, the returned document could look as follows:{"id": 1,"name": "Developers Hub","description": "A place for developers","created_at": "..."} -
POST /api/communities Add the new community to the database based on the request body. The request body contains a JSON document with 2 fields (
nameanddescription) that look as follows:{"name": "Community Name","description": "Community Description",}And respond to the request with the newly created community object with its newly created
idand data as a JSON document.Response JSON:
{"id": 4,"name": "Community Name","description": "Community description","created_at": "..."} -
DELETE /api/communities/:communityId Remove from the database the community that has its
idmatch:communityId, where:communityIdis a path variable, and return a JSON document that contains the removed community.For example, if a
DELETErequest is sent to/api/communities/1, the returned document could look as follows:{"id": 1,"name": "Developers Hub","description": "A place for developers","created_at": "..."}
Submission
Add the repository and controller files to the repositories and controllers folders of the server folder of your overarching project, respectively. Name the files communityRepository.js and communityController.js.
Once ready, zip the contents of the server folder of your overarching project and submit the zip file below. The controllers folder should be at the root of the zip file. The expected file structure of the project is as follows.
Follow the names exactly as given, as the automated tests will check for them. Your project may have additional files (e.g. Dockerfile, deno.json).
.├── controllers│ └── communityController.js (new)├── repositories│ └── communityRepository.js (new)├── app-run.js└── app.jsIn the fifth step, you’ll add API functionality for creating, reading, listing, and deleting posts within communities. The posts will also be stored in the database.
WSD Overarching Project, Step 5
0 / 35 points
In this step, you will implement a set of post-related API using a layered architecture and a new database schema to store post information on the server-side. At the end of this step, your server-side application has the following API endpoints:
- API for creating a post
- API for deleting a post
- API for retrieving post information from the database.
Database Schema
First, add a new migration file to the database-migrations folder of the project. The migration will be used to create a new table called posts. You can use any name for the migration file (as long as it follows the naming convention of the other migration files). The contents of the migration file should be as follows:
CREATE TABLE posts ( id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, community_id INTEGER NOT NULL REFERENCES communities(id) ON DELETE CASCADE, title TEXT, content TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);We explicitly allow the title column to be null, as comments (which will be implemented in the next step) will not have a title. After adding the migration file, run the migration to add the table in the database.
Tasks
The task is to implement the following API routes:
-
GET /api/communities/:communityId/posts Retrieve the list of posts that belong to the community with its
community_idproperty match:communityId, where:communityIdis a path variable.Example response:
[{"id": 1,"title": "Post 1 title","content": "Post 1 content","community_id": ":communityId","created_at": "..."},{"id": 2,"title": "Post 2 title","content": "Post 2 content","community_id": ":communityId","created_at": "..."}] -
GET /api/communities/:communityId/posts/:postId Retrieve a single post from the database that has its
idmatch:postIdandcommunity_idmatch:communityIdand return it as JSON.For example, if a
GETrequest is sent to/api/communities/1/posts/1, the returned document could look as follows:{"id": "1","title": "Post 1 title","content": "Post 1 content","community_id": "1","created_at": "..."} -
POST /api/communities/:communityId/posts Add a new post to the database based on the request body. The request body contains a JSON document with 2 fields (
titleandcontent) that look as follows:{"title": "Post 3 Title","content": "Post 3 Content",}The server should respond with the newly added post, where the
idof the post has been determined by the database.Response JSON:
{"id": 3,"title": "Post 3 title","content": "Post 3 content","community_id": ":communityId","created_at": "..."}community_idfield will have to match with:communityId, where:communityIdis a path variable. -
DELETE /api/communities/:communityId/posts/:postId Removes from the database the post that has its
idmatch:postIdand itscommunity_idmatch:communityId, where:postIdand:communityIdare path variables. Returned the deleted post object as a JSON document.As an example, if a
DELETErequest is sent to/api/communities/1/posts/1. The returned response should look as follows:{"id": "1","title": "Post 1 title","content": "Post 1 content","community_id": "1","created_at": "..."}
Submission
Once ready, zip the contents of the server folder of your overarching project and submit the zip file below. The expected file structure of the project is as follows.
Follow the names exactly as given, as the automated tests will check for them. Your project may have additional files (e.g. Dockerfile, deno.json).
.├── controllers│ ├── communityController.js│ └── postController.js (new)├── repositories│ ├── communityRepository.js│ └── postRepository.js (new)├── app-run.js└── app.js (updated)In the sixth step, you’ll add the possibility for users to comment on posts. Comments will be stored in the database as well. As a part of this, you’ll modify the posts table to include a reference to a parent post, effectively allowing creating posts that are comments to other posts.
WSD Overarching Project, Step 6
0 / 40 points
In this step, you will implement a set of comment-related API using a layered architecture and a new database schema to store comment information on the server-side. At the end of this step, your server-side application has the following API endpoints:
- API for creating a comment
- API for deleting a comment
- API for retrieving comment information from the database.
Database Schema
First, add a new migration file to the database-migrations folder of the project. The migration will be used to alter the table posts to include a new column called parent_post_id that will be used to store the id of the post that a comment belongs to.
You can use any name for the migration file (as long as it follows the naming convention of the other migration files). The contents of the migration file should be as follows:
ALTER TABLE posts ADD COLUMN parent_post_id INTEGER REFERENCES posts(id) ON DELETE CASCADE;After adding the migration file, run the migration to add the table in the database.
Posts and Comments
While posts and comments “live” in the same database table, there are a few characteristics that differentiate them:
- If a post has no parent post, it is considered a top-level post and not a comment.
- If a post has a parent post, it is considered a comment on that parent post.
- If a post is a comment, it does not have a title.
Tasks
The task is to implement the following API routes:
-
GET /api/communities/:communityId/posts/:postId/comments Retrieve from the database the list of comments of the post identified by post id
:postId, where:postIdis a path variable, and return them as a JSON document.Example response:
[{"id": 1,"title": null,"content": "Comment 1 content","community_id": ":communityId","parent_post_id": "Pid","created_at": "..."},{"id": 2,"title": null,"content": "Comment 2 content","community_id": ":communityId","parent_post_id": "Pid","created_at": "..."}] -
POST /api/communities/:communityId/posts/:postId/comments Add a new post to the database based on the request body. The comment will belong to the post identified by
:postIdand the community identified by:communityId.The request body will have one field (content) as follows:{ "content": "Comment 3 content" }Response to the request with the newly created comment object with its newly created
idas JSON.Response example:
{"id": 3,"title": null,"content": "Comment 3 content","community_id": ":communityId","parent_post_id": "Pid","created_at": "..."} -
DELETE /api/communities/:communityId/posts/:postId/comments/:commentId Removes the comment identified by community id
:communityId, post id:postId, and comment id:commentIdfrom the database. Returns a JSON document with the removed comment.
Submission
Once ready, zip the contents of the server folder of your overarching project and submit the zip file below. The controllers folder should be at the root of the zip file. The expected file structure of the project is as follows.
Follow the names exactly as given, as the automated tests will check for them. Your project may have additional files (e.g. Dockerfile, deno.json).
.├── controllers│ ├── commentController.js (new)│ ├── communityController.js│ └── postController.js├── repositories│ ├── commentRepository.js (new)│ ├── communityRepository.js│ └── postRepository.js├── app-run.js└── app.js (updated)