@salesforce/core 8.11.3 → 8.12.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.
@@ -247,7 +247,7 @@ class ConfigFile extends configStore_1.BaseConfigStore {
247
247
  const lockResponse = await (0, fileLocking_1.lockInit)(this.getPath());
248
248
  // lock the file. Returns an unlock function to call when done.
249
249
  try {
250
- const fileTimestamp = (await fs.promises.stat(this.getPath(), { bigint: true })).mtimeNs;
250
+ const fileTimestamp = await getNsTimeStamp(this.getPath());
251
251
  const fileContents = (0, kit_1.parseJsonMap)(await fs.promises.readFile(this.getPath(), 'utf8'), this.getPath());
252
252
  this.logAndMergeContents(fileTimestamp, fileContents);
253
253
  }
@@ -268,7 +268,7 @@ class ConfigFile extends configStore_1.BaseConfigStore {
268
268
  const lockResponse = (0, fileLocking_1.lockInitSync)(this.getPath());
269
269
  try {
270
270
  // get the file modstamp. Do this after the lock acquisition in case the file is being written to.
271
- const fileTimestamp = fs.statSync(this.getPath(), { bigint: true }).mtimeNs;
271
+ const fileTimestamp = getNsTimeStampSync(this.getPath());
272
272
  const fileContents = (0, kit_1.parseJsonMap)(fs.readFileSync(this.getPath(), 'utf8'), this.getPath());
273
273
  this.logAndMergeContents(fileTimestamp, fileContents);
274
274
  }
@@ -394,4 +394,8 @@ class ConfigFile extends configStore_1.BaseConfigStore {
394
394
  }
395
395
  }
396
396
  exports.ConfigFile = ConfigFile;
397
+ const getNsTimeStamp = async (filePath) => getNsTimeStampFromStatus(await fs.promises.stat(filePath, { bigint: true }));
398
+ const getNsTimeStampSync = (filePath) => getNsTimeStampFromStatus(fs.statSync(filePath, { bigint: true }));
399
+ /** in browser environment, memfs is missing the bigInt ns timestamp, so we generate it from the ms */
400
+ const getNsTimeStampFromStatus = (stats) => stats.mtimeNs ?? BigInt(stats.mtimeMs) * BigInt(1_000_000);
397
401
  //# sourceMappingURL=configFile.js.map
@@ -58,6 +58,10 @@ const retrieveKeychain = async (platform) => {
58
58
  }
59
59
  }
60
60
  }
61
+ else if (platform === 'browser') {
62
+ logger.debug(`platform: ${platform}. Using generic keychain.`);
63
+ return keyChainImpl_1.keyChainImpl.generic_unix;
64
+ }
61
65
  else {
62
66
  throw messages.createError('unsupportedOperatingSystemError', [platform]);
63
67
  }
