Build a Simple News App using Adonis v5

AdonisJS has been my framework of choice to get stuff done quickly. The framework has taken a turn for the good with more frequent updates to its latest version - v5, which features Typescript, the same trusted MVC framework, and “everything & kitchen sink” approach that is quite effective to easily build apps. In this post we will create a simple news website using AdonisJS. The focus will be on - ...

Starter Template for AdonisJS

I have used AdonisJS in and out of projects in the last year. Despite it’s smaller community and not-so-regular enhancements, it remains one of my favourite NodeJS frameworks. I recommend AdonisJS for hobby and production projects in full confidence :) I typically use AdonisJS for back-end, which has me start with - adonis new awesomeness --api AdonisJS comes with a neat set of powerful features - An ORM that works quite well Authentication and security already setup Basic features to serve API without pulling a thousand wires just to get started The Case for a New Boilerplate Even with all the features baked in the default boilerplate, I tend to just copy older projects - ...

Prevent test emails going out to users in AdonisJS

Here’s a quick way to prevent emails from going out in test environments in AdonisJS. We typically end up getting production data in part or in whole to test environments for a “proper” round of testing on real data. But all the data attributes cannot be so “real”. We typically end up changing fields like emails so that customers do not start receiving emails from non-production environments. In addition to the above change, we try to specify an explicit opt-in to communications so that people who are not associated with testing do not get confused with test transactions - even when the said people are within the client organization. ...

Use MySQL Load Files Data in AdonisJS

Use MySQL load data function to load data from files within within AdonisJS services. You can perform batch data and file operations efficiently using database utilities. The logic will likely be quicker, lighter on resources, and overall, more suited for batch jobs. Loading data from files is not as sought-after as in the good-ol’ days, but is quite common in enterprise applications. One or more of the following operations may be required to load data from files - ...

Batch Operations in AdonisJS

Use Adonis Scheduler to create batch tasks as well as schedule execution of said tasks. Adonis Scheduler improves your efficiency in writing batch jobs. I am talking about bulk operations that may or may not be suitable for your general purpose service and controllers. Although scheduler’s purpose seems to be, well, scheduling stuff we can reuse Tasks enabled by scheduler to run bulk operations. Install Scheduler First, install scheduler - yarn add adonis-scheduler Let AdonisJS know that you have added scheduler - ...

Using Lucid vs. Database Raw in AdonisJS

Lucid ORM, the official ORM of AdonisJS, is based on knex.js. It is one of the friendlier ORMs that provides the ease of using a readable syntax along with a better performance than some of the feature-heavy ORMs. But, I have been recently torn between using one or the other. Consider the below query that fetches a bunch of related fields - const statusByParSub = await Database.select("sub.sub_num", "sub.status_cd") .from("sub") .innerJoin("par", "sub.par_id", "par.id") .innerJoin("users", "par.owner_id", "users.id") .where("par.start_date", ">", queryFilter) .groupBy("sub.sub_num") .groupBy("sub.status_cd") .count(); While the above query is certainly more readable than using a SQL, I doubt whether it can achieve the same level of performance as a raw SQL. The main reasons for the thought process being the layers involved in ORM, the end-query built from 1:M and M:M relationships, and the time that I personally take in creating an efficient ORM vs. writing a raw SQL. ...

Manage incremental changes to database in AdonisJS

Use database migration utilities in Adonis to its complete potential. Carry out incremental updates - may it be a new table, or changes to existing table using distinct migration files that are version controlled. You have a beautiful Todo application that has a todos table with the following columns: description status end_date Now, let’s say our users ask for a new field called planned_end_date. Your first instinct may be to add the column to the database, change controller code if required, and call it a day. But, what if you to start making changes at different times to - ...

Handle Creation of Single or Multiple Records in AdonisJS

Support creation of a single record or a group of records using same business logic and in the same controller in AdonisJS. Typically you create the following controller to handle record creation - // TodoController.js async create({ request, auth }) { const data = request.all(); //single record return await Todo.create(data); } create will happily create a single record as per the input data. What if you want to create multiple records in one go? The first idea that one may have is to handle everything in the controller. Since the business logic is going to remain the same, and there may be a lot of reuse for auxiliary functions, one is tempted to just do the following. ...

Custom Configuration Parameters in AdonisJS

AdonisJS stores its configuration values in config folder in root. For e.g. you will set database environment values in database.js, authentication params in auth.js and so on. You can update or set new configuration parameters required by your application in those files. You could also create a new configuration file for your application variables and refer to those values from services, controllers, or from any place where it makes sense. ...

Pagination in AdonisJS

AdonisJS provides a standard way to handle pagination and query only a pre-defined number of records in your query result. A typical controller without any pagination looks like the below - // TodoController.js const Todo = use("App/Models/Todo"); class TodoController { async index({ request, response, view }) { return await Todo.query().fetch(); } } The index method outlined in the code block just queries all records and returns everything to caller. This is good as long as you have limited set of records within your database. If the to do records are in hundreds, thousands or more, you have a problem on your hand. ...