Why Nodal is the greatest

Anyone who has tried to build out an api server will know the drudgery which I would have to describe, making models, controllers, a server routes all that and then some. There is a better way. Let me introduce a little tool known as NodalJS.

A little history, NodalJS’s creator is a Hack Reactor bootcamp grad and although it is still in progress this little project is an extremely powerful tool. Once installed, with the cost of a few simple commands we can get a whole API server running.

How to get started? I recommend going to the source https://github.com/keithwhor/nodal , or http://www.nodaljs.com/ to get the docs and other cool stuff. Just a word on the Docs. they’re…..functional, everything is not up to date, and in the beginning they are a little cryptic. For example the methods are written as .method(), or as #method, which designates whether or not it is a static method or a class instance method. For the uninitiated to the ways of ES6, you might ask, What’s that mean?

Lets take a moment to go over ES6 classes. This was JavaScripts attempt to shoehorn the class system which is seen in many other languages into a normally classless system. Below is a simple example ripped straight from nodal. So in the class system, everything is extended from the baseline class, which means that the class is an object. This provides several things to you if you know a lot about how prototyping in JavaScript works.

const Nodal = require(‘nodal’);
class IndexController extends Nodal.Controller {
 constructor() {
super()
}
get() {
this.respond({ message: ‘Welcome to your Nodal Project’ });
}
}
module.exports = IndexController;

Above we have the IndexController, this is the class made for this controller, and it is an extension of another class, Nodal.Controller. This provides a prototype for IndexController, and with that, IndexController now has access to all the methods of a Nodal.Controller, and access to its own method, get(). If you’ve got your glasses on you’ll also notice the constructor() and super() methods. They’re not used in this case, and are actually omitted in the actual controller, but i’d like to illustrate that they would be there in the Nodal.Controller instance and in the event you wanted a fresh Nodal.Controller and not an extension of that controller, you would have to instantiate a new Nodal.Controller(the constructor input) and the super() would allow you to access pieces of the extended constructor. For example, super.method() lets you access Nodal.Controller methods. Its important to note that neither the constructor, nor super are necessary, but you must call super, if there is a constructor, so back to Nodal.

Nodal uses generators to get almost everything done. Instead of setting up a file and making a schema, exporting a model, then having to set up a controller and routes for that model. Nodal simplifies all this with a few generator commands. For a much more in-depth look at setting up models, and controllers I suggest reading https://nsipplswezey.github.io/nodal/docs/tutorial.html, this will get you on your feet.

So to generate a model we just need one command.

nodal g:model mymodel name:string number:int

and thats it. Now we have a schema, a model and all the ORM commands set for this model. A migration file, to insert it in our database, but lets go one step further.

nodal g:controller v1 for --mymodel

Now we really have something, this generates for us the server route, and all four basic CRUD operations for the model we just made mymodel, and a label v1 which maintains version control. Its also worth noting that a controller can be generated without a model. If its generated with a model you’ll get index, show, create and destroy methods, with the necessary model commands to carry them out. Without a model, you just have get, post,put, delete and no other logic.

The basic CRUD commands all come in a similar form

User.create(this.params.body, (err, model) => {       this.respond(err||model)
}

which you may see as Callback hell. Which for simple operations is not a huge deal but when it comes to nesting it can get quite ugly.

User.create(this.params.body, (err) => {
if (err) { this.respond(err); }
this.params.body.grant_type = ‘password’;
AccessToken.login(this.params, (error, accessToken) => {
if (err) { this.respond(err); }
this.params.body.access_token = accessToken._data.access_token;
User.update(accessToken._data.user_id, this.params.body,
(errs, user) => {
this.respond(errs || user);
});
});
});

I experimented with this a lot and found the Q promise library to work for most operations, and cleans up the code some, but Nodal’s ORM sets up model objects for you, which have to be converted back to a regular object to be used in any subsequent command, in which case I suggest you memorize Model.toObject(), where Model is the Model instance. This begs the question, whats a model?

const findUser = Q.nbind(User.find, User);
findUser(this.params.route.id)
.then((model) => {
this.respond(this.respond(model, [
‘id’,
‘email’,
]));
})
.catch((err) => { this.respond(err); });

Above I’ve laid out how I set up one of my controllers. Whenever a Crud operation is carried out, Nodal converts the resultant that is returned from the database as the success criterion, into a model. Which is an instance of the model we inserted into the database. In the case above, we’ve found the user with a certain Id, and the database returns a model based on this information. On first inspection it looks like a regular object, but it isn’t it’s an object created from Nodal’s Model Class which, if you scan Nodal’s docs nodaljs.com/static/docs/index.html#Model it gives you several methods that can be performed on a model instance, as well as the static methods. Which are free methods which come available to be used elsewhere, just by having a model instance available. The thing that is worth noting is that a model will return everything that is available on that model’s schema, so this.respond(model) would return everything about that model, but the model also allows you to return a select number of parameters, in an array.

this.respond(model)                ==whole model comes back 
this.respond(model,[‘id’, ‘name’]) ==only id and name of model                                         
return

This works fine for single operations, but say we wanted to join some models together, like we wanted a user to be returned, plus something like their favorite books. This would assume we have a books model, full of books, which have a reference to the user’s id. Lets just say, that user 1 has 2 books, each that have a user_id column with the value of 1. To carry this out, first we need to join child to parent, in this case books to user. In the books model inputting the below commands will accomplish this.

//import the model
const User= Nodal.require(‘path/to/users.js’)
class Books extends Nodal.Model {}
// join books to users, and any additional criteria
Books.joinsTo(User, {multiple:true, as:’book’})
module.exports =Books;

Thats it, we’ve joined books to users, and now on the model controller, the .joins(‘book’) command is available. AS seen below, now whenever we return the user model, we can access the book and any of the parameters of book, as book on the user, model.

Users.query(this.params).joins(‘book’).end((err,model) =>{
this.respond(model,[
id’,
’name’,
{book:[‘name’]}
]))}

While this was not an all encompassing overview of Nodal, and everything it does. I recommend going through the tutorial I linked in the introductory areas, as it helps better illustrate some of the things I’ve covered, as well as going into more depth on how to set up Authentication which, nodal makes super simple. Nodal is set up to work with PostgreSQL databases, which I neglected to mention this in the beginning. Additional awesomeness that comes with using nodal includes, a provided testing setup, task automation logic, a provided Travis Ci file, which is already set up to run your tests, and Nodal’s github wiki also provides everything needed to Dockerize your new server.

Hopefully this has convinced you that NodalJS is a powerful tool which provides easy setup of a full working API server.