@salesforce/core 5.4.0-crdt.1 → 6.1.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.
Files changed (100) hide show
  1. package/README.md +3 -3
  2. package/lib/config/authInfoConfig.d.ts +1 -1
  3. package/lib/config/config.d.ts +6 -29
  4. package/lib/config/config.js +91 -113
  5. package/lib/config/configAggregator.js +1 -0
  6. package/lib/config/configFile.d.ts +3 -1
  7. package/lib/config/configFile.js +44 -67
  8. package/lib/config/configStore.d.ts +20 -29
  9. package/lib/config/configStore.js +50 -53
  10. package/lib/config/envVars.js +3 -2
  11. package/lib/config/lwwMap.d.ts +4 -5
  12. package/lib/config/lwwMap.js +19 -16
  13. package/lib/config/lwwRegister.d.ts +2 -3
  14. package/lib/config/lwwRegister.js +6 -7
  15. package/lib/config/sandboxOrgConfig.js +1 -1
  16. package/lib/config/sandboxProcessCache.d.ts +1 -1
  17. package/lib/crypto/crypto.js +4 -3
  18. package/lib/crypto/keyChain.js +1 -0
  19. package/lib/crypto/keyChainImpl.d.ts +2 -2
  20. package/lib/crypto/keyChainImpl.js +9 -8
  21. package/lib/crypto/secureBuffer.js +1 -1
  22. package/lib/deviceOauthService.d.ts +1 -1
  23. package/lib/deviceOauthService.js +8 -6
  24. package/lib/exported.d.ts +3 -4
  25. package/lib/exported.js +6 -6
  26. package/lib/global.js +4 -4
  27. package/lib/logger/logger.js +6 -5
  28. package/lib/logger/memoryLogger.d.ts +1 -1
  29. package/lib/logger/memoryLogger.js +2 -2
  30. package/lib/logger/transformStream.d.ts +1 -1
  31. package/lib/logger/transformStream.js +3 -3
  32. package/lib/messageTransformer.js +2 -2
  33. package/lib/messages.js +5 -5
  34. package/lib/org/authInfo.js +11 -10
  35. package/lib/org/authRemover.d.ts +1 -2
  36. package/lib/org/authRemover.js +2 -12
  37. package/lib/org/connection.js +3 -2
  38. package/lib/org/org.js +9 -8
  39. package/lib/org/orgConfigProperties.js +3 -2
  40. package/lib/org/permissionSetAssignment.js +15 -13
  41. package/lib/org/scratchOrgCreate.js +2 -1
  42. package/lib/org/scratchOrgErrorCodes.js +1 -0
  43. package/lib/org/scratchOrgFeatureDeprecation.js +1 -0
  44. package/lib/org/scratchOrgInfoApi.js +1 -0
  45. package/lib/org/scratchOrgInfoGenerator.js +3 -2
  46. package/lib/org/scratchOrgSettingsGenerator.js +3 -3
  47. package/lib/org/user.js +4 -3
  48. package/lib/schema/validator.js +2 -2
  49. package/lib/sfError.d.ts +1 -1
  50. package/lib/sfProject.d.ts +1 -0
  51. package/lib/sfProject.js +12 -11
  52. package/lib/stateAggregator/accessors/aliasAccessor.d.ts +1 -2
  53. package/lib/stateAggregator/accessors/aliasAccessor.js +3 -2
  54. package/lib/stateAggregator/accessors/orgAccessor.d.ts +2 -2
  55. package/lib/stateAggregator/accessors/orgAccessor.js +8 -6
  56. package/lib/stateAggregator/accessors/sandboxAccessor.d.ts +1 -1
  57. package/lib/stateAggregator/stateAggregator.d.ts +0 -2
  58. package/lib/stateAggregator/stateAggregator.js +0 -2
  59. package/lib/status/myDomainResolver.d.ts +1 -1
  60. package/lib/status/myDomainResolver.js +6 -6
  61. package/lib/status/pollingClient.js +1 -1
  62. package/lib/status/streamingClient.js +4 -3
  63. package/lib/status/types.d.ts +1 -1
  64. package/lib/status/types.js +2 -2
  65. package/lib/testSetup.d.ts +3 -7
  66. package/lib/testSetup.js +47 -39
  67. package/lib/util/cache.js +14 -14
  68. package/lib/util/checkLightningDomain.js +2 -2
  69. package/lib/util/directoryWriter.d.ts +1 -1
  70. package/lib/util/directoryWriter.js +7 -7
  71. package/lib/util/fileLocking.d.ts +24 -0
  72. package/lib/util/fileLocking.js +91 -0
  73. package/lib/util/findUppercaseKeys.d.ts +2 -0
  74. package/lib/util/findUppercaseKeys.js +29 -0
  75. package/lib/util/internal.js +7 -6
  76. package/lib/util/sfdc.d.ts +0 -18
  77. package/lib/util/sfdc.js +1 -42
  78. package/lib/util/sfdcUrl.d.ts +2 -2
  79. package/lib/util/sfdcUrl.js +9 -8
  80. package/lib/util/structuredWriter.d.ts +1 -1
  81. package/lib/util/time.d.ts +1 -0
  82. package/lib/util/time.js +13 -0
  83. package/lib/util/uniqid.js +3 -3
  84. package/lib/util/zipWriter.d.ts +1 -1
  85. package/lib/util/zipWriter.js +2 -2
  86. package/lib/webOAuthServer.d.ts +2 -2
  87. package/lib/webOAuthServer.js +16 -15
  88. package/package.json +14 -38
  89. package/lib/config/tokensConfig.d.ts +0 -10
  90. package/lib/config/tokensConfig.js +0 -29
  91. package/lib/org/index.d.ts +0 -6
  92. package/lib/org/index.js +0 -29
  93. package/lib/schema/printer.d.ts +0 -81
  94. package/lib/schema/printer.js +0 -263
  95. package/lib/stateAggregator/accessors/tokenAccessor.d.ts +0 -63
  96. package/lib/stateAggregator/accessors/tokenAccessor.js +0 -80
  97. package/lib/stateAggregator/index.d.ts +0 -4
  98. package/lib/stateAggregator/index.js +0 -27
  99. package/lib/util/jsonXmlTools.d.ts +0 -14
  100. package/lib/util/jsonXmlTools.js +0 -39
