npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

loopback-connector-flexirest

v2.1.2

Published

Loopback FLEXI REST Connector

Downloads

18

Readme

loopback-connector-flexirest

LoopBack FLEXIREST connector allows loopback application to interact with backend REST APIs. It leverages loopback-connector-rest for basic building blocks and adds additional "flexible" features to allow interaction with backend services.

Installation

npm install loopback-connector-flexirest

Features

  • Use custom folder (endpoints) to organize operations
  • Allow outgoing request parameters transformation
  • Allow incoming response body transformation
  • Allow use of templating library like handlebars for transformation
  • Add new hooks before / after outgoing and incoming transformation
  • Allow custom error handler for functions
  • Extend operation template schema to allow errorHandler, incomingTransform and outgoingTransform to be added as configuration
  • Add a "shared" flag in operation template to disable the operation to be added as a remote method

Usage

Configuration in datasources.json

You can configure the Flexirest connector by editing datasources.json. The baseURL attribute gets prefixed to all the URLs defined in operation templates. All fields are required.


"myNewDataSource": {
    "name": "myNewDataSource",
    "connector": "flexirest",
    "path": "endpoints", // path to folder where Operation templates are placed. This is relative to application root.
    "baseURL" : "http://XXX.YYY.ZZZ/api" // The environment specific hostname and URI root
}

Operation templates

Create a new folder under application root as "endpoints" and store all your operation JSON files. Each operation file should have one template defined. For understanding the template structure, follow the documentation provided by Strongloop. Also, look for example-templates in test folder.

Error Handlers

Custom error handlers can be defined for each functions to allow better non-functional as well functional error handling for backend responses

Outgoing Transformation

Outgoing transformation provides ability to transform the parameters before they are applied to the operation functions.

Incoming Transformation

Incoming transformation provides ability to transform the response body received from the backend system

Syntax to configure error handler & transformations

There are two ways in which the error handler, outgoing and incoming transformation functions can be added:

  1. Adding script to boot folder - Functions are added after model association
  2. Adding configuration to operation JSON templates - Functions are added to datasource

Adding Script to boot folder

Add boot script as follows:


module.exports = function(app) {
  var customFunction = app.models.backend.customFunction;

  var errorHandler = function(err,body,response,callback) {
    if(err)
      return callback(err);

    if(body.error && body.error.errorCode) {
      var error = new Error(body.error.message);
      error.statusCode = 500;
      error.code = 'SYS' + body.error.errorCode;
      return callback(error);
    }
    return callback(null,body,response);
  }

  var outgoingTransformFn = function(parameters) {
      parameters.id = 'PRE' + parameters.id;
      return parameters;
  };

  var incomingTransformFn = function(body) {
      return body.query.results;
  };

  customFunction.errorHandler = errorHandler;
  customFunction.outgoingTransform = outgoingTransformFn;
  customFunction.incomingTransform = incomingTransformFn;
};

Adding configuration to operation JSON templates

First modify operation template with additional attributes: (errorHandler, outgoingTransform, incomingTransform)

{
    "template": {
        "method": "GET",
        "url": "/api/backend/{id}",
        "query": {
            "id": "{id}"
        }
    },
    "functions": {
        "customFunction": ["id"]
    },
    "shared" : false,
    "errorHandler": "customFunction.errorHandler",
    "outgoingTransform": "customFunction.outgoingTransform",
    "incomingTransform": "customFunction.incomingTransform"
}

Secondly, add JS file at the same location as of the operation template, with following code. The connector parses the handler string and splits by '.' (dot). First segment is considered as the filename to load and the second segment is considered as the function name.


exports.errorHandler = function(err,body,response,callback){
    console.log('customFunction errorHandler called');

    if(!err) {
        if(!body.query.results) {
            err = new Error('No results found');
            err.statusCode = 404;
        }
    }
    callback(err,body,response);
};

exports.outgoingTransform = function(parameters){
    // can modify parameters before returning
    console.log('customFunction outgoingTransform called');
    return parameters;
};

exports.incomingTransform = function(body){
    // can modify body before returning
    console.log('customFunction incomingTransform called');
    return body;
};

Use of external transformation library

To use external library like handlebars:

  1. Modify datasources.json as:

Add transformer attribute to datasource definition.


"myNewDataSource": {
    "name": "myNewDataSource",
    "connector": "flexirest",
    "endpoints": "endpoints", // path to folder where Operation templates are placed. This is relative to application root.
    "baseURL" : "http://XXX.YYY.ZZZ/api" // The environment specific hostname and URI root
    "transformer" : {
        "library" : "handlebars", // library attribute is path to the transformation file or a npm module. Details are mentioned later
        "ext" : "hbs" // file extension for transformation templates
    }
}
  1. Modify operation template

In place of mentioning the function name for outgoing and incoming transformation, specify the name of the transformation template. Check for examples at example-templates.


{
    "template": {
        "method": "GET",
        "url": "/api/backend/{id}",
        "query": {
            "id": "{id}"
        }
    },
    "functions": {
        "customFunction": ["id"]
    },
    "shared" : false,
    "errorHandler": "customFunction.errorHandler",
    "outgoingTransform": "outgoing.hbs",
    "incomingTransform": "incoming.hbs"
}

Transformation Hooks

Transformation hooks enable application to intercept the parameters during outgoing transformation and response during incoming transformation. All hooks are attached to the connector instance. The hooks leverages observer mixin methods that are available as part of the connector.

before/after outgoingTransform

Context in case of outgoingTransform contains:

  • name : Function name
  • parameters : An Object carrying all function parameters

connector.observe('before outgoingTransform', function(ctx, next) {

    // ctx - name, parameters
    console.log('before outgoingTransform');
    next();
});

connector.observe('after outgoingTransform', function(ctx, next) {

    // ctx - name, parameters
    console.log('after outgoingTransform');
    next();
});

before/after incomingTransform

Context in case of incomingTransform contains:

  • name : Function name
  • response : Instance of the response object received from request module
  • body : JSON object received from the backend service

connector.observe('before incomingTransform', function(ctx, next) {

    // ctx - name, response, body
    console.log('before incomingTransform');
    next();
});

connector.observe('after incomingTransform', function(ctx, next) {

    // ctx - name, response, body
    console.log('after incomingTransform');
    next();
});

To debug

Start node with debug prefix as DEBUG=loopback:connector:flexirest node .

Roadmap

  • Improve documentation
  • Use of mixins to add transformer functions
  • Add promises in place of callbacks
  • Add cache hooks with full / partial-refresh strategy
  • Ability to create a higher level function by orchestrating with multiple low level function
  • Test coverage

See Also