@salesforce/core 2.35.0 → 2.35.3

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/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [2.35.3](https://github.com/forcedotcom/sfdx-core/compare/v2.35.2...v2.35.3) (2022-02-23)
6
+
7
+ ### Bug Fixes
8
+
9
+ - always try to clean up aliases and configs ([cd0adc4](https://github.com/forcedotcom/sfdx-core/commit/cd0adc456978f27fc2d44cbcb61632925edcccd9))
10
+
11
+ ### [2.35.2](https://github.com/forcedotcom/sfdx-core/compare/v2.35.1...v2.35.2) (2022-02-16)
12
+
13
+ ### Bug Fixes
14
+
15
+ - network error tolerance ([#517](https://github.com/forcedotcom/sfdx-core/issues/517)) ([676ebfe](https://github.com/forcedotcom/sfdx-core/commit/676ebfe58b13826b53f461b2fef321c21f583004))
16
+ - remove redundant warnings about no listerners on warnings ([7a5bd23](https://github.com/forcedotcom/sfdx-core/commit/7a5bd2390713da929e886f41d9dcbc811104f99a))
17
+
18
+ ### [2.35.1](https://github.com/forcedotcom/sfdx-core/compare/v2.35.0...v2.35.1) (2022-02-10)
19
+
20
+ ### Bug Fixes
21
+
22
+ - add error message on failed settings deploy ([e218b1e](https://github.com/forcedotcom/sfdx-core/commit/e218b1e40414ea9e4fec256b74224626d96eff4a))
23
+ - prefer instanceUrl for loginUrl on user:create ([#518](https://github.com/forcedotcom/sfdx-core/issues/518)) ([c070a87](https://github.com/forcedotcom/sfdx-core/commit/c070a871861409dea722e85845eeb91f262ab66f))
24
+
5
25
  ## [2.35.0](https://github.com/forcedotcom/sfdx-core/compare/v2.34.2...v2.35.0) (2022-01-25)
6
26
 
7
27
  ### Bug Fixes
@@ -170,7 +170,7 @@ class Lifecycle {
170
170
  */
171
171
  async emit(eventName, data) {
172
172
  const listeners = this.getListeners(eventName);
173
- if (listeners.length === 0) {
173
+ if (listeners.length === 0 && eventName !== Lifecycle.warningEventName) {
174
174
  this.debug(`A lifecycle event with the name ${eventName} does not exist. An event must be registered before it can be emitted.`);
175
175
  }
176
176
  else {
package/lib/org.js CHANGED
@@ -644,35 +644,33 @@ class Org extends kit_1.AsyncCreatable {
644
644
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
645
645
  async removeUsers(throwWhenRemoveFails) {
646
646
  this.logger.debug(`Removing users associate with org: ${this.getOrgId()}`);
647
- const config = await this.retrieveOrgUsersConfig();
647
+ const [config, authInfos, aliases] = await Promise.all([
648
+ this.retrieveOrgUsersConfig(),
649
+ this.readUserAuthFiles(),
650
+ aliases_1.Aliases.create(aliases_1.Aliases.getDefaultOptions()),
651
+ ]);
648
652
  this.logger.debug(`using path for org users: ${config.getPath()}`);
649
- if (await config.exists()) {
650
- const authInfos = await this.readUserAuthFiles();
651
- const aliases = await aliases_1.Aliases.create(aliases_1.Aliases.getDefaultOptions());
652
- this.logger.info(`Cleaning up usernames in org: ${this.getOrgId()}`);
653
- for (const auth of authInfos) {
654
- const username = auth.getFields().username;
655
- const aliasKeys = (username && aliases.getKeysByValue(username)) || [];
656
- aliases.unsetAll(aliasKeys);
657
- let orgForUser;
658
- if (username === this.getUsername()) {
659
- orgForUser = this;
660
- }
661
- else {
662
- const info = await authInfo_1.AuthInfo.create({ username });
663
- const connection = await connection_1.Connection.create({ authInfo: info });
664
- orgForUser = await Org.create({ connection });
665
- }
666
- const orgType = this.isDevHubOrg() ? config_1.Config.DEFAULT_DEV_HUB_USERNAME : config_1.Config.DEFAULT_USERNAME;
667
- const configInfo = orgForUser.configAggregator.getInfo(orgType);
668
- if ((configInfo.value === username || aliasKeys.includes(configInfo.value)) &&
669
- (configInfo.isGlobal() || configInfo.isLocal())) {
670
- await config_1.Config.update(configInfo.isGlobal(), orgType, undefined);
671
- }
672
- await orgForUser.removeAuth();
673
- }
674
- await aliases.write();
675
- }
653
+ this.logger.info(`Cleaning up usernames in org: ${this.getOrgId()}`);
654
+ await Promise.all(authInfos
655
+ .map((auth) => auth.getFields().username)
656
+ .map(async (username) => {
657
+ const aliasKeys = (username && aliases.getKeysByValue(username)) || [];
658
+ aliases.unsetAll(aliasKeys);
659
+ const orgForUser = username === this.getUsername()
660
+ ? this
661
+ : await Org.create({
662
+ connection: await connection_1.Connection.create({ authInfo: await authInfo_1.AuthInfo.create({ username }) }),
663
+ });
664
+ const orgType = this.isDevHubOrg() ? config_1.Config.DEFAULT_DEV_HUB_USERNAME : config_1.Config.DEFAULT_USERNAME;
665
+ const configInfo = orgForUser.configAggregator.getInfo(orgType);
666
+ const needsConfigUpdate = (configInfo.isGlobal() || configInfo.isLocal()) &&
667
+ (configInfo.value === username || aliasKeys.includes(configInfo.value));
668
+ return [
669
+ orgForUser.removeAuth(),
670
+ needsConfigUpdate ? config_1.Config.update(configInfo.isGlobal(), orgType, undefined) : undefined,
671
+ ].filter(Boolean);
672
+ }));
673
+ await aliases.write();
676
674
  }
677
675
  /**
678
676
  * Remove an associate sandbox config.
@@ -1,4 +1,4 @@
1
1
  import { Optional } from '@salesforce/ts-types';
2
2
  import { Logger } from './logger';
3
3
  import { ScratchOrgInfo } from './scratchOrgInfoApi';
4
- export declare const checkScratchOrgInfoForErrors: (orgInfo: ScratchOrgInfo, hubUsername: Optional<string>, logger: Logger) => ScratchOrgInfo;
4
+ export declare const checkScratchOrgInfoForErrors: (orgInfo: Optional<ScratchOrgInfo>, hubUsername: Optional<string>, logger: Logger) => ScratchOrgInfo;
@@ -29,6 +29,9 @@ const optionalErrorCodeMessage = (errorCode, args) => {
29
29
  }
30
30
  };
31
31
  const checkScratchOrgInfoForErrors = (orgInfo, hubUsername, logger) => {
32
+ if (!orgInfo) {
33
+ throw new sfdxError_1.SfdxError('No scratch org info found.', 'ScratchOrgInfoNotFound');
34
+ }
32
35
  if (orgInfo.Status === 'Active') {
33
36
  return orgInfo;
34
37
  }
@@ -1,7 +1,6 @@
1
1
  import { Optional } from '@salesforce/ts-types';
2
2
  import { Duration } from '@salesforce/kit';
3
3
  import { RecordResult } from 'jsforce';
4
- import { retry } from 'ts-retry-promise';
5
4
  import { Org } from './org';
6
5
  import { AuthInfo } from './authInfo';
7
6
  import SettingsGenerator, { ObjectSetting } from './scratchOrgSettingsGenerator';
@@ -18,6 +18,7 @@ const authInfo_1 = require("./authInfo");
18
18
  const messages_1 = require("./messages");
19
19
  const sfdxError_1 = require("./sfdxError");
20
20
  const sfdcUrl_1 = require("./util/sfdcUrl");
21
+ const pollingClient_1 = require("./status/pollingClient");
21
22
  const myDomainResolver_1 = require("./status/myDomainResolver");
22
23
  const scratchOrgErrorCodes_1 = require("./scratchOrgErrorCodes");
23
24
  messages_1.Messages.importMessagesDirectory(__dirname);
@@ -251,30 +252,53 @@ const pollForScratchOrgInfo = async (hubOrg, scratchOrgInfoId,
251
252
  timeout = kit_1.Duration.minutes(15)) => {
252
253
  const logger = await logger_1.Logger.child('scratchOrgInfoApi-pollForScratchOrgInfo');
253
254
  logger.debug(`PollingTimeout in minutes: ${timeout.minutes}`);
254
- const response = await ts_retry_promise_1.retry(async () => {
255
- const resultInProgress = await hubOrg
256
- .getConnection()
257
- .sobject('ScratchOrgInfo')
258
- .retrieve(scratchOrgInfoId);
259
- logger.debug(`polling client result: ${JSON.stringify(resultInProgress, null, 4)}`);
260
- // Once it's "done" we can return it
261
- if (resultInProgress.Status === 'Active' || resultInProgress.Status === 'Error') {
262
- return resultInProgress;
255
+ const pollingOptions = {
256
+ async poll() {
257
+ try {
258
+ const resultInProgress = await hubOrg
259
+ .getConnection()
260
+ .sobject('ScratchOrgInfo')
261
+ .retrieve(scratchOrgInfoId);
262
+ logger.debug(`polling client result: ${JSON.stringify(resultInProgress, null, 4)}`);
263
+ // Once it's "done" we can return it
264
+ if (resultInProgress.Status === 'Active' || resultInProgress.Status === 'Error') {
265
+ return {
266
+ completed: true,
267
+ payload: resultInProgress,
268
+ };
269
+ }
270
+ logger.debug(`Scratch org status is ${resultInProgress.Status}`);
271
+ return {
272
+ completed: false,
273
+ };
274
+ }
275
+ catch (error) {
276
+ logger.debug(`An error occurred trying to retrieve scratchOrgInfo for ${scratchOrgInfoId}`);
277
+ logger.debug(`Error: ${error.message}`);
278
+ logger.debug('Re-trying deploy check again....');
279
+ return {
280
+ completed: false,
281
+ };
282
+ }
283
+ },
284
+ timeout,
285
+ frequency: kit_1.Duration.seconds(1),
286
+ timeoutErrorName: 'ScratchOrgInfoTimeoutError',
287
+ };
288
+ const client = await pollingClient_1.PollingClient.create(pollingOptions);
289
+ try {
290
+ const resultInProgress = await client.subscribe();
291
+ return scratchOrgErrorCodes_1.checkScratchOrgInfoForErrors(resultInProgress, hubOrg.getUsername(), logger);
292
+ }
293
+ catch (error) {
294
+ const err = error;
295
+ if (err.message) {
296
+ throw sfdxError_1.SfdxError.wrap(err);
263
297
  }
264
- // all other statuses, OR lack of status (e.g. network errors) will cause a retry
265
- throw new sfdxError_1.SfdxError(`Scratch org status is ${resultInProgress.Status}`);
266
- }, {
267
- retries: 'INFINITELY',
268
- timeout: timeout.milliseconds,
269
- delay: kit_1.Duration.seconds(2).milliseconds,
270
- backoff: 'LINEAR',
271
- maxBackOff: kit_1.Duration.seconds(30).milliseconds,
272
- }).catch(() => {
273
298
  throw new sfdxError_1.SfdxError(`The scratch org did not complete within ${timeout.minutes} minutes`, 'orgCreationTimeout', [
274
299
  'Try your force:org:create command again with a longer --wait value',
275
300
  ]);
276
- });
277
- return scratchOrgErrorCodes_1.checkScratchOrgInfoForErrors(response, hubOrg.getUsername(), logger);
301
+ }
278
302
  };
279
303
  exports.pollForScratchOrgInfo = pollForScratchOrgInfo;
280
304
  /**
@@ -7,9 +7,7 @@
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.RequestStatus = void 0;
10
- // Node
11
10
  const path = require("path");
12
- // @salesforce
13
11
  const kit_1 = require("@salesforce/kit");
14
12
  const ts_types_1 = require("@salesforce/ts-types");
15
13
  const js2xmlparser = require("js2xmlparser");
@@ -77,7 +75,7 @@ class SettingsGenerator {
77
75
  const pollingOptions = {
78
76
  async poll() {
79
77
  try {
80
- result = await connection.metadata.checkDeployStatus(id);
78
+ result = await connection.metadata.checkDeployStatus(id, true);
81
79
  logger.debug(`Deploy id: ${id} status: ${result.status}`);
82
80
  if (breakPolling.includes(result.status)) {
83
81
  return {
@@ -103,9 +101,13 @@ class SettingsGenerator {
103
101
  timeoutErrorName: 'DeployingSettingsTimeoutError',
104
102
  };
105
103
  const client = await pollingClient_1.PollingClient.create(pollingOptions);
106
- const status = (await client.subscribe());
104
+ const status = await client.subscribe();
107
105
  if (status !== RequestStatus.Succeeded) {
108
- const error = new sfdxError_1.SfdxError(`A scratch org was created with username ${username}, but the settings failed to deploy`, 'ProblemDeployingSettings');
106
+ const componentFailures = ts_types_1.ensureObject(result.details).componentFailures;
107
+ const failures = (Array.isArray(componentFailures) ? componentFailures : [componentFailures])
108
+ .map((failure) => failure.problem)
109
+ .join('\n');
110
+ const error = new sfdxError_1.SfdxError(`A scratch org was created with username ${username}, but the settings failed to deploy due to: \n${failures}`, 'ProblemDeployingSettings');
109
111
  error.setData(result);
110
112
  throw error;
111
113
  }
@@ -38,7 +38,7 @@ export declare class PollingClient extends AsyncOptionalCreatable<PollingClient.
38
38
  * Returns a promise to call the specified polling function using the interval and timeout specified
39
39
  * in the polling options.
40
40
  */
41
- subscribe(): Promise<AnyJson | undefined>;
41
+ subscribe<T = AnyJson>(): Promise<T | undefined>;
42
42
  }
43
43
  export declare namespace PollingClient {
44
44
  /**
@@ -12,6 +12,7 @@ const ts_types_1 = require("@salesforce/ts-types");
12
12
  const ts_retry_promise_1 = require("ts-retry-promise");
13
13
  const logger_1 = require("../logger");
14
14
  const sfdxError_1 = require("../sfdxError");
15
+ const lifecycleEvents_1 = require("../lifecycleEvents");
15
16
  /**
16
17
  * This is a polling client that can be used to poll the status of long running tasks. It can be used as a replacement
17
18
  * for Streaming when streaming topics are not available or when streaming handshakes are failing. Why wouldn't you
@@ -51,6 +52,7 @@ class PollingClient extends kit_1.AsyncOptionalCreatable {
51
52
  * Returns a promise to call the specified polling function using the interval and timeout specified
52
53
  * in the polling options.
53
54
  */
55
+ // TODO v3.0 remove undefined as this method ensures that the payload is always returned
54
56
  async subscribe() {
55
57
  var _a;
56
58
  let errorInPollingFunction; // keep this around for returning in the catch block
@@ -60,11 +62,18 @@ class PollingClient extends kit_1.AsyncOptionalCreatable {
60
62
  result = await this.options.poll();
61
63
  }
62
64
  catch (error) {
63
- errorInPollingFunction = error;
65
+ const err = (errorInPollingFunction = error);
66
+ if (['ETIMEDOUT', 'ENOTFOUND', 'ECONNRESET', 'socket hang up'].some((retryableNetworkError) => err.message.includes(retryableNetworkError))) {
67
+ this.logger.debug('Network error on the request', err);
68
+ await lifecycleEvents_1.Lifecycle.getInstance().emitWarning('Network error occurred. Continuing to poll.');
69
+ throw sfdxError_1.SfdxError.wrap(err);
70
+ }
64
71
  // there was an actual error thrown, so we don't want to keep retrying
65
- throw new ts_retry_promise_1.NotRetryableError(error.name);
72
+ throw new ts_retry_promise_1.NotRetryableError(err.name);
66
73
  }
67
74
  if (result.completed) {
75
+ // TODO v3.0: payload should be of type T always so that
76
+ // consumers get the same type in return.
68
77
  return result.payload;
69
78
  }
70
79
  throw new Error('Operation did not complete. Retrying...'); // triggers a retry
package/lib/user.js CHANGED
@@ -280,6 +280,7 @@ class User extends kit_1.AsyncCreatable {
280
280
  * ```
281
281
  */
282
282
  async createUser(fields) {
283
+ var _a;
283
284
  // Create a user and get a refresh token
284
285
  const refreshTokenSecret = await this.createUserInternal(fields);
285
286
  // Create the initial auth info
@@ -287,7 +288,8 @@ class User extends kit_1.AsyncCreatable {
287
288
  const adminUserAuthFields = authInfo.getFields(true);
288
289
  // Setup oauth options for the new user
289
290
  const oauthOptions = {
290
- loginUrl: adminUserAuthFields.loginUrl,
291
+ // Communities users require the instance for auth
292
+ loginUrl: (_a = adminUserAuthFields.instanceUrl) !== null && _a !== void 0 ? _a : adminUserAuthFields.loginUrl,
291
293
  refreshToken: refreshTokenSecret.buffer.value((buffer) => buffer.toString('utf8')),
292
294
  clientId: adminUserAuthFields.clientId,
293
295
  clientSecret: adminUserAuthFields.clientSecret,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/core",
3
- "version": "2.35.0",
3
+ "version": "2.35.3",
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",
@@ -82,7 +82,7 @@
82
82
  "nyc": "^15.1.0",
83
83
  "prettier": "^2.0.5",
84
84
  "pretty-quick": "^3.1.0",
85
- "shelljs": "0.8.1",
85
+ "shelljs": "0.8.5",
86
86
  "sinon": "10.0.0",
87
87
  "ts-node": "^10.0.0",
88
88
  "typescript": "^4.1.3"