package/README.md CHANGED
@@ -34,11 +34,11 @@ The Messages class, by default, loads message text during run time. It's optimiz
34
34
 
35
35
  If you're using @salesforce/core or other code that uses its Messages class in a bundler (webpack, esbuild, etc) it may struggle with these runtime references.
36
36
 
37
- src/messageTransformer will "inline" the messages into the js files during TS compile using `https://github.com/cevek/ttypescript`.
37
+ src/messageTransformer will "inline" the messages into the js files during TS compile using `https://github.com/nonara/ts-patch`.
38
38
 
39
39
  In your plugin or library,
40
40
 
41
- `yarn add --dev ttypescript`
41
+ `yarn add --dev ts-patch`
42
42
 
43
43
  > tsconfig.json
44
44
 
@@ -54,7 +54,7 @@ In your plugin or library,
54
54
  ```json
55
55
  "wireit": {
56
56
  "compile": {
57
- "command": "ttsc -p . --pretty --incremental",
57
+ "command": "tspc -p . --pretty --incremental",
58
58
  "files": [
59
59
  "src/**/*.ts",
60
60
  "tsconfig.json",
@@ -1,4 +1,4 @@
1
- import { AuthFields } from '../org';
1
+ import { AuthFields } from '../org/authInfo';
2
2
  import { ConfigFile } from './configFile';
3
3
  /**
4
4
  * An auth config file that stores information such as access tokens, usernames, etc.,
@@ -1,7 +1,7 @@
1
- import { JsonCollection, JsonPrimitive, Nullable } from '@salesforce/ts-types';
1
+ import { Nullable } from '@salesforce/ts-types';
2
2
  import { OrgConfigProperties } from '../org/orgConfigProperties';
3
3
  import { ConfigFile } from './configFile';
4
- import { ConfigContents, ConfigValue } from './configStackTypes';
4
+ import { ConfigContents, ConfigValue, Key } from './configStackTypes';
5
5
  /**
6
6
  * Interface for meta information about config properties
7
7
  */
@@ -181,9 +181,7 @@ export declare const SFDX_ALLOWED_PROPERTIES: ({
181
181
  export declare const SfProperty: {
182
182
  [index: string]: ConfigPropertyMeta;
183
183
  };
184
- export type ConfigProperties = {
185
- [index: string]: JsonPrimitive;
186
- };
184
+ export type ConfigProperties = ConfigContents;
187
185
  /**
188
186
  * The files where sfdx config values are stored for projects and the global space.
189
187
  *
@@ -199,7 +197,7 @@ export type ConfigProperties = {
199
197
  */
200
198
  export declare class Config extends ConfigFile<ConfigFile.Options, ConfigProperties> {
201
199
  private static allowedProperties;
202
- private sfdxConfig;
200
+ private sfdxPath?;
203
201
  constructor(options?: ConfigFile.Options);
204
202
  /**
205
203
  * Returns the default file name for a config file.
@@ -224,7 +222,7 @@ export declare class Config extends ConfigFile<ConfigFile.Options, ConfigPropert
224
222
  * @param propertyName The name of the property to set.
225
223
  * @param value The property value.
226
224
  */
227
- static update(isGlobal: boolean, propertyName: string, value?: ConfigValue): Promise<ConfigContents>;
225
+ static update<K extends Key<ConfigProperties>>(isGlobal: boolean, propertyName: K, value?: ConfigProperties[K]): Promise<ConfigContents>;
228
226
  /**
229
227
  * Clear all the configured properties both local and global.
230
228
  */
@@ -260,7 +258,7 @@ export declare class Config extends ConfigFile<ConfigFile.Options, ConfigPropert
260
258
  * @param key The property to set.
261
259
  * @param value The value of the property.
262
260
  */
263
- set(key: string, value: JsonPrimitive | JsonCollection): ConfigProperties;
261
+ set<K extends Key<ConfigProperties>>(key: K, value: ConfigProperties[K]): ConfigProperties;
264
262
  /**
265
263
  * Unsets a value for a property.
266
264
  *
@@ -288,24 +286,3 @@ export declare class Config extends ConfigFile<ConfigFile.Options, ConfigPropert
288
286
  */
289
287
  private cryptProperties;
290
288
  }
291
- export declare class SfdxConfig {
292
- private options;
293
- private config;
294
- private sfdxPath;
295
- constructor(options: ConfigFile.Options, config: Config);
296
- /**
297
- * If Global.SFDX_INTEROPERABILITY is enabled, merge the sfdx config into the sf config
298
- */
299
- merge(config: ConfigProperties): ConfigProperties | undefined;
300
- write(config?: import("@salesforce/ts-types").JsonMap): Promise<void>;
301
- private readSync;
302
- private getSfdxPath;
303
- /**
304
- * If toNew is specified: migrate all deprecated configs with a newKey to the newKey.
305
- * - For example, defaultusername will be renamed to target-org.
306
- *
307
- * If toOld is specified: migrate all deprecated configs back to their original key.
308
- * - For example, target-org will be renamed to defaultusername.
309
- */
310
- private translate;
311
- }
@@ -6,9 +6,9 @@
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
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.SfdxConfig = exports.Config = exports.SfProperty = exports.SFDX_ALLOWED_PROPERTIES = exports.SfdxPropertyKeys = exports.SF_ALLOWED_PROPERTIES = exports.SfConfigProperties = void 0;
10
- const path_1 = require("path");
11
- const fs = require("fs");
9
+ exports.Config = exports.SfProperty = exports.SFDX_ALLOWED_PROPERTIES = exports.SfdxPropertyKeys = exports.SF_ALLOWED_PROPERTIES = exports.SfConfigProperties = void 0;
10
+ const node_path_1 = require("node:path");
11
+ const fs = require("node:fs");
12
12
  const kit_1 = require("@salesforce/kit");
13
13
  const ts_types_1 = require("@salesforce/ts-types");
14
14
  const global_1 = require("../global");
@@ -19,6 +19,8 @@ const sfdcUrl_1 = require("../util/sfdcUrl");
19
19
  const orgConfigProperties_1 = require("../org/orgConfigProperties");
20
20
  const lifecycleEvents_1 = require("../lifecycleEvents");
21
21
  const configFile_1 = require("./configFile");
22
+ const lwwMap_1 = require("./lwwMap");
23
+ ;
22
24
  const messages = new messages_1.Messages('@salesforce/core', 'config', new Map([["unknownConfigKey", "Unknown config name: %s."], ["deprecatedConfigKey", "Deprecated config name: %s. Please use %s instead."], ["invalidWrite", "The writeSync method is not allowed on SfdxConfig. Use the async write method instead."], ["invalidConfigValue", "Invalid config value: %s."], ["invalidInstanceUrl", "Specify a valid Salesforce instance URL."], ["invalidApiVersion", "Specify a valid Salesforce API version, for example, 42.0."], ["invalidCustomOrgMetadataTemplates", "Specify a valid repository URL or directory for the custom org metadata templates."], ["invalidIsvDebuggerSid", "Specify a valid Debugger SID."], ["invalidIsvDebuggerUrl", "Specify a valid Debugger URL."], ["invalidNumberConfigValue", "Specify a valid positive integer, for example, 150000."], ["invalidBooleanConfigValue", "The config value can only be set to true or false."], ["invalidProjectWorkspace", "This directory does not contain a valid Salesforce DX project."], ["schemaValidationError", "The config file \"%s\" is not schema valid.\nDue to: %s"], ["schemaValidationError.actions", ["Fix the invalid entries at %s."]], ["missingDefaultPath", "In sfdx-project.json, be sure to specify which package directory (path) is the default. Example: `[{ \"path\": \"packageDirectory1\", \"default\": true }, { \"path\": \"packageDirectory2\" }]`"], ["missingPackageDirectory", "The path \"%s\", specified in sfdx-project.json, does not exist. Be sure this directory is included in your project root."], ["invalidPackageDirectory", "The path \"%s\", specified in sfdx-project.json, must be indicated as a relative path to the project root."], ["multipleDefaultPaths", "In sfdx-project.json, indicate only one package directory (path) as the default."], ["singleNonDefaultPackage", "The sfdx-project.json file must include one, and only one, default package directory (path). Because your sfdx-project.json file contains only one package directory, it must be the default. Remove the `\"default\": false` key and try again."], ["target-org", "Username or alias of the org that all commands run against by default. (sf only)"], ["target-dev-hub", "Username or alias of your default Dev Hub org. (sf only)"], ["defaultUsername", "Username or alias of the org that all commands run against by default. (sfdx only)"], ["defaultDevHubUsername", "Username or alias of your default Dev Hub org. (sfdx only)"], ["isvDebuggerSid", "ISV debugger SID (sfdx only)"], ["isvDebuggerUrl", "ISV debugger URL (sfdx only)"], ["org-isv-debugger-sid", "ISV debugger SID."], ["org-isv-debugger-url", "ISV debugger URL."], ["apiVersion", "API version of your project. Default: API version of your Dev Hub org. (sfdx only)"], ["org-api-version", "API version of your project. Default: API version of your Dev Hub org."], ["disableTelemetry", "Disables the collection of usage and user environment information, etc. Default: false. (sfdx only)"], ["disable-telemetry", "Disables the collection of usage and user environment information, etc. Default: false."], ["maxQueryLimit", "Maximum number of Salesforce records returned by a CLI command. Default: 10,000. (sfdx only)"], ["org-max-query-limit", "Maximum number of Salesforce records returned by a CLI command. Default: 10,000."], ["restDeploy", "Whether deployments use the Metadata REST API (true) or SOAP API (false, default value). (sfdx only)"], ["instanceUrl", "URL of the Salesforce instance hosting your org. Default: https://login.salesforce.com. (sfdx only)"], ["org-instance-url", "URL of the Salesforce instance hosting your org. Default: https://login.salesforce.com."], ["customOrgMetadataTemplates", "A valid repository URL or directory for the custom org metadata templates."], ["org-custom-metadata-templates", "A valid repository URL or directory for the custom org metadata templates."], ["invalidId", "The given id %s is not a valid 15 or 18 character Salesforce ID."]]));
