@salesforce/core
Version:
Core libraries to interact with SFDX projects, orgs, and APIs.
561 lines • 28.4 kB
JavaScript
/*
* 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
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Config = exports.SfProperty = exports.SFDX_ALLOWED_PROPERTIES = exports.SfdxPropertyKeys = exports.SF_ALLOWED_PROPERTIES = exports.SfConfigProperties = void 0;
const node_path_1 = require("node:path");
const fs = __importStar(require("node:fs"));
const kit_1 = require("@salesforce/kit");
const ts_types_1 = require("@salesforce/ts-types");
const global_1 = require("../global");
const logger_1 = require("../logger/logger");
const messages_1 = require("../messages");
const sfdc_1 = require("../util/sfdc");
const sfdcUrl_1 = require("../util/sfdcUrl");
const orgConfigProperties_1 = require("../org/orgConfigProperties");
const lifecycleEvents_1 = require("../lifecycleEvents");
const configFile_1 = require("./configFile");
const lwwMap_1 = require("./lwwMap");
;
const messages = new messages_1.Messages('@salesforce/core', 'config', new Map([["unknownConfigKey", "Unknown config name: %s."], ["deprecatedConfigKey", "Deprecated config name: %s. Please use %s instead."], ["invalidWrite", "The writeSync method is not allowed on SfdxConfig. Use the async write method instead."], ["invalidConfigValue", "Invalid config value: %s."], ["invalidInstanceUrl", "Specify a valid Salesforce instance URL."], ["invalidApiVersion", "Specify a valid Salesforce API version, for example, 42.0."], ["invalidCustomOrgMetadataTemplates", "Specify a valid repository URL or directory for the custom org metadata templates."], ["invalidIsvDebuggerSid", "Specify a valid Debugger SID."], ["invalidIsvDebuggerUrl", "Specify a valid Debugger URL."], ["invalidNumberConfigValue", "Specify a valid positive integer, for example, 150000."], ["invalidBooleanConfigValue", "The config value can only be set to true or false."], ["invalidProjectWorkspace", "This directory does not contain a valid Salesforce DX project."], ["schemaValidationError", "The config file \"%s\" is not schema valid.\nDue to: %s"], ["schemaValidationError.actions", ["Fix the invalid entries at %s."]], ["missingDefaultPath", "In sfdx-project.json, be sure to specify which package directory (path) is the default. Example: `[{ \"path\": \"packageDirectory1\", \"default\": true }, { \"path\": \"packageDirectory2\" }]`"], ["missingPackageDirectory", "The path \"%s\", specified in sfdx-project.json, does not exist. Be sure this directory is included in your project root."], ["invalidPackageDirectory", "The path \"%s\", specified in sfdx-project.json, must be indicated as a relative path to the project root."], ["multipleDefaultPaths", "In sfdx-project.json, indicate only one package directory (path) as the default."], ["singleNonDefaultPackage", "The sfdx-project.json file must include one, and only one, default package directory (path). Because your sfdx-project.json file contains only one package directory, it must be the default. Remove the `\"default\": false` key and try again."], ["target-org", "Username or alias of the org that all commands run against by default. (sf only)"], ["target-dev-hub", "Username or alias of your default Dev Hub org. (sf only)"], ["defaultUsername", "Username or alias of the org that all commands run against by default. (sfdx only)"], ["defaultDevHubUsername", "Username or alias of your default Dev Hub org. (sfdx only)"], ["isvDebuggerSid", "ISV debugger SID (sfdx only)"], ["isvDebuggerUrl", "ISV debugger URL (sfdx only)"], ["org-isv-debugger-sid", "ISV debugger SID."], ["org-isv-debugger-url", "ISV debugger URL."], ["apiVersion", "API version of your project. Default: API version of your Dev Hub org. (sfdx only)"], ["org-api-version", "API version of your project. Default: API version of your Dev Hub org."], ["disableTelemetry", "Disables the collection of usage and user environment information, etc. Default: false. (sfdx only)"], ["disable-telemetry", "Disables the collection of usage and user environment information, etc. Default: false."], ["maxQueryLimit", "Maximum number of Salesforce records returned by a CLI command. Default: 10,000. (sfdx only)"], ["org-max-query-limit", "Maximum number of Salesforce records returned by a CLI command. Default: 10,000."], ["restDeploy", "Whether deployments use the Metadata REST API (true) or SOAP API (false, default value). (sfdx only)"], ["instanceUrl", "URL of the Salesforce instance hosting your org. Default: https://login.salesforce.com. (sfdx only)"], ["org-instance-url", "URL of the Salesforce instance hosting your org. Default: https://login.salesforce.com."], ["customOrgMetadataTemplates", "A valid repository URL or directory for the custom org metadata templates."], ["org-custom-metadata-templates", "A valid repository URL or directory for the custom org metadata templates."], ["org-capitalize-record-types", "Whether record types are capitalized on scratch org creation."], ["invalidId", "The given id %s is not a valid 15 or 18 character Salesforce ID."]]));
const SFDX_CONFIG_FILE_NAME = 'sfdx-config.json';
const CONFIG_FILE_NAME = 'config.json';
var SfConfigProperties;
(function (SfConfigProperties) {
/**
* Disables telemetry reporting
*/
SfConfigProperties["DISABLE_TELEMETRY"] = "disable-telemetry";
})(SfConfigProperties || (exports.SfConfigProperties = SfConfigProperties = {}));
exports.SF_ALLOWED_PROPERTIES = [
{
key: SfConfigProperties.DISABLE_TELEMETRY,
description: messages.getMessage(SfConfigProperties.DISABLE_TELEMETRY),
input: {
validator: (value) => value == null || isBooleanOrBooleanString(value),
failedMessage: messages.getMessage('invalidBooleanConfigValue'),
},
},
];
var SfdxPropertyKeys;
(function (SfdxPropertyKeys) {
/**
* Username associated with the default dev hub org.
*
* @deprecated Replaced by OrgConfigProperties.TARGET_DEV_HUB in v3 {@link https://github.com/forcedotcom/sfdx-core/blob/v3/MIGRATING_V2-V3.md#config}
* will remain in v3 for the foreseeable future so that `sfdx-core` can map between `sf` and `sfdx` config values
*/
SfdxPropertyKeys["DEFAULT_DEV_HUB_USERNAME"] = "defaultdevhubusername";
/**
* Username associate with the default org.
*
* @deprecated Replaced by OrgConfigProperties.TARGET_ORG in v3 {@link https://github.com/forcedotcom/sfdx-core/blob/v3/MIGRATING_V2-V3.md#config}
* will remain in v3 for the foreseeable future so that `sfdx-core` can map between `sf` and `sfdx` config values
*/
SfdxPropertyKeys["DEFAULT_USERNAME"] = "defaultusername";
/**
* The sid for the debugger configuration.
*
* @deprecated Replaced by OrgConfigProperties.ORG_ISV_DEBUGGER_SID in v3 {@link https://github.com/forcedotcom/sfdx-core/blob/v3/MIGRATING_V2-V3.md#config}
*/
SfdxPropertyKeys["ISV_DEBUGGER_SID"] = "isvDebuggerSid";
/**
* The url for the debugger configuration.
*
* @deprecated Replaced by OrgConfigProperties.ORG_ISV_DEBUGGER_URL in v3 {@link https://github.com/forcedotcom/sfdx-core/blob/v3/MIGRATING_V2-V3.md#config}
*/
SfdxPropertyKeys["ISV_DEBUGGER_URL"] = "isvDebuggerUrl";
/**
* The api version
*
* @deprecated Replaced by OrgConfigProperties.ORG_API_VERSION in v3 {@link https://github.com/forcedotcom/sfdx-core/blob/v3/MIGRATING_V2-V3.md#config}
*/
SfdxPropertyKeys["API_VERSION"] = "apiVersion";
/**
* Disables telemetry reporting
*
* @deprecated Replaced by SfPropertyKeys.DISABLE_TELEMETRY in v3 {@link https://github.com/forcedotcom/sfdx-core/blob/v3/MIGRATING_V2-V3.md#config}
*/
SfdxPropertyKeys["DISABLE_TELEMETRY"] = "disableTelemetry";
/**
* Custom templates repo or local location.
*
* @deprecated Replaced by OrgConfigProperties.ORG_CUSTOM_METADATA_TEMPLATES in v3 {@link https://github.com/forcedotcom/sfdx-core/blob/v3/MIGRATING_V2-V3.md#config}
*/
SfdxPropertyKeys["CUSTOM_ORG_METADATA_TEMPLATES"] = "customOrgMetadataTemplates";
/**
* allows users to override the 10,000 result query limit
*
* @deprecated Replaced by OrgConfigProperties.ORG_MAX_QUERY_LIMIT in v3 {@link https://github.com/forcedotcom/sfdx-core/blob/v3/MIGRATING_V2-V3.md#config}
*/
SfdxPropertyKeys["MAX_QUERY_LIMIT"] = "maxQueryLimit";
/**
* @deprecated
*/
SfdxPropertyKeys["REST_DEPLOY"] = "restDeploy";
/**
* @deprecated Replaced by OrgConfigProperties.ORG_INSTANCE_URL in v3 {@link https://github.com/forcedotcom/sfdx-core/blob/v3/MIGRATING_V2-V3.md#config}
*/
SfdxPropertyKeys["INSTANCE_URL"] = "instanceUrl";
})(SfdxPropertyKeys || (exports.SfdxPropertyKeys = SfdxPropertyKeys = {}));
exports.SFDX_ALLOWED_PROPERTIES = [
{
key: SfdxPropertyKeys.INSTANCE_URL,
description: messages.getMessage(SfdxPropertyKeys.INSTANCE_URL),
newKey: orgConfigProperties_1.OrgConfigProperties.ORG_INSTANCE_URL,
deprecated: true,
input: {
// If a value is provided validate it otherwise no value is unset.
validator: (value) => {
if (value == null)
return true;
// validate if the value is a string and is a valid url and is either a salesforce domain
// or an internal url.
return ((0, ts_types_1.isString)(value) &&
sfdcUrl_1.SfdcUrl.isValidUrl(value) &&
(new sfdcUrl_1.SfdcUrl(value).isSalesforceDomain() || new sfdcUrl_1.SfdcUrl(value).isInternalUrl()));
},
failedMessage: messages.getMessage('invalidInstanceUrl'),
},
},
{
key: SfdxPropertyKeys.API_VERSION,
newKey: orgConfigProperties_1.OrgConfigProperties.ORG_API_VERSION,
deprecated: true,
description: messages.getMessage(SfdxPropertyKeys.API_VERSION),
hidden: true,
input: {
// If a value is provided validate it otherwise no value is unset.
validator: (value) => value == null || ((0, ts_types_1.isString)(value) && (0, sfdc_1.validateApiVersion)(value)),
failedMessage: messages.getMessage('invalidApiVersion'),
},
},
{
// will remain in v3 for the foreseeable future so that `sfdx-core` can map between `sf` and `sfdx` config values
key: SfdxPropertyKeys.DEFAULT_DEV_HUB_USERNAME,
newKey: orgConfigProperties_1.OrgConfigProperties.TARGET_DEV_HUB,
deprecated: true,
description: messages.getMessage('defaultDevHubUsername'),
},
{
// will remain in v3 for the foreseeable future so that `sfdx-core` can map between `sf` and `sfdx` config values
key: SfdxPropertyKeys.DEFAULT_USERNAME,
newKey: orgConfigProperties_1.OrgConfigProperties.TARGET_ORG,
deprecated: true,
description: messages.getMessage('defaultUsername'),
},
{
key: SfdxPropertyKeys.ISV_DEBUGGER_SID,
newKey: orgConfigProperties_1.OrgConfigProperties.ORG_ISV_DEBUGGER_SID,
deprecated: true,
description: messages.getMessage(SfdxPropertyKeys.ISV_DEBUGGER_SID),
encrypted: true,
input: {
// If a value is provided validate it otherwise no value is unset.
validator: (value) => value == null || (0, ts_types_1.isString)(value),
failedMessage: messages.getMessage('invalidIsvDebuggerSid'),
},
},
{
key: SfdxPropertyKeys.ISV_DEBUGGER_URL,
newKey: orgConfigProperties_1.OrgConfigProperties.ORG_ISV_DEBUGGER_URL,
deprecated: true,
description: messages.getMessage(SfdxPropertyKeys.ISV_DEBUGGER_URL),
input: {
// If a value is provided validate it otherwise no value is unset.
validator: (value) => value == null || (0, ts_types_1.isString)(value),
failedMessage: messages.getMessage('invalidIsvDebuggerUrl'),
},
},
{
key: SfdxPropertyKeys.DISABLE_TELEMETRY,
newKey: SfConfigProperties.DISABLE_TELEMETRY,
deprecated: true,
description: messages.getMessage(SfdxPropertyKeys.DISABLE_TELEMETRY),
input: {
validator: (value) => value == null || isBooleanOrBooleanString(value),
failedMessage: messages.getMessage('invalidBooleanConfigValue'),
},
},
{
key: SfdxPropertyKeys.CUSTOM_ORG_METADATA_TEMPLATES,
newKey: orgConfigProperties_1.OrgConfigProperties.ORG_CUSTOM_METADATA_TEMPLATES,
deprecated: true,
description: messages.getMessage(SfdxPropertyKeys.CUSTOM_ORG_METADATA_TEMPLATES),
},
{
key: SfdxPropertyKeys.REST_DEPLOY,
description: messages.getMessage(SfdxPropertyKeys.REST_DEPLOY),
hidden: true,
newKey: 'org-metadata-rest-deploy',
deprecated: true,
input: {
validator: (value) => value != null && isBooleanOrBooleanString(value),
failedMessage: messages.getMessage('invalidBooleanConfigValue'),
},
},
{
key: SfdxPropertyKeys.MAX_QUERY_LIMIT,
description: messages.getMessage(SfdxPropertyKeys.MAX_QUERY_LIMIT),
hidden: true,
newKey: orgConfigProperties_1.OrgConfigProperties.ORG_MAX_QUERY_LIMIT,
deprecated: true,
input: {
// the bit shift will remove the negative bit, and any decimal numbers
// then the parseFloat will handle converting it to a number from a string
validator: (value) => value >>> 0 === parseFloat(value) && value > 0,
failedMessage: messages.getMessage('invalidNumberConfigValue'),
},
},
];
// Generic global config properties. Specific properties can be loaded like orgConfigProperties.ts.
exports.SfProperty = {};
/**
* The files where sfdx config values are stored for projects and the global space.
*
* *Note:* It is not recommended to instantiate this object directly when resolving
* config values. Instead use {@link ConfigAggregator}
*
* ```
* const localConfig = await Config.create();
* localConfig.set('target-org', 'username@company.org');
* await localConfig.write();
* ```
* https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_cli_config_values.htm
*/
class Config extends configFile_1.ConfigFile {
static allowedProperties = [
...exports.SFDX_ALLOWED_PROPERTIES,
...exports.SF_ALLOWED_PROPERTIES,
...orgConfigProperties_1.ORG_CONFIG_ALLOWED_PROPERTIES,
];
sfdxPath;
constructor(options) {
super({
...{ isGlobal: false },
...(options ?? {}),
// Don't let consumers of config override this. If they really really want to,
// they can extend this class.
isState: true,
filename: Config.getFileName(),
stateFolder: global_1.Global.SF_STATE_FOLDER,
});
// Resolve the config path on creation.
this.getPath();
if (global_1.Global.SFDX_INTEROPERABILITY) {
this.sfdxPath = buildSfdxPath(this.options);
}
}
/**
* Returns the default file name for a config file.
*
* **See** {@link CONFIG_FILE_NAME}
*/
static getFileName() {
return CONFIG_FILE_NAME;
}
/**
* Returns an array of objects representing the allowed config properties.
*/
static getAllowedProperties() {
return Config.allowedProperties;
}
/**
* Add an array of allowed config properties.
*
* @param metas Array of objects to set as the allowed config properties.
*/
static addAllowedProperties(metas) {
const currentMetaKeys = Object.keys(Config.propertyConfigMap());
// If logger is needed elsewhere in this file, do not move this outside of the Config class.
// It was causing issues with Bunyan log rotation. See https://github.com/forcedotcom/sfdx-core/pull/562
const logger = logger_1.Logger.childFromRoot('core:config');
metas.forEach((meta) => {
if (currentMetaKeys.includes(meta.key)) {
logger.info(`Key ${meta.key} already exists in allowedProperties, skipping.`);
return;
}
Config.allowedProperties.push(meta);
});
}
/**
* The value of a supported config property.
*
* @param isGlobal True for a global config. False for a local config.
* @param propertyName The name of the property to set.
* @param value The property value.
*/
static async update(isGlobal, propertyName, value) {
const config = await Config.create({ isGlobal });
await config.read();
if (value == null) {
config.unset(propertyName);
}
else {
config.set(propertyName, value);
}
return config.write();
}
/**
* Clear all the configured properties both local and global.
*/
static async clear() {
const [globalConfig, localConfig] = await Promise.all([Config.create({ isGlobal: true }), Config.create()]);
globalConfig.clear();
localConfig.clear();
await Promise.all([globalConfig.write(), localConfig.write()]);
}
static getPropertyConfigMeta(propertyName) {
const prop = Config.propertyConfigMap()[propertyName];
if (prop?.deprecated && prop?.newKey) {
return Config.propertyConfigMap()[prop.newKey];
}
return prop;
}
static propertyConfigMap() {
return (0, kit_1.keyBy)(Config.allowedProperties, 'key');
}
/**
* Read, assign, and return the config contents.
*/
async read(force = true) {
try {
await super.read(false, force);
if (global_1.Global.SFDX_INTEROPERABILITY) {
// will exist if Global.SFDX_INTEROPERABILITY is enabled
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.contents.merge(stateFromSfdxFileSync(this.sfdxPath, this));
}
await this.cryptProperties(false);
return this.getContents();
}
finally {
await this.clearCrypto();
}
}
readSync(force = true) {
super.readSync(false, force);
if (global_1.Global.SFDX_INTEROPERABILITY) {
// will exist if Global.SFDX_INTEROPERABILITY is enabled
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.contents.merge(stateFromSfdxFileSync(this.sfdxPath, this));
}
return this.getContents();
}
/**
* Writes Config properties taking into account encrypted properties.
*
* @param newContents The new Config value to persist.
*/
async write() {
await this.cryptProperties(true);
// super.write will merge the contents if the target file had newer properties
await super.write();
if (global_1.Global.SFDX_INTEROPERABILITY) {
// will exist if Global.SFDX_INTEROPERABILITY is enabled
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
await writeToSfdx(this.sfdxPath, this.getContents());
}
await this.cryptProperties(false);
return this.getContents();
}
/**
* DO NOT CALL - The config file needs to encrypt values which can only be done asynchronously.
* Call {@link SfdxConfig.write} instead.
*
* **Throws** *{@link SfError}{ name: 'InvalidWriteError' }* Always.
*
* @param newContents Contents to write
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars, class-methods-use-this
writeSync(newContents) {
throw messages.createError('invalidWrite');
}
/**
* Sets a value for a property.
*
* **Throws** *{@link SfError}{ name: 'UnknownConfigKeyError' }* An attempt to get a property that's not supported.
* **Throws** *{@link SfError}{ name: 'InvalidConfigValueError' }* If the input validator fails.
*
* @param key The property to set.
* @param value The value of the property.
*/
set(key, value) {
const property = Config.allowedProperties.find((allowedProp) => allowedProp.key === key);
if (!property) {
throw messages.createError('unknownConfigKey', [key]);
}
if (property.deprecated && property.newKey) {
// you're trying to set a deprecated key, but we'll set the new key instead
void lifecycleEvents_1.Lifecycle.getInstance().emitWarning(messages.getMessage('deprecatedConfigKey', [key, property.newKey]));
return this.set(property.newKey, value);
}
if (value !== undefined && property.input) {
if (property.input?.validator(value)) {
super.set(property.key, value);
}
else {
let valueError = value?.toString() ?? '';
if (property.input.failedMessage) {
valueError = (0, ts_types_1.isString)(property.input.failedMessage)
? property.input.failedMessage
: property.input.failedMessage(value);
}
throw messages.createError('invalidConfigValue', [valueError]);
}
}
else {
super.set(property.key, value);
}
return this.getContents();
}
/**
* Unsets a value for a property.
*
* **Throws** *{@link SfError}{ name: 'UnknownConfigKeyError' }* If the input validator fails.
*
* @param key The property to unset.
*/
unset(key) {
const property = Config.allowedProperties.find((allowedProp) => allowedProp.key === key);
if (!property) {
throw messages.createError('unknownConfigKey', [key]);
}
if (property.deprecated && property.newKey) {
// you're trying to set a deprecated key, so we'll ALSO unset the new key
void lifecycleEvents_1.Lifecycle.getInstance().emitWarning(messages.getMessage('deprecatedConfigKey', [key, property.newKey]));
super.unset(property.key);
return this.unset(property.newKey);
}
return super.unset(property.key);
}
/**
* Get an individual property config.
*
* **Throws** *{@link SfError}{ name: 'UnknownConfigKeyError' }* An attempt to get a property that's not supported.
*
* @param propertyName The name of the property.
*/
// eslint-disable-next-line class-methods-use-this
getPropertyConfig(propertyName) {
const prop = Config.propertyConfigMap()[propertyName];
if (!prop) {
const newEquivalent = Config.allowedProperties.find((p) => p.newKey);
if (newEquivalent) {
return this.getPropertyConfig(newEquivalent.key);
}
throw messages.createError('unknownConfigKey', [propertyName]);
}
return prop;
}
/**
* Initializer for supported config types.
*/
async init() {
// Super ConfigFile calls read, which has a dependency on crypto, which finally has a dependency on
// Config.propertyConfigMap being set. This is why init is called after the setup.
await super.init();
}
/**
* Encrypts and content properties that have a encryption attribute.
*
* @param encrypt `true` to encrypt.
*/
async cryptProperties(encrypt) {
const hasEncryptedProperties = this.entries().some(([key]) => !!Config.propertyConfigMap()[key]?.encrypted);
if (hasEncryptedProperties) {
await this.initCrypto();
const crypto = (0, ts_types_1.ensure)(this.crypto);
this.forEach((key, value) => {
if (this.getPropertyConfig(key).encrypted && (0, ts_types_1.isString)(value)) {
super.set(key, (0, ts_types_1.ensure)(encrypt ? crypto.encrypt(value) : crypto.decrypt(value)));
}
});
}
}
}
exports.Config = Config;
/**
* convert from "new" to "old" config names
* - For example, `target-org` will be renamed to `defaultusername`.
*/
const translateToSfdx = (sfContents) => Object.fromEntries(Object.entries(sfContents).map(([key, value]) => {
const propConfig = Config.getAllowedProperties().find((c) => c.newKey === key) ?? {};
return propConfig.deprecated && propConfig.newKey ? [propConfig.key, value] : [key, value];
}));
/**
* convert from "old" to "new" config names
* - For example, `defaultusername` will be renamed to `target-org`
*/
const translateToSf = (sfdxContents, SfConfig) => Object.fromEntries(Object.entries(sfdxContents).map(([key, value]) => {
const propConfig = SfConfig.getPropertyConfig(key);
return propConfig.deprecated && propConfig.newKey ? [propConfig.newKey, value] : [key, value];
}));
/** given the ConfigFile options, calculate the full path where the config file goes */
const buildSfdxPath = (options) => {
// Don't let users store config files in homedir without being in the state folder.
const configRootFolder = options.rootFolder ?? configFile_1.ConfigFile.resolveRootFolderSync(!!options.isGlobal);
const rootWithState = options.isGlobal === true || options.isState === true
? (0, node_path_1.join)(configRootFolder, global_1.Global.SFDX_STATE_FOLDER)
: configRootFolder;
return (0, node_path_1.join)(rootWithState, SFDX_CONFIG_FILE_NAME);
};
/**
* writes (in an unsafe way) the configuration file to the sfdx file location.
* Make sure you call ConfigFile.write and getContents so that the contents passed here are not cross-saving something
*/
const writeToSfdx = async (path, contents) => {
try {
const translated = translateToSfdx(contents);
await fs.promises.mkdir((0, node_path_1.dirname)(path), { recursive: true });
await fs.promises.writeFile(path, JSON.stringify(translated, null, 2));
}
catch (e) {
const logger = logger_1.Logger.childFromRoot('core:config:writeToSfdx');
logger.debug(`Error writing to sfdx config file at ${path}: ${e instanceof Error ? e.message : ''}`);
}
};
/** turn the sfdx config file into a LWWState based on its contents and its timestamp */
const stateFromSfdxFileSync = (path, config) => {
try {
const fileContents = fs.readFileSync(path, 'utf8');
const mtimeNs = fs.statSync(path, { bigint: true }).mtimeNs;
const translatedContents = translateToSf((0, kit_1.parseJsonMap)(fileContents, path), config);
// get the file timestamp
return (0, lwwMap_1.stateFromContents)(translatedContents, mtimeNs);
}
catch (e) {
const logger = logger_1.Logger.childFromRoot('core:config:stateFromSfdxFileSync');
logger.debug(`Error reading state from sfdx config file at ${path}: ${e instanceof Error ? e.message : ''}`);
return {};
}
};
const isBooleanOrBooleanString = (value) => (typeof value === 'string' && ['true', 'false'].includes(value)) || typeof value === 'boolean';
//# sourceMappingURL=config.js.map
;