Setting Up Our API Server with AdonisJs Framework | Full-Stack Google Contacts Clone with AdonisJs (Node.js) and Quasar Framework (Vue.js)
In the last lesson, we discussed why we chose AdonisJS over other Node.js frameworks. In this lesson, we will setup the AdonisJS framework
as our API server
for this Google Contacts Clone App project.
If you are following along this series, you already have the initial installation (as seen here) of the AdonisJS Framework in the api
folder of our project. Now, we have to install some extra packages and then test our API server
.
Start by creating a new branch of your project.
git checkout -b 10-api-server-setup
Install and Configure the Lucid
package
The Lucid
package is used for interacting with the database. It offers a complete suite of SQL functionalities including querying, inserting, deleting, and updating records. It also offer a fluent ORM for interacting with database records, seeding, migrating tables, and working with model factories.
Install the
Lucid
package:yarn add @adonisjs/lucid
Configure
Lucid
:node ace configure @adonisjs/lucid
- When asked to
Select the database driver you want to use
, selectMySQL / MariaDB
. - When asked to
Select where to display instructions
, chooseBrowser
. If the browser does not launch, repeat:node ace configure @adonisjs/lucid
and chooseTerminal
. - When the configuration is done, follow the instructions on the terminal or browser. It is explained below.
- When asked to
Open
api/env.ts
. Add the following to the options object of theEnv.rules()
function:DB_CONNECTION: Env.schema.string(), MYSQL_HOST: Env.schema.string({ format: 'host' }), MYSQL_PORT: Env.schema.number(), MYSQL_USER: Env.schema.string(), MYSQL_PASSWORD: Env.schema.string.optional(), MYSQL_DB_NAME: Env.schema.string(),
Install and Configure the Auth
package
The Auth
package provides authentication functionalities whether you are using AdonisJS as an API server or for server-side rendering of your web application.
Install the
Auth
package:yarn add @adonisjs/auth
Configure the
Auth
package:node ace configure @adonisjs/auth
When asked to
Select provider for finding users
, selectLucid (Uses Data Models)
.When asked to
Select which guard you need for authentication
, selectAPI tokens
.When asked to
Enter model name to be used for authentication
, enter:User
.When asked to
Create migration for the users table
, pressy
.When asked to
Select the provider for storing API tokens
, selectRedis
.
Lucid will complete the setup of the package.
Testing our API server
We will change into our api
directory, start the server, and ping the base route
("/") of the API server.
Don't type the
#
symbol and content after the#
on each line
cd api # <-- change into our `api` directory
node ace serve --watch # <-- start the server
curl 127.0.0.1:3333/ # <-- ping the "/" route
{"hello":"world"} # <-- response
The response came from the api/start/routes.ts
file. Let's inspect that. Press CTRL+P
on your keyboard and type api routes
to search for the file. Click enter to open the api/start/routes.ts
file as seen in the first result.
The file currently contains one route definition after the Route
class is imported:
import Route from '@ioc:Adonis/Core/Route'
Route.get('/', async () => {
return { hello: 'world' }
})
The first argument of the Route.get()
method is the route path. In this case, the path is /
. The second argument is an async
function handler which simply returns an object: { hello: 'world' }
. That's what we received on the terminal.
Read extensively about the AdonisJS routing here.
The route definition calls a static get
method on the Route
class. The get
method corresponds to the HTTP GET
request method. There are other static methods such as Route.post
, Route.put
, Route.delete
, Route.post
, and Route.patch
. Their usage depends on the API operation you want to perform. Typically, you should follow this rules:
HTTP Method | AdonisJS Route Method | Usage |
GET | Route.get() | Use this method when you want to fetch (read) information about a entity. For example: fetching the details of a user. |
POST | Route.post() | Use this method when you want to create a new entity. For example: create a new user. |
PUT | Route.put() | Use this method when you want to edit/override all the properties of an entity. For example: if you have five properties for a user and you want to edit all the five properties. |
DELETE | Route.delete() | Use this method when you want to delete an entity. For example: deleting a user from the users table. |
PATCH | Route.patch() | Use this method when you want to partially edit/override some properties of an entity. For example: changing only the first_name and last_name while other properties remain unchanged. |
Health Check
AdonisJS comes with a health checker for checking if our application is running optimally. It is often used by deployment tools to check if our application is running optimally before and after a new deployment. To add health check, do the following:
Open
api/start/routes.ts
. PressCTRL+P
on your keyboard and typeapi routes
to search for the file. Click enter to open the file as seen in the first result.Below the import statement for the
Route
class, add:import HealthCheck from '@ioc:Adonis/Core/HealthCheck'
Below the route definition for the path
/
, add:
Route.get('health', async ({ response }) => {
const report = await HealthCheck.getReport()
return report.healthy ? response.ok(report) : response.badRequest(report)
})
This adds the health
route via the Route.get()
method. It calls the HealthCheck.getReport()
. The report
object contains a boolean
property: healthy
. If healthy
is true, we use the response.ok()
method to return the report. Else, we use the response.badRequest()
method to return a 400 error with the report as the payload.
Your api/start/routes.ts
should look like this:
import Route from '@ioc:Adonis/Core/Route'
import HealthCheck from '@ioc:Adonis/Core/HealthCheck'
Route.get('/', async () => {
return { hello: 'world' }
})
Route.get('health', async ({ response }) => {
const report = await HealthCheck.getReport()
return report.healthy ? response.ok(report) : response.badRequest(report)
})
Save the file. And ping the health
route:
curl 127.0.0.1/health
# result below
{"healthy":true,"report":{"env":{"displayName":"Node Env Check","health":{"healthy":true}},"appKey":{"displayName":"App Key Check","health":{"healthy":true}}}}
Read more about AdonisJS health checks here.
Configuring the Database Credentials for the API Server
Now, we will pass in the database credentials we created two lessons ago. Open our .env
file for our backend i.e. api/.env
The .env
file is an environment file which contains very import key-value pairs for our application.
More about the .env
file. As you can see from the file, it contains the APP_KEY
, MYSQL_USER
, MYSQL_PASSWORD
, and MYSQL_DB_NAME
. These are very sensitive data for our backend which should not be known to any third party. This is the reason why you should never commit your .env
into GitHub or other version control systems. As a matter of fact, AdonisJS has a file api/.gitignore
which already configures the .env
file to be ignored by git
during commits.
The APP_KEY
value is used as the encryption salt for your application. All encryptions and hashing are done on the basis of the APP_KEY
. It should be very random and never shared across multiple applications. If you need to change the APP_KEY
, run:
node ace generate:key
Then copy the generated key from the terminal into the .env
file replacing the old value for APP_KEY
.
SERIOUS WARNING. Updating the
APP_KEY
for an existing application with users will invalidate all passwords (passwords are hashed) and encrypted data. You should only do this in production in the case of a security breach, in which case, you will inform your users to reset their passwords.
Back to configuring our database credentials:
- For
MYSQL_HOST
, change the value to;127.0.0.1
. - For
MYSQL_USER
, change the value to:google_contacts_clone_user
. - For
MYSQL_PASSWORD
, change the value to the password you chose. - For
MYSQL_DB_NAME
, change the value to:google_contacts_clone_app
- If you did use the default port number of
3306
when installing the MySQL database server, change the value forMYSQL_PORT
to that port number you assigned.
Save and close the file.
Testing the Database Connection
Open api/config/database.ts
file.
Within the mysql
property, change healthCheck
to true.
{
pg: {
client: 'pg',
connection: {
// ... connection details
},
healthCheck: true, // ๐ enabled
}
}
Save and close the file.
Now, ping the health
route again. You will get:
curl 127.0.0.1/health
# result below
{"healthy":true,"report":{"env":{"displayName":"Node Env Check","health":{"healthy":true}},"appKey":{"displayName":"App Key Check","health":{"healthy":true}},"lucid":{"displayName":"Database","health":{"healthy":true,"message":"All connections are healthy"},"meta":[{"connection":"mysql","message":"Connection is healthy","error":null}]}}}
The Database health check is healthy.
If all is going well as shown here, congratulations. Our API server is ready to serve our Google Contacts Clone App.
Save all your files, commit and merge with the master branch.
git add .
git commit -m "feat(api): complete API Server setup"
git push --set-upstream origin 10-api-server-setup
git checkout master
git merge master 10-api-server-setup
git push
In this next lesson, we will setup Postman
and get it ready for real work.