@salesforce/core 6.5.6 → 6.6.0

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.
@@ -2,8 +2,9 @@ import { SandboxProcessObject, SandboxRequest } from '../org/org';
2
2
  import { TTLConfig } from './ttlConfig';
3
3
  export type SandboxRequestCacheEntry = {
4
4
  alias?: string;
5
- setDefault: boolean;
5
+ setDefault?: boolean;
6
6
  prodOrgUsername: string;
7
+ action: 'Create' | 'Refresh';
7
8
  sandboxProcessObject: Partial<SandboxProcessObject>;
8
9
  sandboxRequest: Partial<SandboxRequest>;
9
10
  tracksSource?: boolean;
package/lib/exported.d.ts CHANGED
@@ -20,7 +20,7 @@ export { SfdcUrl } from './util/sfdcUrl';
20
20
  export { getJwtAudienceUrl } from './util/getJwtAudienceUrl';
21
21
  export { Fields, FieldValue, LoggerLevel, LoggerLevelValue, LogLine, LoggerOptions, Logger } from './logger/logger';
22
22
  export { Messages, StructuredMessage } from './messages';
23
- export { Org, SandboxProcessObject, StatusEvent, SandboxEvents, SandboxUserAuthResponse, SandboxUserAuthRequest, SandboxRequest, ResumeSandboxRequest, OrgTypes, ResultEvent, ScratchOrgRequest, } from './org/org';
23
+ export { Org, SandboxProcessObject, StatusEvent, SandboxInfo, SandboxEvents, SandboxUserAuthResponse, SandboxUserAuthRequest, SandboxRequest, ResumeSandboxRequest, OrgTypes, ResultEvent, ScratchOrgRequest, } from './org/org';
24
24
  export { OrgConfigProperties, ORG_CONFIG_ALLOWED_PROPERTIES } from './org/orgConfigProperties';
25
25
  export { PackageDir, NamedPackageDir, PackageDirDependency, SfProject, SfProjectJson } from './sfProject';
26
26
  export { SchemaValidator } from './schema/validator';
package/lib/org/org.d.ts CHANGED
@@ -71,6 +71,24 @@ export type ResumeSandboxRequest = {
71
71
  SandboxName?: string;
72
72
  SandboxProcessObjId?: string;
73
73
  };
74
+ export type SandboxInfo = {
75
+ Id: string;
76
+ IsDeleted: boolean;
77
+ CreatedDate: string;
78
+ CreatedById: string;
79
+ LastModifiedDate: string;
80
+ LastModifiedById: string;
81
+ SandboxName: string;
82
+ LicenseType: 'DEVELOPER' | 'DEVELOPER PRO' | 'PARTIAL' | 'FULL';
83
+ TemplateId?: string;
84
+ HistoryDays: -1 | 0 | 10 | 20 | 30 | 60 | 90 | 120 | 150 | 180;
85
+ CopyChatter: boolean;
86
+ AutoActivate: boolean;
87
+ ApexClassId?: string;
88
+ Description?: string;
89
+ SourceId?: string;
90
+ CopyArchivedActivities?: boolean;
91
+ };
74
92
  export type ScratchOrgRequest = Omit<ScratchOrgCreateOptions, 'hubOrg'>;
75
93
  export type SandboxFields = {
76
94
  sandboxOrgId: string;
@@ -130,6 +148,18 @@ export declare class Org extends AsyncOptionalCreatable<Org.Options> {
130
148
  interval?: Duration;
131
149
  async?: boolean;
132
150
  }): Promise<SandboxProcessObject>;
151
+ /**
152
+ * Refresh (update) a sandbox from a production org.
153
+ * 'this' needs to be a production org with sandbox licenses available
154
+ *
155
+ * @param sandboxInfo SandboxInfo to update the sandbox with
156
+ * @param options Wait: The amount of time to wait before timing out, Interval: The time interval between polling
157
+ */
158
+ refreshSandbox(sandboxInfo: SandboxInfo, options?: {
159
+ wait?: Duration;
160
+ interval?: Duration;
161
+ async?: boolean;
162
+ }): Promise<SandboxProcessObject>;
133
163
  /**
134
164
  *
135
165
  * @param sandboxReq SandboxRequest options to create the sandbox with
@@ -142,10 +172,10 @@ export declare class Org extends AsyncOptionalCreatable<Org.Options> {
142
172
  interval?: Duration;
143
173
  }): Promise<SandboxProcessObject>;
144
174
  /**
145
- * Resume a sandbox creation from a production org.
175
+ * Resume a sandbox create or refresh from a production org.
146
176
  * `this` needs to be a production org with sandbox licenses available.
147
177
  *
148
- * @param resumeSandboxRequest SandboxRequest options to create the sandbox with
178
+ * @param resumeSandboxRequest SandboxRequest options to create/refresh the sandbox with
149
179
  * @param options Wait: The amount of time to wait (default: 0 minutes) before timing out,
150
180
  * Interval: The time interval (default: 30 seconds) between polling
151
181
  */
package/lib/org/org.js CHANGED
@@ -52,7 +52,7 @@ const authInfo_1 = require("./authInfo");
52
52
  const scratchOrgCreate_1 = require("./scratchOrgCreate");
53
53
  const orgConfigProperties_1 = require("./orgConfigProperties");
54
54
  ;
55
- const messages = new messages_1.Messages('@salesforce/core', 'org', new Map([["notADevHub", "The provided dev hub username %s is not a valid dev hub."], ["noUsernameFound", "No username found."], ["noDevHubFound", "Unable to associate this scratch org with a DevHub."], ["deleteOrgHubError", "The Dev Hub org cannot be deleted."], ["insufficientAccessToDelete", "You do not have the appropriate permissions to delete a scratch org. Please contact your Salesforce admin."], ["scratchOrgNotFound", "Attempting to delete an expired or deleted org"], ["sandboxDeleteFailed", "The sandbox org deletion failed with a result of %s."], ["sandboxNotFound", "We can't find a SandboxProcess for the sandbox %s."], ["sandboxInfoCreateFailed", "The sandbox org creation failed with a result of %s."], ["missingAuthUsername", "The sandbox %s does not have an authorized username."], ["orgPollingTimeout", "Sandbox status is %s; timed out waiting for completion."], ["NotFoundOnDevHub", "The scratch org does not belong to the dev hub username %s."], ["AuthInfoOrgIdUndefined", "AuthInfo orgId is undefined."], ["sandboxCreateNotComplete", "The sandbox creation has not completed."], ["SandboxProcessNotFoundBySandboxName", "We can't find a SandboxProcess with the SandboxName %s."], ["MultiSandboxProcessNotFoundBySandboxName", "We found more than one SandboxProcess with the SandboxName %s."], ["sandboxNotResumable", "The sandbox %s cannot resume with status of %s."]]));
55
+ const messages = new messages_1.Messages('@salesforce/core', 'org', new Map([["notADevHub", "The provided dev hub username %s is not a valid dev hub."], ["noUsernameFound", "No username found."], ["noDevHubFound", "Unable to associate this scratch org with a DevHub."], ["deleteOrgHubError", "The Dev Hub org cannot be deleted."], ["insufficientAccessToDelete", "You do not have the appropriate permissions to delete a scratch org. Please contact your Salesforce admin."], ["scratchOrgNotFound", "Attempting to delete an expired or deleted org"], ["sandboxDeleteFailed", "The sandbox org deletion failed with a result of %s."], ["sandboxNotFound", "We can't find a SandboxProcess for the sandbox %s."], ["sandboxInfoCreateFailed", "The sandbox org creation failed with a result of %s."], ["sandboxInfoRefreshFailed", "The sandbox org refresh failed with a result of %s."], ["missingAuthUsername", "The sandbox %s does not have an authorized username."], ["orgPollingTimeout", "Sandbox status is %s; timed out waiting for completion."], ["NotFoundOnDevHub", "The scratch org does not belong to the dev hub username %s."], ["AuthInfoOrgIdUndefined", "AuthInfo orgId is undefined."], ["sandboxCreateNotComplete", "The sandbox creation has not completed."], ["SandboxProcessNotFoundBySandboxName", "We can't find a SandboxProcess with the SandboxName %s."], ["MultiSandboxProcessNotFoundBySandboxName", "We found more than one SandboxProcess with the SandboxName %s."], ["sandboxNotResumable", "The sandbox %s cannot resume with status of %s."]]));
56
56
  var OrgTypes;
57
57
  (function (OrgTypes) {
58
58
  OrgTypes["Scratch"] = "scratch";
@@ -72,6 +72,19 @@ function sandboxIsResumable(value) {
72
72
  return resumableSandboxStatus.includes(value);
73
73
  }
74
74
  exports.sandboxIsResumable = sandboxIsResumable;
75
+ const sandboxProcessFields = [
76
+ 'Id',
77
+ 'Status',
78
+ 'SandboxName',
79
+ 'SandboxInfoId',
80
+ 'LicenseType',
81
+ 'CreatedDate',
82
+ 'CopyProgress',
83
+ 'SandboxOrganization',
84
+ 'SourceId',
85
+ 'Description',
86
+ 'EndDate',
87
+ ];
75
88
  /**
76
89
  * Provides a way to manage a locally authenticated Org.
77
90
  *
@@ -141,6 +154,46 @@ class Org extends kit_1.AsyncOptionalCreatable {
141
154
  pollInterval,
142
155
  });
143
156
  }
157
+ /**
158
+ * Refresh (update) a sandbox from a production org.
159
+ * 'this' needs to be a production org with sandbox licenses available
160
+ *
161
+ * @param sandboxInfo SandboxInfo to update the sandbox with
162
+ * @param options Wait: The amount of time to wait before timing out, Interval: The time interval between polling
163
+ */
164
+ async refreshSandbox(sandboxInfo, options = {
165
+ wait: kit_1.Duration.minutes(6),
166
+ async: false,
167
+ interval: kit_1.Duration.seconds(30),
168
+ }) {
169
+ this.logger.debug(sandboxInfo, 'RefreshSandbox called with SandboxInfo');
170
+ const refreshResult = await this.connection.tooling.update('SandboxInfo', sandboxInfo);
171
+ this.logger.debug(refreshResult, 'Return from calling tooling.update');
172
+ if (!refreshResult.success) {
173
+ throw messages.createError('sandboxInfoRefreshFailed', [JSON.stringify(refreshResult)]);
174
+ }
175
+ const soql = `SELECT ${sandboxProcessFields.join(',')} FROM SandboxProcess WHERE SandboxName='${sandboxInfo.SandboxName}' ORDER BY CreatedDate DESC`;
176
+ const sbxProcessObjects = (await this.connection.tooling.query(soql)).records.filter((item) => !item.Status.startsWith('Del'));
177
+ this.logger.debug(sbxProcessObjects, `SandboxProcesses for ${sandboxInfo.SandboxName}`);
178
+ // throw if none found
179
+ if (sbxProcessObjects?.length === 0) {
180
+ throw new Error(`No SandboxProcesses found for: ${sandboxInfo.SandboxName}`);
181
+ }
182
+ const sandboxRefreshProgress = sbxProcessObjects[0];
183
+ const isAsync = !!options.async;
184
+ if (isAsync) {
185
+ // The user didn't want us to poll, so simply return the status
186
+ await lifecycleEvents_1.Lifecycle.getInstance().emit(SandboxEvents.EVENT_ASYNC_RESULT, sandboxRefreshProgress);
187
+ return sandboxRefreshProgress;
188
+ }
189
+ const [wait, pollInterval] = this.validateWaitOptions(options);
190
+ this.logger.debug(sandboxRefreshProgress, `refresh - pollStatusAndAuth sandboxProcessObj, max wait time of ${wait.minutes} minutes`);
191
+ return this.pollStatusAndAuth({
192
+ sandboxProcessObj: sandboxRefreshProgress,
193
+ wait,
194
+ pollInterval,
195
+ });
196
+ }
144
197
  /**
145
198
  *
146
199
  * @param sandboxReq SandboxRequest options to create the sandbox with
@@ -154,10 +207,10 @@ class Org extends kit_1.AsyncOptionalCreatable {
154
207
  return this.createSandbox(sandboxReq, options);
155
208
  }
156
209
  /**
157
- * Resume a sandbox creation from a production org.
210
+ * Resume a sandbox create or refresh from a production org.
158
211
  * `this` needs to be a production org with sandbox licenses available.
159
212
  *
160
- * @param resumeSandboxRequest SandboxRequest options to create the sandbox with
213
+ * @param resumeSandboxRequest SandboxRequest options to create/refresh the sandbox with
161
214
  * @param options Wait: The amount of time to wait (default: 0 minutes) before timing out,
162
215
  * Interval: The time interval (default: 30 seconds) between polling
163
216
  */
@@ -861,7 +914,7 @@ class Org extends kit_1.AsyncOptionalCreatable {
861
914
  async queryLatestSandboxProcessBySandboxName(sandboxNameIn) {
862
915
  const { tooling } = this.getConnection();
863
916
  this.logger.debug(`QueryLatestSandboxProcessBySandboxName called with SandboxName: ${sandboxNameIn}`);
864
- const queryStr = `SELECT Id, Status, SandboxName, SandboxInfoId, LicenseType, CreatedDate, CopyProgress, SandboxOrganization, SourceId, Description, EndDate FROM SandboxProcess WHERE SandboxName='${sandboxNameIn}' AND Status != 'D' ORDER BY CreatedDate DESC LIMIT 1`;
917
+ const queryStr = `SELECT ${sandboxProcessFields.join(',')} FROM SandboxProcess WHERE SandboxName='${sandboxNameIn}' AND Status != 'D' ORDER BY CreatedDate DESC LIMIT 1`;
865
918
  const queryResult = await tooling.query(queryStr);
866
919
  this.logger.debug(queryResult, 'Return from calling queryToolingApi');
867
920
  if (queryResult?.records?.length === 1) {
@@ -1071,6 +1124,17 @@ class Org extends kit_1.AsyncOptionalCreatable {
1071
1124
  oauth2Options.privateKey = productionAuthFields.privateKey;
1072
1125
  oauth2Options.clientId = productionAuthFields.clientId;
1073
1126
  }
1127
+ // Before creating the AuthInfo, delete any existing auth files for the sandbox.
1128
+ // This is common when refreshing sandboxes, and will cause AuthInfo to throw
1129
+ // because it doesn't want to overwrite existing auth files.
1130
+ const stateAggregator = await stateAggregator_1.StateAggregator.getInstance();
1131
+ try {
1132
+ await stateAggregator.orgs.read(sandboxRes.authUserName);
1133
+ await stateAggregator.orgs.remove(sandboxRes.authUserName);
1134
+ }
1135
+ catch (e) {
1136
+ // ignore since this is only for deleting existing auth files.
1137
+ }
1074
1138
  const authInfo = await authInfo_1.AuthInfo.create({
1075
1139
  username: sandboxRes.authUserName,
1076
1140
  oauth2Options,
@@ -1081,8 +1145,11 @@ class Org extends kit_1.AsyncOptionalCreatable {
1081
1145
  productionAuthFieldsUsername: productionAuthFields.username,
1082
1146
  ...oauth2Options,
1083
1147
  }, 'Creating AuthInfo for sandbox');
1084
- // save auth info for new sandbox
1085
- await authInfo.save();
1148
+ // save auth info for sandbox
1149
+ await authInfo.save({
1150
+ isScratch: false,
1151
+ isSandbox: true,
1152
+ });
1086
1153
  const sandboxOrgId = authInfo.getFields().orgId;
1087
1154
  if (!sandboxOrgId) {
1088
1155
  throw messages.createError('AuthInfoOrgIdUndefined');
@@ -1157,7 +1224,7 @@ class Org extends kit_1.AsyncOptionalCreatable {
1157
1224
  * @private
1158
1225
  */
1159
1226
  async querySandboxProcess(where) {
1160
- const soql = `SELECT Id, Status, SandboxName, SandboxInfoId, LicenseType, CreatedDate, CopyProgress, SandboxOrganization, SourceId, Description, EndDate FROM SandboxProcess WHERE ${where} ORDER BY CreatedDate DESC`;
1227
+ const soql = `SELECT ${sandboxProcessFields.join(',')} FROM SandboxProcess WHERE ${where} ORDER BY CreatedDate DESC`;
1161
1228
  const result = (await this.connection.tooling.query(soql)).records.filter((item) => !item.Status.startsWith('Del'));
1162
1229
  if (result.length === 0) {
1163
1230
  throw new sfError_1.SfError(`No record found for ${soql}`, connection_1.SingleRecordQueryErrors.NoRecords);
@@ -1204,15 +1271,15 @@ class Org extends kit_1.AsyncOptionalCreatable {
1204
1271
  return result;
1205
1272
  }
1206
1273
  catch (err) {
1207
- const error = err;
1274
+ const error = err instanceof Error ? err : sfError_1.SfError.wrap((0, ts_types_1.isString)(err) ? err : 'unknown');
1208
1275
  // There are cases where the endDate is set before the sandbox has actually completed.
1209
1276
  // In that case, the sandboxAuth call will throw a specific exception.
1210
1277
  if (error?.name === 'INVALID_STATUS') {
1211
- this.logger.debug('Error while authenticating the user', error?.toString());
1278
+ this.logger.debug('Error while authenticating the user:', error.message);
1212
1279
  }
1213
1280
  else {
1214
- // If it fails for any unexpected reason, just pass that through
1215
- throw sfError_1.SfError.wrap(error);
1281
+ // If it fails for any unexpected reason, rethrow
1282
+ throw error;
1216
1283
  }
1217
1284
  }
1218
1285
  }
package/messages/org.md CHANGED
@@ -34,6 +34,10 @@ We can't find a SandboxProcess for the sandbox %s.
34
34
 
35
35
  The sandbox org creation failed with a result of %s.
36
36
 
37
+ # sandboxInfoRefreshFailed
38
+
39
+ The sandbox org refresh failed with a result of %s.
40
+
37
41
  # missingAuthUsername
38
42
 
39
43
  The sandbox %s does not have an authorized username.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/core",
3
- "version": "6.5.6",
3
+ "version": "6.6.0",
4
4
  "description": "Core libraries to interact with SFDX projects, orgs, and APIs.",
5
5
  "main": "lib/exported",
6
6
  "types": "lib/exported.d.ts",