@salesforce/core 3.30.10 → 3.30.12
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/README.md +3 -3
- package/lib/config/aliasesConfig.js +1 -0
- package/lib/config/config.js +6 -9
- package/lib/config/configAggregator.d.ts +3 -3
- package/lib/config/configAggregator.js +14 -14
- package/lib/config/configFile.js +7 -9
- package/lib/config/configGroup.js +8 -7
- package/lib/config/configStore.d.ts +4 -4
- package/lib/config/configStore.js +12 -9
- package/lib/config/envVars.js +1 -1
- package/lib/config/tokensConfig.js +1 -0
- package/lib/config/ttlConfig.d.ts +2 -0
- package/lib/config/ttlConfig.js +5 -4
- package/lib/crypto/crypto.js +9 -12
- package/lib/crypto/keyChainImpl.d.ts +2 -0
- package/lib/crypto/keyChainImpl.js +41 -34
- package/lib/deviceOauthService.js +5 -2
- package/lib/exported.js +5 -1
- package/lib/global.js +2 -0
- package/lib/lifecycleEvents.js +3 -0
- package/lib/logger.d.ts +2 -3
- package/lib/logger.js +57 -53
- package/lib/messages.js +2 -3
- package/lib/org/authInfo.js +40 -29
- package/lib/org/authRemover.js +11 -7
- package/lib/org/connection.d.ts +4 -4
- package/lib/org/connection.js +8 -6
- package/lib/org/index.js +5 -1
- package/lib/org/org.js +23 -15
- package/lib/org/scratchOrgCreate.js +2 -1
- package/lib/org/scratchOrgInfoApi.js +4 -6
- package/lib/org/scratchOrgInfoGenerator.d.ts +1 -0
- package/lib/org/scratchOrgInfoGenerator.js +28 -27
- package/lib/org/scratchOrgLifecycleEvents.js +2 -6
- package/lib/org/scratchOrgSettingsGenerator.js +9 -9
- package/lib/org/scratchOrgTypes.d.ts +1 -1
- package/lib/org/user.js +7 -6
- package/lib/schema/printer.d.ts +4 -0
- package/lib/schema/printer.js +30 -29
- package/lib/schema/validator.d.ts +1 -1
- package/lib/schema/validator.js +2 -1
- package/lib/sfError.d.ts +3 -6
- package/lib/sfError.js +26 -9
- package/lib/sfProject.js +14 -6
- package/lib/stateAggregator/accessors/aliasAccessor.js +2 -1
- package/lib/stateAggregator/accessors/orgAccessor.js +11 -6
- package/lib/stateAggregator/accessors/sandboxAccessor.js +1 -0
- package/lib/stateAggregator/index.js +5 -1
- package/lib/status/myDomainResolver.d.ts +1 -1
- package/lib/status/myDomainResolver.js +4 -4
- package/lib/status/streamingClient.js +51 -49
- package/lib/testSetup.d.ts +5 -1
- package/lib/testSetup.js +32 -21
- package/lib/util/cache.d.ts +2 -2
- package/lib/util/cache.js +6 -6
- package/lib/util/directoryWriter.d.ts +2 -1
- package/lib/util/directoryWriter.js +5 -3
- package/lib/util/jsonXmlTools.js +2 -4
- package/lib/util/mapKeys.d.ts +9 -9
- package/lib/util/mapKeys.js +13 -9
- package/lib/util/sfdc.d.ts +2 -2
- package/lib/util/sfdc.js +8 -17
- package/lib/util/sfdcUrl.d.ts +1 -1
- package/lib/util/sfdcUrl.js +2 -4
- package/lib/util/structuredWriter.d.ts +1 -0
- package/lib/util/zipWriter.d.ts +2 -1
- package/lib/util/zipWriter.js +5 -9
- package/lib/webOAuthServer.js +9 -3
- package/package.json +18 -19
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ const $$ = testSetup();
|
|
|
41
41
|
describe('Mocking Auth data', () => {
|
|
42
42
|
it('example', async () => {
|
|
43
43
|
const testData = new MockTestOrgData();
|
|
44
|
-
await $$.stubAuths(testData)
|
|
44
|
+
await $$.stubAuths(testData);
|
|
45
45
|
const auth = await AuthInfo.create({ username: testData.username });
|
|
46
46
|
strictEqual(auth.getUsername(), testData.username);
|
|
47
47
|
});
|
|
@@ -106,7 +106,7 @@ describe('Mocking Config', () => {
|
|
|
106
106
|
it('example', async () => {
|
|
107
107
|
const testData = new MockTestOrgData();
|
|
108
108
|
await $$.stubConfig({ [OrgConfigProperties.TARGET_ORG]: testData.username });
|
|
109
|
-
const {value} = (await ConfigAggregator.create()).getInfo(OrgConfigProperties.TARGET_ORG);
|
|
109
|
+
const { value } = (await ConfigAggregator.create()).getInfo(OrgConfigProperties.TARGET_ORG);
|
|
110
110
|
strictEqual(value, testData.username);
|
|
111
111
|
});
|
|
112
112
|
});
|
|
@@ -121,7 +121,7 @@ describe('Mocking Arbitrary Config Files', () => {
|
|
|
121
121
|
|
|
122
122
|
## Using the Built-in Sinon Sandboxes
|
|
123
123
|
|
|
124
|
-
sfdx-core uses Sinon as its underlying mocking system. If you're unfamiliar with Sinon and
|
|
124
|
+
sfdx-core uses Sinon as its underlying mocking system. If you're unfamiliar with Sinon and its sandboxing concept you can find more information here:
|
|
125
125
|
https://sinonjs.org/
|
|
126
126
|
Sinon `stub`s and `spy`s must be cleaned up after test invocations. To ease the use of Sinon with sfdx core we've exposed our sandbox in TestSetup. After adding your own `stub`s and/or `spy`s they will automatically be cleaned up after each test using mocha's afterEach method.
|
|
127
127
|
|
|
@@ -19,6 +19,7 @@ class AliasesConfig extends configGroup_1.ConfigGroup {
|
|
|
19
19
|
static getDefaultOptions() {
|
|
20
20
|
return { ...configGroup_1.ConfigGroup.getOptions(AliasGroup.ORGS, 'alias.json'), isGlobal: true, isState: true };
|
|
21
21
|
}
|
|
22
|
+
// eslint-disable-next-line class-methods-use-this
|
|
22
23
|
setMethod(contents, key, value) {
|
|
23
24
|
contents[key] = value;
|
|
24
25
|
}
|
package/lib/config/config.js
CHANGED
|
@@ -380,7 +380,7 @@ class Config extends configFile_1.ConfigFile {
|
|
|
380
380
|
*
|
|
381
381
|
* @param newContents Contents to write
|
|
382
382
|
*/
|
|
383
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
383
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, class-methods-use-this
|
|
384
384
|
writeSync(newContents) {
|
|
385
385
|
throw messages.createError('invalidWrite');
|
|
386
386
|
}
|
|
@@ -402,11 +402,11 @@ class Config extends configFile_1.ConfigFile {
|
|
|
402
402
|
throw messages.createError('deprecatedConfigKey', [key, property.newKey]);
|
|
403
403
|
}
|
|
404
404
|
if (property.input) {
|
|
405
|
-
if (property.input
|
|
405
|
+
if (property.input?.validator(value)) {
|
|
406
406
|
super.set(property.key, value);
|
|
407
407
|
}
|
|
408
408
|
else {
|
|
409
|
-
let valueError = value?.toString()
|
|
409
|
+
let valueError = value?.toString() ?? '';
|
|
410
410
|
if (property.input.failedMessage) {
|
|
411
411
|
valueError = (0, ts_types_1.isString)(property.input.failedMessage)
|
|
412
412
|
? property.input.failedMessage
|
|
@@ -444,6 +444,7 @@ class Config extends configFile_1.ConfigFile {
|
|
|
444
444
|
*
|
|
445
445
|
* @param propertyName The name of the property.
|
|
446
446
|
*/
|
|
447
|
+
// eslint-disable-next-line class-methods-use-this
|
|
447
448
|
getPropertyConfig(propertyName) {
|
|
448
449
|
const prop = Config.propertyConfigMap()[propertyName];
|
|
449
450
|
if (!prop) {
|
|
@@ -465,9 +466,7 @@ class Config extends configFile_1.ConfigFile {
|
|
|
465
466
|
* @param encrypt `true` to encrypt.
|
|
466
467
|
*/
|
|
467
468
|
async cryptProperties(encrypt) {
|
|
468
|
-
const hasEncryptedProperties = this.entries().some(([key]) =>
|
|
469
|
-
return !!Config.propertyConfigMap()[key]?.encrypted;
|
|
470
|
-
});
|
|
469
|
+
const hasEncryptedProperties = this.entries().some(([key]) => !!Config.propertyConfigMap()[key]?.encrypted);
|
|
471
470
|
if (hasEncryptedProperties) {
|
|
472
471
|
await this.initCrypto();
|
|
473
472
|
const crypto = (0, ts_types_1.ensure)(this.crypto);
|
|
@@ -537,13 +536,11 @@ class SfdxConfig {
|
|
|
537
536
|
if (!this.sfdxPath) {
|
|
538
537
|
const stateFolder = global_1.Global.SFDX_STATE_FOLDER;
|
|
539
538
|
const fileName = SFDX_CONFIG_FILE_NAME;
|
|
540
|
-
const _isGlobal = (0, ts_types_1.isBoolean)(this.options.isGlobal) && this.options.isGlobal;
|
|
541
|
-
const _isState = (0, ts_types_1.isBoolean)(this.options.isState) && this.options.isState;
|
|
542
539
|
// Don't let users store config files in homedir without being in the state folder.
|
|
543
540
|
let configRootFolder = this.options.rootFolder
|
|
544
541
|
? this.options.rootFolder
|
|
545
542
|
: configFile_1.ConfigFile.resolveRootFolderSync(!!this.options.isGlobal);
|
|
546
|
-
if (
|
|
543
|
+
if (this.options.isGlobal === true || this.options.isState === true) {
|
|
547
544
|
configRootFolder = (0, path_1.join)(configRootFolder, stateFolder);
|
|
548
545
|
}
|
|
549
546
|
this.sfdxPath = (0, path_1.join)(configRootFolder, fileName);
|
|
@@ -60,14 +60,14 @@ export declare class ConfigAggregator extends AsyncOptionalCreatable<ConfigAggre
|
|
|
60
60
|
private localConfig?;
|
|
61
61
|
private globalConfig;
|
|
62
62
|
private envVars;
|
|
63
|
-
private get config();
|
|
64
63
|
/**
|
|
65
64
|
* **Do not directly construct instances of this class -- use {@link ConfigAggregator.create} instead.**
|
|
66
65
|
*
|
|
67
66
|
* @ignore
|
|
68
67
|
*/
|
|
69
68
|
constructor(options?: ConfigAggregator.Options);
|
|
70
|
-
|
|
69
|
+
private get config();
|
|
70
|
+
static create<P extends ConfigAggregator.Options, T extends AsyncOptionalCreatable<P>>(this: new (options?: P) => T, options?: P): Promise<T>;
|
|
71
71
|
/**
|
|
72
72
|
* Get the info for a given key. If the ConfigAggregator was not asynchronously created OR
|
|
73
73
|
* the {@link ConfigAggregator.reload} was not called, the config value may be encrypted.
|
|
@@ -214,7 +214,7 @@ export declare namespace ConfigAggregator {
|
|
|
214
214
|
}
|
|
215
215
|
/**
|
|
216
216
|
* A ConfigAggregator that will work with deprecated config vars (e.g. defaultusername, apiVersion).
|
|
217
|
-
* We do NOT recommend using this class unless you
|
|
217
|
+
* We do NOT recommend using this class unless you absolutely have to.
|
|
218
218
|
*
|
|
219
219
|
* @deprecated
|
|
220
220
|
*/
|
|
@@ -36,7 +36,7 @@ class ConfigAggregator extends kit_1.AsyncOptionalCreatable {
|
|
|
36
36
|
* @ignore
|
|
37
37
|
*/
|
|
38
38
|
constructor(options) {
|
|
39
|
-
super(options
|
|
39
|
+
super(options ?? {});
|
|
40
40
|
this.envVars = {};
|
|
41
41
|
// Don't throw an project error with the aggregator, since it should resolve to global if
|
|
42
42
|
// there is no project.
|
|
@@ -52,7 +52,7 @@ class ConfigAggregator extends kit_1.AsyncOptionalCreatable {
|
|
|
52
52
|
this.setAllowedProperties(config_1.Config.getAllowedProperties());
|
|
53
53
|
}
|
|
54
54
|
get config() {
|
|
55
|
-
return this.resolveProperties(this.globalConfig.getContents(), this.localConfig
|
|
55
|
+
return this.resolveProperties(this.globalConfig.getContents(), this.localConfig?.getContents());
|
|
56
56
|
}
|
|
57
57
|
// Use typing from AsyncOptionalCreatable to support extending ConfigAggregator.
|
|
58
58
|
// We really don't want ConfigAggregator extended but typescript doesn't support a final.
|
|
@@ -147,9 +147,9 @@ class ConfigAggregator extends kit_1.AsyncOptionalCreatable {
|
|
|
147
147
|
location,
|
|
148
148
|
value: this.getPropertyValue(key),
|
|
149
149
|
path: this.getPath(key),
|
|
150
|
-
isLocal: () => location === "Local" /* LOCAL */,
|
|
151
|
-
isGlobal: () => location === "Global" /* GLOBAL */,
|
|
152
|
-
isEnvVar: () => location === "Environment" /* ENVIRONMENT */,
|
|
150
|
+
isLocal: () => location === "Local" /* ConfigAggregator.Location.LOCAL */,
|
|
151
|
+
isGlobal: () => location === "Global" /* ConfigAggregator.Location.GLOBAL */,
|
|
152
|
+
isEnvVar: () => location === "Environment" /* ConfigAggregator.Location.ENVIRONMENT */,
|
|
153
153
|
deprecated: meta.deprecated ?? false,
|
|
154
154
|
};
|
|
155
155
|
}
|
|
@@ -165,13 +165,13 @@ class ConfigAggregator extends kit_1.AsyncOptionalCreatable {
|
|
|
165
165
|
*/
|
|
166
166
|
getLocation(key) {
|
|
167
167
|
if (this.envVars[key] != null) {
|
|
168
|
-
return "Environment" /* ENVIRONMENT */;
|
|
168
|
+
return "Environment" /* ConfigAggregator.Location.ENVIRONMENT */;
|
|
169
169
|
}
|
|
170
|
-
if (this.localConfig
|
|
171
|
-
return "Local" /* LOCAL */;
|
|
170
|
+
if (this.localConfig?.get(key)) {
|
|
171
|
+
return "Local" /* ConfigAggregator.Location.LOCAL */;
|
|
172
172
|
}
|
|
173
|
-
if (this.globalConfig
|
|
174
|
-
return "Global" /* GLOBAL */;
|
|
173
|
+
if (this.globalConfig?.get(key)) {
|
|
174
|
+
return "Global" /* ConfigAggregator.Location.GLOBAL */;
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
177
|
/**
|
|
@@ -192,7 +192,7 @@ class ConfigAggregator extends kit_1.AsyncOptionalCreatable {
|
|
|
192
192
|
if (this.envVars[key] != null) {
|
|
193
193
|
return `$${envVars_1.EnvVars.propertyToEnvName(key)}`;
|
|
194
194
|
}
|
|
195
|
-
if (this.localConfig
|
|
195
|
+
if (this.localConfig?.getContents()[key] != null) {
|
|
196
196
|
return this.localConfig.getPath();
|
|
197
197
|
}
|
|
198
198
|
if (this.globalConfig.getContents()[key] != null) {
|
|
@@ -284,7 +284,7 @@ class ConfigAggregator extends kit_1.AsyncOptionalCreatable {
|
|
|
284
284
|
* Loads all the properties and aggregates them according to location.
|
|
285
285
|
*/
|
|
286
286
|
loadPropertiesSync() {
|
|
287
|
-
this.resolveProperties(this.globalConfig.readSync(), this.localConfig
|
|
287
|
+
this.resolveProperties(this.globalConfig.readSync(), this.localConfig?.readSync());
|
|
288
288
|
}
|
|
289
289
|
resolveProperties(globalConfig, localConfig) {
|
|
290
290
|
const envVars = new envVars_1.EnvVars();
|
|
@@ -311,13 +311,13 @@ exports.ConfigAggregator = ConfigAggregator;
|
|
|
311
311
|
ConfigAggregator.encrypted = true;
|
|
312
312
|
/**
|
|
313
313
|
* A ConfigAggregator that will work with deprecated config vars (e.g. defaultusername, apiVersion).
|
|
314
|
-
* We do NOT recommend using this class unless you
|
|
314
|
+
* We do NOT recommend using this class unless you absolutely have to.
|
|
315
315
|
*
|
|
316
316
|
* @deprecated
|
|
317
317
|
*/
|
|
318
318
|
class SfdxConfigAggregator extends ConfigAggregator {
|
|
319
319
|
static async create(options = {}) {
|
|
320
|
-
const customConfigMeta = options.customConfigMeta
|
|
320
|
+
const customConfigMeta = options.customConfigMeta ?? [];
|
|
321
321
|
// org-metadata-rest-deploy has been moved to plugin-deploy-retrieve but we need to have a placeholder
|
|
322
322
|
// for it here since sfdx needs to know how to set the deprecated restDeploy config var.
|
|
323
323
|
const restDeploy = config_1.SFDX_ALLOWED_PROPERTIES.find((p) => p.key === config_1.SfdxPropertyKeys.REST_DEPLOY);
|
package/lib/config/configFile.js
CHANGED
|
@@ -78,7 +78,7 @@ class ConfigFile extends configStore_1.BaseConfigStore {
|
|
|
78
78
|
return {
|
|
79
79
|
isGlobal,
|
|
80
80
|
isState: true,
|
|
81
|
-
filename: filename
|
|
81
|
+
filename: filename ?? this.getFileName(),
|
|
82
82
|
stateFolder: global_1.Global.SFDX_STATE_FOLDER,
|
|
83
83
|
};
|
|
84
84
|
}
|
|
@@ -88,7 +88,7 @@ class ConfigFile extends configStore_1.BaseConfigStore {
|
|
|
88
88
|
* @param isGlobal True if the config should be global. False for local.
|
|
89
89
|
*/
|
|
90
90
|
static async resolveRootFolder(isGlobal) {
|
|
91
|
-
return isGlobal ? (0, os_1.homedir)() :
|
|
91
|
+
return isGlobal ? (0, os_1.homedir)() : (0, internal_1.resolveProjectPath)();
|
|
92
92
|
}
|
|
93
93
|
/**
|
|
94
94
|
* Helper used to determine what the local and global folder point to. Returns the file path of the root folder.
|
|
@@ -246,7 +246,7 @@ class ConfigFile extends configStore_1.BaseConfigStore {
|
|
|
246
246
|
* Check to see if the config file exists. Returns `true` if the config file exists and has access, false otherwise.
|
|
247
247
|
*/
|
|
248
248
|
async exists() {
|
|
249
|
-
return
|
|
249
|
+
return this.access(fs_1.constants.R_OK);
|
|
250
250
|
}
|
|
251
251
|
/**
|
|
252
252
|
* Check to see if the config file exists. Returns `true` if the config file exists and has access, false otherwise.
|
|
@@ -279,7 +279,7 @@ class ConfigFile extends configStore_1.BaseConfigStore {
|
|
|
279
279
|
async unlink() {
|
|
280
280
|
const exists = await this.exists();
|
|
281
281
|
if (exists) {
|
|
282
|
-
return
|
|
282
|
+
return fs.promises.unlink(this.getPath());
|
|
283
283
|
}
|
|
284
284
|
throw new sfError_1.SfError(`Target file doesn't exist. path: ${this.getPath()}`, 'TargetFileNotFound');
|
|
285
285
|
}
|
|
@@ -308,14 +308,12 @@ class ConfigFile extends configStore_1.BaseConfigStore {
|
|
|
308
308
|
if (!this.options.filename) {
|
|
309
309
|
throw new sfError_1.SfError('The ConfigOptions filename parameter is invalid.', 'InvalidParameter');
|
|
310
310
|
}
|
|
311
|
-
const _isGlobal = (0, ts_types_1.isBoolean)(this.options.isGlobal) && this.options.isGlobal;
|
|
312
|
-
const _isState = (0, ts_types_1.isBoolean)(this.options.isState) && this.options.isState;
|
|
313
311
|
// Don't let users store config files in homedir without being in the state folder.
|
|
314
312
|
let configRootFolder = this.options.rootFolder
|
|
315
313
|
? this.options.rootFolder
|
|
316
|
-
: ConfigFile.resolveRootFolderSync(
|
|
317
|
-
if (
|
|
318
|
-
configRootFolder = (0, path_1.join)(configRootFolder, this.options.stateFolder
|
|
314
|
+
: ConfigFile.resolveRootFolderSync(Boolean(this.options.isGlobal));
|
|
315
|
+
if (this.options.isGlobal === true || this.options.isState === true) {
|
|
316
|
+
configRootFolder = (0, path_1.join)(configRootFolder, this.options.stateFolder ?? global_1.Global.SFDX_STATE_FOLDER);
|
|
319
317
|
}
|
|
320
318
|
this.path = (0, path_1.join)(configRootFolder, this.options.filePath ? this.options.filePath : '', this.options.filename);
|
|
321
319
|
}
|
|
@@ -67,7 +67,7 @@ class ConfigGroup extends configFile_1.ConfigFile {
|
|
|
67
67
|
async updateValues(newEntries, group) {
|
|
68
68
|
// Make sure the contents are loaded
|
|
69
69
|
await this.read();
|
|
70
|
-
Object.entries(newEntries).forEach(([key, val]) => this.setInGroup(key, val, group
|
|
70
|
+
Object.entries(newEntries).forEach(([key, val]) => this.setInGroup(key, val, group ?? this.defaultGroup));
|
|
71
71
|
await this.write();
|
|
72
72
|
return newEntries;
|
|
73
73
|
}
|
|
@@ -81,7 +81,7 @@ class ConfigGroup extends configFile_1.ConfigFile {
|
|
|
81
81
|
async updateValue(key, value, group) {
|
|
82
82
|
// Make sure the content is loaded
|
|
83
83
|
await this.read();
|
|
84
|
-
this.setInGroup(key, value, group
|
|
84
|
+
this.setInGroup(key, value, group ?? this.defaultGroup);
|
|
85
85
|
// Then save it
|
|
86
86
|
await this.write();
|
|
87
87
|
}
|
|
@@ -116,13 +116,13 @@ class ConfigGroup extends configFile_1.ConfigFile {
|
|
|
116
116
|
* Returns an array of the keys from the default group.
|
|
117
117
|
*/
|
|
118
118
|
keys() {
|
|
119
|
-
return Object.keys(this.getGroup(this.defaultGroup)
|
|
119
|
+
return Object.keys(this.getGroup(this.defaultGroup) ?? {});
|
|
120
120
|
}
|
|
121
121
|
/**
|
|
122
122
|
* Returns an array of the values from the default group.
|
|
123
123
|
*/
|
|
124
124
|
values() {
|
|
125
|
-
return (0, ts_types_1.definiteValuesOf)(this.getGroup(this.defaultGroup)
|
|
125
|
+
return (0, ts_types_1.definiteValuesOf)(this.getGroup(this.defaultGroup) ?? {});
|
|
126
126
|
}
|
|
127
127
|
/**
|
|
128
128
|
* Add or updates an element with the specified key in the default group.
|
|
@@ -158,7 +158,7 @@ class ConfigGroup extends configFile_1.ConfigFile {
|
|
|
158
158
|
* @param {string} [group = 'default'] The group.
|
|
159
159
|
*/
|
|
160
160
|
getGroup(group = this.defaultGroup) {
|
|
161
|
-
return (0, ts_types_1.getJsonMap)(this.getContents(), group)
|
|
161
|
+
return (0, ts_types_1.getJsonMap)(this.getContents(), group) ?? undefined;
|
|
162
162
|
}
|
|
163
163
|
/**
|
|
164
164
|
* Returns the value associated to the key and group, or undefined if there is none.
|
|
@@ -189,6 +189,7 @@ class ConfigGroup extends configFile_1.ConfigFile {
|
|
|
189
189
|
Array.from(contents.entries()).forEach(([groupKey, groupContents]) => {
|
|
190
190
|
if (groupContents) {
|
|
191
191
|
Object.entries(groupContents).forEach(([contentKey, contentValue]) => {
|
|
192
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
192
193
|
this.setInGroup(contentKey, contentValue, groupKey);
|
|
193
194
|
});
|
|
194
195
|
}
|
|
@@ -202,11 +203,11 @@ class ConfigGroup extends configFile_1.ConfigFile {
|
|
|
202
203
|
* @param group The group. Uses the default group if not specified.
|
|
203
204
|
*/
|
|
204
205
|
setInGroup(key, value, group) {
|
|
205
|
-
group = group
|
|
206
|
+
group = group ?? this.defaultGroup;
|
|
206
207
|
if (!super.has(group)) {
|
|
207
208
|
super.set(group, {});
|
|
208
209
|
}
|
|
209
|
-
const content = this.getGroup(group)
|
|
210
|
+
const content = this.getGroup(group) ?? {};
|
|
210
211
|
this.setMethod(content, key, value);
|
|
211
212
|
return content;
|
|
212
213
|
}
|
|
@@ -68,7 +68,7 @@ export declare abstract class BaseConfigStore<T extends BaseConfigStore.Options
|
|
|
68
68
|
* If the value is an object, a clone will be returned.
|
|
69
69
|
*/
|
|
70
70
|
get<K extends Key<P>>(key: K, decrypt?: boolean): P[K];
|
|
71
|
-
get<
|
|
71
|
+
get<V = ConfigValue>(key: string, decrypt?: boolean): V;
|
|
72
72
|
/**
|
|
73
73
|
* Returns the list of keys that contain a value.
|
|
74
74
|
*
|
|
@@ -93,7 +93,7 @@ export declare abstract class BaseConfigStore<T extends BaseConfigStore.Options
|
|
|
93
93
|
* @param value The value.
|
|
94
94
|
*/
|
|
95
95
|
set<K extends Key<P>>(key: K, value: P[K]): void;
|
|
96
|
-
set<
|
|
96
|
+
set<V = ConfigValue>(key: string, value: V): void;
|
|
97
97
|
/**
|
|
98
98
|
* Updates the value for the key in the config object. If the value is an object, it
|
|
99
99
|
* will be merged with the existing object.
|
|
@@ -102,7 +102,7 @@ export declare abstract class BaseConfigStore<T extends BaseConfigStore.Options
|
|
|
102
102
|
* @param value The value.
|
|
103
103
|
*/
|
|
104
104
|
update<K extends Key<P>>(key: K, value: Partial<P[K]>): void;
|
|
105
|
-
update<
|
|
105
|
+
update<V = ConfigValue>(key: string, value: Partial<V>): void;
|
|
106
106
|
/**
|
|
107
107
|
* Returns `true` if an element in the config object existed and has been removed, or `false` if the element does not
|
|
108
108
|
* exist. {@link BaseConfigStore.has} will return false afterwards.
|
|
@@ -204,7 +204,7 @@ export declare abstract class BaseConfigStore<T extends BaseConfigStore.Options
|
|
|
204
204
|
* @param keyPaths: The complete path of the (nested) data
|
|
205
205
|
* @param data: The current (nested) data being worked on.
|
|
206
206
|
*/
|
|
207
|
-
protected recursiveEncrypt<
|
|
207
|
+
protected recursiveEncrypt<J extends JsonMap>(data: J, parentKey?: string): J;
|
|
208
208
|
/**
|
|
209
209
|
* Decrypt all values in a nested JsonMap.
|
|
210
210
|
*
|
|
@@ -28,7 +28,7 @@ class BaseConfigStore extends kit_1.AsyncOptionalCreatable {
|
|
|
28
28
|
constructor(options) {
|
|
29
29
|
super(options);
|
|
30
30
|
this.statics = this.constructor;
|
|
31
|
-
this.options = options
|
|
31
|
+
this.options = options ?? {};
|
|
32
32
|
this.setContents(this.initialContents());
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
@@ -183,6 +183,8 @@ class BaseConfigStore extends kit_1.AsyncOptionalCreatable {
|
|
|
183
183
|
async awaitEach(actionFn) {
|
|
184
184
|
const entries = this.entries();
|
|
185
185
|
for (const entry of entries) {
|
|
186
|
+
// prevent ConfigFile collision bug
|
|
187
|
+
// eslint-disable-next-line no-await-in-loop
|
|
186
188
|
await actionFn(entry[0], entry[1]);
|
|
187
189
|
}
|
|
188
190
|
}
|
|
@@ -205,7 +207,7 @@ class BaseConfigStore extends kit_1.AsyncOptionalCreatable {
|
|
|
205
207
|
});
|
|
206
208
|
}
|
|
207
209
|
getEncryptedKeys() {
|
|
208
|
-
return [...(this.options?.encryptedKeys
|
|
210
|
+
return [...(this.options?.encryptedKeys ?? []), ...(this.statics?.encryptedKeys || [])];
|
|
209
211
|
}
|
|
210
212
|
/**
|
|
211
213
|
* This config file has encrypted keys and it should attempt to encrypt them.
|
|
@@ -217,15 +219,18 @@ class BaseConfigStore extends kit_1.AsyncOptionalCreatable {
|
|
|
217
219
|
}
|
|
218
220
|
// Allows extended classes the ability to override the set method. i.e. maybe they want
|
|
219
221
|
// nested object set from kit.
|
|
222
|
+
// eslint-disable-next-line class-methods-use-this
|
|
220
223
|
setMethod(contents, key, value) {
|
|
221
224
|
(0, kit_1.set)(contents, key, value);
|
|
222
225
|
}
|
|
223
226
|
// Allows extended classes the ability to override the get method. i.e. maybe they want
|
|
224
227
|
// nested object get from ts-types.
|
|
225
228
|
// NOTE: Key must stay string to be reliably overwritten.
|
|
229
|
+
// eslint-disable-next-line class-methods-use-this
|
|
226
230
|
getMethod(contents, key) {
|
|
227
231
|
return (0, ts_types_2.get)(contents, key);
|
|
228
232
|
}
|
|
233
|
+
// eslint-disable-next-line class-methods-use-this
|
|
229
234
|
initialContents() {
|
|
230
235
|
return {};
|
|
231
236
|
}
|
|
@@ -267,7 +272,7 @@ class BaseConfigStore extends kit_1.AsyncOptionalCreatable {
|
|
|
267
272
|
const dotAccessor = /\.([a-zA-Z0-9@._-]+)$/;
|
|
268
273
|
const singleQuoteAccessor = /\['([a-zA-Z0-9@._-]+)'\]$/;
|
|
269
274
|
const doubleQuoteAccessor = /\["([a-zA-Z0-9@._-]+)"\]$/;
|
|
270
|
-
const matcher = dotAccessor.exec(key)
|
|
275
|
+
const matcher = dotAccessor.exec(key) ?? singleQuoteAccessor.exec(key) ?? doubleQuoteAccessor.exec(key);
|
|
271
276
|
return matcher ? matcher[1] : key;
|
|
272
277
|
}
|
|
273
278
|
// Any keys named the following should be encrypted/decrypted
|
|
@@ -287,7 +292,7 @@ class BaseConfigStore extends kit_1.AsyncOptionalCreatable {
|
|
|
287
292
|
if (!this.crypto)
|
|
288
293
|
throw new sfError_1.SfError('crypto is not initialized', 'CryptoNotInitializedError');
|
|
289
294
|
if (!(0, ts_types_2.isString)(value))
|
|
290
|
-
throw new sfError_1.SfError(`can only encrypt strings but found: ${typeof value} : ${value}`, 'InvalidCryptoValueError');
|
|
295
|
+
throw new sfError_1.SfError(`can only encrypt strings but found: ${typeof value} : ${value.toString()}`, 'InvalidCryptoValueError');
|
|
291
296
|
return this.crypto.isEncrypted(value) ? value : this.crypto.encrypt(value);
|
|
292
297
|
}
|
|
293
298
|
decrypt(value) {
|
|
@@ -296,7 +301,7 @@ class BaseConfigStore extends kit_1.AsyncOptionalCreatable {
|
|
|
296
301
|
if (!this.crypto)
|
|
297
302
|
throw new sfError_1.SfError('crypto is not initialized', 'CryptoNotInitializedError');
|
|
298
303
|
if (!(0, ts_types_2.isString)(value))
|
|
299
|
-
throw new sfError_1.SfError(`can only encrypt strings but found: ${typeof value} : ${value}`, 'InvalidCryptoValueError');
|
|
304
|
+
throw new sfError_1.SfError(`can only encrypt strings but found: ${typeof value} : ${value.toString()}`, 'InvalidCryptoValueError');
|
|
300
305
|
return this.crypto.isEncrypted(value) ? this.crypto.decrypt(value) : value;
|
|
301
306
|
}
|
|
302
307
|
/**
|
|
@@ -337,10 +342,8 @@ class BaseConfigStore extends kit_1.AsyncOptionalCreatable {
|
|
|
337
342
|
this.recursiveCrypto(method, [...keyPaths, key, newKey], value);
|
|
338
343
|
}
|
|
339
344
|
}
|
|
340
|
-
else {
|
|
341
|
-
|
|
342
|
-
data[key] = method(value);
|
|
343
|
-
}
|
|
345
|
+
else if (this.isCryptoKey(key)) {
|
|
346
|
+
data[key] = method(value);
|
|
344
347
|
}
|
|
345
348
|
}
|
|
346
349
|
}
|
package/lib/config/envVars.js
CHANGED
|
@@ -420,7 +420,7 @@ class EnvVars extends kit_1.Env {
|
|
|
420
420
|
getPropertyFromEnv(property, prefix = EnvVars.defaultPrefix()) {
|
|
421
421
|
const envName = EnvVars.propertyToEnvName(property, prefix);
|
|
422
422
|
const synonym = exports.SUPPORTED_ENV_VARS[envName]?.synonymOf;
|
|
423
|
-
return this.get(envName)
|
|
423
|
+
return this.get(envName) ?? this.get(synonym);
|
|
424
424
|
}
|
|
425
425
|
asDictionary() {
|
|
426
426
|
return this.entries().reduce((accumulator, [key, value]) => {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* Licensed under the BSD 3-Clause license.
|
|
6
6
|
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
7
7
|
*/
|
|
8
|
+
/* eslint-disable class-methods-use-this */
|
|
8
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
10
|
exports.TokensConfig = void 0;
|
|
10
11
|
const configFile_1 = require("./configFile");
|
|
@@ -5,11 +5,13 @@ import { ConfigFile } from './configFile';
|
|
|
5
5
|
* A Time To Live configuration file where each entry is timestamped and removed once the TTL has expired.
|
|
6
6
|
*
|
|
7
7
|
* @example
|
|
8
|
+
* ```
|
|
8
9
|
* import { Duration } from '@salesforce/kit';
|
|
9
10
|
* const config = await TTLConfig.create({
|
|
10
11
|
* isGlobal: false,
|
|
11
12
|
* ttl: Duration.days(1)
|
|
12
13
|
* });
|
|
14
|
+
* ```
|
|
13
15
|
*/
|
|
14
16
|
export declare class TTLConfig<T extends TTLConfig.Options, P extends JsonMap> extends ConfigFile<T, TTLConfig.Contents<P>> {
|
|
15
17
|
set(key: string, value: Partial<TTLConfig.Entry<P>>): void;
|
package/lib/config/ttlConfig.js
CHANGED
|
@@ -12,11 +12,13 @@ const configFile_1 = require("./configFile");
|
|
|
12
12
|
* A Time To Live configuration file where each entry is timestamped and removed once the TTL has expired.
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
|
+
* ```
|
|
15
16
|
* import { Duration } from '@salesforce/kit';
|
|
16
17
|
* const config = await TTLConfig.create({
|
|
17
18
|
* isGlobal: false,
|
|
18
19
|
* ttl: Duration.days(1)
|
|
19
20
|
* });
|
|
21
|
+
* ```
|
|
20
22
|
*/
|
|
21
23
|
class TTLConfig extends configFile_1.ConfigFile {
|
|
22
24
|
set(key, value) {
|
|
@@ -24,13 +26,11 @@ class TTLConfig extends configFile_1.ConfigFile {
|
|
|
24
26
|
}
|
|
25
27
|
getLatestEntry() {
|
|
26
28
|
const entries = this.entries();
|
|
27
|
-
const sorted = entries.sort(([, valueA], [, valueB]) =>
|
|
28
|
-
return new Date(valueB.timestamp).getTime() - new Date(valueA.timestamp).getTime();
|
|
29
|
-
});
|
|
29
|
+
const sorted = entries.sort(([, valueA], [, valueB]) => new Date(valueB.timestamp).getTime() - new Date(valueA.timestamp).getTime());
|
|
30
30
|
return sorted.length > 0 ? sorted[0] : null;
|
|
31
31
|
}
|
|
32
32
|
getLatestKey() {
|
|
33
|
-
const [key] = this.getLatestEntry()
|
|
33
|
+
const [key] = this.getLatestEntry() ?? [null];
|
|
34
34
|
return key;
|
|
35
35
|
}
|
|
36
36
|
isExpired(dateTime, value) {
|
|
@@ -46,6 +46,7 @@ class TTLConfig extends configFile_1.ConfigFile {
|
|
|
46
46
|
}
|
|
47
47
|
this.setContents(purged);
|
|
48
48
|
}
|
|
49
|
+
// eslint-disable-next-line class-methods-use-this
|
|
49
50
|
timestamp(value) {
|
|
50
51
|
return { ...value, timestamp: new Date().toISOString() };
|
|
51
52
|
}
|
package/lib/crypto/crypto.js
CHANGED
|
@@ -53,21 +53,17 @@ const keychainPromises = {
|
|
|
53
53
|
const cacheKey = `${global_1.Global.DIR}:${service}:${account}`;
|
|
54
54
|
const sb = cache_1.Cache.get(cacheKey);
|
|
55
55
|
if (!sb) {
|
|
56
|
-
return new Promise((resolve, reject) => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
});
|
|
63
|
-
});
|
|
56
|
+
return new Promise((resolve, reject) => _keychain.getPassword({ service, account }, (err, password) => {
|
|
57
|
+
if (err)
|
|
58
|
+
return reject(err);
|
|
59
|
+
cache_1.Cache.set(cacheKey, makeSecureBuffer(password));
|
|
60
|
+
return resolve({ username: account, password: (0, ts_types_1.ensure)(password) });
|
|
61
|
+
}));
|
|
64
62
|
}
|
|
65
63
|
else {
|
|
66
64
|
const pw = sb.value((buffer) => buffer.toString('utf8'));
|
|
67
65
|
cache_1.Cache.set(cacheKey, makeSecureBuffer(pw));
|
|
68
|
-
return new Promise((resolve) => {
|
|
69
|
-
return resolve({ username: account, password: (0, ts_types_1.ensure)(pw) });
|
|
70
|
-
});
|
|
66
|
+
return new Promise((resolve) => resolve({ username: account, password: (0, ts_types_1.ensure)(pw) }));
|
|
71
67
|
}
|
|
72
68
|
},
|
|
73
69
|
/**
|
|
@@ -100,7 +96,7 @@ class Crypto extends kit_1.AsyncOptionalCreatable {
|
|
|
100
96
|
constructor(options) {
|
|
101
97
|
super(options);
|
|
102
98
|
this.key = new secureBuffer_1.SecureBuffer();
|
|
103
|
-
this.options = options
|
|
99
|
+
this.options = options ?? {};
|
|
104
100
|
}
|
|
105
101
|
encrypt(text) {
|
|
106
102
|
if (text == null) {
|
|
@@ -155,6 +151,7 @@ class Crypto extends kit_1.AsyncOptionalCreatable {
|
|
|
155
151
|
* @param text The text
|
|
156
152
|
* @returns true if the text is encrypted, false otherwise.
|
|
157
153
|
*/
|
|
154
|
+
// eslint-disable-next-line class-methods-use-this
|
|
158
155
|
isEncrypted(text) {
|
|
159
156
|
if (text == null) {
|
|
160
157
|
return false;
|