diff --git a/app.js b/app.js index 73ea810..6b73b51 100644 --- a/app.js +++ b/app.js @@ -99,14 +99,15 @@ app.use(bodyParser.json()); -/* Middlewares */ +/* Includes */ + +// Middlewares +require('./core/middlewares/loader').process(app, global.opts); // Auth initializing var auth = require('./core/auth')(app); app.use(auth.everyauth.middleware()); -// Clarify -app.use(require('./core/middleware/clarify')); // File tree module var fileTree = require('./core/file-tree'); @@ -135,29 +136,6 @@ app.use('/api/updateFileTree', function(req, res){ }); -// Middleware that loads spec content -var read = require("./core/middleware/read"); -app.use(read.process); - -// Markdown -app.use(require("./core/middleware/md").process); -app.use(require("./core/middleware/mdTag").process); - -// Load user defined middleware, that processes spec content -require("./core/middleware/userMiddleware"); - -// Middleware that wraps spec with Source template -app.use(require("./core/middleware/wrap").process); - -// Middleware that sends final spec response -app.use(require("./core/middleware/send").process); - -/* /Middlewares */ - - - -/* Includes */ - // Routes require('./core/routes'); @@ -233,7 +211,7 @@ app.use(logErrors); -// Server start +/* Server start */ if (!module.parent) { var serverOpts = global.opts.core.server; var port = serverOpts.port; @@ -256,3 +234,4 @@ if (!module.parent) { }); } } +/* Server start */ diff --git a/core/middleware/userMiddleware.js b/core/middleware/userMiddleware.js deleted file mode 100644 index b09952f..0000000 --- a/core/middleware/userMiddleware.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -/** - * - * Loading user middleware - * - * */ - -var fs = require('fs'); -var path = require('path'); -var pathToUserMiddleware = path.join(global.app.get('user'), 'node_modules'); - -// Loading all sourcejs-*/core/index.js files from npm plugins section -if (fs.existsSync(pathToUserMiddleware)) { - var userMiddlewareFiles = fs.readdirSync(pathToUserMiddleware); - - userMiddlewareFiles.map(function (file) { - if ((/^sourcejs-/).test(file)) { - var pluginIndexPath = path.join(pathToUserMiddleware, file, 'core/middleware', 'index.js'); - if (fs.existsSync(pluginIndexPath)) { - var middleware = require(pluginIndexPath); - global.app.use(middleware.process); - } - } - }); -} \ No newline at end of file diff --git a/core/middleware/clarify.js b/core/middlewares/clarify.js similarity index 99% rename from core/middleware/clarify.js rename to core/middlewares/clarify.js index caea523..cae0b58 100644 --- a/core/middleware/clarify.js +++ b/core/middlewares/clarify.js @@ -229,7 +229,7 @@ var getSectionsIDList = function(sections) { return output; }; -module.exports = function(req, res, next) { +module.exports.process = function(req, res, next) { var parsedUrl = url.parse(req.url, true); // Query params diff --git a/core/middlewares/loader.js b/core/middlewares/loader.js new file mode 100644 index 0000000..35de9e7 --- /dev/null +++ b/core/middlewares/loader.js @@ -0,0 +1,162 @@ +'use strict'; + +var _ = require('lodash'); +var fs = require('fs'); +var path = require('path'); + +var appRoot = path.resolve('./'); +var utils = require(path.join(appRoot, 'core/lib/utils')); +var log = require(path.join(appRoot, 'core/logger')).log; + +var gatherMiddlewares = function(dest, filterRegExp, mainJS){ + var output = {}; + + if (fs.existsSync(dest)) { + var userMiddlewareFiles = fs.readdirSync(dest); + + userMiddlewareFiles.map(function (dir) { + if (!filterRegExp || filterRegExp.test(dir)) { + var middlewareName = dir; + var _mainJS = mainJS || 'index.js'; + + var pluginIndexPath = path.join(dest, dir, _mainJS); + if (fs.existsSync(pluginIndexPath)) { + output[middlewareName] = { + enabled: true, + order: 0, + group: 'default', + indexPath: pluginIndexPath + }; + + // Load middleware options + var configPath = path.join(dest, dir, 'options.js'); + if (fs.existsSync(configPath)) { + var middlewareConfig = require(configPath); + + _.forOwn(output[middlewareName], function (value, key) { + var overVal = middlewareConfig[key]; + + if (overVal) { + if (key === 'order') { + if (overVal >= 0) { + output[middlewareName][key] = overVal; + } else { + log.warn('Middlewares are restricted to define order with value lower than 0 (zero). Please modify '+ middlewareName+ ' middleware options.'); + } + } else { + output[middlewareName][key] = overVal; + } + } + }); + } + } + } + }); + } + + return output; +}; + +var sortMiddlewares = function(groupsOrder, list){ + var output = []; + + if (!(groupsOrder && _.isArray(groupsOrder) && list)) return output; + + var groupedList = {}; + + // Sort by groups + _.forOwn(list, function (value, key) { + var group = value.group || 'default'; + var middleware = value; + + if (!middleware.enabled) return; + + middleware.name = middleware.name || key; + + groupedList[group] = groupedList[group] || []; + groupedList[group].push(value); + }); + + // Sort each group + _.forOwn(groupedList, function (value, key) { + groupedList[key] = _.sortByOrder(value, ['order'], ['asc']); + }); + + // Concat groups by order + groupsOrder.forEach(function(item){ + if (groupedList[item]) output = output.concat(groupedList[item]); + }); + + return output; +}; + +var loadMiddlewares = function(listArr, app){ + if (!_.isArray(listArr) && !app) return; + + log.debug('loading', listArr); + + listArr.forEach(function(item){ + if (item && item.indexPath && fs.existsSync(item.indexPath)) { + app.use(require(item.indexPath).process); + } + }); +}; + +module.exports.process = function(app, globalOptions){ + var config = { + loadGroupsOrder: [ + 'request', + 'pre-html', + 'default', + 'html', + 'response' + ], + list: { + md: { + enabled: true, + order: -1, + group: 'pre-html', + indexPath: path.join(appRoot, 'core/middlewares/md.js') + }, + mdTag: { + enabled: true, + order: 0, + group: 'html', + indexPath: path.join(appRoot, 'core/middlewares/mdTag.js') + }, + clarify: { + enabled: true, + order: -2, + group: 'request', + indexPath: path.join(appRoot, 'core/middlewares/clarify.js') + }, + read: { + enabled: true, + order: -1, + group: 'request', + indexPath: path.join(appRoot, 'core/middlewares/read.js') + }, + send: { + enabled: true, + order: -1, + group: 'response', + indexPath: path.join(appRoot, 'core/middlewares/send.js') + }, + wrap: { + enabled: true, + order: -1, + group: 'html', + indexPath: path.join(appRoot, 'core/middlewares/wrap.js') + } + } + }; + utils.extendOptions( + config, + { + list: gatherMiddlewares(path.join(app.get('user'), 'node_modules'), new RegExp(/^sourcejs-/), 'core/middleware/index.js') + }, + globalOptions.core.middlewares + ); + + loadMiddlewares(sortMiddlewares(config.loadGroupsOrder, config.list), app); +}; \ No newline at end of file diff --git a/core/middleware/md.js b/core/middlewares/md.js similarity index 95% rename from core/middleware/md.js rename to core/middlewares/md.js index 9653b0b..971aa41 100644 --- a/core/middleware/md.js +++ b/core/middlewares/md.js @@ -21,6 +21,8 @@ exports.process = function (req, res, next) { var end = process.hrtime(start); global.log.debug('Markdown processing took: ', prettyHrtime(end)); + req.specData.isMd = false; + next(); } else { next(); diff --git a/core/middleware/mdTag.js b/core/middlewares/mdTag.js similarity index 100% rename from core/middleware/mdTag.js rename to core/middlewares/mdTag.js diff --git a/core/middleware/read.js b/core/middlewares/read.js similarity index 100% rename from core/middleware/read.js rename to core/middlewares/read.js diff --git a/core/middleware/send.js b/core/middlewares/send.js similarity index 100% rename from core/middleware/send.js rename to core/middlewares/send.js diff --git a/core/middleware/wrap.js b/core/middlewares/wrap.js similarity index 100% rename from core/middleware/wrap.js rename to core/middlewares/wrap.js