package/lib/global.d.ts CHANGED
@@ -32,6 +32,10 @@ export declare class Global {
32
32
  * The preferred global folder in which state is stored.
33
33
  */
34
34
  static readonly STATE_FOLDER = ".sfdx";
35
+ /**
36
+ * Whether the code is running in a web browser.
37
+ */
38
+ static get isWeb(): boolean;
35
39
  /**
36
40
  * The full system path to the global sfdx state folder.
37
41
  *
package/lib/global.js CHANGED
@@ -70,6 +70,12 @@ class Global {
70
70
  * The preferred global folder in which state is stored.
71
71
  */
72
72
  static STATE_FOLDER = Global.SFDX_STATE_FOLDER;
73
+ /**
74
+ * Whether the code is running in a web browser.
75
+ */
76
+ static get isWeb() {
77
+ return 'window' in globalThis;
78
+ }
73
79
  /**
74
80
  * The full system path to the global sfdx state folder.
75
81
  *
@@ -233,7 +233,7 @@ class Logger {
233
233
  * Gets the name of this logger.
234
234
  */
235
235
  getName() {
236
- return this.pinoLogger.bindings().name ?? '';
236
+ return (this.pinoLogger?.bindings ? this.pinoLogger.bindings().name : '') ?? '';
237
237
  }
238
238
  /**
239
239
  * Gets the current level of this logger.
@@ -409,7 +409,7 @@ const getWriteStream = (level = 'warn') => {
409
409
  // write to a rotating file
410
410
  target: 'pino/file',
411
411
  options: {
412
- destination: path.join(global_1.Global.SF_DIR, `sf-${rotator.get(logRotationPeriod) ?? rotator.get('1d')}.log`),
412
+ destination: path.join(global_1.Global.SF_DIR, `sf-${(0, ts_types_1.ensureString)(rotator.get(logRotationPeriod)) ?? rotator.get('1d')}.log`),
413
413
  mkdir: true,
414
414
  level,
415
415
  },
package/lib/messages.js CHANGED
@@ -538,7 +538,7 @@ class Messages {
538
538
  tokenCur += tokenCount;
539
539
  return util.format(msgStr, ...relevantTokens);
540
540
  }
541
- else {
541
+ else if (tokens.length > 0) {
542
542
  const logger = logger_1.Logger.childFromRoot('core:messages');
543
543
  logger.warn(`Unable to render tokens in message. Ensure a specifier (e.g. %s) exists in the message:\n${msgStr}`);
544
544
  }
@@ -41,6 +41,7 @@ const zipWriter_1 = require("../util/zipWriter");
41
41
  const directoryWriter_1 = require("../util/directoryWriter");
42
42
  const lifecycleEvents_1 = require("../lifecycleEvents");
43
43
  const messages_1 = require("../messages");
44
+ const configAggregator_1 = require("../config/configAggregator");
44
45
  ;
45
46
  var RequestStatus;
46
47
  (function (RequestStatus) {
@@ -233,9 +234,12 @@ class SettingsGenerator {
233
234
  const connection = scratchOrg.getConnection();
234
235
  logger.debug(`deploying to apiVersion: ${apiVersion}`);
235
236
  connection.setApiVersion(apiVersion);
236
- const { id } = await connection.deploy(this.writer.buffer, {});
237
- logger.debug(`deploying settings id ${id}`);
238
- let result = await connection.metadata.checkDeployStatus(id);
237
+ // Get org-metadata-rest-deploy from config aggregator
238
+ const restDeploy = (await configAggregator_1.ConfigAggregator.create()).getPropertyValue('org-metadata-rest-deploy');
239
+ logger.debug(`Deploying settings to scratch org using ${restDeploy ? 'REST' : 'SOAP'} API`);
240
+ const { id } = await connection.deploy(this.writer.buffer, { rest: restDeploy });
241
+ logger.debug(`Settings deploy id: ${id}`);
242
+ let result = await connection.metadata.checkDeployStatus(id, undefined, restDeploy);
239
243
  const pollingOptions = {
240
244
  async poll() {
241
245
  try {
@@ -88,6 +88,5 @@ export declare class AliasAccessor extends AsyncOptionalCreatable {
88
88
  * if the file doesn't exist, create it empty
89
89
  */
90
90
  private readFileToAliasStore;
91
- private saveAliasStoreToFile;
92
91
  }
93
92
  export declare const getFileLocation: () => string;
@@ -10,11 +10,10 @@ exports.getFileLocation = exports.AliasAccessor = exports.FILENAME = exports.DEF
10
10
  const node_path_1 = require("node:path");
11
11
  const node_os_1 = require("node:os");
12
12
  const promises_1 = require("node:fs/promises");
13
- const proper_lockfile_1 = require("proper-lockfile");
14
13
  const kit_1 = require("@salesforce/kit");
15
14
  const global_1 = require("../../global");
16
15
  const sfError_1 = require("../../sfError");
17
- const lockRetryOptions_1 = require("../../util/lockRetryOptions");
16
+ const fileLocking_1 = require("../../util/fileLocking");
18
17
  exports.DEFAULT_GROUP = 'orgs';
19
18
  exports.FILENAME = 'alias.json';
