June release - 2021

This is the first release after the major release of v5. So, this is special as it contains a handful of bug fixes and some improvements that didn't make it to the main release last month.

As always, let's start with the highlights of the release.

Here's the summary of all the completed tasks and their related commits/PRs.

Upgrading to the latest versions

The following packages have been updated during the current release.

You can upgrade to the latest versions of all the packages using the npm update command or manually installing packages with the @latest tag.

npm i @adonisjs/[email protected]
npm i @adonisjs/[email protected]
npm i @adonisjs/[email protected]
npm i @adonisjs/[email protected]
npm i @adonisjs/[email protected]

Async local storage and HTTP Context

This is a big one, contributed by @targos . We are using ALS (async local storage) within the HTTP requests to make the HTTP context available anywhere inside your codebase.

For example, with ALS enabled, you can write the following code.

import HttpContext from '@ioc:Adonis/Core/HttpContext'
class User extends BaseModel {
public static query() {
const ctx = HttpContext.get()!
return super.query(ctx.tenant.connection)
}
}

ALS is a complicated topic, as you first have to understand how the Node.js event loop works and its impact on how we write and structure our code.

We recommend first reading about async hooks and async local storage in general and then head over to AdonisJS ALS guide to learn about the usage within the framework.

Facebook, Linkedin, and Discord social auth drivers

Along with the existing set of Ally drivers. We now also have the following drivers available.

Check out this boilerplate repo to create your custom ally drivers. We will appreciate it if you can publish it as a package on npm and share it with the rest of the community.

Support for calendar events in the mailer

The mailer now allows sending calendar invites by either attaching an existing invite (.ics file) or creating one on the fly using the calendar's fluent API. For example:

Mail.sendLater((message) => {
message.icalEvent((calendar) => {
calendar
.createEvent({
summary: 'Adding support for ALS',
start: DateTime.local().plus({ minutes: 30 }),
end: DateTime.local().plus({ minutes: 60 }),
})
})
})

The docs have been updated to cover the calendar invites API.

Events error handler

The error handling with events so far was not that good. To capture errors that occurred during the emit lifecycle of an event, you will have to wrap your Event.emit calls inside a try/catch statement.

After this release, you can register a custom onError handler to listen for errors occurred during the emit life cycle an event.

import Event from '@ioc:Adonis/Core/Event'
Event.onError((event, error, eventData) => {
// handle the error
})

Run migrations programmatically

The latest release of @adonisjs/lucid allows running migrations programmatically using the Migrator module. For example:

import Route from '@ioc:Adonis/Core/Route'
import Migrator from '@ioc:Adonis/Lucid/Migrator'
import Database from '@ioc:Adonis/Lucid/Database'
import Application from '@ioc:Adonis/Core/Application'
Route.get('/', async () => {
const migrator = new Migrator(Database, Application, {
direction: 'up',
dryRun: true,
})
await migrator.run()
return migrator.migratedFiles
})

Read the migration docs to learn more about the API.

Breaking changes

We have two very minor breaking changes in this release inside the @adonisjs/lucid and @adonisjs/ally packages.

Lucid

We have renamed the following TypeScript ambient modules. This change will ideally not impact your applications, as these modules only contains the static types and were not commonly used.

Ally

As we are adding new drivers to the codebase, the possibility of not able to get a user's email address is increasing. Hence, we have to update the email property in the AllyUserContract type to be null | string.

After this change, you will have to guard against missing emails as follows.

const facebookUser = await ally.use('facebook').user()
if (!facebookUser.email) {
// handle the use case for missing email
}

Features & small improvements

Bug fixes