@salesforce/core 3.31.4 → 3.31.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +11 -11
- package/README.md +222 -222
- package/lib/config/aliasesConfig.d.ts +12 -12
- package/lib/config/aliasesConfig.js +27 -27
- package/lib/config/authInfoConfig.d.ts +19 -19
- package/lib/config/authInfoConfig.js +34 -34
- package/lib/config/config.d.ts +311 -311
- package/lib/config/config.js +574 -574
- package/lib/config/configAggregator.d.ts +232 -232
- package/lib/config/configAggregator.js +379 -379
- package/lib/config/configFile.d.ts +199 -199
- package/lib/config/configFile.js +340 -340
- package/lib/config/configGroup.d.ts +141 -141
- package/lib/config/configGroup.js +224 -224
- package/lib/config/configStore.d.ts +241 -241
- package/lib/config/configStore.js +352 -352
- package/lib/config/envVars.d.ts +101 -101
- package/lib/config/envVars.js +456 -456
- package/lib/config/orgUsersConfig.d.ts +31 -31
- package/lib/config/orgUsersConfig.js +41 -41
- package/lib/config/sandboxOrgConfig.d.ts +37 -37
- package/lib/config/sandboxOrgConfig.js +50 -50
- package/lib/config/sandboxProcessCache.d.ts +16 -16
- package/lib/config/sandboxProcessCache.js +37 -37
- package/lib/config/tokensConfig.d.ts +10 -10
- package/lib/config/tokensConfig.js +28 -28
- package/lib/config/ttlConfig.d.ts +34 -34
- package/lib/config/ttlConfig.js +54 -54
- package/lib/crypto/crypto.d.ts +54 -54
- package/lib/crypto/crypto.js +220 -220
- package/lib/crypto/keyChain.d.ts +8 -8
- package/lib/crypto/keyChain.js +61 -61
- package/lib/crypto/keyChainImpl.d.ts +116 -116
- package/lib/crypto/keyChainImpl.js +486 -486
- package/lib/crypto/secureBuffer.d.ts +46 -46
- package/lib/crypto/secureBuffer.js +82 -82
- package/lib/deviceOauthService.d.ts +71 -71
- package/lib/deviceOauthService.js +191 -191
- package/lib/exported.d.ts +38 -38
- package/lib/exported.js +118 -118
- package/lib/global.d.ts +70 -70
- package/lib/global.js +109 -109
- package/lib/lifecycleEvents.d.ts +93 -93
- package/lib/lifecycleEvents.js +188 -188
- package/lib/logger.d.ts +381 -381
- package/lib/logger.js +734 -734
- package/lib/messages.d.ts +291 -291
- package/lib/messages.js +543 -543
- package/lib/org/authInfo.d.ts +344 -344
- package/lib/org/authInfo.js +892 -892
- package/lib/org/authRemover.d.ts +88 -88
- package/lib/org/authRemover.js +182 -182
- package/lib/org/connection.d.ts +197 -197
- package/lib/org/connection.js +395 -395
- package/lib/org/index.d.ts +6 -6
- package/lib/org/index.js +28 -28
- package/lib/org/org.d.ts +558 -558
- package/lib/org/org.js +1267 -1267
- package/lib/org/orgConfigProperties.d.ts +69 -69
- package/lib/org/orgConfigProperties.js +136 -136
- package/lib/org/permissionSetAssignment.d.ts +35 -35
- package/lib/org/permissionSetAssignment.js +125 -125
- package/lib/org/scratchOrgCache.d.ts +20 -20
- package/lib/org/scratchOrgCache.js +32 -32
- package/lib/org/scratchOrgCreate.d.ts +54 -54
- package/lib/org/scratchOrgCreate.js +216 -216
- package/lib/org/scratchOrgErrorCodes.d.ts +10 -10
- package/lib/org/scratchOrgErrorCodes.js +88 -88
- package/lib/org/scratchOrgFeatureDeprecation.d.ts +26 -26
- package/lib/org/scratchOrgFeatureDeprecation.js +109 -109
- package/lib/org/scratchOrgInfoApi.d.ts +68 -68
- package/lib/org/scratchOrgInfoApi.js +413 -413
- package/lib/org/scratchOrgInfoGenerator.d.ts +64 -64
- package/lib/org/scratchOrgInfoGenerator.js +241 -241
- package/lib/org/scratchOrgLifecycleEvents.d.ts +10 -10
- package/lib/org/scratchOrgLifecycleEvents.js +40 -40
- package/lib/org/scratchOrgSettingsGenerator.d.ts +78 -78
- package/lib/org/scratchOrgSettingsGenerator.js +276 -276
- package/lib/org/scratchOrgTypes.d.ts +43 -43
- package/lib/org/scratchOrgTypes.js +8 -8
- package/lib/org/user.d.ts +187 -187
- package/lib/org/user.js +448 -448
- package/lib/schema/printer.d.ts +79 -79
- package/lib/schema/printer.js +260 -260
- package/lib/schema/validator.d.ts +70 -70
- package/lib/schema/validator.js +169 -169
- package/lib/sfError.d.ts +73 -73
- package/lib/sfError.js +136 -136
- package/lib/sfProject.d.ts +357 -357
- package/lib/sfProject.js +671 -671
- package/lib/stateAggregator/accessors/aliasAccessor.d.ts +98 -98
- package/lib/stateAggregator/accessors/aliasAccessor.js +145 -145
- package/lib/stateAggregator/accessors/orgAccessor.d.ts +101 -101
- package/lib/stateAggregator/accessors/orgAccessor.js +240 -240
- package/lib/stateAggregator/accessors/sandboxAccessor.d.ts +8 -8
- package/lib/stateAggregator/accessors/sandboxAccessor.js +27 -27
- package/lib/stateAggregator/accessors/tokenAccessor.d.ts +63 -63
- package/lib/stateAggregator/accessors/tokenAccessor.js +79 -79
- package/lib/stateAggregator/index.d.ts +4 -4
- package/lib/stateAggregator/index.js +26 -26
- package/lib/stateAggregator/stateAggregator.d.ts +25 -25
- package/lib/stateAggregator/stateAggregator.js +45 -45
- package/lib/status/myDomainResolver.d.ts +66 -66
- package/lib/status/myDomainResolver.js +124 -124
- package/lib/status/pollingClient.d.ts +85 -85
- package/lib/status/pollingClient.js +115 -115
- package/lib/status/streamingClient.d.ts +244 -244
- package/lib/status/streamingClient.js +436 -436
- package/lib/status/types.d.ts +89 -89
- package/lib/status/types.js +17 -17
- package/lib/testSetup.d.ts +553 -553
- package/lib/testSetup.js +871 -871
- package/lib/util/cache.d.ts +11 -11
- package/lib/util/cache.js +69 -69
- package/lib/util/checkLightningDomain.d.ts +1 -1
- package/lib/util/checkLightningDomain.js +28 -28
- package/lib/util/directoryWriter.d.ts +12 -12
- package/lib/util/directoryWriter.js +53 -53
- package/lib/util/getJwtAudienceUrl.d.ts +4 -4
- package/lib/util/getJwtAudienceUrl.js +18 -18
- package/lib/util/internal.d.ts +58 -58
- package/lib/util/internal.js +118 -118
- package/lib/util/jsonXmlTools.d.ts +14 -14
- package/lib/util/jsonXmlTools.js +38 -38
- package/lib/util/mapKeys.d.ts +14 -14
- package/lib/util/mapKeys.js +51 -51
- package/lib/util/sfdc.d.ts +52 -52
- package/lib/util/sfdc.js +85 -85
- package/lib/util/sfdcUrl.d.ts +72 -72
- package/lib/util/sfdcUrl.js +215 -215
- package/lib/util/structuredWriter.d.ts +9 -9
- package/lib/util/structuredWriter.js +2 -2
- package/lib/util/zipWriter.d.ts +16 -16
- package/lib/util/zipWriter.js +67 -67
- package/lib/webOAuthServer.d.ts +156 -156
- package/lib/webOAuthServer.js +388 -388
- package/messages/auth.md +37 -37
- package/messages/config.md +156 -156
- package/messages/connection.md +30 -30
- package/messages/core.json +20 -20
- package/messages/core.md +67 -67
- package/messages/encryption.md +85 -85
- package/messages/envVars.md +303 -303
- package/messages/org.md +63 -63
- package/messages/permissionSetAssignment.md +31 -31
- package/messages/scratchOrgCreate.md +23 -23
- package/messages/scratchOrgErrorCodes.md +115 -115
- package/messages/scratchOrgFeatureDeprecation.md +11 -11
- package/messages/scratchOrgInfoApi.md +15 -15
- package/messages/scratchOrgInfoGenerator.md +23 -23
- package/messages/streaming.md +23 -23
- package/messages/user.md +35 -35
- package/package.json +97 -97
|
@@ -1,414 +1,414 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Copyright (c) 2021, salesforce.com, inc.
|
|
4
|
-
* All rights reserved.
|
|
5
|
-
* Licensed under the BSD 3-Clause license.
|
|
6
|
-
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
7
|
-
*/
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.updateRevisionCounterToZero = exports.resolveUrl = exports.deploySettings = exports.pollForScratchOrgInfo = exports.requestScratchOrgCreation = exports.authorizeScratchOrg = exports.queryScratchOrgInfo = void 0;
|
|
10
|
-
const kit_1 = require("@salesforce/kit");
|
|
11
|
-
const ts_retry_promise_1 = require("ts-retry-promise");
|
|
12
|
-
const logger_1 = require("../logger");
|
|
13
|
-
const messages_1 = require("../messages");
|
|
14
|
-
const sfError_1 = require("../sfError");
|
|
15
|
-
const sfdcUrl_1 = require("../util/sfdcUrl");
|
|
16
|
-
const pollingClient_1 = require("../status/pollingClient");
|
|
17
|
-
const myDomainResolver_1 = require("../status/myDomainResolver");
|
|
18
|
-
const lifecycleEvents_1 = require("../lifecycleEvents");
|
|
19
|
-
const mapKeys_1 = require("../util/mapKeys");
|
|
20
|
-
const authInfo_1 = require("./authInfo");
|
|
21
|
-
const org_1 = require("./org");
|
|
22
|
-
const scratchOrgErrorCodes_1 = require("./scratchOrgErrorCodes");
|
|
23
|
-
const scratchOrgLifecycleEvents_1 = require("./scratchOrgLifecycleEvents");
|
|
24
|
-
messages_1.Messages.importMessagesDirectory(__dirname);
|
|
25
|
-
const messages = messages_1.Messages.loadMessages('@salesforce/core', 'scratchOrgInfoApi');
|
|
26
|
-
const errorCodes = messages_1.Messages.load('@salesforce/core', 'scratchOrgErrorCodes', ['C-1007']);
|
|
27
|
-
/**
|
|
28
|
-
* Returns the url to be used to authorize into the new scratch org
|
|
29
|
-
*
|
|
30
|
-
* @param scratchOrgInfoComplete The completed ScratchOrgInfo
|
|
31
|
-
* @param hubOrgLoginUrl the hun org login url
|
|
32
|
-
* @param signupTargetLoginUrlConfig the login url
|
|
33
|
-
* @returns {string}
|
|
34
|
-
*/
|
|
35
|
-
const getOrgInstanceAuthority = function (scratchOrgInfoComplete, hubOrgLoginUrl, signupTargetLoginUrlConfig) {
|
|
36
|
-
const createdOrgInstance = scratchOrgInfoComplete.SignupInstance;
|
|
37
|
-
if (createdOrgInstance === 'utf8') {
|
|
38
|
-
return hubOrgLoginUrl;
|
|
39
|
-
}
|
|
40
|
-
let altUrl;
|
|
41
|
-
// For non-Falcon (ie - instance names not ending in -s) sandboxes, use the instance URL
|
|
42
|
-
if (createdOrgInstance && !createdOrgInstance.toLowerCase().endsWith('s')) {
|
|
43
|
-
altUrl = `https://${createdOrgInstance}.salesforce.com`;
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
// For Falcon sandboxes, try the LoginURL instead; createdOrgInstance will not yield a valid URL
|
|
47
|
-
altUrl = scratchOrgInfoComplete.LoginUrl;
|
|
48
|
-
}
|
|
49
|
-
return signupTargetLoginUrlConfig ?? altUrl;
|
|
50
|
-
};
|
|
51
|
-
/**
|
|
52
|
-
* Returns OAuth2Options object
|
|
53
|
-
*
|
|
54
|
-
* @returns {OAuth2Options, number, number, number} options, retries, timeout, delay
|
|
55
|
-
* @param options
|
|
56
|
-
*/
|
|
57
|
-
const buildOAuth2Options = async (options) => {
|
|
58
|
-
const logger = await logger_1.Logger.child('buildOAuth2Options');
|
|
59
|
-
const isJwtFlow = !!options.hubOrg.getConnection().getAuthInfoFields().privateKey;
|
|
60
|
-
const oauth2Options = {
|
|
61
|
-
loginUrl: getOrgInstanceAuthority(options.scratchOrgInfoComplete, options.hubOrg.getField(org_1.Org.Fields.LOGIN_URL), options.signupTargetLoginUrlConfig),
|
|
62
|
-
};
|
|
63
|
-
logger.debug(`isJwtFlow: ${isJwtFlow}`);
|
|
64
|
-
if (isJwtFlow && !process.env.SFDX_CLIENT_SECRET) {
|
|
65
|
-
oauth2Options.privateKeyFile = options.hubOrg.getConnection().getAuthInfoFields().privateKey;
|
|
66
|
-
const retries = options?.retry ?? kit_1.env.getNumber('SFDX_JWT_AUTH_RETRY_ATTEMPTS') ?? 0;
|
|
67
|
-
const timeoutInSeconds = kit_1.env.getNumber('SFDX_JWT_AUTH_RETRY_TIMEOUT') ?? 300;
|
|
68
|
-
const timeout = kit_1.Duration.seconds(timeoutInSeconds).milliseconds;
|
|
69
|
-
const delay = retries ? timeout / retries : 1000;
|
|
70
|
-
return {
|
|
71
|
-
options: oauth2Options,
|
|
72
|
-
retries,
|
|
73
|
-
timeout,
|
|
74
|
-
delay,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
// Web Server OAuth "auth code exchange" flow
|
|
79
|
-
if (process.env.SFDX_CLIENT_SECRET) {
|
|
80
|
-
oauth2Options.clientSecret = process.env.SFDX_CLIENT_SECRET;
|
|
81
|
-
}
|
|
82
|
-
else if (options.clientSecret) {
|
|
83
|
-
oauth2Options.clientSecret = options.clientSecret;
|
|
84
|
-
}
|
|
85
|
-
oauth2Options.redirectUri = options.scratchOrgInfoComplete.ConnectedAppCallbackUrl;
|
|
86
|
-
oauth2Options.authCode = options.scratchOrgInfoComplete.AuthCode;
|
|
87
|
-
return {
|
|
88
|
-
options: oauth2Options,
|
|
89
|
-
retries: 0,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
/**
|
|
94
|
-
* Returns OAuth2Options object
|
|
95
|
-
*
|
|
96
|
-
* hubOrg the environment hub org
|
|
97
|
-
* username The OAuth client secret. May be null for JWT OAuth flow.
|
|
98
|
-
* oauth2Options The completed ScratchOrgInfo which should contain an access token.
|
|
99
|
-
* retries auth retry a
|
|
100
|
-
* timeout the login url
|
|
101
|
-
* delay the login url
|
|
102
|
-
*
|
|
103
|
-
* @returns {OAuth2Options, number, number, number} options, retries, timeout, delay
|
|
104
|
-
*/
|
|
105
|
-
const getAuthInfo = async (options) => {
|
|
106
|
-
const logger = await logger_1.Logger.child('getAuthInfo');
|
|
107
|
-
const retryAuthorize = (0, ts_retry_promise_1.retryDecorator)(async (opts) => authInfo_1.AuthInfo.create(opts), {
|
|
108
|
-
timeout: options.timeout,
|
|
109
|
-
delay: options.delay,
|
|
110
|
-
retries: options.retries,
|
|
111
|
-
});
|
|
112
|
-
if (options.retries) {
|
|
113
|
-
try {
|
|
114
|
-
return await retryAuthorize({
|
|
115
|
-
username: options.username,
|
|
116
|
-
parentUsername: options.hubOrg.getUsername(),
|
|
117
|
-
oauth2Options: options.oauth2Options,
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
catch (err) {
|
|
121
|
-
const error = err;
|
|
122
|
-
logger.error(error);
|
|
123
|
-
throw error.lastError || error;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
return authInfo_1.AuthInfo.create({
|
|
128
|
-
username: options.username,
|
|
129
|
-
parentUsername: options.hubOrg.getUsername(),
|
|
130
|
-
oauth2Options: options.oauth2Options,
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
/**
|
|
135
|
-
*
|
|
136
|
-
* @param hubOrg Org
|
|
137
|
-
* @param id Record ID for the ScratchOrgInfoObject
|
|
138
|
-
* @returns Promise<ScratchOrgInfo>
|
|
139
|
-
*/
|
|
140
|
-
const queryScratchOrgInfo = async (hubOrg, id) => (await hubOrg.getConnection().sobject('ScratchOrgInfo').retrieve(id));
|
|
141
|
-
exports.queryScratchOrgInfo = queryScratchOrgInfo;
|
|
142
|
-
/**
|
|
143
|
-
* after we successfully signup an org we need to trade the auth token for access and refresh token.
|
|
144
|
-
*
|
|
145
|
-
* scratchOrgInfoComplete - The completed ScratchOrgInfo which should contain an access token.
|
|
146
|
-
* hubOrg - the environment hub org
|
|
147
|
-
* clientSecret - The OAuth client secret. May be null for JWT OAuth flow.
|
|
148
|
-
* signupTargetLoginUrlConfig - Login url
|
|
149
|
-
* retry - auth retry attempts
|
|
150
|
-
*
|
|
151
|
-
* @returns {Promise<AuthInfo>}
|
|
152
|
-
*/
|
|
153
|
-
const authorizeScratchOrg = async (options) => {
|
|
154
|
-
const { scratchOrgInfoComplete, hubOrg, clientSecret, signupTargetLoginUrlConfig, retry } = options;
|
|
155
|
-
await (0, scratchOrgLifecycleEvents_1.emit)({ stage: 'authenticate', scratchOrgInfo: scratchOrgInfoComplete });
|
|
156
|
-
const logger = await logger_1.Logger.child('authorizeScratchOrg');
|
|
157
|
-
logger.debug(`scratchOrgInfoComplete: ${JSON.stringify(scratchOrgInfoComplete, null, 4)}`);
|
|
158
|
-
// if we didn't have it marked as a devhub but just successfully used it as one, this will update the authFile, fix cache, etc
|
|
159
|
-
if (!hubOrg.isDevHubOrg()) {
|
|
160
|
-
await hubOrg.determineIfDevHubOrg(true);
|
|
161
|
-
}
|
|
162
|
-
const oAuth2Options = await buildOAuth2Options({
|
|
163
|
-
hubOrg,
|
|
164
|
-
clientSecret,
|
|
165
|
-
scratchOrgInfoComplete,
|
|
166
|
-
retry,
|
|
167
|
-
signupTargetLoginUrlConfig,
|
|
168
|
-
});
|
|
169
|
-
const authInfo = await getAuthInfo({
|
|
170
|
-
hubOrg,
|
|
171
|
-
username: scratchOrgInfoComplete.SignupUsername,
|
|
172
|
-
oauth2Options: oAuth2Options.options,
|
|
173
|
-
retries: oAuth2Options.retries,
|
|
174
|
-
timeout: oAuth2Options.timeout,
|
|
175
|
-
delay: oAuth2Options.delay,
|
|
176
|
-
});
|
|
177
|
-
await authInfo.save({
|
|
178
|
-
devHubUsername: hubOrg.getUsername(),
|
|
179
|
-
created: new Date(scratchOrgInfoComplete.CreatedDate ?? new Date()).valueOf().toString(),
|
|
180
|
-
expirationDate: scratchOrgInfoComplete.ExpirationDate,
|
|
181
|
-
clientId: scratchOrgInfoComplete.ConnectedAppConsumerKey,
|
|
182
|
-
createdOrgInstance: scratchOrgInfoComplete.SignupInstance,
|
|
183
|
-
isDevHub: false,
|
|
184
|
-
snapshot: scratchOrgInfoComplete.Snapshot,
|
|
185
|
-
});
|
|
186
|
-
return authInfo;
|
|
187
|
-
};
|
|
188
|
-
exports.authorizeScratchOrg = authorizeScratchOrg;
|
|
189
|
-
const checkOrgDoesntExist = async (scratchOrgInfo) => {
|
|
190
|
-
const usernameKey = Object.keys(scratchOrgInfo).find((key) => key.toUpperCase() === 'USERNAME');
|
|
191
|
-
if (!usernameKey) {
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
const username = scratchOrgInfo[usernameKey];
|
|
195
|
-
if (username && username.length > 0) {
|
|
196
|
-
try {
|
|
197
|
-
await authInfo_1.AuthInfo.create({ username: username.toLowerCase() });
|
|
198
|
-
}
|
|
199
|
-
catch (error) {
|
|
200
|
-
const sfError = sfError_1.SfError.wrap(error);
|
|
201
|
-
// if an AuthInfo couldn't be created that means no AuthFile exists.
|
|
202
|
-
if (sfError.name === 'NamedOrgNotFoundError') {
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
// Something unexpected
|
|
206
|
-
throw sfError;
|
|
207
|
-
}
|
|
208
|
-
// An org file already exists
|
|
209
|
-
throw errorCodes.createError('C-1007');
|
|
210
|
-
}
|
|
211
|
-
};
|
|
212
|
-
/**
|
|
213
|
-
* This extracts orgPrefs/settings from the user input and performs a basic scratchOrgInfo request.
|
|
214
|
-
*
|
|
215
|
-
* @param hubOrg - the environment hub org
|
|
216
|
-
* @param scratchOrgRequest - An object containing the fields of the ScratchOrgInfo
|
|
217
|
-
* @param settings - An object containing org settings
|
|
218
|
-
* @returns {Promise<SaveResult>}
|
|
219
|
-
*/
|
|
220
|
-
const requestScratchOrgCreation = async (hubOrg, scratchOrgRequest, settings) => {
|
|
221
|
-
// If these were present, they were already used to initialize the scratchOrgSettingsGenerator.
|
|
222
|
-
// They shouldn't be submitted as part of the scratchOrgInfo.
|
|
223
|
-
delete scratchOrgRequest.settings;
|
|
224
|
-
delete scratchOrgRequest.objectSettings;
|
|
225
|
-
// We do not allow you to specify the old and the new way of doing post create settings
|
|
226
|
-
if (scratchOrgRequest.orgPreferences && settings.hasSettings()) {
|
|
227
|
-
// This is not allowed
|
|
228
|
-
throw new sfError_1.SfError('SignupDuplicateSettingsSpecifiedError');
|
|
229
|
-
}
|
|
230
|
-
// deprecated old style orgPreferences
|
|
231
|
-
if (scratchOrgRequest.orgPreferences) {
|
|
232
|
-
throw new sfError_1.SfError(messages.getMessage('DeprecatedPrefFormat'));
|
|
233
|
-
}
|
|
234
|
-
const scratchOrgInfo = (0, mapKeys_1.default)(scratchOrgRequest, kit_1.upperFirst, true);
|
|
235
|
-
if (typeof scratchOrgInfo.Username === 'string') {
|
|
236
|
-
scratchOrgInfo.Username = scratchOrgInfo.Username.toLowerCase();
|
|
237
|
-
}
|
|
238
|
-
await checkOrgDoesntExist(scratchOrgInfo); // throw if it does exist.
|
|
239
|
-
try {
|
|
240
|
-
await (0, scratchOrgLifecycleEvents_1.emit)({ stage: 'send request' });
|
|
241
|
-
// return await will cause this catch block to run instead of the caller's catch block
|
|
242
|
-
return await hubOrg.getConnection().sobject('ScratchOrgInfo').create(scratchOrgInfo);
|
|
243
|
-
}
|
|
244
|
-
catch (error) {
|
|
245
|
-
// this is a jsforce error which contains the property "fields" which regular error don't
|
|
246
|
-
const jsForceError = error;
|
|
247
|
-
if (jsForceError.errorCode === 'REQUIRED_FIELD_MISSING') {
|
|
248
|
-
throw new sfError_1.SfError(messages.getMessage('SignupFieldsMissingError', [jsForceError.fields.toString()]));
|
|
249
|
-
}
|
|
250
|
-
throw sfError_1.SfError.wrap(jsForceError);
|
|
251
|
-
}
|
|
252
|
-
};
|
|
253
|
-
exports.requestScratchOrgCreation = requestScratchOrgCreation;
|
|
254
|
-
/**
|
|
255
|
-
* This retrieves the ScratchOrgInfo, polling until the status is Active or Error
|
|
256
|
-
*
|
|
257
|
-
* @param hubOrg
|
|
258
|
-
* @param scratchOrgInfoId - the id of the scratchOrgInfo that we are retrieving
|
|
259
|
-
* @param timeout - A Duration object
|
|
260
|
-
* @returns {Promise<ScratchOrgInfo>}
|
|
261
|
-
*/
|
|
262
|
-
const pollForScratchOrgInfo = async (hubOrg, scratchOrgInfoId,
|
|
263
|
-
// org:create specifies a default timeout of 6. This longer default is for other consumers
|
|
264
|
-
timeout = kit_1.Duration.minutes(15)) => {
|
|
265
|
-
const logger = await logger_1.Logger.child('scratchOrgInfoApi-pollForScratchOrgInfo');
|
|
266
|
-
logger.debug(`PollingTimeout in minutes: ${timeout.minutes}`);
|
|
267
|
-
const pollingOptions = {
|
|
268
|
-
async poll() {
|
|
269
|
-
try {
|
|
270
|
-
const resultInProgress = await (0, exports.queryScratchOrgInfo)(hubOrg, scratchOrgInfoId);
|
|
271
|
-
logger.debug(`polling client result: ${JSON.stringify(resultInProgress, null, 4)}`);
|
|
272
|
-
// Once it's "done" we can return it
|
|
273
|
-
if (resultInProgress.Status === 'Active' || resultInProgress.Status === 'Error') {
|
|
274
|
-
return {
|
|
275
|
-
completed: true,
|
|
276
|
-
payload: resultInProgress,
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
await (0, scratchOrgLifecycleEvents_1.emit)({ stage: 'wait for org', scratchOrgInfo: resultInProgress });
|
|
280
|
-
logger.debug(`Scratch org status is ${resultInProgress.Status}`);
|
|
281
|
-
return {
|
|
282
|
-
completed: false,
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
catch (error) {
|
|
286
|
-
logger.debug(`An error occurred trying to retrieve scratchOrgInfo for ${scratchOrgInfoId}`);
|
|
287
|
-
logger.debug(`Error: ${error.message}`);
|
|
288
|
-
logger.debug('Re-trying deploy check again....');
|
|
289
|
-
return {
|
|
290
|
-
completed: false,
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
|
-
},
|
|
294
|
-
timeout,
|
|
295
|
-
frequency: kit_1.Duration.seconds(1),
|
|
296
|
-
timeoutErrorName: 'ScratchOrgInfoTimeoutError',
|
|
297
|
-
};
|
|
298
|
-
const client = await pollingClient_1.PollingClient.create(pollingOptions);
|
|
299
|
-
try {
|
|
300
|
-
const resultInProgress = await client.subscribe();
|
|
301
|
-
return await (0, scratchOrgErrorCodes_1.checkScratchOrgInfoForErrors)(resultInProgress, hubOrg.getUsername());
|
|
302
|
-
}
|
|
303
|
-
catch (error) {
|
|
304
|
-
if (error instanceof Error) {
|
|
305
|
-
const sfError = sfError_1.SfError.wrap(error);
|
|
306
|
-
sfError.setData({
|
|
307
|
-
username: hubOrg.getUsername(),
|
|
308
|
-
orgId: hubOrg.getOrgId(),
|
|
309
|
-
scratchOrgInfoId,
|
|
310
|
-
});
|
|
311
|
-
throw sfError;
|
|
312
|
-
}
|
|
313
|
-
throw new sfError_1.SfError(`The scratch org did not complete within ${timeout.minutes} minutes`, 'orgCreationTimeout', [
|
|
314
|
-
'Try your force:org:create command again with a longer --wait value',
|
|
315
|
-
]);
|
|
316
|
-
}
|
|
317
|
-
};
|
|
318
|
-
exports.pollForScratchOrgInfo = pollForScratchOrgInfo;
|
|
319
|
-
/**
|
|
320
|
-
* Deploy settings to the newly created scratch org
|
|
321
|
-
*
|
|
322
|
-
* @param scratchOrg an instance of the Org class
|
|
323
|
-
* @param orgSettings an instance of the SettingsGenerator class
|
|
324
|
-
* @param apiVersion the api version (used when created the package.xml)
|
|
325
|
-
*/
|
|
326
|
-
const deploySettings = async (scratchOrg, orgSettings, apiVersion) => {
|
|
327
|
-
const logger = await logger_1.Logger.child('scratchOrgInfoApi-deploySettings');
|
|
328
|
-
if (orgSettings.hasSettings()) {
|
|
329
|
-
// deploy the settings to the newly created scratch org
|
|
330
|
-
logger.debug(`deploying scratch org settings with apiVersion ${apiVersion}`);
|
|
331
|
-
try {
|
|
332
|
-
await orgSettings.createDeploy();
|
|
333
|
-
await orgSettings.deploySettingsViaFolder(scratchOrg, apiVersion);
|
|
334
|
-
// updating the revision num to zero during org:creation if source members are created during org:create.
|
|
335
|
-
// This only happens for some specific scratch org definition file.
|
|
336
|
-
await (0, exports.updateRevisionCounterToZero)(scratchOrg);
|
|
337
|
-
logger.trace('Settings deployed to org');
|
|
338
|
-
}
|
|
339
|
-
catch (error) {
|
|
340
|
-
throw sfError_1.SfError.wrap(error);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
};
|
|
344
|
-
exports.deploySettings = deploySettings;
|
|
345
|
-
/**
|
|
346
|
-
*
|
|
347
|
-
* @param scratchOrgAuthInfo an AuthInfo class from the scratch org
|
|
348
|
-
* @returns AuthInfo
|
|
349
|
-
*/
|
|
350
|
-
const resolveUrl = async (scratchOrgAuthInfo) => {
|
|
351
|
-
const logger = await logger_1.Logger.child('scratchOrgInfoApi-resolveUrl');
|
|
352
|
-
const { instanceUrl } = scratchOrgAuthInfo.getFields();
|
|
353
|
-
if (!instanceUrl) {
|
|
354
|
-
const sfError = new sfError_1.SfError('Org does not have instanceUrl');
|
|
355
|
-
sfError.setData({
|
|
356
|
-
orgId: scratchOrgAuthInfo.getFields().orgId,
|
|
357
|
-
username: scratchOrgAuthInfo.getFields().username,
|
|
358
|
-
instanceUrl,
|
|
359
|
-
});
|
|
360
|
-
throw sfError;
|
|
361
|
-
}
|
|
362
|
-
logger.debug(`processScratchOrgInfoResult - resultData.instanceUrl: ${instanceUrl}`);
|
|
363
|
-
const options = {
|
|
364
|
-
timeout: kit_1.Duration.minutes(3),
|
|
365
|
-
frequency: kit_1.Duration.seconds(10),
|
|
366
|
-
url: new sfdcUrl_1.SfdcUrl(instanceUrl),
|
|
367
|
-
};
|
|
368
|
-
try {
|
|
369
|
-
const resolver = await myDomainResolver_1.MyDomainResolver.create(options);
|
|
370
|
-
await resolver.resolve();
|
|
371
|
-
return scratchOrgAuthInfo;
|
|
372
|
-
}
|
|
373
|
-
catch (error) {
|
|
374
|
-
const sfError = sfError_1.SfError.wrap(error);
|
|
375
|
-
logger.debug('processScratchOrgInfoResult - err: %s', error);
|
|
376
|
-
if (sfError.name === 'MyDomainResolverTimeoutError') {
|
|
377
|
-
sfError.setData({
|
|
378
|
-
orgId: scratchOrgAuthInfo.getFields().orgId,
|
|
379
|
-
username: scratchOrgAuthInfo.getFields().username,
|
|
380
|
-
instanceUrl,
|
|
381
|
-
});
|
|
382
|
-
logger.debug('processScratchOrgInfoResult - err data: %s', sfError.data);
|
|
383
|
-
}
|
|
384
|
-
throw sfError;
|
|
385
|
-
}
|
|
386
|
-
};
|
|
387
|
-
exports.resolveUrl = resolveUrl;
|
|
388
|
-
const updateRevisionCounterToZero = async (scratchOrg) => {
|
|
389
|
-
const conn = scratchOrg.getConnection();
|
|
390
|
-
const queryResult = await conn.tooling.sobject('SourceMember').find({ RevisionCounter: { $gt: 0 } }, ['Id']);
|
|
391
|
-
if (queryResult.length === 0) {
|
|
392
|
-
return;
|
|
393
|
-
}
|
|
394
|
-
try {
|
|
395
|
-
// jsforce has a bug in its `update` code such that tooling#update doesn't work right
|
|
396
|
-
// https://github.com/jsforce/jsforce/blob/265eba5c734439dd7b77610c05b63bde7d4b1e83/src/connection.ts#L1082
|
|
397
|
-
// will result in `this._ensureVersion is not a function`
|
|
398
|
-
// so until that is resolved, we hit the API with singular records
|
|
399
|
-
// once that's fixed, you can use the following code for a single API call
|
|
400
|
-
// await conn.tooling
|
|
401
|
-
// .sobject('SourceMember')
|
|
402
|
-
// .update(queryResult.map((record) => ({ Id: record.Id, RevisionCounter: 0 })));
|
|
403
|
-
await Promise.all(queryResult.map((record) => conn.tooling.sobject('SourceMember').update({ Id: record.Id, RevisionCounter: 0 })));
|
|
404
|
-
}
|
|
405
|
-
catch (err) {
|
|
406
|
-
await lifecycleEvents_1.Lifecycle.getInstance().emitWarning(messages.getMessage('SourceStatusResetFailureError', [
|
|
407
|
-
scratchOrg.getOrgId(),
|
|
408
|
-
scratchOrg.getUsername(),
|
|
409
|
-
err instanceof Error ? err.message : '',
|
|
410
|
-
]));
|
|
411
|
-
}
|
|
412
|
-
};
|
|
413
|
-
exports.updateRevisionCounterToZero = updateRevisionCounterToZero;
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2021, salesforce.com, inc.
|
|
4
|
+
* All rights reserved.
|
|
5
|
+
* Licensed under the BSD 3-Clause license.
|
|
6
|
+
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.updateRevisionCounterToZero = exports.resolveUrl = exports.deploySettings = exports.pollForScratchOrgInfo = exports.requestScratchOrgCreation = exports.authorizeScratchOrg = exports.queryScratchOrgInfo = void 0;
|
|
10
|
+
const kit_1 = require("@salesforce/kit");
|
|
11
|
+
const ts_retry_promise_1 = require("ts-retry-promise");
|
|
12
|
+
const logger_1 = require("../logger");
|
|
13
|
+
const messages_1 = require("../messages");
|
|
14
|
+
const sfError_1 = require("../sfError");
|
|
15
|
+
const sfdcUrl_1 = require("../util/sfdcUrl");
|
|
16
|
+
const pollingClient_1 = require("../status/pollingClient");
|
|
17
|
+
const myDomainResolver_1 = require("../status/myDomainResolver");
|
|
18
|
+
const lifecycleEvents_1 = require("../lifecycleEvents");
|
|
19
|
+
const mapKeys_1 = require("../util/mapKeys");
|
|
20
|
+
const authInfo_1 = require("./authInfo");
|
|
21
|
+
const org_1 = require("./org");
|
|
22
|
+
const scratchOrgErrorCodes_1 = require("./scratchOrgErrorCodes");
|
|
23
|
+
const scratchOrgLifecycleEvents_1 = require("./scratchOrgLifecycleEvents");
|
|
24
|
+
messages_1.Messages.importMessagesDirectory(__dirname);
|
|
25
|
+
const messages = messages_1.Messages.loadMessages('@salesforce/core', 'scratchOrgInfoApi');
|
|
26
|
+
const errorCodes = messages_1.Messages.load('@salesforce/core', 'scratchOrgErrorCodes', ['C-1007']);
|
|
27
|
+
/**
|
|
28
|
+
* Returns the url to be used to authorize into the new scratch org
|
|
29
|
+
*
|
|
30
|
+
* @param scratchOrgInfoComplete The completed ScratchOrgInfo
|
|
31
|
+
* @param hubOrgLoginUrl the hun org login url
|
|
32
|
+
* @param signupTargetLoginUrlConfig the login url
|
|
33
|
+
* @returns {string}
|
|
34
|
+
*/
|
|
35
|
+
const getOrgInstanceAuthority = function (scratchOrgInfoComplete, hubOrgLoginUrl, signupTargetLoginUrlConfig) {
|
|
36
|
+
const createdOrgInstance = scratchOrgInfoComplete.SignupInstance;
|
|
37
|
+
if (createdOrgInstance === 'utf8') {
|
|
38
|
+
return hubOrgLoginUrl;
|
|
39
|
+
}
|
|
40
|
+
let altUrl;
|
|
41
|
+
// For non-Falcon (ie - instance names not ending in -s) sandboxes, use the instance URL
|
|
42
|
+
if (createdOrgInstance && !createdOrgInstance.toLowerCase().endsWith('s')) {
|
|
43
|
+
altUrl = `https://${createdOrgInstance}.salesforce.com`;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
// For Falcon sandboxes, try the LoginURL instead; createdOrgInstance will not yield a valid URL
|
|
47
|
+
altUrl = scratchOrgInfoComplete.LoginUrl;
|
|
48
|
+
}
|
|
49
|
+
return signupTargetLoginUrlConfig ?? altUrl;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Returns OAuth2Options object
|
|
53
|
+
*
|
|
54
|
+
* @returns {OAuth2Options, number, number, number} options, retries, timeout, delay
|
|
55
|
+
* @param options
|
|
56
|
+
*/
|
|
57
|
+
const buildOAuth2Options = async (options) => {
|
|
58
|
+
const logger = await logger_1.Logger.child('buildOAuth2Options');
|
|
59
|
+
const isJwtFlow = !!options.hubOrg.getConnection().getAuthInfoFields().privateKey;
|
|
60
|
+
const oauth2Options = {
|
|
61
|
+
loginUrl: getOrgInstanceAuthority(options.scratchOrgInfoComplete, options.hubOrg.getField(org_1.Org.Fields.LOGIN_URL), options.signupTargetLoginUrlConfig),
|
|
62
|
+
};
|
|
63
|
+
logger.debug(`isJwtFlow: ${isJwtFlow}`);
|
|
64
|
+
if (isJwtFlow && !process.env.SFDX_CLIENT_SECRET) {
|
|
65
|
+
oauth2Options.privateKeyFile = options.hubOrg.getConnection().getAuthInfoFields().privateKey;
|
|
66
|
+
const retries = options?.retry ?? kit_1.env.getNumber('SFDX_JWT_AUTH_RETRY_ATTEMPTS') ?? 0;
|
|
67
|
+
const timeoutInSeconds = kit_1.env.getNumber('SFDX_JWT_AUTH_RETRY_TIMEOUT') ?? 300;
|
|
68
|
+
const timeout = kit_1.Duration.seconds(timeoutInSeconds).milliseconds;
|
|
69
|
+
const delay = retries ? timeout / retries : 1000;
|
|
70
|
+
return {
|
|
71
|
+
options: oauth2Options,
|
|
72
|
+
retries,
|
|
73
|
+
timeout,
|
|
74
|
+
delay,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// Web Server OAuth "auth code exchange" flow
|
|
79
|
+
if (process.env.SFDX_CLIENT_SECRET) {
|
|
80
|
+
oauth2Options.clientSecret = process.env.SFDX_CLIENT_SECRET;
|
|
81
|
+
}
|
|
82
|
+
else if (options.clientSecret) {
|
|
83
|
+
oauth2Options.clientSecret = options.clientSecret;
|
|
84
|
+
}
|
|
85
|
+
oauth2Options.redirectUri = options.scratchOrgInfoComplete.ConnectedAppCallbackUrl;
|
|
86
|
+
oauth2Options.authCode = options.scratchOrgInfoComplete.AuthCode;
|
|
87
|
+
return {
|
|
88
|
+
options: oauth2Options,
|
|
89
|
+
retries: 0,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Returns OAuth2Options object
|
|
95
|
+
*
|
|
96
|
+
* hubOrg the environment hub org
|
|
97
|
+
* username The OAuth client secret. May be null for JWT OAuth flow.
|
|
98
|
+
* oauth2Options The completed ScratchOrgInfo which should contain an access token.
|
|
99
|
+
* retries auth retry a
|
|
100
|
+
* timeout the login url
|
|
101
|
+
* delay the login url
|
|
102
|
+
*
|
|
103
|
+
* @returns {OAuth2Options, number, number, number} options, retries, timeout, delay
|
|
104
|
+
*/
|
|
105
|
+
const getAuthInfo = async (options) => {
|
|
106
|
+
const logger = await logger_1.Logger.child('getAuthInfo');
|
|
107
|
+
const retryAuthorize = (0, ts_retry_promise_1.retryDecorator)(async (opts) => authInfo_1.AuthInfo.create(opts), {
|
|
108
|
+
timeout: options.timeout,
|
|
109
|
+
delay: options.delay,
|
|
110
|
+
retries: options.retries,
|
|
111
|
+
});
|
|
112
|
+
if (options.retries) {
|
|
113
|
+
try {
|
|
114
|
+
return await retryAuthorize({
|
|
115
|
+
username: options.username,
|
|
116
|
+
parentUsername: options.hubOrg.getUsername(),
|
|
117
|
+
oauth2Options: options.oauth2Options,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
const error = err;
|
|
122
|
+
logger.error(error);
|
|
123
|
+
throw error.lastError || error;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
return authInfo_1.AuthInfo.create({
|
|
128
|
+
username: options.username,
|
|
129
|
+
parentUsername: options.hubOrg.getUsername(),
|
|
130
|
+
oauth2Options: options.oauth2Options,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
*
|
|
136
|
+
* @param hubOrg Org
|
|
137
|
+
* @param id Record ID for the ScratchOrgInfoObject
|
|
138
|
+
* @returns Promise<ScratchOrgInfo>
|
|
139
|
+
*/
|
|
140
|
+
const queryScratchOrgInfo = async (hubOrg, id) => (await hubOrg.getConnection().sobject('ScratchOrgInfo').retrieve(id));
|
|
141
|
+
exports.queryScratchOrgInfo = queryScratchOrgInfo;
|
|
142
|
+
/**
|
|
143
|
+
* after we successfully signup an org we need to trade the auth token for access and refresh token.
|
|
144
|
+
*
|
|
145
|
+
* scratchOrgInfoComplete - The completed ScratchOrgInfo which should contain an access token.
|
|
146
|
+
* hubOrg - the environment hub org
|
|
147
|
+
* clientSecret - The OAuth client secret. May be null for JWT OAuth flow.
|
|
148
|
+
* signupTargetLoginUrlConfig - Login url
|
|
149
|
+
* retry - auth retry attempts
|
|
150
|
+
*
|
|
151
|
+
* @returns {Promise<AuthInfo>}
|
|
152
|
+
*/
|
|
153
|
+
const authorizeScratchOrg = async (options) => {
|
|
154
|
+
const { scratchOrgInfoComplete, hubOrg, clientSecret, signupTargetLoginUrlConfig, retry } = options;
|
|
155
|
+
await (0, scratchOrgLifecycleEvents_1.emit)({ stage: 'authenticate', scratchOrgInfo: scratchOrgInfoComplete });
|
|
156
|
+
const logger = await logger_1.Logger.child('authorizeScratchOrg');
|
|
157
|
+
logger.debug(`scratchOrgInfoComplete: ${JSON.stringify(scratchOrgInfoComplete, null, 4)}`);
|
|
158
|
+
// if we didn't have it marked as a devhub but just successfully used it as one, this will update the authFile, fix cache, etc
|
|
159
|
+
if (!hubOrg.isDevHubOrg()) {
|
|
160
|
+
await hubOrg.determineIfDevHubOrg(true);
|
|
161
|
+
}
|
|
162
|
+
const oAuth2Options = await buildOAuth2Options({
|
|
163
|
+
hubOrg,
|
|
164
|
+
clientSecret,
|
|
165
|
+
scratchOrgInfoComplete,
|
|
166
|
+
retry,
|
|
167
|
+
signupTargetLoginUrlConfig,
|
|
168
|
+
});
|
|
169
|
+
const authInfo = await getAuthInfo({
|
|
170
|
+
hubOrg,
|
|
171
|
+
username: scratchOrgInfoComplete.SignupUsername,
|
|
172
|
+
oauth2Options: oAuth2Options.options,
|
|
173
|
+
retries: oAuth2Options.retries,
|
|
174
|
+
timeout: oAuth2Options.timeout,
|
|
175
|
+
delay: oAuth2Options.delay,
|
|
176
|
+
});
|
|
177
|
+
await authInfo.save({
|
|
178
|
+
devHubUsername: hubOrg.getUsername(),
|
|
179
|
+
created: new Date(scratchOrgInfoComplete.CreatedDate ?? new Date()).valueOf().toString(),
|
|
180
|
+
expirationDate: scratchOrgInfoComplete.ExpirationDate,
|
|
181
|
+
clientId: scratchOrgInfoComplete.ConnectedAppConsumerKey,
|
|
182
|
+
createdOrgInstance: scratchOrgInfoComplete.SignupInstance,
|
|
183
|
+
isDevHub: false,
|
|
184
|
+
snapshot: scratchOrgInfoComplete.Snapshot,
|
|
185
|
+
});
|
|
186
|
+
return authInfo;
|
|
187
|
+
};
|
|
188
|
+
exports.authorizeScratchOrg = authorizeScratchOrg;
|
|
189
|
+
const checkOrgDoesntExist = async (scratchOrgInfo) => {
|
|
190
|
+
const usernameKey = Object.keys(scratchOrgInfo).find((key) => key.toUpperCase() === 'USERNAME');
|
|
191
|
+
if (!usernameKey) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const username = scratchOrgInfo[usernameKey];
|
|
195
|
+
if (username && username.length > 0) {
|
|
196
|
+
try {
|
|
197
|
+
await authInfo_1.AuthInfo.create({ username: username.toLowerCase() });
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
const sfError = sfError_1.SfError.wrap(error);
|
|
201
|
+
// if an AuthInfo couldn't be created that means no AuthFile exists.
|
|
202
|
+
if (sfError.name === 'NamedOrgNotFoundError') {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
// Something unexpected
|
|
206
|
+
throw sfError;
|
|
207
|
+
}
|
|
208
|
+
// An org file already exists
|
|
209
|
+
throw errorCodes.createError('C-1007');
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
/**
|
|
213
|
+
* This extracts orgPrefs/settings from the user input and performs a basic scratchOrgInfo request.
|
|
214
|
+
*
|
|
215
|
+
* @param hubOrg - the environment hub org
|
|
216
|
+
* @param scratchOrgRequest - An object containing the fields of the ScratchOrgInfo
|
|
217
|
+
* @param settings - An object containing org settings
|
|
218
|
+
* @returns {Promise<SaveResult>}
|
|
219
|
+
*/
|
|
220
|
+
const requestScratchOrgCreation = async (hubOrg, scratchOrgRequest, settings) => {
|
|
221
|
+
// If these were present, they were already used to initialize the scratchOrgSettingsGenerator.
|
|
222
|
+
// They shouldn't be submitted as part of the scratchOrgInfo.
|
|
223
|
+
delete scratchOrgRequest.settings;
|
|
224
|
+
delete scratchOrgRequest.objectSettings;
|
|
225
|
+
// We do not allow you to specify the old and the new way of doing post create settings
|
|
226
|
+
if (scratchOrgRequest.orgPreferences && settings.hasSettings()) {
|
|
227
|
+
// This is not allowed
|
|
228
|
+
throw new sfError_1.SfError('SignupDuplicateSettingsSpecifiedError');
|
|
229
|
+
}
|
|
230
|
+
// deprecated old style orgPreferences
|
|
231
|
+
if (scratchOrgRequest.orgPreferences) {
|
|
232
|
+
throw new sfError_1.SfError(messages.getMessage('DeprecatedPrefFormat'));
|
|
233
|
+
}
|
|
234
|
+
const scratchOrgInfo = (0, mapKeys_1.default)(scratchOrgRequest, kit_1.upperFirst, true);
|
|
235
|
+
if (typeof scratchOrgInfo.Username === 'string') {
|
|
236
|
+
scratchOrgInfo.Username = scratchOrgInfo.Username.toLowerCase();
|
|
237
|
+
}
|
|
238
|
+
await checkOrgDoesntExist(scratchOrgInfo); // throw if it does exist.
|
|
239
|
+
try {
|
|
240
|
+
await (0, scratchOrgLifecycleEvents_1.emit)({ stage: 'send request' });
|
|
241
|
+
// return await will cause this catch block to run instead of the caller's catch block
|
|
242
|
+
return await hubOrg.getConnection().sobject('ScratchOrgInfo').create(scratchOrgInfo);
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
// this is a jsforce error which contains the property "fields" which regular error don't
|
|
246
|
+
const jsForceError = error;
|
|
247
|
+
if (jsForceError.errorCode === 'REQUIRED_FIELD_MISSING') {
|
|
248
|
+
throw new sfError_1.SfError(messages.getMessage('SignupFieldsMissingError', [jsForceError.fields.toString()]));
|
|
249
|
+
}
|
|
250
|
+
throw sfError_1.SfError.wrap(jsForceError);
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
exports.requestScratchOrgCreation = requestScratchOrgCreation;
|
|
254
|
+
/**
|
|
255
|
+
* This retrieves the ScratchOrgInfo, polling until the status is Active or Error
|
|
256
|
+
*
|
|
257
|
+
* @param hubOrg
|
|
258
|
+
* @param scratchOrgInfoId - the id of the scratchOrgInfo that we are retrieving
|
|
259
|
+
* @param timeout - A Duration object
|
|
260
|
+
* @returns {Promise<ScratchOrgInfo>}
|
|
261
|
+
*/
|
|
262
|
+
const pollForScratchOrgInfo = async (hubOrg, scratchOrgInfoId,
|
|
263
|
+
// org:create specifies a default timeout of 6. This longer default is for other consumers
|
|
264
|
+
timeout = kit_1.Duration.minutes(15)) => {
|
|
265
|
+
const logger = await logger_1.Logger.child('scratchOrgInfoApi-pollForScratchOrgInfo');
|
|
266
|
+
logger.debug(`PollingTimeout in minutes: ${timeout.minutes}`);
|
|
267
|
+
const pollingOptions = {
|
|
268
|
+
async poll() {
|
|
269
|
+
try {
|
|
270
|
+
const resultInProgress = await (0, exports.queryScratchOrgInfo)(hubOrg, scratchOrgInfoId);
|
|
271
|
+
logger.debug(`polling client result: ${JSON.stringify(resultInProgress, null, 4)}`);
|
|
272
|
+
// Once it's "done" we can return it
|
|
273
|
+
if (resultInProgress.Status === 'Active' || resultInProgress.Status === 'Error') {
|
|
274
|
+
return {
|
|
275
|
+
completed: true,
|
|
276
|
+
payload: resultInProgress,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
await (0, scratchOrgLifecycleEvents_1.emit)({ stage: 'wait for org', scratchOrgInfo: resultInProgress });
|
|
280
|
+
logger.debug(`Scratch org status is ${resultInProgress.Status}`);
|
|
281
|
+
return {
|
|
282
|
+
completed: false,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
catch (error) {
|
|
286
|
+
logger.debug(`An error occurred trying to retrieve scratchOrgInfo for ${scratchOrgInfoId}`);
|
|
287
|
+
logger.debug(`Error: ${error.message}`);
|
|
288
|
+
logger.debug('Re-trying deploy check again....');
|
|
289
|
+
return {
|
|
290
|
+
completed: false,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
timeout,
|
|
295
|
+
frequency: kit_1.Duration.seconds(1),
|
|
296
|
+
timeoutErrorName: 'ScratchOrgInfoTimeoutError',
|
|
297
|
+
};
|
|
298
|
+
const client = await pollingClient_1.PollingClient.create(pollingOptions);
|
|
299
|
+
try {
|
|
300
|
+
const resultInProgress = await client.subscribe();
|
|
301
|
+
return await (0, scratchOrgErrorCodes_1.checkScratchOrgInfoForErrors)(resultInProgress, hubOrg.getUsername());
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
if (error instanceof Error) {
|
|
305
|
+
const sfError = sfError_1.SfError.wrap(error);
|
|
306
|
+
sfError.setData({
|
|
307
|
+
username: hubOrg.getUsername(),
|
|
308
|
+
orgId: hubOrg.getOrgId(),
|
|
309
|
+
scratchOrgInfoId,
|
|
310
|
+
});
|
|
311
|
+
throw sfError;
|
|
312
|
+
}
|
|
313
|
+
throw new sfError_1.SfError(`The scratch org did not complete within ${timeout.minutes} minutes`, 'orgCreationTimeout', [
|
|
314
|
+
'Try your force:org:create command again with a longer --wait value',
|
|
315
|
+
]);
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
exports.pollForScratchOrgInfo = pollForScratchOrgInfo;
|
|
319
|
+
/**
|
|
320
|
+
* Deploy settings to the newly created scratch org
|
|
321
|
+
*
|
|
322
|
+
* @param scratchOrg an instance of the Org class
|
|
323
|
+
* @param orgSettings an instance of the SettingsGenerator class
|
|
324
|
+
* @param apiVersion the api version (used when created the package.xml)
|
|
325
|
+
*/
|
|
326
|
+
const deploySettings = async (scratchOrg, orgSettings, apiVersion) => {
|
|
327
|
+
const logger = await logger_1.Logger.child('scratchOrgInfoApi-deploySettings');
|
|
328
|
+
if (orgSettings.hasSettings()) {
|
|
329
|
+
// deploy the settings to the newly created scratch org
|
|
330
|
+
logger.debug(`deploying scratch org settings with apiVersion ${apiVersion}`);
|
|
331
|
+
try {
|
|
332
|
+
await orgSettings.createDeploy();
|
|
333
|
+
await orgSettings.deploySettingsViaFolder(scratchOrg, apiVersion);
|
|
334
|
+
// updating the revision num to zero during org:creation if source members are created during org:create.
|
|
335
|
+
// This only happens for some specific scratch org definition file.
|
|
336
|
+
await (0, exports.updateRevisionCounterToZero)(scratchOrg);
|
|
337
|
+
logger.trace('Settings deployed to org');
|
|
338
|
+
}
|
|
339
|
+
catch (error) {
|
|
340
|
+
throw sfError_1.SfError.wrap(error);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
exports.deploySettings = deploySettings;
|
|
345
|
+
/**
|
|
346
|
+
*
|
|
347
|
+
* @param scratchOrgAuthInfo an AuthInfo class from the scratch org
|
|
348
|
+
* @returns AuthInfo
|
|
349
|
+
*/
|
|
350
|
+
const resolveUrl = async (scratchOrgAuthInfo) => {
|
|
351
|
+
const logger = await logger_1.Logger.child('scratchOrgInfoApi-resolveUrl');
|
|
352
|
+
const { instanceUrl } = scratchOrgAuthInfo.getFields();
|
|
353
|
+
if (!instanceUrl) {
|
|
354
|
+
const sfError = new sfError_1.SfError('Org does not have instanceUrl');
|
|
355
|
+
sfError.setData({
|
|
356
|
+
orgId: scratchOrgAuthInfo.getFields().orgId,
|
|
357
|
+
username: scratchOrgAuthInfo.getFields().username,
|
|
358
|
+
instanceUrl,
|
|
359
|
+
});
|
|
360
|
+
throw sfError;
|
|
361
|
+
}
|
|
362
|
+
logger.debug(`processScratchOrgInfoResult - resultData.instanceUrl: ${instanceUrl}`);
|
|
363
|
+
const options = {
|
|
364
|
+
timeout: kit_1.Duration.minutes(3),
|
|
365
|
+
frequency: kit_1.Duration.seconds(10),
|
|
366
|
+
url: new sfdcUrl_1.SfdcUrl(instanceUrl),
|
|
367
|
+
};
|
|
368
|
+
try {
|
|
369
|
+
const resolver = await myDomainResolver_1.MyDomainResolver.create(options);
|
|
370
|
+
await resolver.resolve();
|
|
371
|
+
return scratchOrgAuthInfo;
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
const sfError = sfError_1.SfError.wrap(error);
|
|
375
|
+
logger.debug('processScratchOrgInfoResult - err: %s', error);
|
|
376
|
+
if (sfError.name === 'MyDomainResolverTimeoutError') {
|
|
377
|
+
sfError.setData({
|
|
378
|
+
orgId: scratchOrgAuthInfo.getFields().orgId,
|
|
379
|
+
username: scratchOrgAuthInfo.getFields().username,
|
|
380
|
+
instanceUrl,
|
|
381
|
+
});
|
|
382
|
+
logger.debug('processScratchOrgInfoResult - err data: %s', sfError.data);
|
|
383
|
+
}
|
|
384
|
+
throw sfError;
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
exports.resolveUrl = resolveUrl;
|
|
388
|
+
const updateRevisionCounterToZero = async (scratchOrg) => {
|
|
389
|
+
const conn = scratchOrg.getConnection();
|
|
390
|
+
const queryResult = await conn.tooling.sobject('SourceMember').find({ RevisionCounter: { $gt: 0 } }, ['Id']);
|
|
391
|
+
if (queryResult.length === 0) {
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
try {
|
|
395
|
+
// jsforce has a bug in its `update` code such that tooling#update doesn't work right
|
|
396
|
+
// https://github.com/jsforce/jsforce/blob/265eba5c734439dd7b77610c05b63bde7d4b1e83/src/connection.ts#L1082
|
|
397
|
+
// will result in `this._ensureVersion is not a function`
|
|
398
|
+
// so until that is resolved, we hit the API with singular records
|
|
399
|
+
// once that's fixed, you can use the following code for a single API call
|
|
400
|
+
// await conn.tooling
|
|
401
|
+
// .sobject('SourceMember')
|
|
402
|
+
// .update(queryResult.map((record) => ({ Id: record.Id, RevisionCounter: 0 })));
|
|
403
|
+
await Promise.all(queryResult.map((record) => conn.tooling.sobject('SourceMember').update({ Id: record.Id, RevisionCounter: 0 })));
|
|
404
|
+
}
|
|
405
|
+
catch (err) {
|
|
406
|
+
await lifecycleEvents_1.Lifecycle.getInstance().emitWarning(messages.getMessage('SourceStatusResetFailureError', [
|
|
407
|
+
scratchOrg.getOrgId(),
|
|
408
|
+
scratchOrg.getUsername(),
|
|
409
|
+
err instanceof Error ? err.message : '',
|
|
410
|
+
]));
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
exports.updateRevisionCounterToZero = updateRevisionCounterToZero;
|
|
414
414
|
//# sourceMappingURL=scratchOrgInfoApi.js.map
|