UNPKG

salesforce-alm

Version:

This package contains tools, and APIs, for an improved salesforce.com developer experience.

200 lines (198 loc) 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 }); // Local const core_1 = require("@salesforce/core"); const almError = require("../core/almError"); const messages = require("../messages"); const srcDevUtil = require("../core/srcDevUtil"); const logApi = require("../core/logApi"); const remoteSourceTrackingService_1 = require("../source/remoteSourceTrackingService"); const scratchOrgInfoApi_1 = require("./scratchOrgInfoApi"); const SettingsGenerator = require("./scratchOrgSettingsGenerator"); const scratchOrgInfoGenerator_1 = require("./scratchOrgInfoGenerator"); const scratchOrgFeatureDeprecation_1 = require("./scratchOrgFeatureDeprecation"); // A validator function to ensure any options parameters entered by the user adhere // to a allowlist of valid option settings. Because org:create allows options to be // input either key=value pairs or within the definition file, this validator is // executed within the ctor and also after parsing/normalization of the definition file. const optionsValidator = (key, value, scratchOrgInfoPayload) => { if (key.toLowerCase() === 'durationdays') { throw almError('unrecognizedScratchOrgOption', 'durationDays'); } if (key.toLowerCase() === 'snapshot') { const foundInvalidFields = []; ScratchOrgCreateCommand.SNAPSHOT_UNSUPPORTED_OPTIONS.forEach((invalidField) => { if (scratchOrgInfoPayload.hasOwnProperty(invalidField)) { foundInvalidFields.push(invalidField); } }); if (foundInvalidFields.length > 0) { const msg = messages().getMessage('unsupportedSnapshotOrgCreateOptions', [foundInvalidFields.join(', ')], 'orgSnapshot'); throw new Error(msg); } } }; /** * constructs a create command helper * * @param force - the force api * @constructor */ class ScratchOrgCreateCommand { constructor(hubOrg, flags, varargs, configAggregator) { this.hubOrg = hubOrg; this.flags = flags; this.varargs = varargs; this.configAggregator = configAggregator; this.settingsGenerator = new SettingsGenerator(); } /** * executes the command. this is a protocol style function intended to be represented by other commands. * * @param cliContext - the cli context * @param stdinValues - param values obtained from stdin * @returns {Promise} */ async execute(clientSecret) { var _a, _b; this.logger = await core_1.Logger.child('scratchOrgCreateCommand'); this.logger.debug('scratchOrgCreateCommand: execute'); this.scratchOrgInfo = await this.getScratchOrgInfo(); // gets the scratch org settings (will use in both signup paths AND to deploy the settings) await this.settingsGenerator.extract(this.scratchOrgInfo); this.logger.debug(`the scratch org def file has settings: ${this.settingsGenerator.hasSettings()}`); // creates the scratch org info in the devhub const scratchOrgInfoRequestResult = await scratchOrgInfoApi_1.requestScratchOrgCreation(this.hubOrg, this.scratchOrgInfo, this.settingsGenerator); if (scratchOrgInfoRequestResult.success === true) { this.scratchOrgInfoId = scratchOrgInfoRequestResult.id; this.logger.debug(`scratch org has recordId ${this.scratchOrgInfoId}`); } const scratchOrgInfoResult = await scratchOrgInfoApi_1.pollForScratchOrgInfo(this.hubOrg, this.scratchOrgInfoId, this.flags.wait); let signupTargetLoginUrlConfig; try { const project = await core_1.SfdxProject.resolve(); const projectJson = await project.resolveProjectConfig(); signupTargetLoginUrlConfig = projectJson.signupTargetLoginUrl; } catch { // a project isn't required for org:create } const scratchOrgAuthInfo = await scratchOrgInfoApi_1.authorizeScratchOrg({ scratchOrgInfoComplete: scratchOrgInfoResult, hubOrg: this.hubOrg, clientSecret, setAsDefault: this.flags.setdefaultusername, alias: this.flags.setalias, signupTargetLoginUrlConfig, retry: this.flags.retry || 0, }); // we'll need this scratch org connection later; this.scratchOrg = await core_1.Org.create({ connection: await core_1.Connection.create({ authInfo: scratchOrgAuthInfo }) }); const orgData = await scratchOrgInfoApi_1.deploySettingsAndResolveUrl(scratchOrgAuthInfo, (_b = (_a = this.flags.apiversion) !== null && _a !== void 0 ? _a : this.configAggregator.getPropertyValue('apiVersion')) !== null && _b !== void 0 ? _b : (await this.scratchOrg.retrieveMaxApiVersion()), this.settingsGenerator); this.logger.trace('Settings deployed to org'); /** updating the revision num to zero during org:creation if source members are created during org:create.This only happens for some specific scratch org definition file.*/ await this.updateRevisionCounterToZero(); // initialize the maxRevision.json file. try { await remoteSourceTrackingService_1.RemoteSourceTrackingService.getInstance({ username: this.scratchOrg.getUsername() }); } catch (err) { // Do nothing. If org:create is not executed within sfdx project, allow the org to be created without errors. this.logger.debug(`Failed to create the maxRevision.json file due to the error : ${err.message}`); } // emit postorgcreate event for hook const postOrgCreateHookInfo = [orgData] .map((result) => result.getFields()) .map((element) => ({ accessToken: element.accessToken, clientId: element.clientId, created: element.created, createdOrgInstance: element.createdOrgInstance, devHubUsername: element.devHubUsername, expirationDate: element.expirationDate, instanceUrl: element.instanceUrl, loginUrl: element.loginUrl, orgId: element.orgId, username: element.username, }))[0]; await core_1.Lifecycle.getInstance().emit('postorgcreate', postOrgCreateHookInfo); return { orgId: orgData.getFields().orgId, username: this.scratchOrg.getUsername() }; } // Returns a valid signup json object async getScratchOrgInfo() { // Varargs input overrides definitionjson (-j option; hidden/deprecated) const definitionJson = this.flags.definitionjson ? JSON.parse(this.flags.definitionjson) : {}; const orgConfigInput = { ...definitionJson, ...(this.varargs || {}) }; let scratchOrgInfoPayload = orgConfigInput; // the -f option if (this.flags.definitionfile) { try { const defFileContents = (await core_1.fs.readJson(this.flags.definitionfile)); // definitionjson and varargs override file input scratchOrgInfoPayload = { ...defFileContents, ...orgConfigInput }; } catch (err) { const thrownErr = srcDevUtil.processReadAndParseJsonFileError(err, this.flags.definitionfile); throw thrownErr; } } // scratchOrgInfoPayload must be heads down camelcase. const upperCaseKey = core_1.sfdc.findUpperCaseKeys(scratchOrgInfoPayload); if (upperCaseKey) { throw almError('InvalidJsonCasing', [upperCaseKey, JSON.stringify(scratchOrgInfoPayload, null, 4)]); } // Now run the fully resolved user input against the validator Object.entries(scratchOrgInfoPayload).forEach(([key, value]) => { optionsValidator(key, value, scratchOrgInfoPayload); }); // the -i option if (this.flags.clientid) { scratchOrgInfoPayload.connectedAppConsumerKey = this.flags.clientid; } // the -d option scratchOrgInfoPayload.durationDays = this.flags.durationdays; // Ignore ancestor ids only when 'nonamespace' or 'noancestors' options are specified const ignoreAncestorIds = this.flags.nonamespace || this.flags.noancestors || false; // Throw warnings for deprecated scratch org features. const scratchOrgFeatureDeprecation = new scratchOrgFeatureDeprecation_1.ScratchOrgFeatureDeprecation(); scratchOrgFeatureDeprecation.getFeatureWarnings(scratchOrgInfoPayload.features).forEach((warning) => { logApi.warnUser(this.flags, warning); }); return scratchOrgInfoGenerator_1.generateScratchOrgInfo({ hubOrg: this.hubOrg, scratchOrgInfoPayload, nonamespace: this.flags.nonamespace, ignoreAncestorIds, }); } async updateRevisionCounterToZero() { const conn = this.scratchOrg.getConnection(); const queryResult = await conn.tooling.sobject('SourceMember').find({ RevisionCounter: { $gt: 0 } }, ['Id']); try { await conn.tooling .sobject('SourceMember') .update(queryResult.map((record) => ({ Id: record.Id, RevisionCounter: 0 }))); } catch (err) { const message = messages().getMessage('SourceStatusResetFailure', [this.scratchOrg.getOrgId(), this.scratchOrg.getUsername()], 'signup'); throw new core_1.SfdxError(message, 'SourceStatusResetFailure'); } } } exports.default = ScratchOrgCreateCommand; ScratchOrgCreateCommand.SNAPSHOT_UNSUPPORTED_OPTIONS = [ 'features', 'orgPreferences', 'edition', 'sourceOrg', 'settingsPath', 'releaseVersion', 'language', ]; //# sourceMappingURL=scratchOrgCreateCommand.js.map