UNPKG

hudson-taylor

Version:

Hudson Taylor is a set of libraries for making awesome microservices

242 lines (202 loc) 5.99 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var async = require('async'); var s = require('ht-schema'); var clone = require('clone'); var utils = require('ht-utils'); var Service = function Service(Transports, config) { var _this = this; if (!(this instanceof Service)) { return new Service(Transports, config); } if (typeof (Transports || {}).Server === 'function') { Transports = [Transports]; } else if ((typeof Transports === 'undefined' ? 'undefined' : _typeof(Transports)) === 'object' && !Array.isArray(Transports)) { config = Transports; Transports = []; } else if (!Transports) { Transports = []; config = {}; } this.config = config; this._methods = {}; this._servers = []; this.listening = false; this._middleware = { before: [], after: [] }; this.fn = function (method, data, cb) { // clone data data = clone(data); var context = { method: method }; var _beforeMiddleware = _this._middleware.before.filter(function (m) { if (m.method && m.method !== context.method) { return false; } return true; }); async.eachSeries(_beforeMiddleware, function (middleware, done) { middleware.fn.call(context, data, function (err, result) { if (err) { return done(err); } data = result; done(); }); }, function (err) { if (err) { return cb(err); } var _tmp = _this._methods[context.method]; if (!_tmp) { return cb({ error: 'unknown-method', method: context.method }); } var finish = function finish(response) { var _afterMiddleware = _this._middleware.after.filter(function (m) { if (m.method && m.method !== context.method) { return false; } return true; }); async.eachSeries(_afterMiddleware, function (middleware, done) { middleware.fn.call(context, response, function (err, _response) { if (err) { return done(err); } response = _response; done(); }); }, function (err) { if (err) { return cb(err); } cb(null, response); }); }; if (_tmp.schema) { _tmp.schema.validate(data, function (err, data) { if (err) { return cb({ $htValidationError: true, error: err.message }); } return go(data); }); } else { go(data); } function go(data) { // Handle both callbacks and promises here. // It is expected that the CALLER only calls the callback OR // returns a promise. If they do both, there will be two callbacks var callbackHandler = function callbackHandler(err, response) { if (err) return cb(err); return finish(response); }; var response = _tmp.fn(data, callbackHandler); if (response && typeof response.then === 'function') { return response.then(finish, cb); // if an exception was thrown from finish(), let it bubble up // as an unhandled rejection, rather than also call cb() } } }); }; this.on('$htMultiCall', s.Array({ opt: false }, [s.Object({ method: s.String(), data: s.Any({ opt: true }) })]), function (data, callback) { utils.getLastResult.call(_this, data, callback, true); }); Transports.forEach(function (transport) { _this.addTransport(transport); }); }; Service.prototype.addTransport = function (transport) { var done = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {}; var server = new transport.Server(this.fn); this._servers.push(server); if (this.listening) { server.listen(done); } else { done(); } }; Service.prototype.on = function (method, schema, fn) { if (!fn) { fn = schema; schema = null; } if (schema) { if (typeof schema.validate !== 'function') { throw new Error('Schema for ' + method + ' does not have a validate function.'); } } this._methods[method] = { schema: schema, fn: fn }; }; Service.prototype.before = function (fn) { var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var method = opts.method; this._middleware.before.push({ method: method, fn: fn }); }; Service.prototype.after = function (fn) { var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var method = opts.method; this._middleware.after.push({ method: method, fn: fn }); }; Service.prototype.listen = function () { var _this2 = this; var done = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; if (this.listening) { return done(); } async.each(this._servers, function (s, cb) { s.listen(cb); }, function (err) { if (err) { return done(err); } _this2.listening = true; done(); }); }; Service.prototype.stop = function () { var _this3 = this; var done = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; if (!this.listening) { return done(); } async.each(this._servers, function (s, cb) { s.stop(cb); }, function (err) { if (err) { return done(err); } _this3.listening = false; done(); }); }; Service.prototype.call = function (method, data, cb) { this.fn(method, data, cb); }; exports.default = Service; module.exports = exports['default'];