UNPKG

@adpt/cli

Version:
193 lines 6.45 kB
"use strict"; /* * Copyright 2020 Unbounded Systems, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const utils_1 = require("@adpt/utils"); const conf_1 = tslib_1.__importDefault(require("conf")); const debug_1 = tslib_1.__importDefault(require("debug")); const fs_extra_1 = tslib_1.__importDefault(require("fs-extra")); const p_defer_1 = tslib_1.__importDefault(require("p-defer")); const path_1 = tslib_1.__importDefault(require("path")); const config_1 = require("./config"); const get_val_1 = require("./get_val"); // tslint:disable-next-line: no-var-requires const pjson = require("../../../package.json"); const debug = debug_1.default("adapt:config"); const envPrefix = "ADAPT_CONFIG_"; const defaultConfigFilenames = [ "config.json5", "config.json", ]; let pConfig; async function findUserConfigFile(pkgConfig) { for (const fn of defaultConfigFilenames) { const filename = path_1.default.join(pkgConfig.configDir, fn); if (await fs_extra_1.default.pathExists(filename)) return filename; } return path_1.default.join(pkgConfig.configDir, defaultConfigFilenames[0]); } exports.findUserConfigFile = findUserConfigFile; async function readUserConfigFile(userConfigFile) { try { const val = await utils_1.readJson5(userConfigFile); if (val == null || !utils_1.isObject(val) || Array.isArray(val)) { throw new Error(`Does not contain a single object in ` + `JSON/JSON5 format (actual type=${typeof val})`); } return val; } catch (err) { if (err && err.code === "ENOENT") return {}; // Empty config return throwConfigFileError(userConfigFile, err); } } function throwConfigFileError(userConfigFile, err, info = "") { err = utils_1.ensureError(err); if (info) info = ` ${info}`; let msg = `Config file '${userConfigFile}'${info}: `; switch (err.code) { case "ENOENT": msg += "File not found"; break; case "EACCES": msg += "Permission denied"; break; default: if (err.message) { msg += err.message.replace(/^Error: /, ""); } else { msg += "Unknown error - " + err.toString(); } } throw new utils_1.UserError(msg); } exports.throwConfigFileError = throwConfigFileError; const envVarPropTransform = (prop) => envPrefix + prop.toUpperCase(); async function loadUserConfig(userConfigFile) { const rawConf = await readUserConfigFile(userConfigFile); const conf = {}; const details = {}; const sources = [ { sourceType: "Environment", source: envVarPropTransform, obj: process.env, opts: { propTransform: envVarPropTransform }, }, { sourceType: "File", source: userConfigFile, obj: rawConf, }, { sourceType: "Default", source: "Default", obj: {}, opts: { useDefault: true }, }, ]; function getVal(key) { for (const s of sources) { const val = get_val_1.getValIfSet(key, s.obj, config_1.userConfigSchema, s.opts); if (val != null) { conf[key] = val.parsed; details[key] = { parsed: val.parsed, sourceType: s.sourceType, source: typeof s.source === "function" ? s.source(key) : s.source, store: val.store, valid: true, }; return; } } } config_1.userConfigProps.forEach(getVal); // Find any user config keys we don't understand const badKeys = Object.keys(rawConf) .filter((key) => !(key in config_1.userConfigSchema)); badKeys.forEach((key) => { details[key] = { parsed: rawConf[key], sourceType: "File", source: userConfigFile, store: rawConf[key], valid: false, }; }); // Print warnings for config keys we don't understand // TODO: This should not be a debug, but rather a log message that doesn't // display with the default CLI log level. if (debug.enabled && badKeys.length) { debug(`The following configuration items are invalid: ${badKeys.join(", ")}`); } return { config: conf, details, }; } exports.loadUserConfig = loadUserConfig; function createState(configDir, versionCheck = true) { const state = new conf_1.default({ configName: ".state", cwd: configDir, defaults: config_1.cliStateDefaults, deserialize: utils_1.parseJson5, serialize: (val) => utils_1.stringifyJson5(val, { space: 2 }) + "\n", }); if (versionCheck && state.get("version") !== pjson.version) { state.set({ installed: Date.now(), version: pjson.version, }); } return state; } exports.createState = createState; async function createConfig(pkgConfig) { const userConfigFile = await findUserConfigFile(pkgConfig); const user = (await loadUserConfig(userConfigFile)).config; const state = createState(pkgConfig.configDir); if (!pConfig) pConfig = p_defer_1.default(); pConfig.resolve({ state, package: pkgConfig, user, userConfigFile, }); } exports.createConfig = createConfig; function config() { if (!pConfig) pConfig = p_defer_1.default(); return pConfig.promise; } exports.config = config; /** * Exported for testing only * @internal */ function _resetConfig() { pConfig = undefined; } exports._resetConfig = _resetConfig; //# sourceMappingURL=load.js.map