/* eslint-disable no-console */ /* eslint-disable no-sync */ 'use strict'; const fs = require ('fs'); const path = require ('path'); /** * @typedef {object} options * @property {any} [opts] object to pass to the handlers * @property {string} [subdir] subdirectory for all requests * @property {boolean} [verbose] enable verbose logging * @property {boolean} [rethrow] rethrow errors (default: true) */ /** * @typedef {object} handler_description * @property {string} module_folder folder the module file is in * @property {string} file name of the module * @property {any} opts optional arguments * @property {boolean} rethrow should errors be rethrown */ /** * wrap a requestor handler to be compatible with express * * @param {handler_description} data handler data * @returns {Function} requestor handler */ function get_handler ({ module_folder, file, opts, rethrow }) { // eslint-disable-next-line global-require const handler = require (path.join (process.cwd (), module_folder, file)); return (req, res, next) => { try { handler (req, res, next, opts); } catch (e) { if (rethrow) throw e; else console.error (e); } }; } /** * register a handler to the given app * * @param {any} app express app * @param {handler_description} handler_description data for the used handler * @param {string} method method to respond to * @param {string} url url to respond to * @param {boolean} verbose should verbose logging be enabled */ function register_handler ( app, handler_description, method, url, verbose ) { const handler = get_handler (handler_description); if (verbose) console.log ( `[requestor info] redirecting ${url} to ${handler_description.file}` ); switch (method) { case 'post': app.post (url, handler); break; case 'get': app.get (url, handler); break; case 'put': app.put (url, handler); break; case 'delete': app.delete (url, handler); break; case 'all': app.all (url, handler); break; default: if (verbose) console.warn ( `'${method}' did not match any request method, ignoring` ); break; } } /** * Load all request handlers in the given folder * * @param {any} app express app * @param {string} module_folder folder that contains all modules * @param {options} options additional options */ module.exports = function main ( app, module_folder, options = { opts: null, subdir: '', verbose: false, rethrow: true } ) { const { opts, subdir, verbose, rethrow } = options; for (const file of fs.readdirSync (module_folder)) { const regex = /(?.*?)-(?.*?)\.js/u; const { groups } = regex.exec (file); if (typeof subdir === 'undefined') groups.url = `/${groups.url}/`; else groups.url = `/${subdir}/${groups.url}/`; groups.url = groups.url .replace (/^\/[^/]*\/root/iu, '/') .replace (/\./gu, '/') .replace (/\/+/gu, '/'); register_handler ( app, { file, module_folder, opts, rethrow }, groups.method, groups.url, verbose ); } };