UNPKG

@salesforce/core

Version:

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

248 lines 12.5 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.scratchOrgCreate = exports.scratchOrgResume = exports.DEFAULT_STREAM_TIMEOUT_MINUTES = void 0; /* * 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 */ const kit_1 = require("@salesforce/kit"); const ts_types_1 = require("@salesforce/ts-types"); const messages_1 = require("../messages"); const logger_1 = require("../logger/logger"); const configAggregator_1 = require("../config/configAggregator"); const orgConfigProperties_1 = require("../org/orgConfigProperties"); const sfProject_1 = require("../sfProject"); const stateAggregator_1 = require("../stateAggregator/stateAggregator"); const sfError_1 = require("../sfError"); const org_1 = require("./org"); const scratchOrgInfoApi_1 = require("./scratchOrgInfoApi"); const scratchOrgSettingsGenerator_1 = __importDefault(require("./scratchOrgSettingsGenerator")); const scratchOrgInfoGenerator_1 = require("./scratchOrgInfoGenerator"); const authInfo_1 = require("./authInfo"); const scratchOrgLifecycleEvents_1 = require("./scratchOrgLifecycleEvents"); const scratchOrgCache_1 = require("./scratchOrgCache"); const scratchOrgErrorCodes_1 = require("./scratchOrgErrorCodes"); ; const messages = new messages_1.Messages('@salesforce/core', 'scratchOrgCreate', new Map([["UnsupportedSnapshotOrgCreateOptionsError", "Org snapshots don\u2019t support one or more options you specified: %s."], ["DurationDaysValidationMinError", "Expected 'durationDays' greater than or equal to %s but received %s."], ["DurationDaysValidationMaxError", "Expected 'durationDays' less than or equal to %s but received %s."], ["DurationDaysNotIntError", "Expected 'durationDays' to be an integer number."], ["RetryNotIntError", "Expected 'retry' to be an integer number."], ["CacheMissError", "The ScratchOrgInfoId %s was not found in the cache."]])); exports.DEFAULT_STREAM_TIMEOUT_MINUTES = 6; const validateDuration = (durationDays) => { const min = 1; const max = 30; if (Number.isInteger(durationDays)) { if (durationDays < min) { throw messages.createError('DurationDaysValidationMinError', [min, durationDays]); } if (durationDays > max) { throw messages.createError('DurationDaysValidationMaxError', [max, durationDays]); } return; } throw messages.createError('DurationDaysNotIntError'); }; const validateRetry = (retry) => { if (!Number.isInteger(retry)) { throw messages.createError('RetryNotIntError'); } }; const scratchOrgResume = async (jobId, timeout = kit_1.Duration.minutes(15)) => { const [logger, cache] = await Promise.all([ logger_1.Logger.child('scratchOrgResume'), scratchOrgCache_1.ScratchOrgCache.create(), (0, scratchOrgLifecycleEvents_1.emit)({ stage: 'send request' }), ]); logger.debug(`resuming scratch org creation for jobId: ${jobId}`); const cached = cache.get(jobId, true); if (!cached) { throw messages.createError('CacheMissError', [jobId]); } const { hubUsername, apiVersion, clientSecret, signupTargetLoginUrlConfig, definitionjson, alias, setDefault, tracksSource, } = cached; const signupTargetLoginUrl = signupTargetLoginUrlConfig ?? (await getSignupTargetLoginUrl()); if (signupTargetLoginUrl) { logger.debug(`resuming org create with LoginUrl override= ${signupTargetLoginUrl}`); } const hubOrg = await org_1.Org.create({ aliasOrUsername: hubUsername }); const soi = await (0, scratchOrgErrorCodes_1.validateScratchOrgInfoForResume)({ jobId, hubOrg, cache, hubUsername, timeout }); // At this point, the scratch org is "good". // Some hubs have all the usernames set to `null` const username = soi.Username ?? soi.SignupUsername; // re-auth only if the org isn't in StateAggregator const stateAggregator = await stateAggregator_1.StateAggregator.getInstance(); const scratchOrgAuthInfo = (await stateAggregator.orgs.exists(username)) ? await authInfo_1.AuthInfo.create({ username }) : await (0, scratchOrgInfoApi_1.authorizeScratchOrg)({ scratchOrgInfoComplete: soi, hubOrg, clientSecret, signupTargetLoginUrl, retry: 0, }); await setExitCodeIfError(68)(scratchOrgAuthInfo.handleAliasAndDefaultSettings({ alias, setDefault: setDefault ?? false, setDefaultDevHub: false, setTracksSource: tracksSource ?? true, })); const scratchOrg = await org_1.Org.create({ aliasOrUsername: username }); const configAggregator = await configAggregator_1.ConfigAggregator.create(); await (0, scratchOrgLifecycleEvents_1.emit)({ stage: 'deploy settings', scratchOrgInfo: soi }); const capitalizeRecordTypes = await getCapitalizeRecordTypesConfig(); const settingsGenerator = new scratchOrgSettingsGenerator_1.default({ capitalizeRecordTypes, }); await settingsGenerator.extract({ ...soi, ...definitionjson }); const [authInfo] = await setExitCodeIfError(68)(Promise.all([ (0, scratchOrgInfoApi_1.resolveUrl)(scratchOrgAuthInfo), (0, scratchOrgInfoApi_1.deploySettings)(scratchOrg, settingsGenerator, apiVersion ?? configAggregator.getPropertyValue(orgConfigProperties_1.OrgConfigProperties.ORG_API_VERSION) ?? (await scratchOrg.retrieveMaxApiVersion())), ])); cache.unset(soi.Id ?? jobId); const authFields = authInfo.getFields(); await Promise.all([(0, scratchOrgLifecycleEvents_1.emit)({ stage: 'done', scratchOrgInfo: soi }), cache.write(), (0, scratchOrgLifecycleEvents_1.emitPostOrgCreate)(authFields)]); return { username, scratchOrgInfo: soi, authInfo, authFields, warnings: [], }; }; exports.scratchOrgResume = scratchOrgResume; const scratchOrgCreate = async (options) => { const logger = await logger_1.Logger.child('scratchOrgCreate'); /** epoch milliseconds */ const startTimestamp = Date.now(); logger.debug('preparing scratch org signup request...'); await (0, scratchOrgLifecycleEvents_1.emit)({ stage: 'prepare request' }); const { hubOrg, connectedAppConsumerKey, durationDays = 1, nonamespace, noancestors, wait = kit_1.Duration.minutes(exports.DEFAULT_STREAM_TIMEOUT_MINUTES), retry = 0, apiversion, definitionjson, definitionfile, orgConfig, clientSecret = undefined, alias, setDefault = false, tracksSource = true, } = options; validateDuration(durationDays); validateRetry(retry); const { scratchOrgInfoPayload, ignoreAncestorIds, warnings } = await (0, scratchOrgInfoGenerator_1.getScratchOrgInfoPayload)({ definitionjson, definitionfile, connectedAppConsumerKey, durationDays, nonamespace, noancestors, orgConfig, }); const scratchOrgInfo = await (0, scratchOrgInfoGenerator_1.generateScratchOrgInfo)({ hubOrg, scratchOrgInfoPayload, nonamespace, ignoreAncestorIds, }); const capitalizeRecordTypes = await getCapitalizeRecordTypesConfig(); // gets the scratch org settings (will use in both signup paths AND to deploy the settings) const settingsGenerator = new scratchOrgSettingsGenerator_1.default({ capitalizeRecordTypes, }); const settings = await settingsGenerator.extract(scratchOrgInfo); logger.debug(`the scratch org def file has settings: ${settingsGenerator.hasSettings()}`); const [scratchOrgInfoRequestResult, signupTargetLoginUrl] = await Promise.all([ // creates the scratch org info in the devhub (0, scratchOrgInfoApi_1.requestScratchOrgCreation)(hubOrg, scratchOrgInfo, settingsGenerator), getSignupTargetLoginUrl(), ]); const scratchOrgInfoId = (0, ts_types_1.ensureString)(scratchOrgInfoRequestResult.id); const cache = await scratchOrgCache_1.ScratchOrgCache.create(); cache.set(scratchOrgInfoId, { hubUsername: hubOrg.getUsername(), hubBaseUrl: hubOrg.getField(org_1.Org.Fields.INSTANCE_URL)?.toString(), // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment definitionjson: { ...(definitionjson ? JSON.parse(definitionjson) : {}), ...orgConfig, ...settings }, clientSecret, alias, setDefault, tracksSource, }); await cache.write(); logger.debug(`scratch org has recordId ${scratchOrgInfoId}`); // this is where we stop--no polling if (wait.minutes === 0) { const soi = await (0, scratchOrgInfoApi_1.queryScratchOrgInfo)(hubOrg, scratchOrgInfoId); return { username: soi.SignupUsername, warnings: [], scratchOrgInfo: soi, }; } const soi = await (0, scratchOrgInfoApi_1.pollForScratchOrgInfo)(hubOrg, scratchOrgInfoId, wait); const scratchOrgAuthInfo = await (0, scratchOrgInfoApi_1.authorizeScratchOrg)({ scratchOrgInfoComplete: soi, hubOrg, clientSecret, signupTargetLoginUrl, retry: retry || 0, }); // anything after this point (org is created and auth'd) is potentially recoverable with the resume scratch command. await setExitCodeIfError(68)(scratchOrgAuthInfo.handleAliasAndDefaultSettings({ ...{ alias, setDefault, setDefaultDevHub: false, setTracksSource: tracksSource === false ? false : true, }, })); // we'll need this scratch org connection later; const scratchOrg = await org_1.Org.create({ aliasOrUsername: soi.Username ?? soi.SignupUsername }); const username = scratchOrg.getUsername(); logger.debug(`scratch org username ${username}`); await (0, scratchOrgLifecycleEvents_1.emit)({ stage: 'deploy settings', scratchOrgInfo: soi }); const configAggregator = await configAggregator_1.ConfigAggregator.create(); const [authInfo] = await setExitCodeIfError(68)(Promise.all([ (0, scratchOrgInfoApi_1.resolveUrl)(scratchOrgAuthInfo), (0, scratchOrgInfoApi_1.deploySettings)(scratchOrg, settingsGenerator, apiversion ?? configAggregator.getPropertyValue(orgConfigProperties_1.OrgConfigProperties.ORG_API_VERSION) ?? (await scratchOrg.retrieveMaxApiVersion()), // some of our "wait" time has already been used. Calculate how much remains that we can spend on the deployment. kit_1.Duration.milliseconds(wait.milliseconds - (Date.now() - startTimestamp))), ])); cache.unset(scratchOrgInfoId); const authFields = authInfo.getFields(); await Promise.all([(0, scratchOrgLifecycleEvents_1.emit)({ stage: 'done', scratchOrgInfo: soi }), cache.write(), (0, scratchOrgLifecycleEvents_1.emitPostOrgCreate)(authFields)]); return { username, scratchOrgInfo: soi, authInfo, authFields: authInfo?.getFields(), warnings, }; }; exports.scratchOrgCreate = scratchOrgCreate; const getSignupTargetLoginUrl = async () => { try { const project = await sfProject_1.SfProject.resolve(); const projectJson = await project.resolveProjectConfig(); const signupTargetLoginUrl = projectJson.signupTargetLoginUrl; if (signupTargetLoginUrl) { logger_1.Logger.childFromRoot('getSignupTargetLoginUrl').debug(`Found signupTargetLoginUrl in project file: ${signupTargetLoginUrl}`); return signupTargetLoginUrl; } } catch { // a project isn't required for org:create } }; async function getCapitalizeRecordTypesConfig() { const configAgg = await configAggregator_1.ConfigAggregator.create(); const value = configAgg.getInfo('org-capitalize-record-types').value; return value !== undefined ? (0, kit_1.toBoolean)(value) : undefined; } /** wrap an async function, intercept error and set the given exit code */ const setExitCodeIfError = (exitCode) => async (p) => { try { return await p; } catch (e) { const sfError = sfError_1.SfError.wrap(e); sfError.exitCode = exitCode; throw sfError; } }; //# sourceMappingURL=scratchOrgCreate.js.map