UNPKG

@arisan/data-api

Version:

The Universal Database API Gateway for CLIO's Modules

246 lines (215 loc) 9.71 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.logger = undefined; var _express = require('express'); var _express2 = _interopRequireDefault(_express); var _moment = require('moment'); var _moment2 = _interopRequireDefault(_moment); var _mongodb = require('mongodb'); var _mongodb2 = _interopRequireDefault(_mongodb); var _os = require('os'); var _os2 = _interopRequireDefault(_os); var _winston = require('winston'); var _winston2 = _interopRequireDefault(_winston); require('winston-daily-rotate-file'); require('winston-loggly-bulk'); var _LogLevel = require('./LogLevel'); var _LogLevel2 = _interopRequireDefault(_LogLevel); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /* eslint-disable import/newline-after-import, import/first */ //region 1. Platform Libraries const requireAll = require('require-all'); //endregion //region 2. Project Libraries //endregion //region K. Constants const context = { heartbeatInterval: null, logger: null, routers: null }; //endregion //region B. Business Helpers const timestamp = () => (0, _moment2.default)().format('YYYY-MM-DDTHH:mm:ss.SSSZ'); const formatter = options => { const timestampPart = `${ options.timestamp() } `; const levelPart = `${ options.level.toUpperCase() }: `; const tagPart = options.meta.tags ? `${ options.meta.tags }> ` : ''; const messagePart = options.message || ''; return `${ timestampPart }${ levelPart }${ tagPart }${ messagePart }`; }; context.logger = function setupDefaultLogger() { const transports = [new _winston2.default.transports.Console({ formatter, timestamp }), new _winston2.default.transports.DailyRotateFile({ datePattern: '.yyyy-MM-dd', filename: `${ process.cwd() }/data-api.log`, formatter, maxFiles: 7, timestamp })]; return new _winston2.default.Logger({ transports }); }(); function setupLogger(logLevel, logglySubdomain, logglyToken) { this.logLevel = _LogLevel2.default[logLevel && logLevel.toUpperCase()] || _LogLevel2.default.DEBUG; const transports = [new _winston2.default.transports.Console({ formatter, timestamp }), new _winston2.default.transports.DailyRotateFile({ datePattern: '.yyyy-MM-dd', filename: `${ process.cwd() }/data-api.log`, formatter, json: false, maxFiles: 7, timestamp })]; if (logglySubdomain && logglySubdomain !== 'null' && logglyToken && logglyToken !== 'null') { const tags = ['data-api', _os2.default.hostname]; if (this.environment) { tags.push(this.environment); } transports.push(new _winston2.default.transports.Loggly({ formatter, json: true, level: this.logLevel.name.toLowerCase(), subdomain: logglySubdomain, tags, timestamp, token: logglyToken })); } context.logger.configure({ level: this.logLevel.name.toLowerCase(), transports }); } //endregion //region E. Exports /** * Class representing a Data-API */ class DataAPI { constructor() { this.expressApp = (0, _express2.default)(); } /** * Initialize Data-API with options * @param {object} [options] Options * @param {string} [options.environment] Environment Tag * @param {number} [options.heartbeatInterval=10] Heartbeat Interval (s) * @param {string} [options.logglySubdomain] Loggly Subdomain * @param {string} [options.logglyToken] Loggly Token * @param {string} [options.logLevel=DEBUG] Log Level * @param {string} [options.mongoUrl=mongodb://localhost] MongoDB Connection URL * @param {number} [options.port=15925] Data-API Port */ initialize(options) { const opts = options || {}; this.environment = opts.environment || ''; setupLogger.bind(this)(opts.logLevel, opts.logglySubdomain, opts.logglyToken); const log = (lvl, msg) => context.logger.log(lvl, msg, { tags: 'initialize' }); log('debug', 'Initializing....'); if (opts.heartbeatInterval === 0) { log('error', `Invalid Heartbeat Interval ${ opts.heartbeatInterval }`); return false; } if (opts.mongoUrl && opts.mongoUrl.substring(0, 10) !== 'mongodb://') { log('error', `Invalid MongoDB Connection URL ${ opts.mongoUrl }`); return false; } if (opts.port < 1 || opts.port > 65535) { log('error', `Port Number Range Exceeded ${ opts.port }`); return false; } context.heartbeatInterval = opts.heartbeatInterval || 10; this.mongoUrl = opts.mongoUrl || 'mongodb://localhost'; this.port = opts.port || 15925; log('info', 'Initialized'); return true; } start(callback) { const log = (lvl, msg) => context.logger.log(lvl, msg, { tags: 'start' }); log('debug', 'Checking existing database connection....'); if (this.database) { log('error', 'Data API has already been started. Start aborted.'); return false; } log('debug', 'Connecting to database....'); _mongodb2.default.connect(this.mongoUrl, (connectErr, connectedDB) => { if (connectErr) { log('error', connectErr.message); return; } log('info', 'Database Connected'); this.database = connectedDB; log('debug', 'Mounting routers....'); context.routers = requireAll({ dirname: `${ __dirname }/routers`, filter: /^((?!spec).)+\.js$/, map(name, path) { const filename = path.substring(path.lastIndexOf('/') + 1, path.lastIndexOf('.')); return name.length === 1 ? filename : name; } }); log('debug', Object.keys(context.routers)); Object.keys(context.routers).forEach(router => { context.routers[router].default({ app: this.expressApp, database: this.database, logger: context.logger }); }); log('info', 'Routers Mounted'); log('debug', 'Launching Data API....'); this.expressServer = this.expressApp.listen(this.port, listenErr => { if (listenErr) { log('error', listenErr.message); return; } log('info', `Data API listening on port ${ this.port }`); if (callback) { callback(); } }); }); return true; } stop(callback) { const log = (lvl, msg) => context.logger.log(lvl, msg, { tags: 'stop' }); log('debug', 'Stopping Data API....'); if (!this.expressServer) { log('info', 'Express Server Already Closed'); if (callback) { callback(); } return; } this.expressServer.close(() => { log('info', 'Express Server Closed'); this.expressServer = null; if (!this.database) { if (callback) { callback(); } return; } this.database.close(() => { log('info', 'Database Closed'); this.database = null; if (callback) { callback(); } }); }); } static get heartbeatInterval() { return context.heartbeatInterval; } } exports.default = DataAPI; const logger = exports.logger = context.logger; //endregion //# sourceMappingURL=DataAPI.js.map