UNPKG

@salesforce/core

Version:

Core libraries to interact with SFDX projects, orgs, and APIs.

282 lines 10 kB
"use strict"; /* * Copyright (c) 2020, salesforce.com, inc. * All rights reserved. * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ Object.defineProperty(exports, "__esModule", { value: true }); exports.ConfigAggregator = void 0; const kit_1 = require("@salesforce/kit"); const ts_types_1 = require("@salesforce/ts-types"); const sfdxError_1 = require("../sfdxError"); const config_1 = require("./config"); const propertyToEnvName = (property) => `SFDX_${kit_1.snakeCase(property).toUpperCase()}`; /** * Aggregate global and local project config files, as well as environment variables for * `sfdx-config.json`. The resolution happens in the following bottom-up order: * * 1. Environment variables (`SFDX_LOG_LEVEL`) * 1. Workspace settings (`<workspace-root>/.sfdx/sfdx-config.json`) * 1. Global settings (`$HOME/.sfdx/sfdx-config.json`) * * Use {@link ConfigAggregator.create} to instantiate the aggregator. * * ``` * const aggregator = await ConfigAggregator.create(); * console.log(aggregator.getPropertyValue('defaultusername')); * ``` */ class ConfigAggregator extends kit_1.AsyncOptionalCreatable { /** * **Do not directly construct instances of this class -- use {@link ConfigAggregator.create} instead.** * * @ignore */ constructor(options) { super(options || {}); // Don't throw an project error with the aggregator, since it should resolve to global if // there is no project. try { this.localConfig = new config_1.Config(config_1.Config.getDefaultOptions(false)); } catch (err) { if (err.name !== 'InvalidProjectWorkspace') { throw err; } } this.globalConfig = new config_1.Config(config_1.Config.getDefaultOptions(true)); this.setAllowedProperties(config_1.Config.getAllowedProperties()); } get config() { return this.resolveProperties(this.globalConfig.getContents(), this.localConfig && this.localConfig.getContents()); } /** * Get the static ConfigAggregator instance. If one doesn't exist, one will be created with * the **encrypted** config values. Encrypted config values need to be resolved * asynchronously by calling {@link ConfigAggregator.reload} */ // Use typing from AsyncOptionalCreatable to support extending ConfigAggregator. // We really don't want ConfigAggregator extended but typescript doesn't support a final. static getInstance() { if (!ConfigAggregator.instance) { ConfigAggregator.instance = new this(); ConfigAggregator.instance.loadPropertiesSync(); } return ConfigAggregator.instance; } // Use typing from AsyncOptionalCreatable to support extending ConfigAggregator. // We really don't want ConfigAggregator extended but typescript doesn't support a final. static async create(options) { let config = ConfigAggregator.instance; if (!config) { config = ConfigAggregator.instance = new this(options); await config.init(); } if (ConfigAggregator.encrypted) { await config.loadProperties(); } return ConfigAggregator.instance; } /** * Get the info for a given key. If the ConfigAggregator was not asynchronously created OR * the {@link ConfigAggregator.reload} was not called, the config value may be encrypted. * * @param key The config key. */ static getValue(key) { return this.getInstance().getInfo(key); } /** * Initialize this instances async dependencies. */ async init() { await this.loadProperties(); } /** * Get a resolved config property. * * **Throws** *{@link SfdxError}{ name: 'UnknownConfigKey' }* An attempt to get a property that's not supported. * * @param key The key of the property. */ getPropertyValue(key) { if (this.getAllowedProperties().some((element) => key === element.key)) { return this.getConfig()[key]; } else { throw new sfdxError_1.SfdxError(`Unknown config key: ${key}`, 'UnknownConfigKey'); } } /** * Get a resolved config property. * * @param key The key of the property. */ getInfo(key) { const location = this.getLocation(key); return { key, location, value: this.getPropertyValue(key), path: this.getPath(key), isLocal: () => location === "Local" /* LOCAL */, isGlobal: () => location === "Global" /* GLOBAL */, isEnvVar: () => location === "Environment" /* ENVIRONMENT */, }; } /** * Gets a resolved config property location. * * For example, `getLocation('logLevel')` will return: * 1. `Location.GLOBAL` if resolved to an environment variable. * 1. `Location.LOCAL` if resolved to local project config. * 1. `Location.ENVIRONMENT` if resolved to the global config. * * @param key The key of the property. */ getLocation(key) { if (this.getEnvVars().get(key) != null) { return "Environment" /* ENVIRONMENT */; } if (this.localConfig && this.localConfig.get(key)) { return "Local" /* LOCAL */; } if (this.globalConfig && this.globalConfig.get(key)) { return "Global" /* GLOBAL */; } } /** * Get a resolved file path or environment variable name of the property. * * For example, `getPath('logLevel')` will return: * 1. `$SFDX_LOG_LEVEL` if resolved to an environment variable. * 1. `./.sfdx/sfdx-config.json` if resolved to the local config. * 1. `~/.sfdx/sfdx-config.json` if resolved to the global config. * 1. `undefined`, if not resolved. * * **Note:** that the path returned may be the absolute path instead of * relative paths such as `./` and `~/`. * * @param key The key of the property. */ getPath(key) { if (this.envVars[key] != null) { return `$${propertyToEnvName(key)}`; } if (this.localConfig && this.localConfig.getContents()[key] != null) { return this.localConfig.getPath(); } if (this.globalConfig.getContents()[key] != null) { return this.globalConfig.getPath(); } } /** * Get all resolved config property keys, values, locations, and paths. * * ``` * > console.log(aggregator.getConfigInfo()); * [ * { key: 'logLevel', val: 'INFO', location: 'Environment', path: '$SFDX_LOG_LEVEL'} * { key: 'defaultusername', val: '<username>', location: 'Local', path: './.sfdx/sfdx-config.json'} * ] * ``` */ getConfigInfo() { const infos = Object.keys(this.getConfig()) .filter((key) => this.getAllowedProperties().some((element) => key === element.key)) .map((key) => this.getInfo(key)) .filter((info) => !!info); return kit_1.sortBy(infos, 'key'); } /** * Get the local project config instance. */ getLocalConfig() { return this.localConfig; } /** * Get the global config instance. */ getGlobalConfig() { return this.globalConfig; } /** * Get the resolved config object from the local, global and environment config instances. */ getConfig() { return this.config; } /** * Get the config properties that are environment variables. */ getEnvVars() { return new Map(ts_types_1.definiteEntriesOf(this.envVars)); } /** * Re-read all property configurations from disk. */ async reload() { await this.loadProperties(); return this; } /** * Loads all the properties and aggregates them according to location. */ async loadProperties() { this.resolveProperties(await this.globalConfig.read(), this.localConfig && (await this.localConfig.read())); ConfigAggregator.encrypted = false; } /** * Loads all the properties and aggregates them according to location. */ loadPropertiesSync() { this.resolveProperties(this.globalConfig.readSync(), this.localConfig && this.localConfig.readSync()); } resolveProperties(globalConfig, localConfig) { const accumulator = {}; this.setEnvVars(this.getAllowedProperties().reduce((obj, property) => { const val = process.env[propertyToEnvName(property.key)]; if (val != null) { obj[property.key] = val; } return obj; }, accumulator)); // Global config must be read first so it is on the left hand of the // object assign and is overwritten by the local config. const configs = [globalConfig]; // We might not be in a project workspace if (localConfig) { configs.push(localConfig); } configs.push(this.envVars); const json = {}; const reduced = configs.filter(ts_types_1.isJsonMap).reduce((acc, el) => kit_1.merge(acc, el), json); return reduced; } /** * Get the allowed properties. */ getAllowedProperties() { return this.allowedProperties; } /** * Set the allowed properties. * * @param properties The properties to set. */ setAllowedProperties(properties) { this.allowedProperties = properties; } /** * Sets the env variables. * * @param envVars The env variables to set. */ setEnvVars(envVars) { this.envVars = envVars; } } exports.ConfigAggregator = ConfigAggregator; ConfigAggregator.encrypted = true; //# sourceMappingURL=configAggregator.js.map