Universal Apps and MeteorJS in 2019

I was a MeteorJS fan. MeteorJS was an excellent tool to quickly create universal apps. I was not quite a professional developer back in the day (circa 2016-17) but I could recognize the power of Meteor in developing complex web applications that could potentially deployed for multiple devices. There was a time when I was flabbergasted as I, rather alarmingly, saw people moving from Meteor to different platforms. I could not quite understand why. ...

Contact Forms in Static Sites

I don’t quite see value in ‘contact us’ forms anymore. No one uses it It is prone to spam No one uses it (yes, this is repeated) However, my personal opinions do not always align with client expectations. So it follows that I create these forms on a static site with resigned indignation. Contact form is not quite a native feature of static sites. However, there are more than few solutions to this problem. ...

CMS, Site Builders and Static Sites

Does the term ‘CMS’ mean anything anymore? And, why a hybrid static site solution is the only way out. Where we stand today? Wordpress really brought web sites to the masses. Instead of writing obscure code using HTML / Javascript, using Blogspot, or using third party site builders, Wordpress and its ecosystem allowed all humans with basic computer skills to whip up a site within no time. Wordpress is a content management system (“CMS”), and a good CMS at that. ...

Web Inspector to design static sites

Chrome and Firefox web inspectors are my new best friends in my quest to develop static sites. I never took the time to appreciate the complete power of web inspection - until I actually started changing the design of this very site. I have been redesigning techformist.com website on Hugo. The plan is to migrate from Jekyll and design a simpler site that can easily showcase what I have to offer (ahem..). ...

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. ...

Role-based Access to Routes in AdonisJS

AdonisJS provides a standard way to define a middleware and enable access to routes based on defined validation rules. This middleware is leveraged to allow role-based access to routes. Your start | routes.js file will have something akin to below - const Route = use("Route"); Route.get("/", () => { return { greeting: "Hello world!" }; }); First, we will group routes for the different roles and introduce the middleware. // start | Routes.js Route.group(() => { Route.post("/user-register", "UserController.register"); Route.post("/user-login", "UserController.login"); }); Route.group(() => { Route.get("/todo", "TodoController.index"); Route.post("/todo", "TodoController.create"); }).middleware("auth"); Route.group(() => { Route.delete("/todo", "TodoController.delete"); }).middleware(["auth", "admin"]); register and login methods are available to unauthenticated and authenticated users To do create and index are available only to authenticated users. auth is provided by AdonisJS Deleting to do is allowed only for admin Now, we write the actual middleware for admin. ...