Part 3:- API using GraphQL and Node.js
This is Article 3 for this series. You can find first article here and second article here.
About this Article
In this article you will be able to do the following things:-
- Create an Auth based system.
- Use JWT to verify the tokens
- CRUD(Create Read Update Delete) operations for Todo using GraphQL
- Write tests for it.
Creating a Auth based system
We need to have a system where users can create a todo only when they authenticate themselves as real user. For example, if we don’t authenticate our routes, anyone can create a todo and spammers can spam the database. Also we need to keep track of todo for a particular user. Including them and many other reasons we need to create an Auth based system. So let’s create a folder inside src
called as middleware
and then create 2 files inside it:-
- auth.ts
- index.ts
Inside src/middleware/auth.ts
copy this :
Explanation:-
- Line 1–6:- We require necessary modules for this file.
- Line 16:- We are exporting a function to check whether a user is authenticated or not. This functions takes an argument which
context
which is generally a form ofrequest.
- Line 17:- This function is returning a promise.
- Line 18–23:- Now as said earlier
context
is in form of request so it will containheaders
, now we will check if any token is passed inx-access-token
header. This is a custom header that we will use to pass our JWT token when making a GraphQL request to CRUD operation on a Todo. If token is not present in header we reject our promise with a newresponse
that we created inresponse.ts
. - Line 26–30:- You can check here how a JWT works. So if any modification is made to our token then it will reject the with a new response.
- Line 32–48:- If token is not tampered with then we recieve a decoded data. That decode data contains
id
of user. We then find that user with that id and return it. If no user is found we reject with a response. - Line 43–44:- We resolve the promise by passing it to
completeRequest
and gets back another promise but this promise has response in form we want. We then return the value.
After 2 articles you might have idea what we are going to write in src/middleware/index.ts
. You may have already written it 😄, but let’s be sure and copy this code.
export * from "./auth";
Now lets create our Schema for Todo for our mongoose model. Create a file inside schemas
named todoSchema.ts
and copy this inside
src/schemas/todoSchema.ts
We already understood how to make a schema when we created userSchema
. Here is just one new thing on line 25–28:- We need to reference the todo that is created to the user who created it. So postedBy
will contain _id
of user who will create that todo. Line 29–31 will store the name of the user.
Also update your src/schemas/index.ts
and add
export * from "./todoSchema";
Now we will create functions for CRUD operations on a todo. So create file todo.ts
inside routes
folder and copy this inside
src/routes/todo.ts
You might now have idea what we are doing. We have 4 functions.
- addTodo :- This creates a new todo.
- getAlltodosForUser :- This returns all todos for an authenticated user.
- update :- This updates a particular Todo.
- deleteTodo :- This deletes a particular todo.
All Functions are authenticated. That is, only authenticated user can make request to perform CRUD operation.
Now lets create a graphQL schema for our Todo. Create a file todographqlSchema.ts
inside schemas
folder and copy this inside
src/schemas/todographqlSchema.ts
You might have idea about it, as it is somewhat similar to userLoginSchema.ts
and userRegisterSchema.ts
for graphQL. Also we need to export this file so paste this line inside
src/schemas/index.ts
export * from "./todographqlSchema";
Now we need to finally add queries and mutation inside our graphql.ts
. Like we did for loginUser
and registerUser
. So copy and replace your old code with this inside
src/schemas/graphql.ts
Now lets write tests for our code changes. First we need to create 2 new files inside our test
folder.
- profileQueries.ts
- todoQueries.ts
Inside src/test/profileQueries.ts
copy this code
Also copy this to src/test/todoQueries.ts
We need to update our user-test.spec.ts
file. This file is very big, so open the link given below and copy the file into your src/test/user-test.spec.ts
Lets run our test by running npm run build && npm run coverage
. Make sure your MongoDB is up and running. You will get this output.
Accessing the API
First check your mongoDB server is up and running. Then start your server by running the following command
npm start
Now to access the API of application open your GraphQL-Playground and enter url http://localhost:3000/graphql
Creating a Todo
Enter Query
mutation addTodo($input: todoInput) {
addTodo(input: $input) {
code
message
data {
success
todo {
id
postedByid
description
updatedAt
createdAt
name
}
}
}
}
and then query variable
{
"input": {
"title": "This is a test todo",
"description": "Lets see if this works"
}
}
Important:- You need to set HTTP HEADERS. You can get this token with the use of login API.
query loginUser($input: UserInputLogin) {
loginUser(input: $input) {
data {
token
}
}
}
and then query variable
{
"input": {
"username": "knrt10",
"password": "test"
}
}
From this response copy the token and then copy this code to your HTTP HEADERS
{
"x-access-token": "your access token from login API"
}
Then hit play button, you will get response like this. Try removing the token or changing token to something else and see the response.
Updating a Todo
Enter Query
mutation updateTodo($input: todoInputUpdate) {
updateTodo(input: $input) {
code
message
data {
success
todo {
id
postedByid
description
updatedAt
createdAt
name
title
}
}
}
}
and then query variable. You can get the id
from the todo you created before.
{
"input": {
"id": "id of your todo you created before",
"title": "Second check?",
"description": "Yaaho."
}
}
You also need to set header like above. After that when you hit play button you will get this response
Getting all Todo
Enter Query
query todoUsers {
todoUsers{
code
message
data {
success
todos {
title
description
id
}
}
}
}
and then set HTTP HEADERS like above API.
{
"x-access-token": "Your access token"
}
After that when you hit play button you will get this response
Deleting a Todo
Enter Query
mutation deleteTodo($id: String) {
deleteTodo(id: $id) {
code
message
data {
success
}
}
}
and then query variable. You can get the id
from the todo you created before.
{
"id": "5c25156f70d37365ede03609"
}
You also need to set header like above. After that when you hit play button you will get this response
Conclusion
That is for this part. In this part you learnt following things:-
- How to write Schema for GraphQL.
- How to create Schema for Todo and link it with a User
- Perform CRUD operation on a Todo using GraphQL.
- How to write clean code.
- How maintain 💯 code coverage 😉.
- You can see it took 33 tests to run in about 804ms. Which is less than a second. It shows how fast and precise our code is.
Code for this series
Code is open sourced on Github under MIT license. Feel free to use it as reference if you are stuck anywhere.
Support
I wrote this series of articles by using my free time. A little motivation and support helps me a lot. If you like this nifty hack you can support me by doing any (or all 😉 ) of the following: