Assignment
As usual, create a PR in your HYF assignments repository.
In the repository, create a nodejs-week1 branch from main to work on the assignment (git checkout -b nodejs-week1 )
Setup
Go to nodejs/week1 in your hyf-assignment repo:
npm init -y
npm pkg set type="module"
npm i express
npm pkg set scripts.dev="node --watch app.js"You should ensure that the node_modules/ folder is ignored by Git:
echo node_modules/ >> .gitignoreCreate app.js and as a starting point you can use the following code:
import express from "express";
const app = express();
const port = process.env.PORT || 3000;
// Support parsing JSON requests
app.use(express.json());
app.get("/", (req, res) => {
res.send("This is a search engine");
});
app.listen(port, () => {
console.log(`Listening on port ${port}`);
});Part 1: Add more snippets and tags
You will continue working with the schema used in the session. This week you will build more endpoints, developing some CRUD operations to be able to add more data via your backend.
Excercise goal
We have users and users post snippets. We need to be able to post those snippets to the database and also edit or delete the snippets via backend endpoints.
We also need some categorisation mechanics. Let's add a tags table, that will store tags available to be added to our snippets, so it is easier to search them. Each snippet can have many tags and each tag can belong to many snippets.
Note: you need to modify the snippets column in the database on top of adding new tables to achieve this.
Routes
For this week's assignment, we will have two categories of routes: snippets and tags.
The routes for snippets will go into
/api/src/routers/snippets.jsThe tags routes will live in
/api/src/routers/tags.js
This means that we will end up having two Routers: a snippets and tags router. You can read more about Express Routers.
Snippets
/api/snippets
GET
Returns all snippets
/api/snippets
POST
Adds a new snippet to the database
/api/snippets/:id
GET
Returns the snippet by id
/api/snippets/:id
PUT
Updates the snippet by id
/api/snippets/:id
DELETE
Deletes the snippet by id
Tags
Now that you have built the basic set of endpoints for snippets, you can get some more practice and expand your app backend by creating the same for tags:
/api/tags
GET
Returns all tags
/api/tags
POST
Adds a new tag to the database
/api/tags/:id
GET
Returns a tag by id
/api/tags/:id
PUT
Updates the tag by id
/api/tags/:id
DELETE
Deletes the tag by id
Requests
All the POST or PUT endpoints will require a request body - the information that your database will be updated with.
Responses
All the specified GET routes should respond with JSON with the available columns from the associated tables.
The GET, PUT and DELETE routes that include an /:id in the path should make sure to handle the case when the row with that ID does not exist.
Think about what special HTTP status code would be appropriate for that scenario.
You are free to decide on the response for a successful POST, PUT and DELETE request. Some ideas:
Respond with an acknowledgement message:
{ "message": "Deleted snippet" }Respond with data from the row itself like with
GET
And lastly, if the POST request is successful, the response status code should be 201 Created, as that would indicate something was created.
Knex
Your usage of Knex should be getting a bit more advanced now. You will move from knex.raw on to different knex function, for example:
.select,.from,.where.insert.update.del(for deletion)
Check out the Knex cheatsheet!
Part 2: search engine
For the excercise you're going to build a search engine. The search engine will have 3 routes:
GET /searchGET /snippets/:idPOST /search
GET /search
GET /searchThis endpoint will accept a query parameter called q, short for query. A bit confusing to have a query parameter called q(uery) but hang in there 💪
If
qis not provided, the endpoint should return all documents.If
qis provided, the endpoint should return the documents with some field that matches the value ofq.
Example response if we call GET /search?q=react:
[
{
"id": 2,
"title": "React Hooks",
"contents": "Explaining useState and useEffect with examples."
}
]GET /snippets/:id
GET /snippets/:idThis endpoint is simple: find and respond with the snippet matching the id parameter. If there is no such snippet, respond with a 404 Not Found. You can assume that the snippet IDs are unique so there's no need to handle duplicates.
POST /search
POST /searchThis endpoint is sort of like GET /search.
It also accepts a query parameter called q and it should behave just like GET /search. But it also accepts a field called fields in the JSON request body. fields is an object where it will be possible to filter by specific fields.
Example request:
POST /search
{
"fields": {
"tags": "React"
}
}Response to the example request:
[
{
"id": 1,
"title": "React Hooks",
"contents": "Explaining useState and useEffect with examples.",
"tags": ["React"]
}
]If both q (query parameter) and fields (in body) are provided, we should respond with status 400 Bad Request and explain that both can't be provided.
Last updated