"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadConfig = void 0;
const debugFactory = require("debug");
const path = require("path");
const _merge = require("lodash.merge");
// Use vendored and patched nconf without yargs and with our custom TRUE/FALSE logic in env.ts file
const nconf_1 = require("./nconf/nconf");
const debug = debugFactory('snyk:config');
function loadConfig(dir, options) {
    if (!dir) {
        dir = '';
    }
    options = options || {};
    const secretConfig = options.secretConfig ||
        process.env['CONFIG_SECRET_FILE'] ||
        path.resolve(dir, 'config.secret.json');
    const parseEnvValues = getParseEnvValues(options);
    if (!path.isAbsolute(dir)) {
        throw new Error('config requires absolute path to read from');
    }
    const serviceEnv = process.env['SERVICE_ENV'];
    const localConfig = serviceEnv ? serviceEnv : 'local';
    const localConfigPath = path.resolve(dir, `config.${localConfig}.json`);
    debug('dir: %s, local: %s, secret: %s', dir, localConfigPath, secretConfig);
    const snykMatch = /^SNYK_.*$/;
    nconf_1.default.env({
        parseValues: parseEnvValues,
        separator: '__',
        match: snykMatch,
        whitelist: ['NODE_ENV', 'PORT'],
    });
    // This argv parser is using minimist on the background, instead of yargs as nconf by default
    // Do not pass `options` to this parser
    nconf_1.default.argv();
    nconf_1.default.file('secret', { file: path.resolve(secretConfig) });
    nconf_1.default.file('local', { file: localConfigPath });
    nconf_1.default.file('default', { file: path.resolve(dir, 'config.default.json') });
    const config = nconf_1.default.get();
    // strip prefix from env vars in config
    Object.keys(config).forEach(function (key) {
        if (key.match(snykMatch)) {
            const trimmedKey = key.replace(/^SNYK_/, '');
            if (typeof config[trimmedKey] === 'object' &&
                typeof config[key] === 'object') {
                config[trimmedKey] = _merge(config[trimmedKey], config[key]);
            }
            else {
                config[trimmedKey] = config[key];
            }
            delete config[key];
        }
    });
    substituteEnvVarValues(config);
    debug('loading from %s', dir, JSON.stringify(config, null, 2));
    return config;
}
exports.loadConfig = loadConfig;
// recursively replace ${VAL} in config values with process.env.VAL
function substituteEnvVarValues(config) {
    Object.keys(config).forEach(function (key) {
        // recurse through nested objects
        if (typeof config[key] === 'object') {
            return substituteEnvVarValues(config[key]);
        }
        // replace /\${.*?}/g in strings with env var if such exists
        if (typeof config[key] === 'string') {
            config[key] = config[key].replace(/(\${.*?})/g, function (_, match) {
                const val = match.slice(2, -1); // ditch the wrappers
                // explode if env var is missing
                if (process.env[val] === undefined) {
                    throw new Error('Missing env var to substitute ' +
                        val +
                        " in '" +
                        key +
                        ': "' +
                        config[key] +
                        '"\'');
                }
                return process.env[val];
            });
        }
    });
}
function getParseEnvValues(configOptions) {
    if (configOptions.parseEnvValues !== undefined) {
        if (typeof configOptions.parseEnvValues !== 'boolean') {
            throw new Error('options.parseEnvValues must be a boolean');
        }
        return configOptions.parseEnvValues;
    }
    const envVarVal = process.env['CONFIG_PARSE_ENV_VALUES'];
    if (envVarVal !== undefined &&
        envVarVal !== '' &&
        envVarVal !== 'undefined') {
        let parsed;
        try {
            parsed = JSON.parse(envVarVal.toLowerCase());
        }
        catch (_a) {
            throw new Error('CONFIG_PARSE_ENV_VALUES must be a boolean');
        }
        if (typeof parsed !== 'boolean') {
            throw new Error('CONFIG_PARSE_ENV_VALUES must be a boolean');
        }
        return parsed;
    }
    return false;
}
//# sourceMappingURL=index.js.map