@salesforce/core 5.3.8 → 5.4.0-crdt.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.
Files changed (36) hide show
  1. package/lib/config/config.d.ts +4 -4
  2. package/lib/config/config.js +6 -9
  3. package/lib/config/configFile.d.ts +4 -3
  4. package/lib/config/configFile.js +63 -14
  5. package/lib/config/configStackTypes.d.ts +14 -0
  6. package/lib/config/configStackTypes.js +3 -0
  7. package/lib/config/configStore.d.ts +8 -19
  8. package/lib/config/configStore.js +36 -37
  9. package/lib/config/lwwMap.d.ts +25 -0
  10. package/lib/config/lwwMap.js +93 -0
  11. package/lib/config/lwwRegister.d.ts +19 -0
  12. package/lib/config/lwwRegister.js +39 -0
  13. package/lib/config/orgUsersConfig.d.ts +5 -1
  14. package/lib/config/tokensConfig.d.ts +1 -1
  15. package/lib/config/ttlConfig.js +4 -1
  16. package/lib/exported.d.ts +2 -1
  17. package/lib/org/authInfo.d.ts +3 -1
  18. package/lib/org/authInfo.js +2 -0
  19. package/lib/org/org.js +2 -2
  20. package/lib/org/orgConfigProperties.d.ts +1 -1
  21. package/lib/org/user.js +1 -2
  22. package/lib/sfProject.d.ts +3 -3
  23. package/lib/sfProject.js +5 -19
  24. package/lib/stateAggregator/accessors/aliasAccessor.d.ts +2 -2
  25. package/lib/stateAggregator/accessors/aliasAccessor.js +3 -7
  26. package/lib/stateAggregator/accessors/orgAccessor.d.ts +2 -1
  27. package/lib/stateAggregator/accessors/orgAccessor.js +1 -0
  28. package/lib/stateAggregator/accessors/tokenAccessor.d.ts +1 -1
  29. package/lib/stateAggregator/accessors/tokenAccessor.js +1 -1
  30. package/lib/testSetup.d.ts +3 -20
  31. package/lib/testSetup.js +24 -58
  32. package/lib/util/lockRetryOptions.d.ts +11 -0
  33. package/lib/util/lockRetryOptions.js +16 -0
  34. package/lib/util/uniqid.d.ts +14 -0
  35. package/lib/util/uniqid.js +34 -0
  36. package/package.json +5 -5
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2023, salesforce.com, inc.
4
+ * All rights reserved.
5
+ * Licensed under the BSD 3-Clause license.
6
+ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.LWWRegister = void 0;
10
+ /** a CRDT implementation. Uses timestamps to resolve conflicts when updating the value (last write wins)
11
+ * mostly based on https://jakelazaroff.com/words/an-interactive-intro-to-crdts/
12
+ *
13
+ * @param T the type of the value stored in the register
14
+ */
15
+ class LWWRegister {
16
+ constructor(id, state) {
17
+ this.id = id;
18
+ this.state = state;
19
+ }
20
+ get value() {
21
+ return this.state.value;
22
+ }
23
+ set(value) {
24
+ // set the peer ID to the local ID, timestamp it and set the value
25
+ this.state = { peer: this.id, timestamp: process.hrtime.bigint(), value };
26
+ }
27
+ merge(incoming) {
28
+ // only update if the incoming timestamp is greater than the local timestamp
29
+ // console.log(`incoming: ${}`);
30
+ // console.log(`local: ${JSON.stringify(this.state)}`);
31
+ if (incoming.timestamp > this.state.timestamp) {
32
+ this.state = incoming;
33
+ }
34
+ // TODO: if the timestamps match, use the peer ID to break the tie (prefer self?)
35
+ return this.state;
36
+ }
37
+ }
38
+ exports.LWWRegister = LWWRegister;
39
+ //# sourceMappingURL=lwwRegister.js.map
@@ -1,8 +1,11 @@
1
1
  import { ConfigFile } from './configFile';
2
+ type UserConfig = {
3
+ usernames: string[];
4
+ };
2
5
  /**
3
6
  * A config file that stores usernames for an org.
4
7
  */
