UNPKG

actionhero

Version:

actionhero.js is a multi-transport API Server with integrated cluster capabilities and delayed tasks

170 lines (169 loc) 7.72 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.config = exports.buildConfig = exports.configPaths = void 0; const fs = require("fs"); const path = require("path"); const glob = require("glob"); const optimist_1 = require("optimist"); const utils_1 = require("./utils"); const ensureNoTsHeaderFiles_1 = require("./utils/ensureNoTsHeaderFiles"); const env_1 = require("./../classes/process/env"); const id_1 = require("./../classes/process/id"); const actionheroVersion_1 = require("./../classes/process/actionheroVersion"); const typescript_1 = require("./../classes/process/typescript"); const projectRoot_1 = require("./../classes/process/projectRoot"); exports.configPaths = []; function buildConfig(_startingParams = {}) { let config = { process: { env: env_1.env, id: id_1.id, typescript: typescript_1.typescript, projectRoot: projectRoot_1.projectRoot, actionheroVersion: actionheroVersion_1.actionheroVersion, }, }; utils_1.utils.hashMerge(config, _startingParams); // We support multiple configuration paths as follows: // // 1. Use the project 'config' folder, if it exists. // 2. "actionhero --config=PATH1 --config=PATH2 --config=PATH3,PATH4" // 3. "ACTIONHERO_CONFIG=PATH1,PATH2 npm start" // // Note that if --config or ACTIONHERO_CONFIG are used, they _overwrite_ the use of the default "config" folder. If // you wish to use both, you need to re-specify "config", e.g. "--config=config,local-config". Also, note that // specifying multiple --config options on the command line does exactly the same thing as using one parameter with // comma separators, however the environment variable method only supports the comma-delimited syntax. function addConfigPath(pathToCheck, alreadySplit) { if (typeof pathToCheck === "string") { if (!alreadySplit) { addConfigPath(pathToCheck.split(","), true); } else { if (pathToCheck.charAt(0) !== "/") { pathToCheck = path.resolve(projectRoot_1.projectRoot, pathToCheck); } if (fs.existsSync(pathToCheck)) { exports.configPaths.push(pathToCheck); } } } else if (Array.isArray(pathToCheck)) { pathToCheck.map((entry) => { addConfigPath(entry, alreadySplit); }); } } [optimist_1.argv.config, process.env.ACTIONHERO_CONFIG].map((entry) => { addConfigPath(entry, false); }); if (exports.configPaths.length < 1 && typescript_1.typescript) { addConfigPath("src/config", false); } if (exports.configPaths.length < 1) { addConfigPath("dist/config", false); } if (exports.configPaths.length < 1) { throw new Error(exports.configPaths + "No config directory found in this project. Did you compile your typescript project?"); } const loadConfigFile = (f) => { const localConfig = require(f); if (f.includes("routes.js") || f.includes("routes.ts")) { let localRoutes = { routes: {} }; if (localConfig.DEFAULT) { localRoutes = utils_1.utils.hashMerge(localRoutes, localConfig.DEFAULT, config); } if (localConfig[env_1.env]) { localRoutes = utils_1.utils.hashMerge(localRoutes, localConfig[env_1.env], config); } Object.keys(localRoutes.routes).forEach((v) => { if (config.routes && config.routes[v]) { config.routes[v].push(...localRoutes.routes[v]); } else { if (!config.routes) { config.routes = {}; } config.routes[v] = localRoutes.routes[v]; } }); } else { if (localConfig.DEFAULT) { config = utils_1.utils.hashMerge(config, localConfig.DEFAULT, config); } if (localConfig[env_1.env]) { config = utils_1.utils.hashMerge(config, localConfig[env_1.env], config); } } }; const loadConfigDirectory = (configPath, watch) => { const configFiles = ensureNoTsHeaderFiles_1.ensureNoTsHeaderFiles(glob.sync(path.join(configPath, "**", "**/*(*.js|*.ts)"))); let loadRetries = 0; let loadErrors = {}; for (let i = 0, limit = configFiles.length; i < limit; i++) { const f = configFiles[i]; try { // attempt configuration file load loadConfigFile(f); // configuration file load success: clear retries and // errors since progress has been made loadRetries = 0; loadErrors = {}; } catch (error) { // error loading configuration, abort if all remaining // configuration files have been tried and failed // indicating inability to progress loadErrors[f] = { error: error, msg: error.toString() }; if (++loadRetries === limit - i) { Object.keys(loadErrors).forEach((e) => { console.log(loadErrors[e].error.stack); console.log(""); delete loadErrors[e].error; }); throw new Error("Unable to load configurations, errors: " + JSON.stringify(loadErrors)); } // adjust configuration files list: remove and push // failed configuration to the end of the list and // continue with next file at same index configFiles.push(configFiles.splice(i--, 1)[0]); continue; } } // We load the config twice. Utilize configuration files load order that succeeded on the first pass. // This is to allow 'literal' values to be loaded whenever possible, and then for references to be resolved configFiles.forEach(loadConfigFile); // Remove duplicate routes since we might be loading from multiple config directories, also we load every // config directory twice. if (config.routes) { Object.keys(config.routes).forEach((v) => { config.routes[v] = config.routes[v].filter((route, index, self) => index === self.findIndex((r) => r.path === route.path && r.action === route.action && r.apiVersion === route.apiVersion && r.matchTrailingPathParts === route.matchTrailingPathParts && r.dir === route.dir)); }); } }; // load the default config of actionhero loadConfigDirectory(path.join(__dirname, "/../config"), false); // load the project specific config exports.configPaths.map((p) => loadConfigDirectory(p, false)); // apply any configChanges if (_startingParams && _startingParams.configChanges) { config = utils_1.utils.hashMerge(config, _startingParams.configChanges); } if (process.env.configChanges) { config = utils_1.utils.hashMerge(config, JSON.parse(process.env.configChanges)); } if (optimist_1.argv.configChanges) { config = utils_1.utils.hashMerge(config, JSON.parse(optimist_1.argv.configChanges)); } return config; } exports.buildConfig = buildConfig; exports.config = buildConfig();