Custom application logic for Loopback models

Here's little background about Loopback

Loopback.js is a highly scalable node.js & typescript framework based on express. In simple words it lets you create and extend REST API in modularized manner. If you're new you can learn more about it on https://loopback.io/doc/

This post is a continuation to this post.

💡
What if you want to customize your REST API or add different methods for it? When building an application, you’ll generally need to implement custom logic to process data and perform other operations before responding to client requests.

Loopback has defined majorly 3 ways to do it:

  1. Adding logic to models

  2. Defining boot scripts

  3. Defining middleware

For this post I'm explaining about the first one, Adding logic to models. There are 3 types of custom application logic to model.

  • Remote Method

  • Remote Hook

  • Operation Hook

Remote Method

A remote method is nothing, but NodeJS function mapped to REST endpoints. You can create remote method by cli or typing by yourself (click here to know how).

In the previous post, I used memory db. For this one, I'm going to use MongoDB as DataSource. You need to install loopback-connector-mongodb to connect to MongoDB.

npm install loopback-connector-mongodb --save

Then you need to add DataSource:

lb datasource

Enter the datasource name and select MongoDB connector from the list. Then, configure the MongoDB database configuration.

After adding datasource, create a model as described in the previous post (select the freshly created datasource).

Now, for creating remote method, run this command:

lb remote-method

Select the model, in which you want the remote-method, enter the name of remote-method, enter endpoints (you can set multiple endpoints for the same remote-method) to be mapped to this remote-method, select method type (get, post, put, delete) and set arguments to be passed with the appropriate type.

? Select the model: library
? Enter the remote method name: test
? Is Static? Yes
? Description for method: 

Let's configure where to expose your new method in the public REST API.
You can provide multiple HTTP endpoints, enter an empty path when you are done.
? Enter the path of this endpoint: /test
? HTTP verb: post

Let's add another endpoint, enter an empty name when done.
? Enter the path of this endpoint: 

Describe the input ("accepts") arguments of your remote method.
You can define multiple input arguments.
Enter an empty name when you've defined all input arguments.
? What is the name of this argument? name
? Select argument's type: string
? Is this argument required? Yes
? Please describe the argument: 
? Where to get the value from? (auto)
/**
*

* @param {string} name

* @param {Function(Error)} callback

*/

library.test = function (name, callback) { 
// TODO 
callback(null); 
};

At last, there is a sample code given in cli, copy that and paste it into your model.js. You can write your logic instead of // TODO. If you are returning anything in response, you must set return type in the model.json. If you are returning an Object set type object and if there is no root in an object or other type set root to true.

 "returns": {
    "type": "object",
     "root": true
 },

To return response use callback(). callback accepts two arguments, first as error and second as success. If there is some logical error you just use this callback(error), otherwise callback(null,success).

This remote method is now listed in loopback explorer.

Remote Hook:

Hooks in loopback used to do something before the method executes or after the method executes. Sometimes you get some parameters with a blank value, then you must set the default value for them, so you can use them before hook. Just like that, sometimes you must process something after the method is done executing, so you use after hook.

This runs before the remote method:

modelName.beforeRemote(methodName, function (ctx, next) {
    //...
    next();
 });

This runs after the remote method:

modelName.afterRemote( methodName, async function( ctx) {
    //...
    return;
 });

Remote hooks are provided with a Context ctx object that contains transport-specific data (for HTTP: req and res). The ctx object also has a set of consistent APIs across transports.

The context object passed to afterRemoteError() hooks has an additional property ctx.error set to the Error reported by the remote method.

Operation Hook:

Operation hooks are not tied to a particular method, but rather are triggered from all methods that execute a particular high-level create, read, update, or delete operation. These are all methods of PersistedModel that application models inherit.

So, basically, if you want to check the data passed in the built-in create operation, use create-hook before. Similarly, after the create operation, based on the response you need to add some logs or want to perform some action using after create-hook.

These are the operation hooks supported in loopback:

access, before save, after save, before delete, after delete, loaded, persist

Here is how you use these hooks. I am using only after save and before save here, for example, you can use any of above you need. This is after save method,

Library.observe('after save', function (ctx, next) {
    ctx.instance //the request data
    ctx.Model.modelName //name of the model
    next();
})

Here's before save,

Transaction.observe('before save', async function (ctx, next) {
    ctx.instance //the request data
    ctx.Model.modelName //name of the model
    next();
})

So, that's how you can add custom logic to the existing methods in Loopback. That's all for this post. See you again.


Did you find this article valuable?

Support Maulik Sompura by becoming a sponsor. Any amount is appreciated!