5
- export declare class OrgUsersConfig extends ConfigFile<OrgUsersConfig.Options> {
8
+ export declare class OrgUsersConfig extends ConfigFile<OrgUsersConfig.Options, UserConfig> {
6
9
  /**
7
10
  * Constructor.
8
11
  * **Do not directly construct instances of this class -- use {@link OrgUsersConfig.create} instead.**
@@ -29,3 +32,4 @@ export declare namespace OrgUsersConfig {
29
32
  orgId: string;
30
33
  }
31
34
  }
35
+ export {};
@@ -1,7 +1,7 @@
1
1
  import { Optional } from '@salesforce/ts-types';
2
2
  import { SfTokens } from '../stateAggregator';
3
3
  import { ConfigFile } from './configFile';
4
- import { ConfigContents, ConfigValue } from './configStore';
4
+ import { ConfigContents, ConfigValue } from './configStackTypes';
5
5
  export declare class TokensConfig extends ConfigFile<ConfigFile.Options, SfTokens> {
6
6
  protected static encryptedKeys: RegExp[];
7
7
  static getDefaultOptions(): ConfigFile.Options;
@@ -39,7 +39,10 @@ class TTLConfig extends configFile_1.ConfigFile {
39
39
  async init() {
40
40
  const contents = await this.read(this.options.throwOnNotFound);
41
41
  const date = new Date().getTime();
42
- this.setContents(Object.fromEntries(Object.entries(contents).filter(([, value]) => !this.isExpired(date, value))));
42
+ // delete all the expired entries
43
+ Object.entries(contents)
44
+ .filter(([, value]) => this.isExpired(date, value))
45
+ .map(([key]) => this.unset(key));
43
46
  }
44
47
  // eslint-disable-next-line class-methods-use-this
45
48
  timestamp(value) {
package/lib/exported.d.ts CHANGED
@@ -2,7 +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 { ConfigContents, ConfigEntry, ConfigStore, ConfigValue } from './config/configStore';
5
+ export { ConfigStore } from './config/configStore';
6
+ export { ConfigEntry, ConfigContents, ConfigValue } from './config/configStackTypes';
6
7
  export { SfTokens, StateAggregator } from './stateAggregator';
7
8
  export { DeviceOauthService, DeviceCodeResponse, DeviceCodePollingResponse } from './deviceOauthService';
8
9
  export { OrgUsersConfig } from './config/orgUsersConfig';
@@ -242,8 +242,10 @@ export declare class AuthInfo extends AsyncOptionalCreatable<AuthInfo.Options> {
242
242
  * Get the authorization fields.
243
243
  *
244
244
  * @param decrypt Decrypt the fields.
245
+ *
246
+ * Returns a ReadOnly object of the fields. If you need to modify the fields, use AuthInfo.update()
245
247
  */
246
- getFields(decrypt?: boolean): AuthFields;
248
+ getFields(decrypt?: boolean): Readonly<AuthFields>;
247
249
  /**
248
250
  * Get the org front door (used for web based oauth flows)
249
251
  */
@@ -461,6 +461,8 @@ class AuthInfo extends kit_1.AsyncOptionalCreatable {
461
461
  * Get the authorization fields.
462
462
  *
463
463
  * @param decrypt Decrypt the fields.
464
+ *
465
+ * Returns a ReadOnly object of the fields. If you need to modify the fields, use AuthInfo.update()
464
466
  */
465
467
  getFields(decrypt) {
466
468
  return this.stateAggregator.orgs.get(this.username, decrypt) ?? {};
package/lib/org/org.js CHANGED
@@ -631,8 +631,8 @@ class Org extends kit_1.AsyncOptionalCreatable {
631
631
  const orgConfig = await this.retrieveOrgUsersConfig();
632
632
  const contents = await orgConfig.read();
633
633
  const targetUser = authInfo.getFields().username;
634
- const usernames = (contents.usernames ?? []);
635
- contents.usernames = usernames.filter((username) => username !== targetUser);
634
+ const usernames = (contents.usernames ?? []).filter((username) => username !== targetUser);
635
+ orgConfig.set('usernames', usernames);
636
636
  await orgConfig.write();
637
637
  return this;
638
638
  }
@@ -1,4 +1,4 @@
1
- import { ConfigValue } from '../config/configStore';
1
+ import { ConfigValue } from '../config/configStackTypes';
2
2
  export declare enum OrgConfigProperties {
3
3
  /**
4
4
  * Username associate with the default org.
package/lib/org/user.js CHANGED
@@ -303,8 +303,7 @@ class User extends kit_1.AsyncCreatable {
303
303
  oauth2Options: oauthOptions,
304
304
  });
305
305
  // Update the auth info object with created user id.
306
- const newUserAuthFields = newUserAuthInfo.getFields();
307
- newUserAuthFields.userId = refreshTokenSecret.userId;
306
+ newUserAuthInfo.update({ userId: refreshTokenSecret.userId });
308
307
  // Make sure we can connect and if so save the auth info.
309
308
  await this.describeUserAndSave(newUserAuthInfo);
310
309
  // Let the org know there is a new user. See $HOME/.sfdx/[orgid].json for the mapping.
@@ -1,6 +1,6 @@
1
1
  import { Dictionary, JsonMap, Nullable, Optional } from '@salesforce/ts-types';
2
2
  import { ConfigFile } from './config/configFile';
3
- import { ConfigContents } from './config/configStore';
3
+ import { ConfigContents } from './config/configStackTypes';
4
4
  export type PackageDirDependency = {
5
5
  [k: string]: unknown;
6
6
  package: string;
@@ -70,8 +70,8 @@ export declare class SfProjectJson extends ConfigFile {
70
70
  static getDefaultOptions(isGlobal?: boolean): ConfigFile.Options;
71
71
  read(): Promise<ConfigContents>;
72
72
  readSync(): ConfigContents;
73
- write(newContents?: ConfigContents): Promise<ConfigContents>;
74
- writeSync(newContents?: ConfigContents): ConfigContents;
73
+ write(): Promise<ConfigContents>;
74
+ writeSync(): ConfigContents;
75
75
  getContents(): ProjectJson;
76
76
  getDefaultOptions(options?: ConfigFile.Options): ConfigFile.Options;
77
77
  /**
package/lib/sfProject.js CHANGED
@@ -57,17 +57,11 @@ class SfProjectJson extends configFile_1.ConfigFile {
57
57
  this.validateKeys();
58
58
  return contents;
59
59
  }
60
- async write(newContents) {
61
- if (newContents) {
62
- this.setContents(newContents);
63
- }
60
+ async write() {
64
61
  this.validateKeys();
65
62
  return super.write();
66
63
  }
67
- writeSync(newContents) {
68
- if (newContents) {
69
- this.setContents(newContents);
70
- }
64
+ writeSync() {
71
65
  this.validateKeys();
72
66
  return super.writeSync();
73
67
  }
@@ -76,11 +70,7 @@ class SfProjectJson extends configFile_1.ConfigFile {
76
70
  }
77
71
  // eslint-disable-next-line class-methods-use-this
78
72
  getDefaultOptions(options) {
79
- const defaultOptions = {
80
- isState: false,
81
- };
82
- Object.assign(defaultOptions, options ?? {});
83
- return defaultOptions;
73
+ return { ...{ isState: false }, ...(options ?? {}) };
84
74
  }
85
75
  /**
86
76
  * Validates sfdx-project.json against the schema.
@@ -259,12 +249,8 @@ class SfProjectJson extends configFile_1.ConfigFile {
259
249
  if (!/^.{15,18}$/.test(id)) {
260
250
  throw messages.createError('invalidId', [id]);
261
251
  }
262
- const contents = this.getContents();
263
- if (!contents.packageAliases) {
264
- contents.packageAliases = {};
265
- }
266
- contents.packageAliases[alias] = id;
267
- this.setContents(contents);
252
+ const newAliases = { ...(this.getContents().packageAliases ?? {}), [alias]: id };
253
+ this.contents.set('packageAliases', newAliases);
268
254
  }
269
255
  /**
270
256
  * Add a package directory to the project.
@@ -1,7 +1,7 @@
1
1
  import { AsyncOptionalCreatable } from '@salesforce/kit';
2
2
  import { Nullable } from '@salesforce/ts-types';
3
3
  import { AuthFields } from '../../org/authInfo';
4
- import { ConfigContents } from '../../config/configStore';
4
+ import { ConfigContents } from '../../config/configStackTypes';
5
5
  import { SfToken } from './tokenAccessor';
6
6
  export type Aliasable = string | (Partial<AuthFields> & Partial<SfToken>);
7
7
  export declare const DEFAULT_GROUP = "orgs";
@@ -103,7 +103,7 @@ export declare class AliasAccessor extends AsyncOptionalCreatable {
103
103
  /**
104
104
  * @deprecated the set/unset methods now write to the file when called. Use (un)setAndSave instead of calling (un)set and then calling write()
105
105
  */
106
- write(): Promise<ConfigContents>;
106
+ write(): Promise<ConfigContents<string>>;
107
107
  /**
108
108
  * Returns true if the provided alias exists
109
109
  *
@@ -15,13 +15,9 @@ const proper_lockfile_1 = require("proper-lockfile");
15
15
  const kit_1 = require("@salesforce/kit");
16
16
  const global_1 = require("../../global");
17
17
  const sfError_1 = require("../../sfError");
18
+ const lockRetryOptions_1 = require("../../util/lockRetryOptions");
18
19
  exports.DEFAULT_GROUP = 'orgs';
19
20
  exports.FILENAME = 'alias.json';
20
- const lockOptions = { stale: 10000 };
21
- const lockRetryOptions = {
22
- ...lockOptions,
23
- retries: { retries: 10, maxTimeout: 1000, factor: 2 },
24
- };
25
21
  class AliasAccessor extends kit_1.AsyncOptionalCreatable {
26
22
  getAll(entity) {
27
23
  // This will only return aliases under "orgs". This will need to be modified
@@ -181,7 +177,7 @@ class AliasAccessor extends kit_1.AsyncOptionalCreatable {
181
177
  */
182
178
  async readFileToAliasStore(useLock = false) {
183
179
  if (useLock) {
184
- await (0, proper_lockfile_1.lock)(this.fileLocation, lockRetryOptions);
180
+ await (0, proper_lockfile_1.lock)(this.fileLocation, lockRetryOptions_1.lockRetryOptions);
185
181
  }
186
182
  try {
187
183
  this.aliasStore = fileContentsRawToAliasStore(await (0, promises_1.readFile)(this.fileLocation, 'utf-8'));
@@ -208,7 +204,7 @@ class AliasAccessor extends kit_1.AsyncOptionalCreatable {
208
204
  readFileToAliasStoreSync() {
209
205
  // the file is guaranteed to exist because this init method ensures it
210
206
  // put a lock in place. This method is only used by legacy set/unset methods.
211
- (0, proper_lockfile_1.lockSync)(this.fileLocation, lockOptions);
207
+ (0, proper_lockfile_1.lockSync)(this.fileLocation, lockRetryOptions_1.lockOptions);
212
208
  this.aliasStore = fileContentsRawToAliasStore((0, node_fs_1.readFileSync)(this.fileLocation, 'utf-8'));
213
209
  }
214
210
  /**
@@ -5,9 +5,10 @@ import { AsyncOptionalCreatable } from '@salesforce/kit';
5
5
  import { AuthInfoConfig } from '../../config/authInfoConfig';
6
6
  import { AuthFields } from '../../org';
7
7
  import { ConfigFile } from '../../config/configFile';
8
- import { ConfigContents } from '../../config/configStore';
8
+ import { ConfigContents } from '../../config/configStackTypes';
9
9
  export declare abstract class BaseOrgAccessor<T extends ConfigFile, P extends ConfigContents> extends AsyncOptionalCreatable {
10
10
  private configs;
11
+ /** map of Org files by username */
11
12
  private contents;
12
13
  private logger;
13
14
  /**
@@ -25,6 +25,7 @@ class BaseOrgAccessor extends kit_1.AsyncOptionalCreatable {
25
25
  constructor() {
26
26
  super(...arguments);
27
27
  this.configs = new Map();
28
+ /** map of Org files by username */
28
29
  this.contents = new Map();
29
30
  }
30
31
  /**
@@ -48,7 +48,7 @@ export declare class TokenAccessor extends AsyncOptionalCreatable {
48
48
  */
49
49
  update(name: string, token: Partial<SfToken>): void;
50
50
  /**
51
- * Unet the token for the provided name.
51
+ * Unset the token for the provided name.
52
52
  *
53
53
  * @param name
54
54
  */
@@ -57,7 +57,7 @@ class TokenAccessor extends kit_1.AsyncOptionalCreatable {
57
57
  this.config.update(name, token);
58
58
  }
59
59
  /**
60
- * Unet the token for the provided name.
60
+ * Unset the token for the provided name.
61
61
  *
62
62
  * @param name
63
63
  */
@@ -2,12 +2,14 @@
2
2
  import { EventEmitter } from 'events';
3
3
  import { SinonSandbox, SinonStatic, SinonStub } from 'sinon';
4
4
  import { AnyJson, JsonMap, Optional } from '@salesforce/ts-types';
5
- import { ConfigContents } from './config/configStore';
5
+ import { ConfigContents } from './config/configStackTypes';
6
6
  import { Connection } from './org/connection';
7
7
  import { Logger } from './logger/logger';
8
8
  import { SfError } from './sfError';
9
9
  import { CometClient, CometSubscription, Message, StreamingExtension } from './status/streamingClient';
10
10
  import { AuthFields, SandboxFields } from './org';
11
+ import { uniqid } from './util/uniqid';
12
+ export { uniqid };
11
13
  /**
12
14
  * Different parts of the system that are mocked out. They can be restored for
13
15
  * individual tests. Test's stubs should always go on the DEFAULT which is exposed
@@ -48,10 +50,6 @@ export interface ConfigStub {
48
50
  * A function to conditionally read based on the config instance. The `this` value will be the config instance.
49
51
  */
50
52
  retrieveContents?: () => Promise<JsonMap>;
51
- /**
52
- * A function to conditionally set based on the config instance. The `this` value will be the config instance.
53
- */
54
- updateContents?: () => Promise<JsonMap>;
55
53
  }
56
54
  /**
57
55
  * Instantiate a @salesforce/core test context.
@@ -203,20 +201,6 @@ export declare class TestContext {
203
201
  setup(): void;
204
202
  private requireSinon;
205
203
  }
206
- /**
207
- * A function to generate a unique id and return it in the context of a template, if supplied.
208
- *
209
- * A template is a string that can contain `${%s}` to be replaced with a unique id.
210
- * If the template contains the "%s" placeholder, it will be replaced with the unique id otherwise the id will be appended to the template.
211
- *
212
- * @param options an object with the following properties:
213
- * - template: a template string.
214
- * - length: the length of the unique id as presented in hexadecimal.
215
- */
216
- export declare function uniqid(options?: {
217
- template?: string;
218
- length?: number;
219
- }): string;
220
204
  /**
221
205
  * Instantiate a @salesforce/core test context. This is automatically created by `const $$ = testSetup()`
222
206
  * but is useful if you don't want to have a global stub of @salesforce/core and you want to isolate it to
@@ -528,4 +512,3 @@ export declare class MockTestSandboxData {
528
512
  */
529
513
  getConfig(): Promise<SandboxFields>;
530
514
  }
531
- export {};
package/lib/testSetup.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MockTestSandboxData = exports.MockTestOrgData = exports.StreamingMockCometClient = exports.StreamingMockCometSubscription = exports.StreamingMockSubscriptionCall = exports.shouldThrowSync = exports.shouldThrow = exports.unexpectedResult = exports.restoreContext = exports.stubContext = exports.instantiateContext = exports.uniqid = exports.TestContext = void 0;
3
+ exports.MockTestSandboxData = exports.MockTestOrgData = exports.StreamingMockCometClient = exports.StreamingMockCometSubscription = exports.StreamingMockSubscriptionCall = exports.shouldThrowSync = exports.shouldThrow = exports.unexpectedResult = exports.restoreContext = exports.stubContext = exports.instantiateContext = exports.TestContext = exports.uniqid = void 0;
4
4
  /*
5
5
  * Copyright (c) 2020, salesforce.com, inc.
6
6
  * All rights reserved.
@@ -13,17 +13,15 @@ exports.MockTestSandboxData = exports.MockTestOrgData = exports.StreamingMockCom
13
13
  /* eslint-disable @typescript-eslint/no-unsafe-member-access */
14
14
  /* eslint-disable @typescript-eslint/no-unsafe-call */
15
15
  const fs = require("node:fs");
16
- const crypto_1 = require("crypto");
17
16
  const events_1 = require("events");
18
17
  const os_1 = require("os");
19
18
  const path_1 = require("path");
20
- const util = require("util");
21
19
  const ts_sinon_1 = require("@salesforce/ts-sinon");
22
20
  const ts_types_1 = require("@salesforce/ts-types");
23
21
  const configAggregator_1 = require("./config/configAggregator");
24
22
  const configFile_1 = require("./config/configFile");
25
23
  const connection_1 = require("./org/connection");
26
- const crypto_2 = require("./crypto/crypto");
24
+ const crypto_1 = require("./crypto/crypto");
27
25
  const logger_1 = require("./logger/logger");
28
26
  const messages_1 = require("./messages");
29
27
  const sfError_1 = require("./sfError");
@@ -34,6 +32,8 @@ const stateAggregator_1 = require("./stateAggregator");
34
32
  const org_1 = require("./org");
35
33
  const sandboxAccessor_1 = require("./stateAggregator/accessors/sandboxAccessor");
36
34
  const global_1 = require("./global");
35
+ const uniqid_1 = require("./util/uniqid");
36
+ Object.defineProperty(exports, "uniqid", { enumerable: true, get: function () { return uniqid_1.uniqid; } });
37
37
  /**
38
38
  * Instantiate a @salesforce/core test context.
39
39
  */
@@ -42,7 +42,7 @@ class TestContext {
42
42
  /**
43
43
  * id A unique id for the test run.
44
44
  */
45
- this.id = uniqid();
45
+ this.id = (0, uniqid_1.uniqid)();
46
46
  /**
47
47
  * An object used in tests that interact with config files.
48
48
  */
@@ -73,7 +73,7 @@ class TestContext {
73
73
  * Generate unique string.
74
74
  */
75
75
  uniqid() {
76
- return uniqid();
76
+ return (0, uniqid_1.uniqid)();
77
77
  }
78
78
  /**
79
79
  * A function used when resolving the local path. Calls localPathResolverSync by default.
@@ -300,39 +300,17 @@ class TestContext {
300
300
  }
301
301
  }
302
302
  exports.TestContext = TestContext;
303
- /**
304
- * A function to generate a unique id and return it in the context of a template, if supplied.
305
- *
306
- * A template is a string that can contain `${%s}` to be replaced with a unique id.
307
- * If the template contains the "%s" placeholder, it will be replaced with the unique id otherwise the id will be appended to the template.
308
- *
309
- * @param options an object with the following properties:
310
- * - template: a template string.
311
- * - length: the length of the unique id as presented in hexadecimal.
312
- */
313
- function uniqid(options) {
314
- const uniqueString = (0, crypto_1.randomBytes)(Math.ceil((options?.length ?? 32) / 2.0))
315
- .toString('hex')
316
- .slice(0, options?.length ?? 32);
317
- if (!options?.template) {
318
- return uniqueString;
319
- }
320
- return options.template.includes('%s')
321
- ? util.format(options.template, uniqueString)
322
- : `${options.template}${uniqueString}`;
323
- }
324
- exports.uniqid = uniqid;
325
303
  function getTestLocalPath(uid) {
326
304
  return (0, path_1.join)((0, os_1.tmpdir)(), uid, 'sfdx_core', 'local');
327
305
  }
328
306
  function getTestGlobalPath(uid) {
329
307
  return (0, path_1.join)((0, os_1.tmpdir)(), uid, 'sfdx_core', 'global');
330
308
  }
331
- function retrieveRootPathSync(isGlobal, uid = uniqid()) {
309
+ function retrieveRootPathSync(isGlobal, uid = (0, uniqid_1.uniqid)()) {
332
310
  return isGlobal ? getTestGlobalPath(uid) : getTestLocalPath(uid);
333
311
  }
334
312
  // eslint-disable-next-line @typescript-eslint/require-await
335
- async function retrieveRootPath(isGlobal, uid = uniqid()) {
313
+ async function retrieveRootPath(isGlobal, uid = (0, uniqid_1.uniqid)()) {
336
314
  return retrieveRootPathSync(isGlobal, uid);
337
315
  }
338
316
  function defaultFakeConnectionRequest() {
@@ -398,6 +376,7 @@ const stubContext = (testContext) => {
398
376
  testContext.SANDBOXES.CONFIG.stub(configFile_1.ConfigFile, 'resolveRootFolderSync').callsFake((isGlobal) => testContext.rootPathRetrieverSync(isGlobal, testContext.id));
399
377
  (0, ts_sinon_1.stubMethod)(testContext.SANDBOXES.PROJECT, sfProject_1.SfProjectJson.prototype, 'doesPackageExist').callsFake(() => true);
400
378
  const initStubForRead = (configFile) => {
379
+ testContext.configStubs[configFile.constructor.name] ??= {};
401
380
  const stub = testContext.configStubs[configFile.constructor.name] ?? {};
402
381
  // init calls read calls getPath which sets the path on the config file the first time.
403
382
  // Since read is now stubbed, make sure to call getPath to initialize it.
@@ -408,7 +387,7 @@ const stubContext = (testContext) => {
408
387
  };
409
388
  const readSync = function (newContents) {
410
389
  const stub = initStubForRead(this);
411
- this.setContentsFromObject(newContents ?? stub.contents ?? {});
390
+ this.setContentsFromFileContents(newContents ?? stub.contents ?? {}, BigInt(Date.now()));
412
391
  return this.getContents();
413
392
  };
414
393
  const read = async function () {
@@ -427,36 +406,22 @@ const stubContext = (testContext) => {
427
406
  stubs.configRead = testContext.SANDBOXES.CONFIG.stub(configFile_1.ConfigFile.prototype, 'read').callsFake(read);
428
407
  // @ts-expect-error: muting exact type match for stub readSync
429
408
  stubs.configReadSync = testContext.SANDBOXES.CONFIG.stub(configFile_1.ConfigFile.prototype, 'readSync').callsFake(readSync);
430
- const writeSync = function (newContents) {
431
- if (!testContext.configStubs[this.constructor.name]) {
432
- testContext.configStubs[this.constructor.name] = {};
433
- }
434
- const stub = testContext.configStubs[this.constructor.name];
435
- if (!stub)
436
- return;
437
- this.setContents(newContents ?? this.getContents());
409
+ const writeSync = function () {
410
+ testContext.configStubs[this.constructor.name] ??= {};
411
+ const stub = testContext.configStubs[this.constructor.name] ?? {};
438
412
  stub.contents = this.toObject();
439
413
  };
440
- const write = async function (newContents) {
441
- if (!testContext.configStubs[this.constructor.name]) {
442
- testContext.configStubs[this.constructor.name] = {};
443
- }
444
- const stub = testContext.configStubs[this.constructor.name];
445
- if (!stub)
446
- return;
414
+ const write = async function () {
415
+ testContext.configStubs[this.constructor.name] ??= {};
416
+ const stub = testContext.configStubs[this.constructor.name] ?? {};
447
417
  if (stub.writeFn) {
448
- return stub.writeFn.call(this, newContents);
449
- }
450
- if (stub.updateContents) {
451
- writeSync.call(this, await stub.updateContents.call(this));
452
- }
453
- else {
454
- writeSync.call(this);
418
+ return stub.writeFn.call(this);
455
419
  }
420
+ writeSync.call(this);
456
421
  };
457
422
  stubs.configWriteSync = (0, ts_sinon_1.stubMethod)(testContext.SANDBOXES.CONFIG, configFile_1.ConfigFile.prototype, 'writeSync').callsFake(writeSync);
458
423
  stubs.configWrite = (0, ts_sinon_1.stubMethod)(testContext.SANDBOXES.CONFIG, configFile_1.ConfigFile.prototype, 'write').callsFake(write);
459
- (0, ts_sinon_1.stubMethod)(testContext.SANDBOXES.CRYPTO, crypto_2.Crypto.prototype, 'getKeyChain').callsFake(() => Promise.resolve({
424
+ (0, ts_sinon_1.stubMethod)(testContext.SANDBOXES.CRYPTO, crypto_1.Crypto.prototype, 'getKeyChain').callsFake(() => Promise.resolve({
460
425
  setPassword: () => Promise.resolve(),
461
426
  getPassword: (data, cb) => cb(undefined, '12345678901234567890123456789012'),
462
427
  }));
@@ -720,7 +685,7 @@ exports.StreamingMockCometClient = StreamingMockCometClient;
720
685
  * ```
721
686
  */
722
687
  class MockTestOrgData {
723
- constructor(id = uniqid(), options) {
688
+ constructor(id = (0, uniqid_1.uniqid)(), options) {
724
689
  this.testId = id;
725
690
  this.userId = `user_id_${this.testId}`;
726
691
  this.orgId = `${this.testId}`;
@@ -791,7 +756,7 @@ class MockTestOrgData {
791
756
  * Return the auth config file contents.
792
757
  */
793
758
  async getConfig() {
794
- const crypto = await crypto_2.Crypto.create();
759
+ const crypto = await crypto_1.Crypto.create();
795
760
  const config = {};
796
761
  config.orgId = this.orgId;
797
762
  config.clientId = this.clientId;
@@ -816,7 +781,8 @@ class MockTestOrgData {
816
781
  if (this.password) {
817
782
  config.password = crypto.encrypt(this.password);
818
783
  }
819
- return config;
784
+ // remove "undefined" properties that don't exist in actual files
785
+ return Object.fromEntries(Object.entries(config).filter(([, v]) => v !== undefined));
820
786
  }
821
787
  /**
822
788
  * Return the Connection for the org.
@@ -836,7 +802,7 @@ exports.MockTestOrgData = MockTestOrgData;
836
802
  * ```
837
803
  */
838
804
  class MockTestSandboxData {
839
- constructor(id = uniqid(), options) {
805
+ constructor(id = (0, uniqid_1.uniqid)(), options) {
840
806
  this.id = id;
841
807
  this.sandboxOrgId = id;
842
808
  this.prodOrgUsername = options?.prodOrgUsername ?? `admin_${id}@gb.org`;
@@ -0,0 +1,11 @@
1
+ export declare const lockOptions: {
2
+ stale: number;
3
+ };
4
+ export declare const lockRetryOptions: {
5
+ retries: {
6
+ retries: number;
7
+ maxTimeout: number;
8
+ factor: number;
9
+ };
10
+ stale: number;
11
+ };
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2023, salesforce.com, inc.
4
+ * All rights reserved.
5
+ * Licensed under the BSD 3-Clause license.
6
+ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.lockRetryOptions = exports.lockOptions = void 0;
10
+ // docs: https://github.com/moxystudio/node-proper-lockfile
11
+ exports.lockOptions = { stale: 10000 };
12
+ exports.lockRetryOptions = {
13
+ ...exports.lockOptions,
14
+ retries: { retries: 10, maxTimeout: 1000, factor: 2 },
15
+ };
16
+ //# sourceMappingURL=lockRetryOptions.js.map
@@ -0,0 +1,14 @@
1
+ /**
2
+ * A function to generate a unique id and return it in the context of a template, if supplied.
3
+ *
4
+ * A template is a string that can contain `${%s}` to be replaced with a unique id.
5
+ * If the template contains the "%s" placeholder, it will be replaced with the unique id otherwise the id will be appended to the template.
6
+ *
7
+ * @param options an object with the following properties:
8
+ * - template: a template string.
9
+ * - length: the length of the unique id as presented in hexadecimal.
10
+ */
11
+ export declare function uniqid(options?: {
12
+ template?: string;
13
+ length?: number;
14
+ }): string;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.uniqid = void 0;
4
+ /*
5
+ * Copyright (c) 2023, salesforce.com, inc.
6
+ * All rights reserved.
7
+ * Licensed under the BSD 3-Clause license.
8
+ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
9
+ */
10
+ const crypto_1 = require("crypto");
11
+ const util = require("util");
12
+ /**
13
+ * A function to generate a unique id and return it in the context of a template, if supplied.
14
+ *
15
+ * A template is a string that can contain `${%s}` to be replaced with a unique id.
16
+ * If the template contains the "%s" placeholder, it will be replaced with the unique id otherwise the id will be appended to the template.
17
+ *
18
+ * @param options an object with the following properties:
19
+ * - template: a template string.
20
+ * - length: the length of the unique id as presented in hexadecimal.
21
+ */
22
+ function uniqid(options) {
23
+ const uniqueString = (0, crypto_1.randomBytes)(Math.ceil((options?.length ?? 32) / 2))
24
+ .toString('hex')
25
+ .slice(0, options?.length ?? 32);
26
+ if (!options?.template) {
27
+ return uniqueString;
28
+ }
29
+ return options.template.includes('%s')
30
+ ? util.format(options.template, uniqueString)
31
+ : `${options.template}${uniqueString}`;
32
+ }
33
+ exports.uniqid = uniqid;
34
+ //# sourceMappingURL=uniqid.js.map