@salesforce/core 3.21.5 → 3.22.1
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 +15 -0
- package/README.md +75 -9
- package/lib/config/configStore.js +1 -0
- package/lib/config/tokensConfig.js +1 -1
- package/lib/exported.d.ts +2 -2
- package/lib/exported.js +2 -4
- package/lib/org/authInfo.d.ts +2 -0
- package/lib/org/authInfo.js +15 -14
- package/lib/org/connection.js +1 -1
- package/lib/org/org.js +1 -1
- package/lib/org/permissionSetAssignment.js +2 -1
- package/lib/org/scratchOrgCreate.js +1 -1
- package/lib/org/scratchOrgInfoApi.js +2 -3
- package/lib/org/user.js +9 -9
- package/lib/sfProject.js +6 -2
- package/lib/stateAggregator/accessors/orgAccessor.d.ts +69 -0
- package/lib/stateAggregator/accessors/orgAccessor.js +69 -0
- package/lib/stateAggregator/accessors/tokenAccessor.d.ts +41 -0
- package/lib/stateAggregator/accessors/tokenAccessor.js +41 -0
- package/lib/stateAggregator/globalInfoConfig.js +1 -1
- package/lib/testSetup.d.ts +101 -7
- package/lib/testSetup.js +113 -18
- package/package.json +4 -2
- package/lib/config/keychainConfig.d.ts +0 -19
- package/lib/config/keychainConfig.js +0 -44
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
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
|
+
### [3.22.1](https://github.com/forcedotcom/sfdx-core/compare/v3.22.0...v3.22.1) (2022-06-28)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- encrypted key regex tests will no longer be stateful ([06b7fa2](https://github.com/forcedotcom/sfdx-core/commit/06b7fa2f41401155b472c84f13cbf5608150a43e))
|
|
10
|
+
- update dev-scripts so yarn build won't change line endings for LICENSE.txt on Windows ([ec5e48e](https://github.com/forcedotcom/sfdx-core/commit/ec5e48ee1dab2b3999f630aa56c53d353baa717e))
|
|
11
|
+
|
|
12
|
+
## [3.22.0](https://github.com/forcedotcom/sfdx-core/compare/v3.21.6...v3.22.0) (2022-06-23)
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
- modify uniqid to accept length and template ([#604](https://github.com/forcedotcom/sfdx-core/issues/604)) ([1fd1b5c](https://github.com/forcedotcom/sfdx-core/commit/1fd1b5c40ab7f9b4d66eada94f3ecfa149b263b7))
|
|
17
|
+
|
|
18
|
+
### [3.21.6](https://github.com/forcedotcom/sfdx-core/compare/v3.21.5...v3.21.6) (2022-06-23)
|
|
19
|
+
|
|
5
20
|
### [3.21.5](https://github.com/forcedotcom/sfdx-core/compare/v3.21.4...v3.21.5) (2022-06-23)
|
|
6
21
|
|
|
7
22
|
### Bug Fixes
|
package/README.md
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
[](https://www.npmjs.com/package/@salesforce/core)
|
|
2
2
|
[](https://circleci.com/gh/forcedotcom/sfdx-core)
|
|
3
3
|
|
|
4
|
+
- [Description](#description)
|
|
5
|
+
- [Usage](#usage)
|
|
6
|
+
- [Contributing](#contributing)
|
|
7
|
+
- [Using TestSetup](#using-testsetup)
|
|
8
|
+
- [Mocking Authorizations](#mocking-authorizations)
|
|
9
|
+
- [Mocking Config Files](#mocking-config-files)
|
|
10
|
+
- [Using the Built-in Sinon Sandboxes](#using-the-built-in-sinon-sandboxes)
|
|
11
|
+
- [Testing Expected Failures](#testing-expected-failures)
|
|
12
|
+
- [Testing Log Lines](#testing-log-lines)
|
|
13
|
+
|
|
4
14
|
# Description
|
|
5
15
|
|
|
6
|
-
The @salesforce/core library provides client-side management of Salesforce DX projects, org authentication, connections to Salesforce APIs, and other utilities. Much of the core functionality that powers the
|
|
16
|
+
The @salesforce/core library provides client-side management of Salesforce DX projects, org authentication, connections to Salesforce APIs, and other utilities. Much of the core functionality that powers the Salesforce CLI plugins comes from this library. You can use this functionality in your plugins too.
|
|
7
17
|
|
|
8
18
|
# Usage
|
|
9
19
|
|
|
@@ -13,16 +23,11 @@ See the [API documentation](https://forcedotcom.github.io/sfdx-core/).
|
|
|
13
23
|
|
|
14
24
|
If you are interested in contributing, please take a look at the [CONTRIBUTING](CONTRIBUTING.md) guide.
|
|
15
25
|
|
|
16
|
-
# Related Docs and Repositories
|
|
17
|
-
|
|
18
|
-
- [@salesforce/command](https://github.com/forcedotcom/cli-packages/tree/main/packages/command) - Contains base Salesforce CLI command, `SfdxCommand`.
|
|
19
|
-
- [@salesforce/plugin-generator](https://github.com/forcedotcom/sfdx-plugin-generate) - The generator plug-in for building plug-ins for Salesforce CLI.
|
|
20
|
-
|
|
21
26
|
# Using TestSetup
|
|
22
27
|
|
|
23
28
|
The Salesforce DX Core Library provides a unit testing utility to help with mocking and sand-boxing core components. This feature allows unit tests to execute without needing to make API calls to salesforce.com.
|
|
24
29
|
|
|
25
|
-
## Mocking
|
|
30
|
+
## Mocking Authorizations
|
|
26
31
|
|
|
27
32
|
Here you can mock authorization for a Salesforce scratch org.
|
|
28
33
|
|
|
@@ -77,6 +82,43 @@ describe('Mocking a force server call', () => {
|
|
|
77
82
|
});
|
|
78
83
|
```
|
|
79
84
|
|
|
85
|
+
## Mocking Config Files
|
|
86
|
+
|
|
87
|
+
You can mock the contents of various config files
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { strictEqual } from 'assert';
|
|
91
|
+
import { MockTestOrgData, testSetup } from '@salesforce/core/lib/testSetup';
|
|
92
|
+
import { StateAggregator, OrgConfigProperties } from '@salesforce/core';
|
|
93
|
+
|
|
94
|
+
const $$ = testSetup();
|
|
95
|
+
|
|
96
|
+
describe('Mocking Aliases', () => {
|
|
97
|
+
it('example', async () => {
|
|
98
|
+
const testData = new MockTestOrgData();
|
|
99
|
+
await $$.stubAliases({ myAlias: testData.username });
|
|
100
|
+
const alias = (await StateAggregator.getInstance()).aliases.get(testData.username);
|
|
101
|
+
strictEqual(alias, 'myAlais');
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe('Mocking Config', () => {
|
|
106
|
+
it('example', async () => {
|
|
107
|
+
const testData = new MockTestOrgData();
|
|
108
|
+
await $$.stubConfig({ [OrgConfigProperties.TARGET_ORG]: testData.username });
|
|
109
|
+
const {value} = (await ConfigAggregator.create()).getInfo(OrgConfigProperties.TARGET_ORG);
|
|
110
|
+
strictEqual(value, testData.username);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
describe('Mocking Arbitrary Config Files', () => {
|
|
115
|
+
it('example', async () => {
|
|
116
|
+
// MyConfigFile must extend the ConfigFile class in order for this to work properly.
|
|
117
|
+
$$.setConfigStubContents('MyConfigFile', { contents: { foo: 'bar' } });
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
80
122
|
## Using the Built-in Sinon Sandboxes
|
|
81
123
|
|
|
82
124
|
sfdx-core uses Sinon as its underlying mocking system. If you're unfamiliar with Sinon and it's sandboxing concept you can find more information here:
|
|
@@ -126,6 +168,30 @@ describe('Testing for expected errors', () => {
|
|
|
126
168
|
});
|
|
127
169
|
```
|
|
128
170
|
|
|
171
|
+
You can also use `shouldThrowSync` for syncrhonous functions you expect to fail
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
import { SfError } from '@salesforce/core';
|
|
175
|
+
import { shouldThrowSync } from '@salesforce/core/lib/testSetup';
|
|
176
|
+
import { strictEqual } from 'assert';
|
|
177
|
+
|
|
178
|
+
class TestObject {
|
|
179
|
+
public static method() {
|
|
180
|
+
throw new SfError('Error', 'ExpectedError');
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
describe('Testing for expected errors', () => {
|
|
185
|
+
it('example', async () => {
|
|
186
|
+
try {
|
|
187
|
+
shouldThrowSync(() => TestObject.method());
|
|
188
|
+
} catch (e) {
|
|
189
|
+
strictEqual(e.name, 'ExpectedError');
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
129
195
|
## Testing Log Lines
|
|
130
196
|
|
|
131
197
|
It's also useful to check expected values and content from log lines. TestSetup configures the sfdx-core logger to use an in memory LogLine storage structure. These can be easily accessed from tests.
|
|
@@ -151,9 +217,9 @@ class TestObject {
|
|
|
151
217
|
|
|
152
218
|
describe('Testing log lines', () => {
|
|
153
219
|
it('example', async () => {
|
|
154
|
-
const obj
|
|
220
|
+
const obj = new TestObject($$.TEST_LOGGER);
|
|
155
221
|
obj.method();
|
|
156
|
-
const records
|
|
222
|
+
const records = $$.TEST_LOGGER.getBufferedRecords();
|
|
157
223
|
strictEqual(records.length, 1);
|
|
158
224
|
strictEqual(records[0].msg, TEST_STRING);
|
|
159
225
|
});
|
|
@@ -346,5 +346,6 @@ class BaseConfigStore extends kit_1.AsyncOptionalCreatable {
|
|
|
346
346
|
}
|
|
347
347
|
}
|
|
348
348
|
exports.BaseConfigStore = BaseConfigStore;
|
|
349
|
+
// If encryptedKeys is an array of RegExps, they should not contain the /g (global) or /y (sticky) flags to avoid stateful issues.
|
|
349
350
|
BaseConfigStore.encryptedKeys = [];
|
|
350
351
|
//# sourceMappingURL=configStore.js.map
|
|
@@ -24,5 +24,5 @@ class TokensConfig extends configFile_1.ConfigFile {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
exports.TokensConfig = TokensConfig;
|
|
27
|
-
TokensConfig.encryptedKeys = [/token/
|
|
27
|
+
TokensConfig.encryptedKeys = [/token/i, /password/i, /secret/i];
|
|
28
28
|
//# sourceMappingURL=tokensConfig.js.map
|
package/lib/exported.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ export { OAuth2Config } from 'jsforce';
|
|
|
2
2
|
export { ConfigFile } from './config/configFile';
|
|
3
3
|
export { TTLConfig } from './config/ttlConfig';
|
|
4
4
|
export { envVars, EnvironmentVariable, SUPPORTED_ENV_VARS, EnvVars } from './config/envVars';
|
|
5
|
-
export {
|
|
6
|
-
export { GlobalInfo,
|
|
5
|
+
export { ConfigContents, ConfigEntry, ConfigStore, ConfigValue } from './config/configStore';
|
|
6
|
+
export { GlobalInfo, SfInfo, SfInfoKeys, SfOrg, SfOrgs, SfToken, SfTokens, StateAggregator } from './stateAggregator';
|
|
7
7
|
export { DeviceOauthService, DeviceCodeResponse, DeviceCodePollingResponse } from './deviceOauthService';
|
|
8
8
|
export { OrgUsersConfig } from './config/orgUsersConfig';
|
|
9
9
|
export { ConfigPropertyMeta, ConfigPropertyMetaInput, Config, SfdxPropertyKeys, SfConfigProperties, SFDX_ALLOWED_PROPERTIES, SF_ALLOWED_PROPERTIES, } from './config/config';
|
package/lib/exported.js
CHANGED
|
@@ -16,8 +16,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
17
17
|
};
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.MyDomainResolver = exports.StreamingClient = exports.CometClient = exports.PollingClient = exports.SfdxError = exports.SfError = exports.SchemaValidator = exports.SchemaPrinter = exports.SfdxProjectJson = exports.SfdxProject = exports.SfProjectJson = exports.SfProject = exports.ORG_CONFIG_ALLOWED_PROPERTIES = exports.OrgConfigProperties = exports.OrgTypes = exports.SandboxEvents = exports.Org = exports.Messages = exports.Logger = exports.LoggerLevel = exports.getJwtAudienceUrl = exports.SfdcUrl = exports.WebOAuthServer = exports.Lifecycle = exports.Global = exports.Mode = exports.SFDX_HTTP_HEADERS = exports.Connection = exports.AuthRemover = exports.AuthInfo = exports.SfdxConfigAggregator = exports.ConfigAggregator = exports.SandboxRequestCache = exports.SF_ALLOWED_PROPERTIES = exports.SFDX_ALLOWED_PROPERTIES = exports.SfConfigProperties = exports.SfdxPropertyKeys = exports.Config = exports.OrgUsersConfig = exports.DeviceOauthService = exports.StateAggregator = exports.SfInfoKeys = exports.GlobalInfo = exports.
|
|
20
|
-
exports.ScratchOrgCache = exports.scratchOrgLifecycleStages = exports.scratchOrgLifecycleEventName = exports.scratchOrgResume = exports.scratchOrgCreate = exports.PermissionSetAssignment = exports.User = exports.REQUIRED_FIELDS =
|
|
19
|
+
exports.DefaultUserFields = exports.MyDomainResolver = exports.StreamingClient = exports.CometClient = exports.PollingClient = exports.SfdxError = exports.SfError = exports.SchemaValidator = exports.SchemaPrinter = exports.SfdxProjectJson = exports.SfdxProject = exports.SfProjectJson = exports.SfProject = exports.ORG_CONFIG_ALLOWED_PROPERTIES = exports.OrgConfigProperties = exports.OrgTypes = exports.SandboxEvents = exports.Org = exports.Messages = exports.Logger = exports.LoggerLevel = exports.getJwtAudienceUrl = exports.SfdcUrl = exports.WebOAuthServer = exports.Lifecycle = exports.Global = exports.Mode = exports.SFDX_HTTP_HEADERS = exports.Connection = exports.AuthRemover = exports.AuthInfo = exports.SfdxConfigAggregator = exports.ConfigAggregator = exports.SandboxRequestCache = exports.SF_ALLOWED_PROPERTIES = exports.SFDX_ALLOWED_PROPERTIES = exports.SfConfigProperties = exports.SfdxPropertyKeys = exports.Config = exports.OrgUsersConfig = exports.DeviceOauthService = exports.StateAggregator = exports.SfInfoKeys = exports.GlobalInfo = exports.EnvVars = exports.SUPPORTED_ENV_VARS = exports.EnvironmentVariable = exports.envVars = exports.TTLConfig = exports.ConfigFile = void 0;
|
|
20
|
+
exports.ScratchOrgCache = exports.scratchOrgLifecycleStages = exports.scratchOrgLifecycleEventName = exports.scratchOrgResume = exports.scratchOrgCreate = exports.PermissionSetAssignment = exports.User = exports.REQUIRED_FIELDS = void 0;
|
|
21
21
|
const messages_1 = require("./messages");
|
|
22
22
|
messages_1.Messages.importMessagesDirectory(__dirname);
|
|
23
23
|
var configFile_1 = require("./config/configFile");
|
|
@@ -29,8 +29,6 @@ Object.defineProperty(exports, "envVars", { enumerable: true, get: function () {
|
|
|
29
29
|
Object.defineProperty(exports, "EnvironmentVariable", { enumerable: true, get: function () { return envVars_1.EnvironmentVariable; } });
|
|
30
30
|
Object.defineProperty(exports, "SUPPORTED_ENV_VARS", { enumerable: true, get: function () { return envVars_1.SUPPORTED_ENV_VARS; } });
|
|
31
31
|
Object.defineProperty(exports, "EnvVars", { enumerable: true, get: function () { return envVars_1.EnvVars; } });
|
|
32
|
-
var configStore_1 = require("./config/configStore");
|
|
33
|
-
Object.defineProperty(exports, "BaseConfigStore", { enumerable: true, get: function () { return configStore_1.BaseConfigStore; } });
|
|
34
32
|
var stateAggregator_1 = require("./stateAggregator");
|
|
35
33
|
Object.defineProperty(exports, "GlobalInfo", { enumerable: true, get: function () { return stateAggregator_1.GlobalInfo; } });
|
|
36
34
|
Object.defineProperty(exports, "SfInfoKeys", { enumerable: true, get: function () { return stateAggregator_1.SfInfoKeys; } });
|
package/lib/org/authInfo.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare type OAuth2Config = JsforceOAuth2Config & {
|
|
|
8
8
|
authCode?: string;
|
|
9
9
|
refreshToken?: string;
|
|
10
10
|
loginUrl?: string;
|
|
11
|
+
username?: string;
|
|
11
12
|
};
|
|
12
13
|
/**
|
|
13
14
|
* Fields for authorization, org, and local information.
|
|
@@ -289,6 +290,7 @@ export declare class AuthInfo extends AsyncOptionalCreatable<AuthInfo.Options> {
|
|
|
289
290
|
private loadDecryptedAuthFromConfig;
|
|
290
291
|
private isTokenOptions;
|
|
291
292
|
private refreshFn;
|
|
293
|
+
private readJwtKey;
|
|
292
294
|
private authJwt;
|
|
293
295
|
private tryJwtAuth;
|
|
294
296
|
private buildRefreshTokenConfig;
|
package/lib/org/authInfo.js
CHANGED
|
@@ -522,7 +522,7 @@ class AuthInfo extends kit_1.AsyncOptionalCreatable {
|
|
|
522
522
|
async init() {
|
|
523
523
|
this.stateAggregator = await stateAggregator_1.StateAggregator.getInstance();
|
|
524
524
|
const username = this.options.username;
|
|
525
|
-
const authOptions = this.options.oauth2Options || this.options.accessTokenOptions;
|
|
525
|
+
const authOptions = (this.options.oauth2Options || this.options.accessTokenOptions);
|
|
526
526
|
// Must specify either username and/or options
|
|
527
527
|
if (!username && !authOptions) {
|
|
528
528
|
throw messages.createError('authInfoCreationError');
|
|
@@ -534,7 +534,7 @@ class AuthInfo extends kit_1.AsyncOptionalCreatable {
|
|
|
534
534
|
throw messages.createError('authInfoOverwriteError');
|
|
535
535
|
}
|
|
536
536
|
}
|
|
537
|
-
const oauthUsername = username || (0
|
|
537
|
+
const oauthUsername = username || (authOptions === null || authOptions === void 0 ? void 0 : authOptions.username);
|
|
538
538
|
if (oauthUsername) {
|
|
539
539
|
this.username = oauthUsername;
|
|
540
540
|
await this.stateAggregator.orgs.read(oauthUsername, false, false);
|
|
@@ -562,9 +562,9 @@ class AuthInfo extends kit_1.AsyncOptionalCreatable {
|
|
|
562
562
|
}
|
|
563
563
|
}
|
|
564
564
|
getInstanceUrl(options, aggregator) {
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
return instanceUrl
|
|
565
|
+
var _a;
|
|
566
|
+
const instanceUrl = (_a = options === null || options === void 0 ? void 0 : options.instanceUrl) !== null && _a !== void 0 ? _a : aggregator.getPropertyValue(orgConfigProperties_1.OrgConfigProperties.ORG_INSTANCE_URL);
|
|
567
|
+
return instanceUrl !== null && instanceUrl !== void 0 ? instanceUrl : sfdcUrl_1.SfdcUrl.PRODUCTION;
|
|
568
568
|
}
|
|
569
569
|
/**
|
|
570
570
|
* Initialize this AuthInfo instance with the specified options. If options are not provided, initialize it from cache
|
|
@@ -668,15 +668,19 @@ class AuthInfo extends kit_1.AsyncOptionalCreatable {
|
|
|
668
668
|
return await callback(error);
|
|
669
669
|
}
|
|
670
670
|
}
|
|
671
|
+
async readJwtKey(keyFile) {
|
|
672
|
+
return fs.promises.readFile(keyFile, 'utf8');
|
|
673
|
+
}
|
|
671
674
|
// Build OAuth config for a JWT auth flow
|
|
672
675
|
async authJwt(options) {
|
|
676
|
+
var _a;
|
|
673
677
|
if (!options.clientId) {
|
|
674
678
|
throw messages.createError('missingClientId');
|
|
675
679
|
}
|
|
676
|
-
const privateKeyContents = await
|
|
680
|
+
const privateKeyContents = await this.readJwtKey((0, ts_types_1.ensureString)(options.privateKey));
|
|
677
681
|
const { loginUrl = sfdcUrl_1.SfdcUrl.PRODUCTION } = options;
|
|
678
682
|
const url = new sfdcUrl_1.SfdcUrl(loginUrl);
|
|
679
|
-
const createdOrgInstance = (
|
|
683
|
+
const createdOrgInstance = ((_a = this.getFields().createdOrgInstance) !== null && _a !== void 0 ? _a : '').trim().toLowerCase();
|
|
680
684
|
const audienceUrl = await url.getJwtAudienceUrl(createdOrgInstance);
|
|
681
685
|
let authFieldsBuilder;
|
|
682
686
|
const authErrors = [];
|
|
@@ -751,7 +755,6 @@ class AuthInfo extends kit_1.AsyncOptionalCreatable {
|
|
|
751
755
|
const { orgId } = parseIdUrl(authFieldsBuilder.id);
|
|
752
756
|
let username = this.getUsername();
|
|
753
757
|
if (!username) {
|
|
754
|
-
// @ts-ignore
|
|
755
758
|
const userInfo = await this.retrieveUserInfo(authFieldsBuilder.instance_url, authFieldsBuilder.access_token);
|
|
756
759
|
username = (0, ts_types_1.ensureString)(userInfo === null || userInfo === void 0 ? void 0 : userInfo.username);
|
|
757
760
|
}
|
|
@@ -854,18 +857,16 @@ class AuthInfo extends kit_1.AsyncOptionalCreatable {
|
|
|
854
857
|
* @private
|
|
855
858
|
*/
|
|
856
859
|
throwUserGetException(response) {
|
|
857
|
-
var _a;
|
|
860
|
+
var _a, _b, _c;
|
|
858
861
|
let errorMsg = '';
|
|
859
|
-
const bodyAsString = (
|
|
862
|
+
const bodyAsString = (_a = response.body) !== null && _a !== void 0 ? _a : JSON.stringify({ message: 'UNKNOWN', errorCode: 'UNKNOWN' });
|
|
860
863
|
try {
|
|
861
864
|
const body = (0, kit_1.parseJson)(bodyAsString);
|
|
862
865
|
if ((0, ts_types_1.isArray)(body)) {
|
|
863
|
-
errorMsg = body
|
|
864
|
-
.map((line) => { var _a; return (_a = (0, ts_types_1.getString)(line, 'message')) !== null && _a !== void 0 ? _a : (0, ts_types_1.getString)(line, 'errorCode', 'UNKNOWN'); })
|
|
865
|
-
.join(os.EOL);
|
|
866
|
+
errorMsg = body.map((line) => { var _a, _b; return (_b = (_a = line.message) !== null && _a !== void 0 ? _a : line.errorCode) !== null && _b !== void 0 ? _b : 'UNKNOWN'; }).join(os.EOL);
|
|
866
867
|
}
|
|
867
868
|
else {
|
|
868
|
-
errorMsg = (
|
|
869
|
+
errorMsg = (_c = (_b = body.message) !== null && _b !== void 0 ? _b : body.errorCode) !== null && _c !== void 0 ? _c : 'UNKNOWN';
|
|
869
870
|
}
|
|
870
871
|
}
|
|
871
872
|
catch (err) {
|
package/lib/org/connection.js
CHANGED
|
@@ -380,7 +380,7 @@ class Connection extends jsforce_1.Connection {
|
|
|
380
380
|
async loadInstanceApiVersion() {
|
|
381
381
|
const authFileFields = this.options.authInfo.getFields();
|
|
382
382
|
const lastCheckedDateString = authFileFields.instanceApiVersionLastRetrieved;
|
|
383
|
-
let version =
|
|
383
|
+
let version = authFileFields.instanceApiVersion;
|
|
384
384
|
let lastChecked;
|
|
385
385
|
try {
|
|
386
386
|
if (lastCheckedDateString && (0, ts_types_1.isString)(lastCheckedDateString)) {
|
package/lib/org/org.js
CHANGED
|
@@ -292,7 +292,7 @@ class Org extends kit_1.AsyncOptionalCreatable {
|
|
|
292
292
|
const DEV_HUB_SOQL = `SELECT CreatedDate,Edition,ExpirationDate FROM ActiveScratchOrg WHERE ScratchOrg='${trimmedId}'`;
|
|
293
293
|
try {
|
|
294
294
|
const results = await devHubConnection.query(DEV_HUB_SOQL);
|
|
295
|
-
if (
|
|
295
|
+
if (results.records.length !== 1) {
|
|
296
296
|
throw new sfError_1.SfError('No results', 'NoResultsError');
|
|
297
297
|
}
|
|
298
298
|
}
|
|
@@ -49,6 +49,7 @@ class PermissionSetAssignment {
|
|
|
49
49
|
* @param permSetString An array of permission set names.
|
|
50
50
|
*/
|
|
51
51
|
async create(id, permSetString) {
|
|
52
|
+
var _a;
|
|
52
53
|
if (!id) {
|
|
53
54
|
throw messages.createError('userIdRequired');
|
|
54
55
|
}
|
|
@@ -61,7 +62,7 @@ class PermissionSetAssignment {
|
|
|
61
62
|
query += ` AND NamespacePrefix='${nsPrefix}'`;
|
|
62
63
|
}
|
|
63
64
|
const result = await this.org.getConnection().query(query);
|
|
64
|
-
const permissionSetId = (0
|
|
65
|
+
const permissionSetId = (_a = result === null || result === void 0 ? void 0 : result.records[0]) === null || _a === void 0 ? void 0 : _a.Id;
|
|
65
66
|
if (!permissionSetId) {
|
|
66
67
|
if (nsPrefix) {
|
|
67
68
|
throw messages.createError('assignCommandPermissionSetNotFoundForNSError', [permSetName, nsPrefix]);
|
|
@@ -142,7 +142,7 @@ const scratchOrgCreate = async (options) => {
|
|
|
142
142
|
(0, scratchOrgInfoApi_1.requestScratchOrgCreation)(hubOrg, scratchOrgInfo, settingsGenerator),
|
|
143
143
|
getSignupTargetLoginUrl(),
|
|
144
144
|
]);
|
|
145
|
-
const scratchOrgInfoId = (0, ts_types_1.ensureString)(
|
|
145
|
+
const scratchOrgInfoId = (0, ts_types_1.ensureString)(scratchOrgInfoRequestResult.id);
|
|
146
146
|
const cache = await scratchOrgCache_1.ScratchOrgCache.create();
|
|
147
147
|
cache.set(scratchOrgInfoId, {
|
|
148
148
|
hubUsername: hubOrg.getUsername(),
|
|
@@ -8,16 +8,15 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.updateRevisionCounterToZero = exports.resolveUrl = exports.deploySettings = exports.pollForScratchOrgInfo = exports.requestScratchOrgCreation = exports.authorizeScratchOrg = exports.queryScratchOrgInfo = void 0;
|
|
10
10
|
const kit_1 = require("@salesforce/kit");
|
|
11
|
-
const ts_types_1 = require("@salesforce/ts-types");
|
|
12
11
|
const ts_retry_promise_1 = require("ts-retry-promise");
|
|
13
12
|
const logger_1 = require("../logger");
|
|
14
|
-
const mapKeys_1 = require("../util/mapKeys");
|
|
15
13
|
const messages_1 = require("../messages");
|
|
16
14
|
const sfError_1 = require("../sfError");
|
|
17
15
|
const sfdcUrl_1 = require("../util/sfdcUrl");
|
|
18
16
|
const pollingClient_1 = require("../status/pollingClient");
|
|
19
17
|
const myDomainResolver_1 = require("../status/myDomainResolver");
|
|
20
18
|
const lifecycleEvents_1 = require("../lifecycleEvents");
|
|
19
|
+
const mapKeys_1 = require("../util/mapKeys");
|
|
21
20
|
const authInfo_1 = require("./authInfo");
|
|
22
21
|
const org_1 = require("./org");
|
|
23
22
|
const scratchOrgErrorCodes_1 = require("./scratchOrgErrorCodes");
|
|
@@ -195,7 +194,7 @@ const checkOrgDoesntExist = async (scratchOrgInfo) => {
|
|
|
195
194
|
if (!usernameKey) {
|
|
196
195
|
return;
|
|
197
196
|
}
|
|
198
|
-
const username =
|
|
197
|
+
const username = scratchOrgInfo[usernameKey];
|
|
199
198
|
if (username && username.length > 0) {
|
|
200
199
|
try {
|
|
201
200
|
await authInfo_1.AuthInfo.create({ username: username.toLowerCase() });
|
package/lib/org/user.js
CHANGED
|
@@ -86,16 +86,16 @@ async function retrieveUserFields(logger, username) {
|
|
|
86
86
|
if (result.totalSize === 1) {
|
|
87
87
|
const results = (0, kit_1.mapKeys)(result.records[0], (value, key) => (0, kit_1.lowerFirst)(key));
|
|
88
88
|
const fields = {
|
|
89
|
-
id: (0, ts_types_1.
|
|
89
|
+
id: (0, ts_types_1.ensureString)(results[exports.REQUIRED_FIELDS.id]),
|
|
90
90
|
username,
|
|
91
|
-
alias: (0, ts_types_1.
|
|
92
|
-
email: (0, ts_types_1.
|
|
93
|
-
emailEncodingKey: (0, ts_types_1.
|
|
94
|
-
languageLocaleKey: (0, ts_types_1.
|
|
95
|
-
localeSidKey: (0, ts_types_1.
|
|
96
|
-
profileId: (0, ts_types_1.
|
|
97
|
-
lastName: (0, ts_types_1.
|
|
98
|
-
timeZoneSidKey: (0, ts_types_1.
|
|
91
|
+
alias: (0, ts_types_1.ensureString)(results[exports.REQUIRED_FIELDS.alias]),
|
|
92
|
+
email: (0, ts_types_1.ensureString)(results[exports.REQUIRED_FIELDS.email]),
|
|
93
|
+
emailEncodingKey: (0, ts_types_1.ensureString)(results[exports.REQUIRED_FIELDS.emailEncodingKey]),
|
|
94
|
+
languageLocaleKey: (0, ts_types_1.ensureString)(results[exports.REQUIRED_FIELDS.languageLocaleKey]),
|
|
95
|
+
localeSidKey: (0, ts_types_1.ensureString)(results[exports.REQUIRED_FIELDS.localeSidKey]),
|
|
96
|
+
profileId: (0, ts_types_1.ensureString)(results[exports.REQUIRED_FIELDS.profileId]),
|
|
97
|
+
lastName: (0, ts_types_1.ensureString)(results[exports.REQUIRED_FIELDS.lastName]),
|
|
98
|
+
timeZoneSidKey: (0, ts_types_1.ensureString)(results[exports.REQUIRED_FIELDS.timeZoneSidKey]),
|
|
99
99
|
};
|
|
100
100
|
return fields;
|
|
101
101
|
}
|
package/lib/sfProject.js
CHANGED
|
@@ -68,13 +68,17 @@ class SfProjectJson extends configFile_1.ConfigFile {
|
|
|
68
68
|
return contents;
|
|
69
69
|
}
|
|
70
70
|
async write(newContents) {
|
|
71
|
-
|
|
71
|
+
if (newContents) {
|
|
72
|
+
this.setContents(newContents);
|
|
73
|
+
}
|
|
72
74
|
this.validateKeys();
|
|
73
75
|
await this.schemaValidate();
|
|
74
76
|
return super.write();
|
|
75
77
|
}
|
|
76
78
|
writeSync(newContents) {
|
|
77
|
-
|
|
79
|
+
if (newContents) {
|
|
80
|
+
this.setContents(newContents);
|
|
81
|
+
}
|
|
78
82
|
this.validateKeys();
|
|
79
83
|
this.schemaValidateSync();
|
|
80
84
|
return super.writeSync();
|
|
@@ -25,18 +25,87 @@ export declare abstract class BaseOrgAccessor<T extends ConfigFile, P extends Co
|
|
|
25
25
|
private configs;
|
|
26
26
|
private contents;
|
|
27
27
|
private logger;
|
|
28
|
+
/**
|
|
29
|
+
* Read the auth file for the given useranme. Once the file has been read, it can be reaccessed with the `get` method.
|
|
30
|
+
*
|
|
31
|
+
* @param username username to read
|
|
32
|
+
* @param decrypt if true, decrypt encrypted values
|
|
33
|
+
* @param throwOnNotFound throw if file is not found for username
|
|
34
|
+
*/
|
|
28
35
|
read(username: string, decrypt?: boolean, throwOnNotFound?: boolean): Promise<Nullable<P>>;
|
|
36
|
+
/**
|
|
37
|
+
* Read all the auth files under the global state directory
|
|
38
|
+
*
|
|
39
|
+
* @param decrypt if true, decrypt encrypted values
|
|
40
|
+
*/
|
|
29
41
|
readAll(decrypt?: boolean): Promise<P[]>;
|
|
42
|
+
/**
|
|
43
|
+
* Return the contents of the username's auth file from cache. The `read` or `readAll` methods must be called first in order to populate the cache.
|
|
44
|
+
*
|
|
45
|
+
* @param username username to get
|
|
46
|
+
* @param decrypt if true, decrypt encrypted values
|
|
47
|
+
*/
|
|
30
48
|
get(username: string, decrypt?: boolean): Nullable<P>;
|
|
49
|
+
/**
|
|
50
|
+
* Return the contents of all the auth files from cache. The `read` or `readAll` methods must be called first in order to populate the cache.
|
|
51
|
+
*
|
|
52
|
+
* @param decrypt if true, decrypt encrypted values
|
|
53
|
+
* @returns
|
|
54
|
+
*/
|
|
31
55
|
getAll(decrypt?: boolean): P[];
|
|
56
|
+
/**
|
|
57
|
+
* Returns true if the username has been cached.
|
|
58
|
+
*
|
|
59
|
+
* @param username
|
|
60
|
+
*/
|
|
32
61
|
has(username: string): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Returns true if there is an auth file for the given username. The `read` or `readAll` methods must be called first in order to populate the cache.
|
|
64
|
+
*
|
|
65
|
+
* @param username
|
|
66
|
+
*/
|
|
33
67
|
exists(username: string): Promise<boolean>;
|
|
68
|
+
/**
|
|
69
|
+
* Return the file stats for a given userame's auth file.
|
|
70
|
+
*
|
|
71
|
+
* @param username
|
|
72
|
+
*/
|
|
34
73
|
stat(username: string): Promise<Nullable<fs.Stats>>;
|
|
74
|
+
/**
|
|
75
|
+
* Returns true if there is an auth file for the given username
|
|
76
|
+
*
|
|
77
|
+
* @param username
|
|
78
|
+
*/
|
|
35
79
|
hasFile(username: string): Promise<boolean>;
|
|
80
|
+
/**
|
|
81
|
+
* Return all auth files under the global state directory.
|
|
82
|
+
*/
|
|
36
83
|
list(): Promise<string[]>;
|
|
84
|
+
/**
|
|
85
|
+
* Set the contents for a given username.
|
|
86
|
+
*
|
|
87
|
+
* @param username
|
|
88
|
+
* @param org
|
|
89
|
+
*/
|
|
37
90
|
set(username: string, org: P): void;
|
|
91
|
+
/**
|
|
92
|
+
* Update the contents for a given username.
|
|
93
|
+
*
|
|
94
|
+
* @param username
|
|
95
|
+
* @param org
|
|
96
|
+
*/
|
|
38
97
|
update(username: string, org: Partial<P> & JsonMap): void;
|
|
98
|
+
/**
|
|
99
|
+
* Delete the auth file for a given username.
|
|
100
|
+
*
|
|
101
|
+
* @param username
|
|
102
|
+
*/
|
|
39
103
|
remove(username: string): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Write the contents of the auth file for a given username.
|
|
106
|
+
*
|
|
107
|
+
* @param username
|
|
108
|
+
*/
|
|
40
109
|
write(username: string): Promise<Nullable<P>>;
|
|
41
110
|
protected init(): Promise<void>;
|
|
42
111
|
private getAllFiles;
|
|
@@ -63,6 +63,13 @@ class BaseOrgAccessor extends kit_1.AsyncOptionalCreatable {
|
|
|
63
63
|
this.configs = new Map();
|
|
64
64
|
this.contents = new Map();
|
|
65
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Read the auth file for the given useranme. Once the file has been read, it can be reaccessed with the `get` method.
|
|
68
|
+
*
|
|
69
|
+
* @param username username to read
|
|
70
|
+
* @param decrypt if true, decrypt encrypted values
|
|
71
|
+
* @param throwOnNotFound throw if file is not found for username
|
|
72
|
+
*/
|
|
66
73
|
async read(username, decrypt = false, throwOnNotFound = true) {
|
|
67
74
|
try {
|
|
68
75
|
const config = await this.initAuthFile(username, throwOnNotFound);
|
|
@@ -73,6 +80,11 @@ class BaseOrgAccessor extends kit_1.AsyncOptionalCreatable {
|
|
|
73
80
|
return null;
|
|
74
81
|
}
|
|
75
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Read all the auth files under the global state directory
|
|
85
|
+
*
|
|
86
|
+
* @param decrypt if true, decrypt encrypted values
|
|
87
|
+
*/
|
|
76
88
|
async readAll(decrypt = false) {
|
|
77
89
|
const fileChunks = chunk(await this.getAllFiles(), 50);
|
|
78
90
|
for (const fileChunk of fileChunks) {
|
|
@@ -85,6 +97,12 @@ class BaseOrgAccessor extends kit_1.AsyncOptionalCreatable {
|
|
|
85
97
|
}
|
|
86
98
|
return this.getAll(decrypt);
|
|
87
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Return the contents of the username's auth file from cache. The `read` or `readAll` methods must be called first in order to populate the cache.
|
|
102
|
+
*
|
|
103
|
+
* @param username username to get
|
|
104
|
+
* @param decrypt if true, decrypt encrypted values
|
|
105
|
+
*/
|
|
88
106
|
get(username, decrypt = false) {
|
|
89
107
|
const config = this.configs.get(username);
|
|
90
108
|
if (config) {
|
|
@@ -92,23 +110,49 @@ class BaseOrgAccessor extends kit_1.AsyncOptionalCreatable {
|
|
|
92
110
|
}
|
|
93
111
|
return this.contents.get(username);
|
|
94
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* Return the contents of all the auth files from cache. The `read` or `readAll` methods must be called first in order to populate the cache.
|
|
115
|
+
*
|
|
116
|
+
* @param decrypt if true, decrypt encrypted values
|
|
117
|
+
* @returns
|
|
118
|
+
*/
|
|
95
119
|
getAll(decrypt = false) {
|
|
96
120
|
return [...this.configs.keys()].reduce((orgs, username) => {
|
|
97
121
|
const org = this.get(username, decrypt);
|
|
98
122
|
return org && !(0, kit_1.isEmpty)(org) ? orgs.concat([org]) : orgs;
|
|
99
123
|
}, []);
|
|
100
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Returns true if the username has been cached.
|
|
127
|
+
*
|
|
128
|
+
* @param username
|
|
129
|
+
*/
|
|
101
130
|
has(username) {
|
|
102
131
|
return this.contents.has(username);
|
|
103
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Returns true if there is an auth file for the given username. The `read` or `readAll` methods must be called first in order to populate the cache.
|
|
135
|
+
*
|
|
136
|
+
* @param username
|
|
137
|
+
*/
|
|
104
138
|
async exists(username) {
|
|
105
139
|
const config = this.configs.get(username);
|
|
106
140
|
return config ? await config.exists() : false;
|
|
107
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Return the file stats for a given userame's auth file.
|
|
144
|
+
*
|
|
145
|
+
* @param username
|
|
146
|
+
*/
|
|
108
147
|
async stat(username) {
|
|
109
148
|
const config = this.configs.get(username);
|
|
110
149
|
return config ? await config.stat() : null;
|
|
111
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Returns true if there is an auth file for the given username
|
|
153
|
+
*
|
|
154
|
+
* @param username
|
|
155
|
+
*/
|
|
112
156
|
async hasFile(username) {
|
|
113
157
|
try {
|
|
114
158
|
await fs.promises.access(this.parseFilename(username));
|
|
@@ -119,9 +163,18 @@ class BaseOrgAccessor extends kit_1.AsyncOptionalCreatable {
|
|
|
119
163
|
return false;
|
|
120
164
|
}
|
|
121
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Return all auth files under the global state directory.
|
|
168
|
+
*/
|
|
122
169
|
async list() {
|
|
123
170
|
return this.getAllFiles();
|
|
124
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* Set the contents for a given username.
|
|
174
|
+
*
|
|
175
|
+
* @param username
|
|
176
|
+
* @param org
|
|
177
|
+
*/
|
|
125
178
|
set(username, org) {
|
|
126
179
|
var _a, _b;
|
|
127
180
|
const config = this.configs.get(username);
|
|
@@ -137,17 +190,33 @@ class BaseOrgAccessor extends kit_1.AsyncOptionalCreatable {
|
|
|
137
190
|
this.contents.set(username, org);
|
|
138
191
|
}
|
|
139
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Update the contents for a given username.
|
|
195
|
+
*
|
|
196
|
+
* @param username
|
|
197
|
+
* @param org
|
|
198
|
+
*/
|
|
140
199
|
update(username, org) {
|
|
141
200
|
const existing = this.get(username) || {};
|
|
142
201
|
const merged = Object.assign({}, existing, org);
|
|
143
202
|
return this.set(username, merged);
|
|
144
203
|
}
|
|
204
|
+
/**
|
|
205
|
+
* Delete the auth file for a given username.
|
|
206
|
+
*
|
|
207
|
+
* @param username
|
|
208
|
+
*/
|
|
145
209
|
async remove(username) {
|
|
146
210
|
var _a;
|
|
147
211
|
await ((_a = this.configs.get(username)) === null || _a === void 0 ? void 0 : _a.unlink());
|
|
148
212
|
this.configs.delete(username);
|
|
149
213
|
this.contents.delete(username);
|
|
150
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* Write the contents of the auth file for a given username.
|
|
217
|
+
*
|
|
218
|
+
* @param username
|
|
219
|
+
*/
|
|
151
220
|
async write(username) {
|
|
152
221
|
const config = this.configs.get(username);
|
|
153
222
|
if (config) {
|