REST Handler Middleware for Akera Application Server.
As opposed to the @akera/web that can only execute special
					'handlers' - either the 'classical' WebSpeed wrap-cgi procedures (includes wrap-cgi.i) or the new
					WebHandler objects (implements OpenEdge.Web.WebHandler) - this module ca be used to expose
					generic business logic by dynamically calling any procedure (internal entries included) through the
				api module or expose database(s) content for basic CRUD operation through the crud or jsdo modules.
$ npm set registry "http://repository.akera.io/"
$ npm install @akera/rest
				doc folder.var akeraRest = require('@akera/rest')
				The akeraRest object exposes a number of factories that can be used to create an Express middleware.
					Often when building web interfaces it might happen the web server does not share the same machine
					as the server exposing micro-services and CORS related issues might be experienced. This is also true
				for akera.io REST services, this can be solved by using the CORS module. 
Returns an akera.io API Handler middleware that can be used on an Express application to execute any generic business logic by passing input/output parameters much like the @akera/api does.
The middleware can then be used to call business logic procedures on the akera.io broker(s) by making
				HTTP POST or GET requests and send the business logic call information using the request parameters.
The api interface must be enabled on all akera.io application server(s) used, otherwise the API
				connections are rejected by the brokers.
Can be either a 'shared' @akera/web instance or one or more broker configuration(s) for remote akera.io brokers. If one configuration is used then all requests on the middleware router will be dispatched directly to that broker.
When multiple configurations are used then for each unique broker a sub-route is added
					to the router using the broker's alias as route and each request on the middleware requires
					one route parameter - the broker alias, based on which the request is dispatched to the
					corresponding broker. If all configurations have the same alias - fail-over configuration,
				then the broker will be mounted on the router's root as if a single configuration is provided.
An instance of AkeraLogger to be used by the router for logging.
When a single broker is configured for the middleware the api interface will dispatch all requests
				to that one broker:
POST 
URL: /BODY: Business Logic Information in JSON format.Content-Type: application/jsonGET 
URL: /Query String: ?call=[call]¶meters=[parameters]  Parameters must be an encoded string value of the JSON array holding parameters
					information. Optional information can be sent through additional query string
				parameters: method, type, returns.
For convenience more specific routes were defined for calling internal entries:
/[external procedure path]/procedure/[internal procedure name]/[external procedure path]/function/[internal function name]/[class full name]/method/[instance method name]/[class full name]/static/[static method name]The information on what business logic need to be executed is sent either in
				a JSON format for POST requests or through query parameters for GET requests.
call: the business logic object namemethod: the internal entry of the business logic objecttype: the call type (procedure, function, method or static).returns: the data type of return parameter, only for function or method.parameters: array of optional call parametersThe business logic object name must include the relative path (if any), and it can be an external procedure or an OO class.
If method value is not set the business logic must be an external procedure
				that normally takes parameters although this is not required.
When calling internal entries of 'super procedures' the external procedure
					must not have any parameters. Depending on the type value an internal
					function or procedure can be executed, the name of the internal entry is
				specified using the method information.
When calling methods of OO instance objects the class must have a
					public constructor with no parameters. Depending on the type value
					an instance (method) or a static method can be executed, the name of the
				method is specified using the method information.
If type value is not set it defaults to procedure.
If the parameters sent does not match the business logic entry parameters an
				error will be thrown back. 
Each parameter entry has the following structure:
type: parameter data typedirection: parameter directionvalue: parameter value for input/input-output parametersjson: for output/input-output parameters of type character/longchar.All Progress primitive data types are supported as input/output/input-output
					parameters - character, date, datetime, dataset, decimal, integer,
					int64, logical, longchar, memptr - for output complex data types like
				table and dataset are also supported.
If type is not specified it defaults to character.
Valid values for parameter direction are:
input (in, i), if not set this is the default.output (out, o)input-output (inout, io)For input/input-output parameters if value is not set it defaults to null (? in 4GL).
If json flag is set to true the value is sent as a JSON object instead of encoding it as a string.
				Dataset and table parameters are always sent as JSON objects.
