/*!
* clout-js
* Copyright(c) 2018 Muhammad Dadu
* MIT Licensed
*/
const { merge } = require('lodash');
const CloutApiRoute = require('../hookslib/CloutApiRoute');
const express = require('express');
const utils = require('../lib/utils');
const path = require('path');
const PRIORITIZED_FILES = ['index.js', 'clout.hook.js'];
/**
* CloutApiRoutes
* @class
*/
class CloutApiRoutes {
/**
* @constructor
* @param {object} app clout instance
*/
constructor(app) {
this.clout = app;
this.config = {
basePath: '/api',
acceptTypes: {
json: 'application/json',
html: 'text/html'
}
};
this.routes = {};
this.router = express.Router();
this.initializeAcceptTypeHandler();
this.clout.logger.debug('Module CloutApiRoutes loaded');
}
/**
* Clout-JS handler for custom content requests
*/
initializeAcceptTypeHandler() {
this.router.param('acceptType', (req, resp, next, type) => {
let acceptType = this.config.acceptTypes[type];
req.logger.info(`handling param '${acceptType}'`);
if (acceptType) {
req.headers['accept'] = `${acceptType},` + req.headers['accept'];
}
next();
});
}
/**
* Attaches router to clout-app
*/
attachRouterToApp() {
let basePath = this.config.basePath;
this.clout.app.use(basePath, this.router);
this.clout.logger.debug(`router attached at ${basePath}`);
}
/**
* Add CloutApiRouter to router
* @param {object} CloutApiRouter
*/
addRoute(cloutRoute) {
if (!this.routes[cloutRoute.group]) {
this.routes[cloutRoute.group] = [];
}
this.routes[cloutRoute.group].push(cloutRoute);
cloutRoute.attachRouter(this.router);
}
/**
* Load APIs from a file
* @param {string} filePath
*/
loadAPIFromFile(filePath) {
let groupName = path.basename(filePath).replace('.js', '');
let apis = require(filePath);
this.clout.logger.debug(`loading API from file ${filePath}`);
return Object.keys(apis).map((apiName) => {
let opts = merge({
name: apiName,
group: groupName
}, apis[apiName]);
return this.addRoute(new CloutApiRoute(opts));
});
}
/**
* Finds all the **.js files inside a directory and loads it
* @param {string} dir path containing directory of APIs
*/
loadAPIsFromDir(dir) {
let globbedDirs = utils.getGlobbedFiles(path.join(dir, '**/**.js'));
return globbedDirs.sort((a, b) => {
const aPriority = PRIORITIZED_FILES.indexOf(a) !== -1;
const bPriority = PRIORITIZED_FILES.indexOf(b) !== -1;
const weight = {a: 0, b: 0};
if (aPriority !== -1) {
weight.a = aPriority + 1;
}
if (bPriority !== -1) {
weight.b = aPriority + 1;
}
return weight.a > weight.b ? 1 : weight.b > weight.a ? -1 : 0;
}).map((filePath) => this.loadAPIFromFile(filePath));
}
/**
* Finds all the **.js files inside an array of directories and loads it
* @param {array} dirs array of paths containing directory of APIs
*/
loadAPIsFromDirs(dirs) {
return dirs.map((dir) => this.loadAPIsFromDir(dir));
}
};
module.exports = CloutApiRoutes;