A few months back I was working on a Full-stack project using NodeJS with express and MongoDB, this used to be my go to framework for building full-stack applications, usually coupled with vue or react.
As much as I enjoy working with this stack I usually get frustrated at the amount of boilerplate I need to write first and the lack of project structure which really slowed down my development speed. So I decided I need more of a structured framework and set out to scour the internet for a NodeJS framework similar to Laravel, Django or Rails.
Low and behold after hours of searching and almost giving up I stumbled upon AdonisJS after going through their documentation I was hooked!
Here I will go over all the features AdonisJS offers, if you are familiar with Laravel, Django or Rails and you have a strong interest in typescript you should enjoy working with AdonisJS.
What is AdonisJS
AdonisJS is a backend framework. It helps you create data-driven dynamic web applications. Using AdonisJS, you can handle the HTTP requests, query the database, authenticate users, upload files, send emails, and do a lot more.
Creating Routes is super simple
import Route from '@ioc:Adonis/Core/Route'
Route.get('/', () => {
return 'Hello! This is the homepage of my new app'
})
This how you would query the database within a route using dynamic params.
import Route from '@ioc:Adonis/Core/Route'
import Database from '@ioc:Adonis/Lucid/Database'
Route.get('posts/:id', ({ params }) => {
return Database
.from('posts')
.select('*')
.where('id', params.id)
.first()
})
Controllers are your best friend for HTTP requests
Where is my laravel devs?
01 Create a controller
node ace make:controller Posts
02 Implement the required methods
import Database from '@ioc:Adonis/Lucid/Database'
export default class PostsController {
public async show({ params }) {
return Database
.from('posts')
.select('*')
.where('id', params.id)
.first()
}
}
03 Register it with the route
Route.get('posts/:id', 'PostsController.show')
Query database using the ORM
Interacting with databases is super simple using an offical package called Lucid (epic name btw), Lucid has a rich API to perform schema migrations, seed databases with dummy data, and construct SQL queries.
01 Create a new model
node ace make:model Post
02 Configure columns
import { column, BaseModel } from '@ioc:Adonis/Lucid/Orm'
export default class Post extends BaseModel {
@column({ isPrimary: true })
public id: number
@column()
public title: string
@column()
public description: string
}
03 Import and use it inside the controller
import Post from 'App/Models/Post'
export default class PostsController {
public async show({ params }) {
const post = await Post.find(1)
return post
}
}
Render HTML using templates
AdonisJS also ships with a homegrown template engine - “Edge”. Edge is really easy to use especially if you are used to React or Vue, using your Frontend JS Framework skills can come in handy here.
01 Create a view template
node ace make:view posts/index
02 Write the markup
<div class="article">
<h1> {{ post.title }} </h1>
<p> {{ post.description }} </p>
</div>
03 Render it inside the controller
import Post from 'App/Models/Post'
export default class PostsController {
public async show({ params, view }) {
const post = await Post.find(1)
return view.render('posts/index', { post })
}
}
If you prefer to stick to React or VueJS no problem, AdonisJS supports both via InertiaJS
Authenticate users using the auth package
Auth has never been easier than this in my entire life. It’s too easy!!
01 Install and configure the auth package
npm i @adonisjs/auth
node ace configure @adonisjs/auth
02 Login users using sessions
export default class AuthController {
public async login({ request, auth, response }) {
const email = request.input('email')
const password = request.input('password')
await auth
.use('web') // 👈 using sessions guard
.attempt(email, password)
response.redirect().toRoute('dashboard')
}
}
03 Generate an API token instead
export default class AuthController {
public async login({ request, auth }) {
const email = request.input('email')
const password = request.input('password')
const token = await auth
.use('api') // 👈 using API guard
.attempt(email, password)
return token
}
}
Validate input using the validator
Server Side Validation is just as easy, and Adonis provides a bunch of common rules to help along with the ability to create custom rules and error messages.
01 Create a validator
node ace make:validator CreatePost
02 Define the validation schema
import { schema, rules } from '@ioc:Adonis/Core/Validator'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class CreatePostValidator {
constructor (protected ctx: HttpContextContract) {
}
public schema = schema.create({
title: schema.string(),
description: schema.string({}, [
rules.escape()
]),
})
}
03 Validate the request
import CreatePost from 'App/Validators/CreatePostValidator'
export default class PostsController {
public async store({ request }) {
const post = await request.validate(CreatePost)
console.log(post.title)
console.log(post.description)
}
}
Compile assets using webpack encore
At some point in time, you may reach for a CSS framework and might want to sprinkle some JavaScript to make your web apps interactive.
As per the standards today, the CSS and the frontend JavaScript need to be transpiled and minified before serving it to the browser. This bundling process is not that simple, and hence you must use a bundler for it.
AdonisJS pre-configures Webpack (an industry-standard bundler) with sane defaults so that you don’t have to waste time adjusting its knobs.
Still not convinced I got you!
Do you need Social Authentication ? No problem.
AdonisJS support social auth with their package called ally. It supports multiple providers. Google, Twitter, LinkedIn, Facebook, Discord, Spotify, and GitHub and has an extensible API to add custom social providers.
But what about TDD ? hmmmm…
E2E, Unit tests and HTTP tests Adonis got you covered heres what they have to say:
AdonisJS has out of the box support for testing, and there is no need to install any third-party packages for the same. Just run the node ace test and the magic will happen. AdonisJS uses Japa (A homegrown testing framework) for writing and executing tests.
I18n ????
npm i @adonisjs/i18n
Helpers to perform language-sensitive formatting for dates, currencies, names, and so on. Support for storing translations in ICU messages format. Add your custom messages formatter and translations loader.
But my SAAS needs to send emails!
AdonisJS comes with a mailer packaged called mail. It is built on top of nodemailer and it has support for multiple drivers. SparkPost, SES, Mailgun and Smtp, plus you can use their edge templates to create markup for your emails.
Massive file uploads with Drive.
AdonisJS Drive is an abstraction on top of cloud storage services, such as: Amazon S3, DigitalOcean Spaces, and Google Cloud Storage.
If you like to get Started head over to AdonisJS
Here is a full list of additional features for you to ponder over:
-
Full typescript support
-
Web security
-
CORS Config
-
Encryption
-
Signed URls
-
Hashing
-
REPL
-
Logger
-
Events
-
Helpers Utilities
-
Redis
-
Rate Limiting
-
VS Code Extension
-
Community Packages