23
25
  const SFDX_CONFIG_FILE_NAME = 'sfdx-config.json';
24
26
  const CONFIG_FILE_NAME = 'config.json';
@@ -28,13 +30,13 @@ var SfConfigProperties;
28
30
  * Disables telemetry reporting
29
31
  */
30
32
  SfConfigProperties["DISABLE_TELEMETRY"] = "disable-telemetry";
31
- })(SfConfigProperties = exports.SfConfigProperties || (exports.SfConfigProperties = {}));
33
+ })(SfConfigProperties || (exports.SfConfigProperties = SfConfigProperties = {}));
32
34
  exports.SF_ALLOWED_PROPERTIES = [
33
35
  {
34
36
  key: SfConfigProperties.DISABLE_TELEMETRY,
35
37
  description: messages.getMessage(SfConfigProperties.DISABLE_TELEMETRY),
36
38
  input: {
37
- validator: (value) => value == null || ['true', 'false'].includes(value.toString()),
39
+ validator: (value) => value == null || isBooleanOrBooleanString(value),
38
40
  failedMessage: messages.getMessage('invalidBooleanConfigValue'),
39
41
  },
40
42
  },
@@ -99,7 +101,7 @@ var SfdxPropertyKeys;
99
101
  * @deprecated Replaced by OrgConfigProperties.ORG_INSTANCE_URL in v3 {@link https://github.com/forcedotcom/sfdx-core/blob/v3/MIGRATING_V2-V3.md#config}
100
102
  */
101
103
  SfdxPropertyKeys["INSTANCE_URL"] = "instanceUrl";
102
- })(SfdxPropertyKeys = exports.SfdxPropertyKeys || (exports.SfdxPropertyKeys = {}));
104
+ })(SfdxPropertyKeys || (exports.SfdxPropertyKeys = SfdxPropertyKeys = {}));
103
105
  exports.SFDX_ALLOWED_PROPERTIES = [
104
106
  {
105
107
  key: SfdxPropertyKeys.INSTANCE_URL,
@@ -175,7 +177,7 @@ exports.SFDX_ALLOWED_PROPERTIES = [
175
177
  deprecated: true,
176
178
  description: messages.getMessage(SfdxPropertyKeys.DISABLE_TELEMETRY),
177
179
  input: {
178
- validator: (value) => value == null || ['true', 'false'].includes(value.toString()),
180
+ validator: (value) => value == null || isBooleanOrBooleanString(value),
179
181
  failedMessage: messages.getMessage('invalidBooleanConfigValue'),
180
182
  },
181
183
  },
@@ -192,7 +194,7 @@ exports.SFDX_ALLOWED_PROPERTIES = [
192
194
  newKey: 'org-metadata-rest-deploy',
193
195
  deprecated: true,
194
196
  input: {
195
- validator: (value) => value != null && ['true', 'false'].includes(value.toString()),
197
+ validator: (value) => value != null && isBooleanOrBooleanString(value),
196
198
  failedMessage: messages.getMessage('invalidBooleanConfigValue'),
197
199
  },
198
200
  },
@@ -227,18 +229,20 @@ exports.SfProperty = {};
227
229
  */
228
230
  class Config extends configFile_1.ConfigFile {
229
231
  constructor(options) {
230
- super(Object.assign({
231
- isGlobal: false,
232
- }, options ?? {}, {
232
+ super({
233
+ ...{ isGlobal: false },
234
+ ...(options ?? {}),
233
235
  // Don't let consumers of config override this. If they really really want to,
234
236
  // they can extend this class.
235
237
  isState: true,
236
238
  filename: Config.getFileName(),
237
239
  stateFolder: global_1.Global.SF_STATE_FOLDER,
238
- }));
240
+ });
239
241
  // Resolve the config path on creation.
240
242
  this.getPath();
241
- this.sfdxConfig = new SfdxConfig(this.options, this);
243
+ if (global_1.Global.SFDX_INTEROPERABILITY) {
244
+ this.sfdxPath = buildSfdxPath(this.options);
245
+ }
242
246
  }
243
247
  /**
244
248
  * Returns the default file name for a config file.
@@ -282,7 +286,7 @@ class Config extends configFile_1.ConfigFile {
282
286
  static async update(isGlobal, propertyName, value) {
283
287
  const config = await Config.create({ isGlobal });
284
288
  await config.read();
285
- if (value == null || value === undefined) {
289
+ if (value == null) {
286
290
  config.unset(propertyName);
287
291
  }
288
292
  else {
@@ -294,12 +298,10 @@ class Config extends configFile_1.ConfigFile {
294
298
  * Clear all the configured properties both local and global.
295
299
  */
296
300
  static async clear() {
297
- const globalConfig = await Config.create({ isGlobal: true });
301
+ const [globalConfig, localConfig] = await Promise.all([Config.create({ isGlobal: true }), Config.create()]);
298
302
  globalConfig.clear();
299
- await globalConfig.write();
300
- const localConfig = await Config.create();
301
303
  localConfig.clear();
302
- await localConfig.write();
304
+ await Promise.all([globalConfig.write(), localConfig.write()]);
303
305
  }
304
306
  static getPropertyConfigMeta(propertyName) {
305
307
  const prop = Config.propertyConfigMap()[propertyName];
@@ -316,10 +318,12 @@ class Config extends configFile_1.ConfigFile {
316
318
  */
317
319
  async read(force = true) {
318
320
  try {
319
- const config = await super.read(false, force);
320
- // Merge .sfdx/sfdx-config.json and .sf/config.json
321
- const merged = this.sfdxConfig.merge(config);
322
- this.setContents(merged);
321
+ await super.read(false, force);
322
+ if (global_1.Global.SFDX_INTEROPERABILITY) {
323
+ // will exist if Global.SFDX_INTEROPERABILITY is enabled
324
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
325
+ this.contents.merge(stateFromSfdxFileSync(this.sfdxPath, this));
326
+ }
323
327
  await this.cryptProperties(false);
324
328
  return this.getContents();
325
329
  }
@@ -328,10 +332,12 @@ class Config extends configFile_1.ConfigFile {
328
332
  }
329
333
  }
330
334
  readSync(force = true) {
331
- const config = super.readSync(false, force);
332
- // Merge .sfdx/sfdx-config.json and .sf/config.json
333
- const merged = this.sfdxConfig.merge(config);
334
- this.setContents(merged);
335
+ super.readSync(false, force);
336
+ if (global_1.Global.SFDX_INTEROPERABILITY) {
337
+ // will exist if Global.SFDX_INTEROPERABILITY is enabled
338
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
339
+ this.contents.merge(stateFromSfdxFileSync(this.sfdxPath, this));
340
+ }
335
341
  return this.getContents();
336
342
  }
337
343
  /**
@@ -341,9 +347,13 @@ class Config extends configFile_1.ConfigFile {
341
347
  */
342
348
  async write() {
343
349
  await this.cryptProperties(true);
350
+ // super.write will merge the contents if the target file had newer properties
344
351
  await super.write();
345
- if (global_1.Global.SFDX_INTEROPERABILITY)
346
- await this.sfdxConfig.write();
352
+ if (global_1.Global.SFDX_INTEROPERABILITY) {
353
+ // will exist if Global.SFDX_INTEROPERABILITY is enabled
354
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
355
+ await writeToSfdx(this.sfdxPath, this.getContents());
356
+ }
347
357
  await this.cryptProperties(false);
348
358
  return this.getContents();
349
359
  }
@@ -378,7 +388,7 @@ class Config extends configFile_1.ConfigFile {
378
388
  void lifecycleEvents_1.Lifecycle.getInstance().emitWarning(messages.getMessage('deprecatedConfigKey', [key, property.newKey]));
379
389
  return this.set(property.newKey, value);
380
390
  }
381
- if (property.input) {
391
+ if (value !== undefined && property.input) {
382
392
  if (property.input?.validator(value)) {
383
393
  super.set(property.key, value);
384
394
  }
@@ -468,92 +478,60 @@ Config.allowedProperties = [
468
478
  ...exports.SF_ALLOWED_PROPERTIES,
469
479
  ...orgConfigProperties_1.ORG_CONFIG_ALLOWED_PROPERTIES,
470
480
  ];
471
- class SfdxConfig {
472
- constructor(options = {}, config) {
473
- this.options = options;
474
- this.config = config;
475
- this.sfdxPath = this.getSfdxPath();
476
- }
477
- /**
478
- * If Global.SFDX_INTEROPERABILITY is enabled, merge the sfdx config into the sf config
479
- */
480
- merge(config) {
481
- if (!global_1.Global.SFDX_INTEROPERABILITY)
482
- return config;
483
- const sfdxConfig = this.readSync();
484
- const sfdxPropKeys = Object.values(SfdxPropertyKeys);
485
- // Get a list of config keys that are NOT provided by SfdxPropertyKeys
486
- const nonSfdxPropKeys = Config.getAllowedProperties()
487
- .filter((p) => !sfdxPropKeys.includes(p.key))
488
- .map((p) => p.key);
489
- // Remove any config from .sf that isn't also in .sfdx
490
- // This handles the scenario where a config has been deleted
491
- // from .sfdx and we want to mirror that change in .sf
492
- for (const key of nonSfdxPropKeys) {
493
- if (!sfdxConfig[key])
494
- delete config[key];
495
- }
496
- return Object.assign(config, sfdxConfig);
497
- }
498
- async write(config = this.config.toObject()) {
499
- try {
500
- const translated = this.translate(config, 'toOld');
501
- const sfdxPath = this.getSfdxPath();
502
- await fs.promises.mkdir((0, path_1.dirname)(sfdxPath), { recursive: true });
503
- await fs.promises.writeFile(sfdxPath, JSON.stringify(translated, null, 2));
504
- }
505
- catch (error) {
506
- /* Do nothing */
507
- }
481
+ /**
482
+ * convert from "new" to "old" config names
483
+ * - For example, `target-org` will be renamed to `defaultusername`.
484
+ */
485
+ const translateToSfdx = (sfContents) => Object.fromEntries(Object.entries(sfContents).map(([key, value]) => {
486
+ const propConfig = Config.getAllowedProperties().find((c) => c.newKey === key) ?? {};
487
+ return propConfig.deprecated && propConfig.newKey ? [propConfig.key, value] : [key, value];
488
+ }));
489
+ /**
490
+ * convert from "old" to "new" config names
491
+ * - For example, `defaultusername` will be renamed to `target-org`
492
+ */
493
+ const translateToSf = (sfdxContents, SfConfig) => Object.fromEntries(Object.entries(sfdxContents).map(([key, value]) => {
494
+ const propConfig = SfConfig.getPropertyConfig(key);
495
+ return propConfig.deprecated && propConfig.newKey ? [propConfig.newKey, value] : [key, value];
496
+ }));
497
+ /** given the ConfigFile options, calculate the full path where the config file goes */
498
+ const buildSfdxPath = (options) => {
499
+ // Don't let users store config files in homedir without being in the state folder.
500
+ const configRootFolder = options.rootFolder ?? configFile_1.ConfigFile.resolveRootFolderSync(!!options.isGlobal);
501
+ const rootWithState = options.isGlobal === true || options.isState === true
502
+ ? (0, node_path_1.join)(configRootFolder, global_1.Global.SFDX_STATE_FOLDER)
503
+ : configRootFolder;
504
+ return (0, node_path_1.join)(rootWithState, SFDX_CONFIG_FILE_NAME);
505
+ };
506
+ /**
507
+ * writes (in an unsafe way) the configuration file to the sfdx file location.
508
+ * Make sure you call ConfigFile.write and getContents so that the contents passed here are not cross-saving something
509
+ */
510
+ const writeToSfdx = async (path, contents) => {
511
+ try {
512
+ const translated = translateToSfdx(contents);
513
+ await fs.promises.mkdir((0, node_path_1.dirname)(path), { recursive: true });
514
+ await fs.promises.writeFile(path, JSON.stringify(translated, null, 2));
508
515
  }
509
- readSync() {
510
- try {
511
- const contents = (0, kit_1.parseJsonMap)(fs.readFileSync(this.getSfdxPath(), 'utf8'));
512
- return this.translate(contents, 'toNew');
513
- }
514
- catch (error) {
515
- /* Do nothing */
516
- return {};
517
- }
516
+ catch (e) {
517
+ const logger = logger_1.Logger.childFromRoot('core:config:writeToSfdx');
518
+ logger.debug(`Error writing to sfdx config file at ${path}: ${e instanceof Error ? e.message : ''}`);
518
519
  }
519
- getSfdxPath() {
520
- if (!this.sfdxPath) {
521
- const stateFolder = global_1.Global.SFDX_STATE_FOLDER;
522
- const fileName = SFDX_CONFIG_FILE_NAME;
523
- // Don't let users store config files in homedir without being in the state folder.
524
- let configRootFolder = this.options.rootFolder
525
- ? this.options.rootFolder
526
- : configFile_1.ConfigFile.resolveRootFolderSync(!!this.options.isGlobal);
527
- if (this.options.isGlobal === true || this.options.isState === true) {
528
- configRootFolder = (0, path_1.join)(configRootFolder, stateFolder);
529
- }
530
- this.sfdxPath = (0, path_1.join)(configRootFolder, fileName);
531
- }
532
- return this.sfdxPath;
520
+ };
521
+ /** turn the sfdx config file into a LWWState based on its contents and its timestamp */
522
+ const stateFromSfdxFileSync = (path, config) => {
523
+ try {
524
+ const fileContents = fs.readFileSync(path, 'utf8');
525
+ const mtimeNs = fs.statSync(path, { bigint: true }).mtimeNs;
526
+ const translatedContents = translateToSf((0, kit_1.parseJsonMap)(fileContents, path), config);
527
+ // get the file timestamp
528
+ return (0, lwwMap_1.stateFromContents)(translatedContents, mtimeNs);
533
529
  }
534
- /**
535
- * If toNew is specified: migrate all deprecated configs with a newKey to the newKey.
536
- * - For example, defaultusername will be renamed to target-org.
537
- *
538
- * If toOld is specified: migrate all deprecated configs back to their original key.
539
- * - For example, target-org will be renamed to defaultusername.
540
- */
541
- translate(contents, direction) {
542
- const translated = {};
543
- for (const [key, value] of Object.entries(contents)) {
544
- const propConfig = direction === 'toNew'
545
- ? this.config.getPropertyConfig(key)
546
- : Config.getAllowedProperties().find((c) => c.newKey === key) ?? {};
547
- if (propConfig.deprecated && propConfig.newKey) {
548
- const normalizedKey = direction === 'toNew' ? propConfig.newKey : propConfig.key;
549
- translated[normalizedKey] = value;
550
- }
551
- else {
552
- translated[key] = value;
553
- }
554
- }
555
- return translated;
530
+ catch (e) {
531
+ const logger = logger_1.Logger.childFromRoot('core:config:stateFromSfdxFileSync');
532
+ logger.debug(`Error reading state from sfdx config file at ${path}: ${e instanceof Error ? e.message : ''}`);
533
+ return {};
556
534
  }
557
- }
558
- exports.SfdxConfig = SfdxConfig;
535
+ };
536
+ const isBooleanOrBooleanString = (value) => (typeof value === 'string' && ['true', 'false'].includes(value)) || typeof value === 'boolean';
559
537
  //# sourceMappingURL=config.js.map
@@ -13,6 +13,7 @@ const messages_1 = require("../messages");
13
13
  const lifecycleEvents_1 = require("../lifecycleEvents");
14
14
  const envVars_1 = require("./envVars");
15
15
  const config_1 = require("./config");
16
+ ;
16
17
  const messages = new messages_1.Messages('@salesforce/core', 'config', new Map([["unknownConfigKey", "Unknown config name: %s."], ["deprecatedConfigKey", "Deprecated config name: %s. Please use %s instead."], ["invalidWrite", "The writeSync method is not allowed on SfdxConfig. Use the async write method instead."], ["invalidConfigValue", "Invalid config value: %s."], ["invalidInstanceUrl", "Specify a valid Salesforce instance URL."], ["invalidApiVersion", "Specify a valid Salesforce API version, for example, 42.0."], ["invalidCustomOrgMetadataTemplates", "Specify a valid repository URL or directory for the custom org metadata templates."], ["invalidIsvDebuggerSid", "Specify a valid Debugger SID."], ["invalidIsvDebuggerUrl", "Specify a valid Debugger URL."], ["invalidNumberConfigValue", "Specify a valid positive integer, for example, 150000."], ["invalidBooleanConfigValue", "The config value can only be set to true or false."], ["invalidProjectWorkspace", "This directory does not contain a valid Salesforce DX project."], ["schemaValidationError", "The config file \"%s\" is not schema valid.\nDue to: %s"], ["schemaValidationError.actions", ["Fix the invalid entries at %s."]], ["missingDefaultPath", "In sfdx-project.json, be sure to specify which package directory (path) is the default. Example: `[{ \"path\": \"packageDirectory1\", \"default\": true }, { \"path\": \"packageDirectory2\" }]`"], ["missingPackageDirectory", "The path \"%s\", specified in sfdx-project.json, does not exist. Be sure this directory is included in your project root."], ["invalidPackageDirectory", "The path \"%s\", specified in sfdx-project.json, must be indicated as a relative path to the project root."], ["multipleDefaultPaths", "In sfdx-project.json, indicate only one package directory (path) as the default."], ["singleNonDefaultPackage", "The sfdx-project.json file must include one, and only one, default package directory (path). Because your sfdx-project.json file contains only one package directory, it must be the default. Remove the `\"default\": false` key and try again."], ["target-org", "Username or alias of the org that all commands run against by default. (sf only)"], ["target-dev-hub", "Username or alias of your default Dev Hub org. (sf only)"], ["defaultUsername", "Username or alias of the org that all commands run against by default. (sfdx only)"], ["defaultDevHubUsername", "Username or alias of your default Dev Hub org. (sfdx only)"], ["isvDebuggerSid", "ISV debugger SID (sfdx only)"], ["isvDebuggerUrl", "ISV debugger URL (sfdx only)"], ["org-isv-debugger-sid", "ISV debugger SID."], ["org-isv-debugger-url", "ISV debugger URL."], ["apiVersion", "API version of your project. Default: API version of your Dev Hub org. (sfdx only)"], ["org-api-version", "API version of your project. Default: API version of your Dev Hub org."], ["disableTelemetry", "Disables the collection of usage and user environment information, etc. Default: false. (sfdx only)"], ["disable-telemetry", "Disables the collection of usage and user environment information, etc. Default: false."], ["maxQueryLimit", "Maximum number of Salesforce records returned by a CLI command. Default: 10,000. (sfdx only)"], ["org-max-query-limit", "Maximum number of Salesforce records returned by a CLI command. Default: 10,000."], ["restDeploy", "Whether deployments use the Metadata REST API (true) or SOAP API (false, default value). (sfdx only)"], ["instanceUrl", "URL of the Salesforce instance hosting your org. Default: https://login.salesforce.com. (sfdx only)"], ["org-instance-url", "URL of the Salesforce instance hosting your org. Default: https://login.salesforce.com."], ["customOrgMetadataTemplates", "A valid repository URL or directory for the custom org metadata templates."], ["org-custom-metadata-templates", "A valid repository URL or directory for the custom org metadata templates."], ["invalidId", "The given id %s is not a valid 15 or 18 character Salesforce ID."]]));
17
18
  /**
18
19
  * Aggregate global and local project config files, as well as environment variables for
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { Stats as fsStats } from 'fs';
2
+ import { Stats as fsStats } from 'node:fs';
3
3
  import { Logger } from '../logger/logger';
4
4
  import { BaseConfigStore } from './configStore';
5
5
  import { ConfigContents } from './configStackTypes';
@@ -162,6 +162,8 @@ export declare class ConfigFile<T extends ConfigFile.Options = ConfigFile.Option
162
162
  * options.throwOnNotFound is true.
163
163
  */
164
164
  protected init(): Promise<void>;
165
+ private logAndMergeContents;
166
+ private handleWriteError;
165
167
  }
166
168
  export declare namespace ConfigFile {
167
169
  /**