@salesforce/core
Version:
Core libraries to interact with SFDX projects, orgs, and APIs.
717 lines • 29.4 kB
JavaScript
"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.Org = void 0;
const path_1 = require("path");
const kit_1 = require("@salesforce/kit");
const ts_types_1 = require("@salesforce/ts-types");
const aliases_1 = require("../config/aliases");
const config_1 = require("../config/config");
const configAggregator_1 = require("../config/configAggregator");
const orgUsersConfig_1 = require("../config/orgUsersConfig");
const sandboxOrgConfig_1 = require("../config/sandboxOrgConfig");
const global_1 = require("../global");
const logger_1 = require("../logger");
const sfdxError_1 = require("../sfdxError");
const fs_1 = require("../util/fs");
const sfdc_1 = require("../util/sfdc");
const globalInfoConfig_1 = require("../config/globalInfoConfig");
const messages_1 = require("../messages");
const connection_1 = require("./connection");
const authInfo_1 = require("./authInfo");
const orgConfigProperties_1 = require("./orgConfigProperties");
messages_1.Messages.importMessagesDirectory(__dirname);
const messages = messages_1.Messages.load('@salesforce/core', 'org', ['notADevHub']);
/**
* Provides a way to manage a locally authenticated Org.
*
* **See** {@link AuthInfo}
*
* **See** {@link Connection}
*
* **See** {@link Aliases}
*
* **See** {@link Config}
*
* ```
* // Email username
* const org1: Org = await Org.create({ aliasOrUsername: 'foo@example.com' });
* // The defaultusername config property
* const org2: Org = await Org.create();
* // Full Connection
* const org3: Org = await Org.create({
* connection: await Connection.create({
* authInfo: await AuthInfo.create({ username: 'username' })
* })
* });
* ```
*
* **See** https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_cli_usernames_orgs.htm
*/
class Org extends kit_1.AsyncOptionalCreatable {
/**
* @ignore
*/
constructor(options) {
super(options);
this.status = Org.Status.UNKNOWN;
this.options = options || {};
}
/**
* Clean all data files in the org's data path. Usually <workspace>/.sfdx/orgs/<username>.
*
* @param orgDataPath A relative path other than "orgs/".
* @param throwWhenRemoveFails Should the remove org operations throw an error on failure?
*/
async cleanLocalOrgData(orgDataPath, throwWhenRemoveFails = false) {
let dataPath;
try {
const rootFolder = await config_1.Config.resolveRootFolder(false);
dataPath = path_1.join(rootFolder, global_1.Global.SFDX_STATE_FOLDER, orgDataPath ? orgDataPath : 'orgs');
this.logger.debug(`cleaning data for path: ${dataPath}`);
}
catch (err) {
if (err.name === 'InvalidProjectWorkspaceError') {
// If we aren't in a project dir, we can't clean up data files.
// If the user unlink this org outside of the workspace they used it in,
// data files will be left over.
return;
}
throw err;
}
return this.manageDelete(async () => await fs_1.fs.remove(dataPath), dataPath, throwWhenRemoveFails);
}
/**
* @ignore
*/
async retrieveOrgUsersConfig() {
return await orgUsersConfig_1.OrgUsersConfig.create(orgUsersConfig_1.OrgUsersConfig.getOptions(this.getOrgId()));
}
/**
* Removes the scratch org config file at $HOME/.sfdx/[name].json, any project level org
* files, all user auth files for the org, matching default config settings, and any
* matching aliases.
*
* @param throwWhenRemoveFails Determines if the call should throw an error or fail silently.
*/
async remove(throwWhenRemoveFails = false) {
// If deleting via the access token there shouldn't be any auth config files
// so just return;
if (this.getConnection().isUsingAccessToken()) {
return Promise.resolve();
}
await this.removeSandboxConfig(throwWhenRemoveFails);
await this.removeUsers(throwWhenRemoveFails);
await this.removeUsersConfig();
// An attempt to remove this org's auth file occurs in this.removeUsersConfig. That's because this org's usersname is also
// included in the OrgUser config file.
//
// So, just in case no users are added to this org we will try the remove again.
await this.removeAuth();
}
/**
* Check that this org is a scratch org by asking the dev hub if it knows about it.
*
* **Throws** *{@link SfdxError}{ name: 'NotADevHubError' }* Not a Dev Hub.
*
* **Throws** *{@link SfdxError}{ name: 'NoResultsError' }* No results.
*
* @param devHubUsernameOrAlias The username or alias of the dev hub org.
*/
async checkScratchOrg(devHubUsernameOrAlias) {
let aliasOrUsername = devHubUsernameOrAlias;
if (!aliasOrUsername) {
aliasOrUsername =
this.configAggregator.getPropertyValue(orgConfigProperties_1.OrgConfigProperties.TARGET_DEV_HUB) ||
this.configAggregator.getPropertyValue(config_1.SfdxPropertyKeys.DEFAULT_DEV_HUB_USERNAME);
}
const devHubConnection = (await Org.create({ aliasOrUsername })).getConnection();
const thisOrgAuthConfig = this.getConnection().getAuthInfoFields();
const trimmedId = sfdc_1.sfdc.trimTo15(thisOrgAuthConfig.orgId);
const DEV_HUB_SOQL = `SELECT CreatedDate,Edition,ExpirationDate FROM ActiveScratchOrg WHERE ScratchOrg='${trimmedId}'`;
let results;
try {
results = await devHubConnection.query(DEV_HUB_SOQL);
}
catch (err) {
if (err.name === 'INVALID_TYPE') {
throw messages.createError('notADevHub', [devHubConnection.getUsername()]);
}
throw err;
}
if (ts_types_1.getNumber(results, 'records.length') !== 1) {
throw new sfdxError_1.SfdxError('No results', 'NoResultsError');
}
return thisOrgAuthConfig;
}
/**
* Returns the Org object or null if this org is not affiliated with a Dev Hub (according to the local config).
*/
async getDevHubOrg() {
if (this.isDevHubOrg()) {
return this;
}
else if (this.getField(Org.Fields.DEV_HUB_USERNAME)) {
const devHubUsername = ts_types_1.ensureString(this.getField(Org.Fields.DEV_HUB_USERNAME));
return Org.create({
connection: await connection_1.Connection.create({
authInfo: await authInfo_1.AuthInfo.create({ username: devHubUsername }),
}),
});
}
}
/**
* Returns `true` if the org is a Dev Hub.
*
* **Note** This relies on a cached value in the auth file. If that property
* is not cached, this method will **always return false even if the org is a
* dev hub**. If you need accuracy, use the {@link Org.determineIfDevHubOrg} method.
*/
isDevHubOrg() {
const isDevHub = this.getField(Org.Fields.IS_DEV_HUB);
if (ts_types_1.isBoolean(isDevHub)) {
return isDevHub;
}
else {
return false;
}
}
/**
* Returns `true` if the org is a Dev Hub.
*
* Use a cached value. If the cached value is not set, then check access to the
* ScratchOrgInfo object to determine if the org is a dev hub.
*
* @param forceServerCheck Ignore the cached value and go straight to the server
* which will be required if the org flips on the dev hub after the value is already
* cached locally.
*/
async determineIfDevHubOrg(forceServerCheck = false) {
const cachedIsDevHub = this.getField(Org.Fields.IS_DEV_HUB);
if (!forceServerCheck && ts_types_1.isBoolean(cachedIsDevHub)) {
return cachedIsDevHub;
}
if (this.isDevHubOrg()) {
return true;
}
this.logger.debug('isDevHub is not cached - querying server...');
const conn = this.getConnection();
let isDevHub = false;
try {
await conn.query('SELECT Id FROM ScratchOrgInfo limit 1');
isDevHub = true;
}
catch (err) {
/* Not a dev hub */
}
const username = ts_types_1.ensure(this.getUsername());
const authInfo = await authInfo_1.AuthInfo.create({ username });
await authInfo.save({ isDevHub });
// Reset the connection with the updated auth file
this.connection = await connection_1.Connection.create({ authInfo });
return isDevHub;
}
/**
* Returns `true` if the org is a scratch org.
*
* **Note** This relies on a cached value in the auth file. If that property
* is not cached, this method will **always return false even if the org is a
* scratch org**. If you need accuracy, use the {@link Org.determineIfScratch} method.
*/
isScratch() {
const isScratch = this.getField(Org.Fields.IS_SCRATCH);
if (ts_types_1.isBoolean(isScratch)) {
return isScratch;
}
else {
return false;
}
}
/**
* Returns `true` if the org is a scratch org.
*
* Use a cached value. If the cached value is not set, then check
* `Organization.IsSandbox == true && Organization.TrialExpirationDate != null`
* using {@link Org.retrieveOrganizationInformation}.
*/
async determineIfScratch() {
let cache = this.getField(Org.Fields.IS_SCRATCH);
if (!cache) {
await this.updateLocalInformation();
cache = this.getField(Org.Fields.IS_SCRATCH);
}
return cache;
}
/**
* Returns `true` if the org is a sandbox.
*
* **Note** This relies on a cached value in the auth file. If that property
* is not cached, this method will **always return false even if the org is a
* sandbox**. If you need accuracy, use the {@link Org.determineIfDevHubOrg} method.
*/
isSandbox() {
const isSandbox = this.getField(Org.Fields.IS_SANDBOX);
if (ts_types_1.isBoolean(isSandbox)) {
return isSandbox;
}
else {
return false;
}
}
/**
* Returns `true` if the org is a sandbox.
*
* Use a cached value. If the cached value is not set, then check
* `Organization.IsSandbox == true && Organization.TrialExpirationDate == null`
* using {@link Org.retrieveOrganizationInformation}.
*/
async determineIfSandbox() {
let cache = this.getField(Org.Fields.IS_SANDBOX);
if (!cache) {
await this.updateLocalInformation();
cache = this.getField(Org.Fields.IS_SANDBOX);
}
return cache;
}
/**
* Retrieve a handful of fields from the Organization table in Salesforce. If this does not have the
* data you need, just use {@link Connection.singleRecordQuery} with `SELECT <needed fields> FROM Organization`.
*
* @returns org information
*/
async retrieveOrganizationInformation() {
return this.getConnection().singleRecordQuery('SELECT Name, InstanceName, IsSandbox, TrialExpirationDate, NamespacePrefix FROM Organization');
}
/**
* Some organization information is locally cached, such as if the org name or if it is a scratch org.
* This method populates/updates the filesystem from information retrieved from the org.
*/
async updateLocalInformation() {
const username = this.getUsername();
if (username) {
const organization = await this.retrieveOrganizationInformation();
const isScratch = organization.IsSandbox && organization.TrialExpirationDate;
const isSandbox = organization.IsSandbox && !organization.TrialExpirationDate;
const info = await globalInfoConfig_1.GlobalInfo.getInstance();
info.updateOrg(username, {
[Org.Fields.NAME]: organization.Name,
[Org.Fields.INSTANCE_NAME]: organization.InstanceName,
[Org.Fields.NAMESPACE_PREFIX]: organization.NamespacePrefix,
[Org.Fields.IS_SANDBOX]: isSandbox,
[Org.Fields.IS_SCRATCH]: isScratch,
[Org.Fields.TRIAL_EXPIRATION_DATE]: organization.TrialExpirationDate,
});
await info.write();
}
}
/**
* Refreshes the auth for this org's instance by calling HTTP GET on the baseUrl of the connection object.
*/
async refreshAuth() {
this.logger.debug('Refreshing auth for org.');
const requestInfo = {
url: this.getConnection().baseUrl(),
method: 'GET',
};
const conn = this.getConnection();
await conn.request(requestInfo);
}
/**
* Reads and returns the content of all user auth files for this org as an array.
*/
async readUserAuthFiles() {
const config = await this.retrieveOrgUsersConfig();
const contents = await config.read();
const thisUsername = ts_types_1.ensure(this.getUsername());
const usernames = ts_types_1.ensureJsonArray(contents.usernames || [thisUsername]);
return Promise.all(usernames.map((username) => {
if (username === thisUsername) {
return authInfo_1.AuthInfo.create({
username: this.getConnection().getUsername(),
});
}
else {
return authInfo_1.AuthInfo.create({ username: ts_types_1.ensureString(username) });
}
}));
}
/**
* Adds a username to the user config for this org. For convenience `this` object is returned.
*
* ```
* const org: Org = await Org.create({
* connection: await Connection.create({
* authInfo: await AuthInfo.create('foo@example.com')
* })
* });
* const userAuth: AuthInfo = await AuthInfo.create({
* username: 'bar@example.com'
* });
* await org.addUsername(userAuth);
* ```
*
* @param {AuthInfo | string} auth The AuthInfo for the username to add.
*/
async addUsername(auth) {
if (!auth) {
throw new sfdxError_1.SfdxError('Missing auth info', 'MissingAuthInfo');
}
const authInfo = ts_types_1.isString(auth) ? await authInfo_1.AuthInfo.create({ username: auth }) : auth;
this.logger.debug(`adding username ${authInfo.getFields().username}`);
const orgConfig = await this.retrieveOrgUsersConfig();
const contents = await orgConfig.read();
// TODO: This is kind of screwy because contents values can be `AnyJson | object`...
// needs config refactoring to improve
const usernames = contents.usernames || [];
if (!ts_types_1.isArray(usernames)) {
throw new sfdxError_1.SfdxError('Usernames is not an array', 'UnexpectedDataFormat');
}
let shouldUpdate = false;
const thisUsername = ts_types_1.ensure(this.getUsername());
if (!usernames.includes(thisUsername)) {
usernames.push(thisUsername);
shouldUpdate = true;
}
const username = authInfo.getFields().username;
if (username) {
usernames.push(username);
shouldUpdate = true;
}
if (shouldUpdate) {
orgConfig.set('usernames', usernames);
await orgConfig.write();
}
return this;
}
/**
* Removes a username from the user config for this object. For convenience `this` object is returned.
*
* **Throws** *{@link SfdxError}{ name: 'MissingAuthInfoError' }* Auth info is missing.
*
* @param {AuthInfo | string} auth The AuthInfo containing the username to remove.
*/
async removeUsername(auth) {
if (!auth) {
throw new sfdxError_1.SfdxError('Missing auth info', 'MissingAuthInfoError');
}
const authInfo = ts_types_1.isString(auth) ? await authInfo_1.AuthInfo.create({ username: auth }) : auth;
this.logger.debug(`removing username ${authInfo.getFields().username}`);
const orgConfig = await this.retrieveOrgUsersConfig();
const contents = await orgConfig.read();
const targetUser = authInfo.getFields().username;
const usernames = (contents.usernames || []);
contents.usernames = usernames.filter((username) => username !== targetUser);
await orgConfig.write();
return this;
}
/**
* Sets the key/value pair in the sandbox config for this org. For convenience `this` object is returned.
*
*
* @param {key} The key for this value
* @param {value} The value to save
*/
async setSandboxOrgConfigField(field, value) {
const sandboxOrgConfig = await this.retrieveSandboxOrgConfig();
sandboxOrgConfig.set(field, value);
await sandboxOrgConfig.write();
return this;
}
/**
* Returns an org config field. Returns undefined if the field is not set or invalid.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async getSandboxOrgConfigField(field) {
const sandboxOrgConfig = await this.retrieveSandboxOrgConfig();
return sandboxOrgConfig.get(field);
}
/**
* Retrieves the highest api version that is supported by the target server instance. If the apiVersion configured for
* Sfdx is greater than the one returned in this call an api version mismatch occurs. In the case of the CLI that
* results in a warning.
*/
async retrieveMaxApiVersion() {
return await this.getConnection().retrieveMaxApiVersion();
}
/**
* Returns the admin username used to create the org.
*/
getUsername() {
return this.getConnection().getUsername();
}
/**
* Returns the orgId for this org.
*/
getOrgId() {
return this.orgId || this.getField(Org.Fields.ORG_ID);
}
/**
* Returns for the config aggregator.
*/
getConfigAggregator() {
return this.configAggregator;
}
/**
* Returns an org field. Returns undefined if the field is not set or invalid.
*/
getField(key) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore Legacy. We really shouldn't be doing this.
const ownProp = this[key];
if (ownProp && typeof ownProp !== 'function')
return ownProp;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return this.getConnection().getAuthInfoFields()[key];
}
/**
* Returns a map of requested fields.
*/
getFields(keys) {
const json = {};
return keys.reduce((map, key) => {
map[key] = this.getField(key);
return map;
}, json);
}
/**
* Returns the JSForce connection for the org.
*/
getConnection() {
return this.connection;
}
/**
* Initialize async components.
*/
async init() {
this.logger = await logger_1.Logger.child('Org');
this.configAggregator = this.options.aggregator ? this.options.aggregator : await configAggregator_1.ConfigAggregator.create();
if (!this.options.connection) {
if (this.options.aliasOrUsername == null) {
this.configAggregator = this.getConfigAggregator();
const aliasOrUsername = this.options.isDevHub
? this.configAggregator.getPropertyValue(orgConfigProperties_1.OrgConfigProperties.TARGET_DEV_HUB) ||
// Fall back to old sfdx key
this.configAggregator.getPropertyValue(config_1.SfdxPropertyKeys.DEFAULT_DEV_HUB_USERNAME)
: this.configAggregator.getPropertyValue(orgConfigProperties_1.OrgConfigProperties.TARGET_ORG) ||
// Fall back to old sfdx key
this.configAggregator.getPropertyValue(config_1.SfdxPropertyKeys.DEFAULT_USERNAME);
this.options.aliasOrUsername = aliasOrUsername || undefined;
}
const username = this.options.aliasOrUsername;
this.connection = await connection_1.Connection.create({
// If no username is provided or resolvable from an alias, AuthInfo will throw an SfdxError.
authInfo: await authInfo_1.AuthInfo.create({
username: (username != null && (await aliases_1.Aliases.fetch(username))) || username,
}),
});
}
else {
this.connection = this.options.connection;
}
this.orgId = this.getField(Org.Fields.ORG_ID);
}
/**
* **Throws** *{@link SfdxError}{ name: 'NotSupportedError' }* Throws an unsupported error.
*/
getDefaultOptions() {
throw new sfdxError_1.SfdxError('Not Supported', 'NotSupportedError');
}
/**
* Delete an auth info file from the local file system and any related cache information for
* this Org. You don't want to call this method directly. Instead consider calling Org.remove()
*/
async removeAuth() {
const config = await globalInfoConfig_1.GlobalInfo.getInstance();
const username = this.getUsername();
// If there is no username, it has already been removed from the globalInfo.
// We can skip the unset and just ensure that globalInfo is updated.
if (username) {
this.logger.debug(`Removing auth for user: ${username}`);
this.logger.debug(`Clearing auth cache for user: ${username}`);
config.unsetOrg(username);
}
await config.write();
}
/**
* Deletes the users config file
*/
async removeUsersConfig() {
const config = await this.retrieveOrgUsersConfig();
if (await config.exists()) {
this.logger.debug(`Removing org users config at: ${config.getPath()}`);
await config.unlink();
}
}
/**
* @ignore
*/
async retrieveSandboxOrgConfig() {
return await sandboxOrgConfig_1.SandboxOrgConfig.create(sandboxOrgConfig_1.SandboxOrgConfig.getOptions(this.getOrgId()));
}
manageDelete(cb, dirPath, throwWhenRemoveFails) {
return cb().catch((e) => {
if (throwWhenRemoveFails) {
throw e;
}
else {
this.logger.warn(`failed to read directory ${dirPath}`);
return;
}
});
}
/**
* Remove the org users auth file.
*
* @param throwWhenRemoveFails true if manageDelete should throw or not if the deleted fails.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async removeUsers(throwWhenRemoveFails) {
this.logger.debug(`Removing users associate with org: ${this.getOrgId()}`);
const config = await this.retrieveOrgUsersConfig();
this.logger.debug(`using path for org users: ${config.getPath()}`);
if (await config.exists()) {
const authInfos = await this.readUserAuthFiles();
const aliases = await aliases_1.Aliases.create(aliases_1.Aliases.getDefaultOptions());
this.logger.info(`Cleaning up usernames in org: ${this.getOrgId()}`);
for (const auth of authInfos) {
const username = auth.getFields().username;
const aliasKeys = (username && aliases.getKeysByValue(username)) || [];
aliases.unsetAll(aliasKeys);
let orgForUser;
if (username === this.getUsername()) {
orgForUser = this;
}
else {
const info = await authInfo_1.AuthInfo.create({ username });
const connection = await connection_1.Connection.create({ authInfo: info });
orgForUser = await Org.create({ connection });
}
const removeConfig = async (configInfo) => {
if ((configInfo.value === username || aliasKeys.includes(configInfo.value)) &&
(configInfo.isGlobal() || configInfo.isLocal())) {
await config_1.Config.update(configInfo.isGlobal(), configInfo.key, undefined);
}
};
await removeConfig(this.configAggregator.getInfo(config_1.SfdxPropertyKeys.DEFAULT_DEV_HUB_USERNAME));
await removeConfig(this.configAggregator.getInfo(config_1.SfdxPropertyKeys.DEFAULT_USERNAME));
await removeConfig(this.configAggregator.getInfo(orgConfigProperties_1.OrgConfigProperties.TARGET_DEV_HUB));
await removeConfig(this.configAggregator.getInfo(orgConfigProperties_1.OrgConfigProperties.TARGET_ORG));
await orgForUser.removeAuth();
}
await aliases.write();
}
}
/**
* Remove an associate sandbox config.
*
* @param throwWhenRemoveFails true if manageDelete should throw or not if the deleted fails.
*/
async removeSandboxConfig(throwWhenRemoveFails) {
const sandboxOrgConfig = await this.retrieveSandboxOrgConfig();
if (await sandboxOrgConfig.exists()) {
await this.manageDelete(async () => await sandboxOrgConfig.unlink(), sandboxOrgConfig.getPath(), throwWhenRemoveFails);
}
}
}
exports.Org = Org;
(function (Org) {
/**
* Scratch Org status.
*/
let Status;
(function (Status) {
/**
* The scratch org is active.
*/
Status["ACTIVE"] = "ACTIVE";
/**
* The scratch org has expired.
*/
Status["EXPIRED"] = "EXPIRED";
/**
* The org is a scratch Org but no dev hub is indicated.
*/
Status["UNKNOWN"] = "UNKNOWN";
/**
* The dev hub configuration is reporting an active Scratch org but the AuthInfo cannot be found.
*/
Status["MISSING"] = "MISSING";
})(Status = Org.Status || (Org.Status = {}));
/**
* Org Fields.
*/
// A subset of fields from AuthInfoFields and properties that are specific to Org,
// and properties that are defined on Org itself.
let Fields;
(function (Fields) {
/**
* The org alias.
*/
// From AuthInfo
Fields["ALIAS"] = "alias";
Fields["CREATED"] = "created";
// From Organization
Fields["NAME"] = "name";
Fields["NAMESPACE_PREFIX"] = "namespacePrefix";
Fields["INSTANCE_NAME"] = "instanceName";
Fields["TRIAL_EXPIRATION_DATE"] = "trailExpirationDate";
/**
* The Salesforce instance the org was created on. e.g. `cs42`.
*/
Fields["CREATED_ORG_INSTANCE"] = "createdOrgInstance";
/**
* The username of the dev hub org that created this org. Only populated for scratch orgs.
*/
Fields["DEV_HUB_USERNAME"] = "devHubUsername";
/**
* The full url of the instance the org lives on.
*/
Fields["INSTANCE_URL"] = "instanceUrl";
/**
* Is the current org a dev hub org. e.g. They have access to the `ScratchOrgInfo` object.
*/
Fields["IS_DEV_HUB"] = "isDevHub";
/**
* Is the current org a scratch org. e.g. Organization has IsSandbox == true and TrialExpirationDate != null.
*/
Fields["IS_SCRATCH"] = "isScratch";
/**
* Is the current org a dev hub org. e.g. Organization has IsSandbox == true and TrialExpirationDate == null.
*/
Fields["IS_SANDBOX"] = "isSandbox";
/**
* The login url of the org. e.g. `https://login.salesforce.com` or `https://test.salesforce.com`.
*/
Fields["LOGIN_URL"] = "loginUrl";
/**
* The org ID.
*/
Fields["ORG_ID"] = "orgId";
/**
* The `OrgStatus` of the org.
*/
Fields["STATUS"] = "status";
/**
* The snapshot used to create the scratch org.
*/
Fields["SNAPSHOT"] = "snapshot";
// Should it be on org? Leave it off for now, as it might
// be confusing to the consumer what this actually is.
// USERNAMES = 'usernames',
// Keep separation of concerns. I think these should be on a "user" that belongs to the org.
// Org can have a list of user objects that belong to it? Should connection be on user and org.getConnection()
// gets the orgs current user for the process? Maybe we just want to keep with the Org only model for
// the end of time?
// USER_ID = 'userId',
// USERNAME = 'username',
// PASSWORD = 'password',
// USER_PROFILE_NAME = 'userProfileName'
})(Fields = Org.Fields || (Org.Fields = {}));
})(Org = exports.Org || (exports.Org = {}));
//# sourceMappingURL=org.js.map