npm package: @grupojaque/external-communication
Description: Module to manage basic requests to external servers
Author: JaqueOSS
Latest version: 1.0.5

# external-communication
  external-communication is a module that allows the user to make basic http requests to other servers, it also allows to mock responses from any server depending on the current environment where it is used.

[![pipeline status](https://gitlab.com/grupojaque/jaqueoss/external-communication/badges/master/pipeline.svg)](https://gitlab.com/grupojaque/jaqueoss/external-communication/commits/master)
[![coverage report](https://gitlab.com/grupojaque/jaqueoss/external-communication/badges/master/coverage.svg)](https://gitlab.com/grupojaque/jaqueoss/external-communication/commits/master)

## Setup
### Requirements

### Initialization

To use it simply call
```javascript
  const external = require('../index.js')(config);
```
passing a config JSON; this config will be explained in detail below.

external-communication comes as a function that returns a JSON with two methods called configure and initialize. Configure checks the config file integrity and loads it to the module. It also exposes it as a global variable to be used by the internal request file.

Initialize checks every defined server in the conf file and exposes it as a global variable with ready to use http methods GET, PUT, POST and DELETE.

For using it simply do something like this:
```javascript
const config = require('../config.js')
const external = require('../index.js')(config);
```
Once done you are ready to make http requests to every service you defined previously.

### Configuration

external-communication needs some configuration that can be loaded from a .js file.
A config file template should look like this:
```javascript
  module.exports = {
    logging: __,
    externalcommunication: {
      active: [__],
      service1: __
      service2: __
      .
      .
      .      
    }
  };
```
##### Configuration values

The following values are used to configure the module:

``[your_config_file].js``

| Key  | Description |
| ---- | ----------- |
| logging  | A reference to the custom logging of preference, console can be used. The passed logger must have the info method available. If no logger found, it will default to a dummy function. |
| externalcommunication  | Object containing the active services available to be called and the preferences for each service |

To define a service, one must give it a name and place it as an object inside externalcommunication, for every service there is a list of custom values that can be used:

| Key  | Description |
| ---- | ----------- |
| host | url of the service to be requested, e.g. 'localhost:1330' |
| https | boolean that indicates if https should be used, defaults to false |
| timeout | integer value for request timeout |
| discard | boolean that indicates if any status response not expected should be ignored |
| getHeaders | function that returns custom headers if needed |
| mock | An object containing the responses for custom routes depending on the environment, if no environment is defined in process.env.NODE_ENV, the default response will be used, please note that at least the default environment needs to be defined to be able to mock responses |

An example for a config file is shown below:

```javascript
module.exports = {
  logging: console,
  externalcommunication: {
    active: ['serviceA','serviceB', 'serviceC'],
    serviceA: {
      host: 'httpbin.org',
      https: false,
      timeout: 25000,
      discard: false,
      getHeaders: function() {
        return {
          'Authorization': 'JWT mycustomjwttoken'
        };
      }
    },
    serviceB: {
      host: 'some-service.com',
      https: false,
      timeout: 25000,
      discard: false,
      getHeaders: function() {
        return {};
      },
      mock: {
        default: {
          'get /users': {
            statusCode: 200,
            body: [
              {
                id: 1,
                username: 'awesome'
              }
            ]
          }
        }
      }
    },
    serviceC: {
      host: 'httpbin.org',
      https: false,
      timeout: 2000,
      discard: true,
      getHeaders: function() {
        return {};
      },
      defaultError: () => {
        return 'notFound';
      }
    }
  }
};
```

## Usage

Every service defined is able to make the http basic requests by calling the appropiate method using promises. Remember that the global service variable starts with uppercase e.g. ServiceA.

Lets say that we are using the services in the example config file above. If you want to make a GET request to /users/info, expecting an status code (in this example, a 200) one should simply do:
```javascript
return ServiceA.get('/users/info',200)
```
Now let's say that if you get a 200 or a 404 code it's ok, so use it like this:
```javascript
return ServiceA.get('/users/info',[200,404])
```
If you want to send payload please do the following:
```javascript
return ServiceA.post('/status/400',{foo: 'bar'},200)
```
Say that you just want to make the request and no matter what status code you get, you want to keep going. If that is the case place true instead of the status code(s) that you expect:
```javascript
return ServiceA.post('/status/400',{foo: 'bar'},true)
```
If you want to map an statusCode to a custom error you can do so by placing a mapping object like this:
```javascript
return ServiceA.post('/status/400',{foo: 'bar'},200,{
  errors: {
    400: {
      'codeString': 'conflict',
      'status': 409
    }
  }
})
```
Note that if we get a status code of 400, the module will map it to a conflict custom error.

Last but not least, if you want to discard any error not in your expected status list and send an specific default error, please do the following (Check the config! It's a different service):
```javascript
return ServiceC.post('/status/400',{foo: 'bar'},200)
//this will throw new ExternalCommunicationError('notFound', err.message, err.code);
```
Here any error apart from the expected ones will be mapped to the default error specified in the config.

### Errors

All errors in this module will be instances of ExternalCommunicationError, which extends
the Error class with the following attributes.

- `status`: The HTTP status name or number for the error.
- `codeString` A short string to describe the http status code received e.g. badRequest.

 This errors can be easily managed by your custom error manager, feel free to do so.

 ```javascript
 throw new ExternalCommunicationError(codeString, message, status);
```


## Contributors

- Alejandra Coloapa Díaz [github](https://github.com/aleexkj)
- Francisco Javier Márquez Cortés [github](https://github.com/ratrabbit)
- Susana Hahn Martin Lunas [github](https://github.com/susuhahnml)