20
19
  class AliasAccessor extends kit_1.AsyncOptionalCreatable {
@@ -94,18 +93,20 @@ class AliasAccessor extends kit_1.AsyncOptionalCreatable {
94
93
  */
95
94
  async setAndSave(alias, entity) {
96
95
  // get a very fresh copy to merge with to avoid conflicts, then lock
97
- await this.readFileToAliasStore(true);
96
+ const lockResponse = await (0, fileLocking_1.lockInit)(this.fileLocation);
97
+ await this.readFileToAliasStore();
98
98
  this.aliasStore.set(alias, getNameOf(entity));
99
- return this.saveAliasStoreToFile();
99
+ return lockResponse.writeAndUnlock(aliasStoreToRawFileContents(this.aliasStore));
100
100
  }
101
101
  /**
102
102
  * Unset the given alias(es). Writes to the file
103
103
  *
104
104
  */
105
105
  async unsetAndSave(alias) {
106
- await this.readFileToAliasStore(true);
106
+ const lockResponse = await (0, fileLocking_1.lockInit)(this.fileLocation);
107
+ await this.readFileToAliasStore();
107
108
  this.aliasStore.delete(alias);
108
- return this.saveAliasStoreToFile();
109
+ return lockResponse.writeAndUnlock(aliasStoreToRawFileContents(this.aliasStore));
109
110
  }
110
111
  /**
111
112
  * Unset all the aliases for the given array of entity.
@@ -113,11 +114,12 @@ class AliasAccessor extends kit_1.AsyncOptionalCreatable {
113
114
  * @param entity the aliasable entity for which you want to unset all aliases
114
115
  */
115
116
  async unsetValuesAndSave(aliasees) {
116
- await this.readFileToAliasStore(true);
117
+ const lockResponse = await (0, fileLocking_1.lockInit)(this.fileLocation);
118
+ await this.readFileToAliasStore();
117
119
  (0, kit_1.ensureArray)(aliasees)
118
120
  .flatMap((a) => this.getAll(a))
119
121
  .map((a) => this.aliasStore.delete(a));
120
- return this.saveAliasStoreToFile();
122
+ return lockResponse.writeAndUnlock(aliasStoreToRawFileContents(this.aliasStore));
121
123
  }
122
124
  /**
123
125
  * Returns true if the provided alias exists
@@ -135,29 +137,19 @@ class AliasAccessor extends kit_1.AsyncOptionalCreatable {
135
137
  * go to the fileSystem and read the file, storing a copy in the class's store
136
138
  * if the file doesn't exist, create it empty
137
139
  */
138
- async readFileToAliasStore(useLock = false) {
139
- if (useLock) {
140
- await (0, proper_lockfile_1.lock)(this.fileLocation, lockRetryOptions_1.lockRetryOptions);
141
- }
140
+ async readFileToAliasStore() {
142
141
  try {
143
142
  this.aliasStore = fileContentsRawToAliasStore(await (0, promises_1.readFile)(this.fileLocation, 'utf-8'));
144
143
  }
145
144
  catch (e) {
146
145
  if (e instanceof Error && 'code' in e && typeof e.code === 'string' && ['ENOENT', 'ENOTDIR'].includes(e.code)) {
147
- this.aliasStore = new Map();
148
146
  await (0, promises_1.mkdir)((0, node_path_1.dirname)(this.fileLocation), { recursive: true });
149
- await this.saveAliasStoreToFile();
150
- return;
147
+ this.aliasStore = new Map();
148
+ return (0, promises_1.writeFile)(this.fileLocation, aliasStoreToRawFileContents(this.aliasStore));
151
149
  }
152
- if (useLock)
153
- return unlockIfLocked(this.fileLocation);
154
150
  throw e;
155
151
  }
156
152
  }
157
- async saveAliasStoreToFile() {
158
- await (0, promises_1.writeFile)(this.fileLocation, aliasStoreToRawFileContents(this.aliasStore));
159
- return unlockIfLocked(this.fileLocation);
160
- }
161
153
  }
162
154
  exports.AliasAccessor = AliasAccessor;
163
155
  /**
@@ -166,11 +158,11 @@ exports.AliasAccessor = AliasAccessor;
166
158
  const getNameOf = (entity) => {
167
159
  if (typeof entity === 'string')
168
160
  return entity;
169
- const aliaseeName = entity.username;
170
- if (!aliaseeName) {
161
+ const { username } = entity;
162
+ if (!username) {
171
163
  throw new sfError_1.SfError(`Invalid aliasee, it must contain a user or username property: ${JSON.stringify(entity)}`);
172
164
  }
173
- return aliaseeName;
165
+ return username;
174
166
  };
175
167
  const fileContentsRawToAliasStore = (contents) => {
176
168
  const fileContents = JSON.parse(contents);
@@ -181,16 +173,4 @@ const aliasStoreToRawFileContents = (aliasStore) => JSON.stringify({ [exports.DE
181
173
  // exported for testSetup mocking
182
174
  const getFileLocation = () => (0, node_path_1.join)((0, node_os_1.homedir)(), global_1.Global.SFDX_STATE_FOLDER, exports.FILENAME);
183
175
  exports.getFileLocation = getFileLocation;
184
- const unlockIfLocked = async (fileLocation) => {
185
- try {
186
- await (0, proper_lockfile_1.unlock)(fileLocation);
187
- }
188
- catch (e) {
189
- // ignore the error. If it wasn't locked, that's what we wanted
190
- if (errorIsNotAcquired(e))
191
- return;
192
- throw e;
193
- }
194
- };
195
- const errorIsNotAcquired = (e) => e instanceof Error && 'code' in e && e.code === 'ENOTACQUIRED';
196
176
  //# sourceMappingURL=aliasAccessor.js.map
@@ -38,6 +38,7 @@ export declare class MyDomainResolver extends AsyncOptionalCreatable<MyDomainRes
38
38
  * executing the dns loookup.
39
39
  */
40
40
  resolve(): Promise<string>;
41
+ /** @deprecated there is nothing using this in forcedotcom, salesforcecli, or public github search */
41
42
  getCnames(): Promise<string[]>;
42
43
  /**
43
44
  * Used to initialize asynchronous components.
@@ -14,6 +14,7 @@ const ts_types_1 = require("@salesforce/ts-types");
14
14
  const kit_1 = require("@salesforce/kit");
15
15
  const logger_1 = require("../logger/logger");
16
16
  const sfdcUrl_1 = require("../util/sfdcUrl");
17
+ const global_1 = require("../global");
17
18
  const pollingClient_1 = require("./pollingClient");
18
19
  // Timeout for DNS lookup polling defaults to 3 seconds and should always be at least 3 seconds
19
20
  const DNS_TIMEOUT = Math.max(3, new kit_1.Env().getNumber('SFDX_DNS_TIMEOUT', 3));
@@ -69,6 +70,10 @@ class MyDomainResolver extends kit_1.AsyncOptionalCreatable {
69
70
  this.logger.debug('SF_DISABLE_DNS_CHECK set to true. Skipping DNS check...');
70
71
  return this.options.url.host;
71
72
  }
73
+ if (global_1.Global.isWeb) {
74
+ this.logger.debug('Web browser detected. Skipping DNS check...');
75
+ return this.options.url.host;
76
+ }
72
77
  // eslint-disable-next-line @typescript-eslint/no-this-alias
73
78
  const self = this;
74
79
  const pollingOptions = {
@@ -106,6 +111,7 @@ class MyDomainResolver extends kit_1.AsyncOptionalCreatable {
106
111
  const client = await pollingClient_1.PollingClient.create(pollingOptions);
107
112
  return (0, ts_types_1.ensureString)(await client.subscribe());
108
113
  }
114
+ /** @deprecated there is nothing using this in forcedotcom, salesforcecli, or public github search */
109
115
  async getCnames() {
110
116
  try {
111
117
  await this.resolve();
@@ -55,11 +55,10 @@ const lockInit = async (filePath) => {
55
55
  catch (err) {
56
56
  throw sfError_1.SfError.wrap(err);
57
57
  }
58
- const unlock = await (0, proper_lockfile_1.lock)(filePath, { ...lockRetryOptions_1.lockRetryOptions, realpath: false });
58
+ const unlock = await (0, proper_lockfile_1.lock)(filePath, { ...lockRetryOptions_1.lockRetryOptions, realpath: false, fs });
59
59
  return {
60
60
  writeAndUnlock: async (data) => {
61
- const logger = await logger_1.Logger.child('fileLocking.writeAndUnlock');
62
- logger.debug(`Writing to file: ${filePath}`);
61
+ (await logger_1.Logger.child('fileLocking.writeAndUnlock')).debug(`Writing to file: ${filePath}`);
63
62
  try {
64
63
  await fs.promises.writeFile(filePath, data);
65
64
  }
@@ -83,7 +82,7 @@ const lockInitSync = (filePath) => {
83
82
  catch (err) {
84
83
  throw sfError_1.SfError.wrap(err);
85
84
  }
86
- const unlock = (0, proper_lockfile_1.lockSync)(filePath, { ...lockRetryOptions_1.lockOptions, realpath: false });
85
+ const unlock = (0, proper_lockfile_1.lockSync)(filePath, { ...lockRetryOptions_1.lockOptions, realpath: false, fs });
87
86
  return {
88
87
  writeAndUnlock: (data) => {
89
88
  const logger = logger_1.Logger.childFromRoot('fileLocking.writeAndUnlock');
@@ -1,3 +1,4 @@
1
+ import fs from 'node:fs';
1
2
  export declare const lockOptions: {
2
3
  stale: number;
3
4
  };
@@ -7,5 +8,6 @@ export declare const lockRetryOptions: {
7
8
  maxTimeout: number;
8
9
  factor: number;
9
10
  };
11
+ fs: typeof fs;
10
12
  stale: number;
11
13
  };
@@ -5,12 +5,17 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
8
11
  Object.defineProperty(exports, "__esModule", { value: true });
9
12
  exports.lockRetryOptions = exports.lockOptions = void 0;
10
13
  // docs: https://github.com/moxystudio/node-proper-lockfile
14
+ const node_fs_1 = __importDefault(require("node:fs"));
11
15
  exports.lockOptions = { stale: 10_000 };
12
16
  exports.lockRetryOptions = {
13
17
  ...exports.lockOptions,
14
18
  retries: { retries: 10, maxTimeout: 1000, factor: 2 },
19
+ fs: node_fs_1.default, // lockfile supports injectable fs, which is needed for browser use
15
20
  };
16
21
  //# sourceMappingURL=lockRetryOptions.js.map
@@ -1 +1,2 @@
1
+ /** using globalThis.performance instead importing from node:perf_hooks so it works in browser */
1
2
  export declare const nowBigInt: () => bigint;
package/lib/util/time.js CHANGED
@@ -7,7 +7,7 @@ exports.nowBigInt = void 0;
7
7
  * Licensed under the BSD 3-Clause license.
8
8
  * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
9
9
  */
10
- const node_perf_hooks_1 = require("node:perf_hooks");
11
- const nowBigInt = () => BigInt((node_perf_hooks_1.performance.now() + node_perf_hooks_1.performance.timeOrigin) * 1_000_000);
10
+ /** using globalThis.performance instead importing from node:perf_hooks so it works in browser */
11
+ const nowBigInt = () => BigInt((globalThis.performance.now() + globalThis.performance.timeOrigin) * 1_000_000);
12
12
  exports.nowBigInt = nowBigInt;
13
13
  //# sourceMappingURL=time.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/core",
3
- "version": "8.11.3",
3
+ "version": "8.12.0",
4
4
  "description": "Core libraries to interact with SFDX projects, orgs, and APIs.",
5
5
  "main": "lib/index",
6
6
  "types": "lib/index.d.ts",
@@ -77,7 +77,7 @@
77
77
  "@salesforce/ts-sinon": "^1.4.30",
78
78
  "@types/benchmark": "^2.1.5",
79
79
  "@types/fast-levenshtein": "^0.0.4",
80
- "@types/jsonwebtoken": "9.0.7",
80
+ "@types/jsonwebtoken": "9.0.9",
81
81
  "@types/proper-lockfile": "^4.1.4",
82
82
  "@types/semver": "^7.5.8",
83
83
  "benchmark": "^2.1.4",