Recently, our organization planned to migrate an internal application web API to Nodejs web API. We have everything to work on node app, but we were lacking a console where we can run queries and examine results to implement them in our controller or vice-versa.
What we have in Ruby on Rails framework
rails_app $ rails c
irb(main):005:0> User.first
User Load (0.7ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1
=> #<User id: 1, email: "aravind@kiprosh.com", created_at: "2018-11-29 07:56:26", updated_at: "2018-11-29 07:56:26">
Problem
In the existing node console, we need to require each model to perform an operation and sometimes we get an error when we run complex queries like includes or joins if we forget require/assign that specific model, one such error I encountered as follows
$ node
> models = require('./app/models')
> User.findOne().then(u => user = u)
ReferenceError: User is not defined
> // Oops! forgot to assign User = models.User
After googling found out that we can modify REPL and set up some configuration before REPL context begins.
Solution
To modify REPL add a file to the root folder of your app and name it console.js
as shown in script 1. console.js
To make it clear here is our dir structure,
root
|- app
| |- models
| |- index.js
| |- User.js
|- lib
| |- DateTime.js
|- console.js
|- package.json
|- server.js
|- yarn.lock
console.js
Let’s see what’s going on in console.js
As you can see on line no 28 (in script 1), first we need to require nodejs REPL, To know more about Nodejs REPL visit https://nodejs.org/api/repl.html.
on line no. 29, we require sequelize models as we are using sequelize ORM in our project. The models will now have an object with key, value pairs of our database models and all other logical stuff of ORM. But, we can access our models directly using models
which we required.
$ node
> const models = require('./app/models')
undefined
> User = models['User'] // models.User will also works
undefined
> User.findOne().then(u => user = u) // Promise
> user.toJSON() // will return {id: 1, email: "user@email.com", ....
global
is a Global object of nodejs. In browser we have window
as a global object likewise, In nodejs we have global
named variable as global object
Before modifying global objects we need to make sure that we are not breaking existing global object properties.
Hence, on line no. 31(script 1. console.js) we fetching keys of models object and assigning on global object, now when we type User in console we get as follows
$ node
> User
User { ...
on line no. 35, we are assigning DateTime object, which is custom tailored class to handle date objects in our project.
on line no. 37, we start the repl server as follows
let replServer = repl.start({ prompt: 'app > '});
on line no. 39, we are assigning models to a db variable so later we can access our models using db
variable. The output of replServer.context
will be shown in fig. 4, it will have global object and all other required objects.
Now run console.js
using command
$ npm run console
OR we can run using yarn
// package.json
"scripts": {
"console": "node run console"
}
$ yarn console
app > user = await User.findOne()
Executing ....
app > user.toJSON()
{ id: 241,
first_name: 'Aravind',
last_name: 'Vemula',
email: 'aravind@kiprosh.com',
password_hash: '$2b$10$eTnpwZuLfAdcg...',
company_id: 1,
inserted_at: 2018-11-29T01:00:46.846Z,
updated_at: 2018-11-29T01:00:46.846Z,
nickname: 'AravindVemula',
deleted_at: null,
timezone: 'Asia/Calcutta',
reset_password_token: null,
reset_token_sent_at: null,
profile_pic_url: null,
default_project_id: null }
app >
Modify console.js
to add more functionality, like reloading console whenever a file change happens etc.