/* * Copyright (C) Sapphirecode - All Rights Reserved * This file is part of Requestor which is released under BSD-3-Clause. * See file 'LICENSE' for full license details. * Created by Timo Hocker , March 2020 */ /* 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 _a * @param {handler_description} data handler data * @returns {Function} requestor handler */ function get_handler (_a) { const { module_folder } = _a; const { file } = _a; const { opts } = _a; const { rethrow } = _a; // eslint-disable-next-line global-require const handler = require (path.join (process.cwd (), module_folder, file)); return function (req, res, next) { return new Promise ((resolve) => resolve (handler (req, res, next, opts))) .catch ((e) => { if (rethrow) throw 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) { if (options === void 0) options = { opts: null, subdir: '', verbose: false, rethrow: true }; const { opts } = options; const { subdir } = options; const { verbose } = options; const { rethrow } = options; for (let _i = 0, _a = fs.readdirSync (module_folder); _i < _a.length; _i++) { const file = _a[_i]; 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); } };