The response is a always a JSON object sent as response body with a parameters property
				as array. 
Only output and input-output parameters are sent back in the parameters array keeping
					the same order as in the input parameters array - the first entry in the array will be
				the first parameter with direction input or input-output. 
If an internal function or method is executed the response object might also have an
				return object, the value depends on the data type of the function/method return parameter.
{ "parameters": [
        "Hello world!",
        2018
    ],
    "return": true
}
				If there was an error while executing the business logic the response body will contain an
				error property containing the error message as string.
{"error": "Mismatched number of parameters passed to routine xxxxxx.p. (3234)"}
				The Express.js application or router where the middleware is mounted must have a
					JSON body parser installed in order for POST
				requests to work (Content-Type header value set to application/json).
Only the procedures available in akera.io application server WEBPATH can be executed - not everything
				from agent's PROPATH is available through the REST API interface.
A 'failsafe' configuration is defined using two akera.io application servers
					running on different ports on the same computer as the Express web server (localhost).
					All requests sent on /api path will be handled by the API Handler middleware and will
					be dispatched to the first broker to which a connection can be established.
					All requests sent on /crud path will be handled by the CRUD Handler middleware while
				those made on /jsdo will be handled by the JSDO Handler.
import * as express from 'express';
import * as bodyParser from 'body-parser';
import akeraRest from '@akera/rest';
let app: express.Application = express();
let config = [ { "name": "demo",
                 "host": "localhost",
                 "port": 8900 },
               { "name": "failsafe",
                 "alias": "demo",
                 "host": "localhost",
                 "port": 9900 } ];
app.use(bodyParser.json());
app.use('/api', akeraRest.api(config));
app.use('/crud', akeraRest.crud(config));
app.use('/jsdo', akeraRest.jsdo(config));
				A HTTP POST request made on /api with the body:
{
    "call": "demo/sports/getCustBalance.p", 
    "parameters": [
        { "direction": "i", "value": 2 },
    { "direction": "o", "type": "decimal" },
    { "direction": "o", "type": "decimal" },
    { "direction": "o", "type": "decimal" }
    ] 
}
				will run the external procedure demo/sports/getCustBalance.p on the akera.io
					application server passing one input parameter with a value of 2 and expecting
				three output parameters all of decimal data type.
A configuration is defined using two separate akera.io application servers
					running on different ports on the same computer as the Express web server (localhost).
					All requests sent on /api path will be handled by the API Handler middleware and will
					be dispatched to the corresponding broker based on the broker alias (first route parameter).
					All requests sent on /crud path will be handled by the CRUD Handler middleware while
				those made on /jsdo will be handled by the JSDO Handler.
import * as express from 'express';
import {AkeraWeb} from '@akera/web';
import akeraRest from '@akera/rest';
let app: express.Application = express();
let config = [ { "name": "demo1",
                 "host": "localhost",
                 "port": 8900 },
               { "name": "demo2",
                 "host": "localhost",
                 "port": 9900 } ];
let akeraWeb = new AkeraWeb(config);
app.use('/api', akeraRest.api(akeraWeb));
app.use('/crud', akeraRest.crud(akeraWeb));
app.use('/jsdo', akeraRest.jsdo(akeraWeb));
				A request made on /api/demo1 will be executed on the demo1 broker while requests
					made on /api/demo2 will be dispatched to the demo2 broker.
					Multiple akera.io application servers can be configured for each 'broker' - using
				the same alias, for failover setup.
As of version 1.0.8 the interface also support GET requests with procedure
					and parameters values passed through the query string value, also on POST
					requests the call wrapper object is no longer mandatory - procedure and
				parameters can be sent directly into the root JSON object.
As of version 1.0.10 the interface also support json flag for
				output/input-output string parameters (characters/longchar). 
As of version 1.1.1 the API and CRUD interfaces were integrated in
				@akera/rest and code was migrated to typescript. 
MIT