@salesforce/core 4.0.1 → 4.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -95,7 +95,7 @@ describe('Mocking Aliases', () => {
95
95
  const testData = new MockTestOrgData();
96
96
  await $$.stubAliases({ myAlias: testData.username });
97
97
  const alias = (await StateAggregator.getInstance()).aliases.get(testData.username);
98
- strictEqual(alias, 'myAlais');
98
+ strictEqual(alias, 'myAlias');
99
99
  });
100
100
  });
101
101
 
package/lib/org/org.js CHANGED
@@ -984,12 +984,8 @@ class Org extends kit_1.AsyncOptionalCreatable {
984
984
  this.logger.debug(`Removing users associate with org: ${this.getOrgId()}`);
985
985
  const config = await this.retrieveOrgUsersConfig();
986
986
  this.logger.debug(`using path for org users: ${config.getPath()}`);
987
- const authInfos = await this.readUserAuthFiles();
988
- await Promise.all(authInfos
989
- .map((auth) => auth.getFields().username)
990
- .map(async (username) => {
991
- const aliasKeys = (username && stateAggregator.aliases.getAll(username)) ?? [];
992
- stateAggregator.aliases.unsetAll(username);
987
+ const usernames = (await this.readUserAuthFiles()).map((auth) => auth.getFields().username).filter(ts_types_1.isString);
988
+ await Promise.all(usernames.map(async (username) => {
993
989
  const orgForUser = username === this.getUsername()
994
990
  ? this
995
991
  : await Org.create({
@@ -998,13 +994,14 @@ class Org extends kit_1.AsyncOptionalCreatable {
998
994
  const orgType = this.isDevHubOrg() ? orgConfigProperties_1.OrgConfigProperties.TARGET_DEV_HUB : orgConfigProperties_1.OrgConfigProperties.TARGET_ORG;
999
995
  const configInfo = orgForUser.configAggregator.getInfo(orgType);
1000
996
  const needsConfigUpdate = (configInfo.isGlobal() || configInfo.isLocal()) &&
1001
- (configInfo.value === username || aliasKeys.includes(configInfo.value));
997
+ (configInfo.value === username || stateAggregator.aliases.get(configInfo.value) === username);
1002
998
  return [
1003
999
  orgForUser.removeAuth(),
1004
1000
  needsConfigUpdate ? config_1.Config.update(configInfo.isGlobal(), orgType, undefined) : undefined,
1005
1001
  ].filter(Boolean);
1006
1002
  }));
1007
- await stateAggregator.aliases.write();
1003
+ // now that we're done with all the aliases, we can unset those
1004
+ await stateAggregator.aliases.unsetValuesAndSave(usernames);
1008
1005
  }
1009
1006
  async removeSandboxConfig() {
1010
1007
  const stateAggregator = await stateAggregator_1.StateAggregator.getInstance();
@@ -1,10 +1,15 @@
1
1
  import { AsyncOptionalCreatable } from '@salesforce/kit';
2
2
  import { Nullable } from '@salesforce/ts-types';
3
- import { AuthFields, ConfigContents } from '../../exported';
3
+ import { AuthFields } from '../../org/authInfo';
4
+ import { ConfigContents } from '../../config/configStore';
4
5
  import { SfToken } from './tokenAccessor';
5
6
  export type Aliasable = string | (Partial<AuthFields> & Partial<SfToken>);
7
+ export declare const DEFAULT_GROUP = "orgs";
8
+ export declare const FILENAME = "alias.json";
6
9
  export declare class AliasAccessor extends AsyncOptionalCreatable {
7
- private config;
10
+ private fileLocation;
11
+ /** orgs is the default group */
12
+ private aliasStore;
8
13
  /**
9
14
  * Returns all the aliases for all the values
10
15
  */
@@ -33,17 +38,6 @@ export declare class AliasAccessor extends AsyncOptionalCreatable {
33
38
  * @param alias the alias that corresponds to a username
34
39
  */
35
40
  getUsername(alias: string): Nullable<string>;
36
- /**
37
- * If the provided string is an alias, it returns the corresponding value.
38
- * If the provided string is not an alias, we assume that the provided string
39
- * is the value and return it.
40
- *
41
- * This method is helpful when you don't know if the string you have is a value
42
- * or an alias.
43
- *
44
- * @param valueOrAlias a string that might be a value or might be an alias
45
- */
46
- resolveValue(valueOrAlias: string): string;
47
41
  /**
48
42
  * If the provided string is an alias, it returns the corresponding username.
49
43
  * If the provided string is not an alias, we assume that the provided string
@@ -64,25 +58,51 @@ export declare class AliasAccessor extends AsyncOptionalCreatable {
64
58
  *
65
59
  * @param usernameOrAlias a string that might be a username or might be an alias
66
60
  */
67
- resolveAlias(usernameOrAlias: string): Nullable<string>;
61
+ resolveAlias(usernameOrAlias: string): string | undefined;
68
62
  /**
69
- * Set an alias for the given aliasable entity
63
+ * Set an alias for the given aliasable entity. Writes to the file
70
64
  *
65
+ * @deprecated use setAndSave
71
66
  * @param alias the alias you want to set
72
67
  * @param entity the aliasable entity that's being aliased
73
68
  */
74
69
  set(alias: string, entity: Aliasable): void;
75
70
  /**
76
- * Unset the given alias.
71
+ * Set an alias for the given aliasable entity. Writes to the file
72
+ *
73
+ * @param alias the alias you want to set
74
+ * @param entity the aliasable entity that's being aliased
75
+ */
76
+ setAndSave(alias: string, entity: Aliasable): Promise<void>;
77
+ /**
78
+ * Unset the given alias. Writes to the file
79
+ *
80
+ * @deprecated use unsetAndSave
77
81
  *
78
82
  */
79
83
  unset(alias: string): void;
84
+ /**
85
+ * Unset the given alias(es). Writes to the file
86
+ *
87
+ */
88
+ unsetAndSave(alias: string): Promise<void>;
80
89
  /**
81
90
  * Unsets all the aliases for the given entity.
82
91
  *
92
+ * @deprecated use unsetValuesAndSave
93
+ *
83
94
  * @param entity the aliasable entity for which you want to unset all aliases
84
95
  */
85
96
  unsetAll(entity: Aliasable): void;
97
+ /**
98
+ * Unset all the aliases for the given array of entity.
99
+ *
100
+ * @param entity the aliasable entity for which you want to unset all aliases
101
+ */
102
+ unsetValuesAndSave(aliasees: Aliasable[]): Promise<void>;
103
+ /**
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
+ */
86
106
  write(): Promise<ConfigContents>;
87
107
  /**
88
108
  * Returns true if the provided alias exists
@@ -92,7 +112,18 @@ export declare class AliasAccessor extends AsyncOptionalCreatable {
92
112
  has(alias: string): boolean;
93
113
  protected init(): Promise<void>;
94
114
  /**
95
- * Returns the username of given aliasable entity
115
+ * go to the fileSystem and read the file, storing a copy in the class's store
116
+ * if the file doesn't exist, create it empty
96
117
  */
97
- private getNameOf;
118
+ private readFileToAliasStore;
119
+ private saveAliasStoreToFile;
120
+ /**
121
+ * @deprecated use the async version of this method instead
122
+ * provided for the legacy sync set/unset methods. */
123
+ private readFileToAliasStoreSync;
124
+ /**
125
+ * @deprecated use the async version of this method instead
126
+ * provided for the legacy sync set/unset methods */
127
+ private saveAliasStoreToFileSync;
98
128
  }
129
+ export declare const getFileLocation: () => string;
@@ -6,23 +6,34 @@
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.AliasAccessor = void 0;
9
+ exports.getFileLocation = exports.AliasAccessor = exports.FILENAME = exports.DEFAULT_GROUP = void 0;
10
+ const node_path_1 = require("node:path");
11
+ const node_os_1 = require("node:os");
12
+ const promises_1 = require("node:fs/promises");
13
+ const node_fs_1 = require("node:fs");
14
+ const proper_lockfile_1 = require("proper-lockfile");
10
15
  const kit_1 = require("@salesforce/kit");
11
- const aliasesConfig_1 = require("../../config/aliasesConfig");
16
+ const global_1 = require("../../global");
12
17
  const sfError_1 = require("../../sfError");
18
+ exports.DEFAULT_GROUP = 'orgs';
19
+ exports.FILENAME = 'alias.json';
20
+ const lockOptions = { stale: 10000 };
21
+ const lockRetryOptions = {
22
+ ...lockOptions,
23
+ retries: { retries: 10, maxTimeout: 1000, factor: 2 },
24
+ };
13
25
  class AliasAccessor extends kit_1.AsyncOptionalCreatable {
14
26
  getAll(entity) {
15
27
  // This will only return aliases under "orgs". This will need to be modified
16
28
  // if/when we want to support more aliases groups.
17
- const all = (this.config.getGroup() ?? {});
18
29
  if (entity) {
19
- const value = this.getNameOf(entity);
20
- return Object.entries(all)
21
- .filter((entry) => entry[1] === value)
22
- .map((entry) => entry[0]);
30
+ const nameFromEntity = getNameOf(entity);
31
+ return Array.from(this.aliasStore.entries())
32
+ .filter(([, value]) => nameFromEntity === value)
33
+ .map(([alias]) => alias);
23
34
  }
24
35
  else {
25
- return all;
36
+ return Object.fromEntries(this.aliasStore.entries());
26
37
  }
27
38
  }
28
39
  /**
@@ -31,7 +42,7 @@ class AliasAccessor extends kit_1.AsyncOptionalCreatable {
31
42
  * @param entity the aliasable entity that you want to get the alias of
32
43
  */
33
44
  get(entity) {
34
- return this.getAll(entity).find((alias) => alias) ?? null;
45
+ return this.getAll(entity)[0] ?? null;
35
46
  }
36
47
  /**
37
48
  * Returns the value that corresponds to the given alias if it exists
@@ -39,7 +50,7 @@ class AliasAccessor extends kit_1.AsyncOptionalCreatable {
39
50
  * @param alias the alias that corresponds to a value
40
51
  */
41
52
  getValue(alias) {
42
- return this.getAll()[alias] ?? null;
53
+ return this.aliasStore.get(alias) ?? null;
43
54
  }
44
55
  /**
45
56
  * Returns the username that corresponds to the given alias if it exists
@@ -47,20 +58,7 @@ class AliasAccessor extends kit_1.AsyncOptionalCreatable {
47
58
  * @param alias the alias that corresponds to a username
48
59
  */
49
60
  getUsername(alias) {
50
- return this.getAll()[alias] ?? null;
51
- }
52
- /**
53
- * If the provided string is an alias, it returns the corresponding value.
54
- * If the provided string is not an alias, we assume that the provided string
55
- * is the value and return it.
56
- *
57
- * This method is helpful when you don't know if the string you have is a value
58
- * or an alias.
59
- *
60
- * @param valueOrAlias a string that might be a value or might be an alias
61
- */
62
- resolveValue(valueOrAlias) {
63
- return this.getValue(valueOrAlias) ?? valueOrAlias;
61
+ return this.aliasStore.get(alias) ?? null;
64
62
  }
65
63
  /**
66
64
  * If the provided string is an alias, it returns the corresponding username.
@@ -85,37 +83,85 @@ class AliasAccessor extends kit_1.AsyncOptionalCreatable {
85
83
  * @param usernameOrAlias a string that might be a username or might be an alias
86
84
  */
87
85
  resolveAlias(usernameOrAlias) {
88
- if (this.has(usernameOrAlias))
86
+ if (this.aliasStore.has(usernameOrAlias))
89
87
  return usernameOrAlias;
90
- return Object.entries(this.getAll()).find(([, username]) => username === usernameOrAlias)?.[0];
88
+ return Array.from(this.aliasStore.entries()).find(([, value]) => value === usernameOrAlias)?.[0];
91
89
  }
92
90
  /**
93
- * Set an alias for the given aliasable entity
91
+ * Set an alias for the given aliasable entity. Writes to the file
94
92
  *
93
+ * @deprecated use setAndSave
95
94
  * @param alias the alias you want to set
96
95
  * @param entity the aliasable entity that's being aliased
97
96
  */
98
97
  set(alias, entity) {
99
- this.config.set(alias, this.getNameOf(entity));
98
+ // get a very fresh copy to merge with to avoid conflicts
99
+ this.readFileToAliasStoreSync();
100
+ this.aliasStore.set(alias, getNameOf(entity));
101
+ this.saveAliasStoreToFileSync();
102
+ }
103
+ /**
104
+ * Set an alias for the given aliasable entity. Writes to the file
105
+ *
106
+ * @param alias the alias you want to set
107
+ * @param entity the aliasable entity that's being aliased
108
+ */
109
+ async setAndSave(alias, entity) {
110
+ // get a very fresh copy to merge with to avoid conflicts, then lock
111
+ await this.readFileToAliasStore(true);
112
+ this.aliasStore.set(alias, getNameOf(entity));
113
+ return this.saveAliasStoreToFile();
100
114
  }
101
115
  /**
102
- * Unset the given alias.
116
+ * Unset the given alias. Writes to the file
117
+ *
118
+ * @deprecated use unsetAndSave
103
119
  *
104
120
  */
105
121
  unset(alias) {
106
- this.config.unset(alias);
122
+ this.readFileToAliasStoreSync();
123
+ this.aliasStore.delete(alias);
124
+ this.saveAliasStoreToFileSync();
125
+ }
126
+ /**
127
+ * Unset the given alias(es). Writes to the file
128
+ *
129
+ */
130
+ async unsetAndSave(alias) {
131
+ await this.readFileToAliasStore(true);
132
+ this.aliasStore.delete(alias);
133
+ return this.saveAliasStoreToFile();
107
134
  }
108
135
  /**
109
136
  * Unsets all the aliases for the given entity.
110
137
  *
138
+ * @deprecated use unsetValuesAndSave
139
+ *
111
140
  * @param entity the aliasable entity for which you want to unset all aliases
112
141
  */
113
142
  unsetAll(entity) {
143
+ this.readFileToAliasStoreSync();
114
144
  const aliases = this.getAll(entity);
115
- aliases.forEach((alias) => this.unset(alias));
145
+ aliases.forEach((a) => this.aliasStore.delete(a));
146
+ this.saveAliasStoreToFileSync();
116
147
  }
148
+ /**
149
+ * Unset all the aliases for the given array of entity.
150
+ *
151
+ * @param entity the aliasable entity for which you want to unset all aliases
152
+ */
153
+ async unsetValuesAndSave(aliasees) {
154
+ await this.readFileToAliasStore(true);
155
+ (0, kit_1.ensureArray)(aliasees)
156
+ .flatMap((a) => this.getAll(a))
157
+ .map((a) => this.aliasStore.delete(a));
158
+ return this.saveAliasStoreToFile();
159
+ }
160
+ /**
161
+ * @deprecated the set/unset methods now write to the file when called. Use (un)setAndSave instead of calling (un)set and then calling write()
162
+ */
117
163
  async write() {
118
- return this.config.write();
164
+ return Promise.resolve(this.getAll());
119
165
  }
120
166
  /**
121
167
  * Returns true if the provided alias exists
@@ -123,24 +169,95 @@ class AliasAccessor extends kit_1.AsyncOptionalCreatable {
123
169
  * @param alias the alias you want to check
124
170
  */
125
171
  has(alias) {
126
- return this.config.has(alias);
172
+ return this.aliasStore.has(alias);
127
173
  }
128
174
  async init() {
129
- this.config = await aliasesConfig_1.AliasesConfig.create(aliasesConfig_1.AliasesConfig.getDefaultOptions());
175
+ this.fileLocation = (0, exports.getFileLocation)();
176
+ await this.readFileToAliasStore();
130
177
  }
131
178
  /**
132
- * Returns the username of given aliasable entity
179
+ * go to the fileSystem and read the file, storing a copy in the class's store
180
+ * if the file doesn't exist, create it empty
133
181
  */
134
- // eslint-disable-next-line class-methods-use-this
135
- getNameOf(entity) {
136
- if (typeof entity === 'string')
137
- return entity;
138
- const aliaseeName = entity.username ?? entity.user;
139
- if (!aliaseeName) {
140
- throw new sfError_1.SfError(`Invalid aliasee, it must contain a user or username property: ${JSON.stringify(entity)}`);
182
+ async readFileToAliasStore(useLock = false) {
183
+ if (useLock) {
184
+ await (0, proper_lockfile_1.lock)(this.fileLocation, lockRetryOptions);
185
+ }
186
+ try {
187
+ this.aliasStore = fileContentsRawToAliasStore(await (0, promises_1.readFile)(this.fileLocation, 'utf-8'));
188
+ }
189
+ catch (e) {
190
+ if (e instanceof Error && 'code' in e && e.code === 'ENOENT') {
191
+ this.aliasStore = new Map();
192
+ await (0, promises_1.mkdir)((0, node_path_1.dirname)(this.fileLocation), { recursive: true });
193
+ await this.saveAliasStoreToFile();
194
+ return;
195
+ }
196
+ if (useLock)
197
+ return unlockIfLocked(this.fileLocation);
198
+ throw e;
199
+ }
200
+ }
201
+ async saveAliasStoreToFile() {
202
+ await (0, promises_1.writeFile)(this.fileLocation, aliasStoreToRawFileContents(this.aliasStore));
203
+ return unlockIfLocked(this.fileLocation);
204
+ }
205
+ /**
206
+ * @deprecated use the async version of this method instead
207
+ * provided for the legacy sync set/unset methods. */
208
+ readFileToAliasStoreSync() {
209
+ // the file is guaranteed to exist because this init method ensures it
210
+ // put a lock in place. This method is only used by legacy set/unset methods.
211
+ (0, proper_lockfile_1.lockSync)(this.fileLocation, lockOptions);
212
+ this.aliasStore = fileContentsRawToAliasStore((0, node_fs_1.readFileSync)(this.fileLocation, 'utf-8'));
213
+ }
214
+ /**
215
+ * @deprecated use the async version of this method instead
216
+ * provided for the legacy sync set/unset methods */
217
+ saveAliasStoreToFileSync() {
218
+ (0, node_fs_1.writeFileSync)(this.fileLocation, aliasStoreToRawFileContents(this.aliasStore));
219
+ try {
220
+ (0, proper_lockfile_1.unlockSync)(this.fileLocation);
221
+ }
222
+ catch (e) {
223
+ // ignore the error. If it wasn't locked, that's what we wanted
224
+ if (errorIsNotAcquired(e))
225
+ return;
226
+ throw e;
141
227
  }
142
- return aliaseeName;
143
228
  }
144
229
  }
145
230
  exports.AliasAccessor = AliasAccessor;
231
+ /**
232
+ * Returns the username of given aliasable entity
233
+ */
234
+ const getNameOf = (entity) => {
235
+ if (typeof entity === 'string')
236
+ return entity;
237
+ const aliaseeName = entity.username ?? entity.user;
238
+ if (!aliaseeName) {
239
+ throw new sfError_1.SfError(`Invalid aliasee, it must contain a user or username property: ${JSON.stringify(entity)}`);
240
+ }
241
+ return aliaseeName;
242
+ };
243
+ const fileContentsRawToAliasStore = (contents) => {
244
+ const fileContents = JSON.parse(contents);
245
+ return new Map(Object.entries(fileContents[exports.DEFAULT_GROUP]));
246
+ };
247
+ const aliasStoreToRawFileContents = (aliasStore) => JSON.stringify({ [exports.DEFAULT_GROUP]: Object.fromEntries(Array.from(aliasStore.entries())) });
248
+ // exported for testSetup mocking
249
+ const getFileLocation = () => (0, node_path_1.join)((0, node_os_1.homedir)(), global_1.Global.SFDX_STATE_FOLDER, exports.FILENAME);
250
+ exports.getFileLocation = getFileLocation;
251
+ const unlockIfLocked = async (fileLocation) => {
252
+ try {
253
+ await (0, proper_lockfile_1.unlock)(fileLocation);
254
+ }
255
+ catch (e) {
256
+ // ignore the error. If it wasn't locked, that's what we wanted
257
+ if (errorIsNotAcquired(e))
258
+ return;
259
+ throw e;
260
+ }
261
+ };
262
+ const errorIsNotAcquired = (e) => e instanceof Error && 'code' in e && e.code === 'ENOTACQUIRED';
146
263
  //# sourceMappingURL=aliasAccessor.js.map
@@ -61,8 +61,9 @@ class MyDomainResolver extends kit_1.AsyncOptionalCreatable {
61
61
  * executing the dns loookup.
62
62
  */
63
63
  async resolve() {
64
- if (new kit_1.Env().getBoolean('SFDX_DISABLE_DNS_CHECK', false)) {
65
- this.logger.debug('SFDX_DISABLE_DNS_CHECK set to true. Skipping DNS check...');
64
+ const env = new kit_1.Env();
65
+ if (env.getBoolean('SF_DISABLE_DNS_CHECK', env.getBoolean('SFDX_DISABLE_DNS_CHECK', false))) {
66
+ this.logger.debug('SF_DISABLE_DNS_CHECK set to true. Skipping DNS check...');
66
67
  return this.options.url.host;
67
68
  }
68
69
  // eslint-disable-next-line @typescript-eslint/no-this-alias
@@ -8,7 +8,6 @@ import { Logger } from './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 { AliasGroup } from './config/aliasesConfig';
12
11
  /**
13
12
  * Different parts of the system that are mocked out. They can be restored for
14
13
  * individual tests. Test's stubs should always go on the DEFAULT which is exposed
@@ -82,7 +81,6 @@ export declare class TestContext {
82
81
  */
83
82
  configStubs: {
84
83
  [configName: string]: Optional<ConfigStub>;
85
- AliasesConfig?: ConfigStub;
86
84
  AuthInfoConfig?: ConfigStub;
87
85
  Config?: ConfigStub;
88
86
  SfProjectJson?: ConfigStub;
@@ -187,7 +185,7 @@ export declare class TestContext {
187
185
  /**
188
186
  * Stub the aliases in the global aliases config file.
189
187
  */
190
- stubAliases(aliases: Record<string, string>, group?: AliasGroup): void;
188
+ stubAliases(aliases: Record<string, string>, group?: string): void;
191
189
  /**
192
190
  * Stub contents in the config file.
193
191
  */
package/lib/testSetup.js CHANGED
@@ -1,4 +1,6 @@
1
1
  "use strict";
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;
2
4
  /*
3
5
  * Copyright (c) 2020, salesforce.com, inc.
4
6
  * All rights reserved.
@@ -10,8 +12,7 @@
10
12
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
11
13
  /* eslint-disable @typescript-eslint/no-unsafe-member-access */
12
14
  /* eslint-disable @typescript-eslint/no-unsafe-call */
13
- Object.defineProperty(exports, "__esModule", { value: true });
14
- 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;
15
+ const fs = require("node:fs");
15
16
  const crypto_1 = require("crypto");
16
17
  const events_1 = require("events");
17
18
  const os_1 = require("os");
@@ -27,11 +28,11 @@ const logger_1 = require("./logger");
27
28
  const messages_1 = require("./messages");
28
29
  const sfError_1 = require("./sfError");
29
30
  const sfProject_1 = require("./sfProject");
31
+ const aliasAccessorEntireFile = require("./stateAggregator/accessors/aliasAccessor");
30
32
  const streamingClient_1 = require("./status/streamingClient");
31
33
  const stateAggregator_1 = require("./stateAggregator");
32
34
  const org_1 = require("./org");
33
35
  const sandboxAccessor_1 = require("./stateAggregator/accessors/sandboxAccessor");
34
- const aliasesConfig_1 = require("./config/aliasesConfig");
35
36
  const global_1 = require("./global");
36
37
  /**
37
38
  * Instantiate a @salesforce/core test context.
@@ -246,8 +247,11 @@ class TestContext {
246
247
  /**
247
248
  * Stub the aliases in the global aliases config file.
248
249
  */
249
- stubAliases(aliases, group = aliasesConfig_1.AliasGroup.ORGS) {
250
- this.configStubs.AliasesConfig = { contents: { [group]: aliases } };
250
+ stubAliases(aliases, group = aliasAccessorEntireFile.DEFAULT_GROUP) {
251
+ // we don't really "stub" these since they don't use configFile.
252
+ // write the fileContents to location
253
+ fs.mkdirSync((0, path_1.dirname)(getAliasFileLocation()), { recursive: true });
254
+ fs.writeFileSync(getAliasFileLocation(), JSON.stringify({ [group]: aliases }));
251
255
  }
252
256
  /**
253
257
  * Stub contents in the config file.
@@ -463,6 +467,7 @@ const stubContext = (testContext) => {
463
467
  }
464
468
  return testContext.fakeConnectionRequest.call(this, request, options);
465
469
  });
470
+ (0, ts_sinon_1.stubMethod)(testContext.SANDBOX, aliasAccessorEntireFile, 'getFileLocation').returns(getAliasFileLocation());
466
471
  stubs.configExists = (0, ts_sinon_1.stubMethod)(testContext.SANDBOXES.ORGS, stateAggregator_1.OrgAccessor.prototype, 'exists').callsFake(async function (username) {
467
472
  // @ts-expect-error because private member
468
473
  if ([...this.contents.keys()].includes(username))
@@ -483,6 +488,7 @@ const stubContext = (testContext) => {
483
488
  return stubs;
484
489
  };
485
490
  exports.stubContext = stubContext;
491
+ const getAliasFileLocation = () => (0, path_1.join)((0, os_1.tmpdir)(), global_1.Global.SFDX_STATE_FOLDER, aliasAccessorEntireFile.FILENAME);
486
492
  /**
487
493
  * Restore a @salesforce/core test context. This is automatically stubbed in the global beforeEach created by
488
494
  * `const $$ = testSetup()` but is useful if you don't want to have a global stub of @salesforce/core and you
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/core",
3
- "version": "4.0.1",
3
+ "version": "4.1.1",
4
4
  "description": "Core libraries to interact with SFDX projects, orgs, and APIs.",
5
5
  "main": "lib/exported",
6
6
  "types": "lib/exported.d.ts",
@@ -52,6 +52,7 @@
52
52
  "js2xmlparser": "^4.0.1",
53
53
  "jsforce": "^2.0.0-beta.23",
54
54
  "jsonwebtoken": "9.0.0",
55
+ "proper-lockfile": "^4.1.2",
55
56
  "ts-retry-promise": "^0.7.0"
56
57
  },
57
58
  "devDependencies": {
@@ -64,6 +65,7 @@
64
65
  "@types/debug": "0.0.31",
65
66
  "@types/jsonwebtoken": "9.0.2",
66
67
  "@types/lodash": "^4.14.194",
68
+ "@types/proper-lockfile": "^4.1.2",
67
69
  "@types/shelljs": "0.8.12",
68
70
  "@typescript-eslint/eslint-plugin": "^5.59.7",
69
71
  "@typescript-eslint/parser": "^5.59.7",
@@ -1,12 +0,0 @@
1
- import { ConfigGroup } from './configGroup';
2
- import { ConfigContents, ConfigValue } from './configStore';
3
- /**
4
- * Different groups of aliases. Currently only support orgs.
5
- */
6
- export declare enum AliasGroup {
7
- ORGS = "orgs"
8
- }
9
- export declare class AliasesConfig extends ConfigGroup<ConfigGroup.Options> {
10
- static getDefaultOptions(): ConfigGroup.Options;
11
- protected setMethod(contents: ConfigContents, key: string, value?: ConfigValue): void;
12
- }
@@ -1,28 +0,0 @@
1
- "use strict";
2
- /*
3
- * Copyright (c) 2022, 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.AliasesConfig = exports.AliasGroup = void 0;
10
- const configGroup_1 = require("./configGroup");
11
- /**
12
- * Different groups of aliases. Currently only support orgs.
13
- */
14
- var AliasGroup;
15
- (function (AliasGroup) {
16
- AliasGroup["ORGS"] = "orgs";
17
- })(AliasGroup = exports.AliasGroup || (exports.AliasGroup = {}));
18
- class AliasesConfig extends configGroup_1.ConfigGroup {
19
- static getDefaultOptions() {
20
- return { ...configGroup_1.ConfigGroup.getOptions(AliasGroup.ORGS, 'alias.json'), isGlobal: true, isState: true };
21
- }
22
- // eslint-disable-next-line class-methods-use-this
23
- setMethod(contents, key, value) {
24
- contents[key] = value;
25
- }
26
- }
27
- exports.AliasesConfig = AliasesConfig;
28
- //# sourceMappingURL=aliasesConfig.js.map
@@ -1,141 +0,0 @@
1
- import { Dictionary, JsonMap, Optional } from '@salesforce/ts-types';
2
- import { ConfigFile } from './configFile';
3
- import { ConfigContents, ConfigEntry, ConfigValue } from './configStore';
4
- /**
5
- * A config file that stores config values in groups. e.g. to store different config
6
- * values for different commands, without having manually manipulate the config.
7
- *
8
- * **Note:** All config methods are overwritten to use the {@link ConfigGroup.setDefaultGroup}.
9
- *
10
- * ```
11
- * class MyPluginConfig extends ConfigGroup<ConfigGroup.Options> {
12
- * public static getFileName(): string {
13
- * return 'myPluginConfigFilename.json';
14
- * }
15
- * }
16
- * const myConfig = await MyPluginConfig.create(ConfigGroup.getOptions('all'));
17
- * myConfig.setDefaultGroup('myCommand'); // Can be set in your command's init.
18
- * myConfig.set('mykey', 'myvalue'); // Sets 'myKey' for the 'myCommand' group.
19
- * myConfig.setInGroup('myKey', 'myvalue', 'all'); // Manually set in another group.
20
- * await myConfig.write();
21
- * ```
22
- */
23
- export declare class ConfigGroup<T extends ConfigGroup.Options> extends ConfigFile<T> {
24
- protected defaultGroup: string;
25
- /**
26
- * Get ConfigGroup specific options, such as the default group.
27
- *
28
- * @param defaultGroup The default group to use when creating the config.
29
- * @param filename The filename of the config file. Uses the static {@link getFileName} by default.
30
- */
31
- static getOptions(defaultGroup: string, filename?: string): ConfigGroup.Options;
32
- /**
33
- * Sets the default group for all {@link BaseConfigStore} methods to use.
34
- * **Throws** *{@link SfError}{ name: 'MissingGroupName' }* The group parameter is null or undefined.
35
- *
36
- * @param group The group.
37
- */
38
- setDefaultGroup(group: string): void;
39
- /**
40
- * Set a group of entries in a bulk save. Returns The new properties that were saved.
41
- *
42
- * @param newEntries An object representing the aliases to set.
43
- * @param group The group the property belongs to.
44
- */
45
- updateValues(newEntries: Dictionary<ConfigValue>, group?: string): Promise<Dictionary<ConfigValue>>;
46
- /**
47
- * Set a value on a group. Returns the promise resolved when the value is set.
48
- *
49
- * @param key The key.
50
- * @param value The value.
51
- * @param group The group.
52
- */
53
- updateValue(key: string, value: ConfigValue, group?: string): Promise<void>;
54
- /**
55
- * Gets an array of key value pairs.
56
- */
57
- entries(): ConfigEntry[];
58
- /**
59
- * Returns a specified element from ConfigGroup. Returns the associated value.
60
- *
61
- * @param key The key.
62
- */
63
- get(key: string): Optional<ConfigValue>;
64
- /**
65
- * Returns a boolean if an element with the specified key exists in the default group.
66
- *
67
- * @param {string} key The key.
68
- */
69
- has(key: string): boolean;
70
- /**
71
- * Returns an array of the keys from the default group.
72
- */
73
- keys(): string[];
74
- /**
75
- * Returns an array of the values from the default group.
76
- */
77
- values(): ConfigValue[];
78
- /**
79
- * Add or updates an element with the specified key in the default group.
80
- *
81
- * @param key The key.
82
- * @param value The value.
83
- */
84
- set(key: string, value: ConfigValue): ConfigContents;
85
- /**
86
- * Removes an element with the specified key from the default group. Returns `true` if the item was deleted.
87
- *
88
- * @param key The key.
89
- */
90
- unset(key: string): boolean;
91
- /**
92
- * Remove all key value pairs from the default group.
93
- */
94
- clear(): void;
95
- /**
96
- * Get all config contents for a group.
97
- *
98
- * @param {string} [group = 'default'] The group.
99
- */
100
- getGroup(group?: string): Optional<ConfigContents>;
101
- /**
102
- * Returns the value associated to the key and group, or undefined if there is none.
103
- *
104
- * @param key The key.
105
- * @param group The group. Defaults to the default group.
106
- */
107
- getInGroup(key: string, group?: string): Optional<ConfigValue>;
108
- /**
109
- * Convert the config object to a json object.
110
- */
111
- toObject(): JsonMap;
112
- /**
113
- * Convert an object to a {@link ConfigContents} and set it as the config contents.
114
- *
115
- * @param {object} obj The object.
116
- */
117
- setContentsFromObject<U extends object>(obj: U): void;
118
- /**
119
- * Sets the value for the key and group in the config object.
120
- *
121
- * @param key The key.
122
- * @param value The value.
123
- * @param group The group. Uses the default group if not specified.
124
- */
125
- setInGroup(key: string, value?: ConfigValue, group?: string): ConfigContents;
126
- /**
127
- * Initialize the asynchronous dependencies.
128
- */
129
- init(): Promise<void>;
130
- }
131
- export declare namespace ConfigGroup {
132
- /**
133
- * Options when creating the config file.
134
- */
135
- interface Options extends ConfigFile.Options {
136
- /**
137
- * The default group for properties to go into.
138
- */
139
- defaultGroup?: string;
140
- }
141
- }
@@ -1,225 +0,0 @@
1
- "use strict";
2
- /*
3
- * Copyright (c) 2020, 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.ConfigGroup = void 0;
10
- const ts_types_1 = require("@salesforce/ts-types");
11
- const sfError_1 = require("../sfError");
12
- const configFile_1 = require("./configFile");
13
- /**
14
- * A config file that stores config values in groups. e.g. to store different config
15
- * values for different commands, without having manually manipulate the config.
16
- *
17
- * **Note:** All config methods are overwritten to use the {@link ConfigGroup.setDefaultGroup}.
18
- *
19
- * ```
20
- * class MyPluginConfig extends ConfigGroup<ConfigGroup.Options> {
21
- * public static getFileName(): string {
22
- * return 'myPluginConfigFilename.json';
23
- * }
24
- * }
25
- * const myConfig = await MyPluginConfig.create(ConfigGroup.getOptions('all'));
26
- * myConfig.setDefaultGroup('myCommand'); // Can be set in your command's init.
27
- * myConfig.set('mykey', 'myvalue'); // Sets 'myKey' for the 'myCommand' group.
28
- * myConfig.setInGroup('myKey', 'myvalue', 'all'); // Manually set in another group.
29
- * await myConfig.write();
30
- * ```
31
- */
32
- class ConfigGroup extends configFile_1.ConfigFile {
33
- constructor() {
34
- super(...arguments);
35
- this.defaultGroup = 'default';
36
- }
37
- /**
38
- * Get ConfigGroup specific options, such as the default group.
39
- *
40
- * @param defaultGroup The default group to use when creating the config.
41
- * @param filename The filename of the config file. Uses the static {@link getFileName} by default.
42
- */
43
- static getOptions(defaultGroup, filename) {
44
- const options = configFile_1.ConfigFile.getDefaultOptions(true, filename);
45
- const configGroupOptions = { defaultGroup };
46
- Object.assign(configGroupOptions, options);
47
- return configGroupOptions;
48
- }
49
- /**
50
- * Sets the default group for all {@link BaseConfigStore} methods to use.
51
- * **Throws** *{@link SfError}{ name: 'MissingGroupName' }* The group parameter is null or undefined.
52
- *
53
- * @param group The group.
54
- */
55
- setDefaultGroup(group) {
56
- if (!group) {
57
- throw new sfError_1.SfError('null or undefined group', 'MissingGroupName');
58
- }
59
- this.defaultGroup = group;
60
- }
61
- /**
62
- * Set a group of entries in a bulk save. Returns The new properties that were saved.
63
- *
64
- * @param newEntries An object representing the aliases to set.
65
- * @param group The group the property belongs to.
66
- */
67
- async updateValues(newEntries, group) {
68
- // Make sure the contents are loaded
69
- await this.read();
70
- Object.entries(newEntries).forEach(([key, val]) => this.setInGroup(key, val, group ?? this.defaultGroup));
71
- await this.write();
72
- return newEntries;
73
- }
74
- /**
75
- * Set a value on a group. Returns the promise resolved when the value is set.
76
- *
77
- * @param key The key.
78
- * @param value The value.
79
- * @param group The group.
80
- */
81
- async updateValue(key, value, group) {
82
- // Make sure the content is loaded
83
- await this.read();
84
- this.setInGroup(key, value, group ?? this.defaultGroup);
85
- // Then save it
86
- await this.write();
87
- }
88
- /**
89
- * Gets an array of key value pairs.
90
- */
91
- entries() {
92
- const group = this.getGroup();
93
- if (group) {
94
- return (0, ts_types_1.definiteEntriesOf)(group);
95
- }
96
- return [];
97
- }
98
- /**
99
- * Returns a specified element from ConfigGroup. Returns the associated value.
100
- *
101
- * @param key The key.
102
- */
103
- get(key) {
104
- return this.getInGroup(key);
105
- }
106
- /**
107
- * Returns a boolean if an element with the specified key exists in the default group.
108
- *
109
- * @param {string} key The key.
110
- */
111
- has(key) {
112
- const group = this.getGroup();
113
- return !!group && super.has(this.defaultGroup) && !!group[key];
114
- }
115
- /**
116
- * Returns an array of the keys from the default group.
117
- */
118
- keys() {
119
- return Object.keys(this.getGroup(this.defaultGroup) ?? {});
120
- }
121
- /**
122
- * Returns an array of the values from the default group.
123
- */
124
- values() {
125
- return (0, ts_types_1.definiteValuesOf)(this.getGroup(this.defaultGroup) ?? {});
126
- }
127
- /**
128
- * Add or updates an element with the specified key in the default group.
129
- *
130
- * @param key The key.
131
- * @param value The value.
132
- */
133
- set(key, value) {
134
- return this.setInGroup(key, value, this.defaultGroup);
135
- }
136
- /**
137
- * Removes an element with the specified key from the default group. Returns `true` if the item was deleted.
138
- *
139
- * @param key The key.
140
- */
141
- unset(key) {
142
- const groupContents = this.getGroup(this.defaultGroup);
143
- if (groupContents) {
144
- delete groupContents[key];
145
- return true;
146
- }
147
- return false;
148
- }
149
- /**
150
- * Remove all key value pairs from the default group.
151
- */
152
- clear() {
153
- delete this.getContents()[this.defaultGroup];
154
- }
155
- /**
156
- * Get all config contents for a group.
157
- *
158
- * @param {string} [group = 'default'] The group.
159
- */
160
- getGroup(group = this.defaultGroup) {
161
- return (0, ts_types_1.getJsonMap)(this.getContents(), group) ?? undefined;
162
- }
163
- /**
164
- * Returns the value associated to the key and group, or undefined if there is none.
165
- *
166
- * @param key The key.
167
- * @param group The group. Defaults to the default group.
168
- */
169
- getInGroup(key, group) {
170
- const groupContents = this.getGroup(group);
171
- if (groupContents) {
172
- return groupContents[key];
173
- }
174
- }
175
- /**
176
- * Convert the config object to a json object.
177
- */
178
- toObject() {
179
- return this.getContents();
180
- }
181
- /**
182
- * Convert an object to a {@link ConfigContents} and set it as the config contents.
183
- *
184
- * @param {object} obj The object.
185
- */
186
- // eslint-disable-next-line @typescript-eslint/ban-types
187
- setContentsFromObject(obj) {
188
- const contents = new Map(Object.entries(obj));
189
- Array.from(contents.entries()).forEach(([groupKey, groupContents]) => {
190
- if (groupContents) {
191
- Object.entries(groupContents).forEach(([contentKey, contentValue]) => {
192
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
193
- this.setInGroup(contentKey, contentValue, groupKey);
194
- });
195
- }
196
- });
197
- }
198
- /**
199
- * Sets the value for the key and group in the config object.
200
- *
201
- * @param key The key.
202
- * @param value The value.
203
- * @param group The group. Uses the default group if not specified.
204
- */
205
- setInGroup(key, value, group) {
206
- group = group ?? this.defaultGroup;
207
- if (!super.has(group)) {
208
- super.set(group, {});
209
- }
210
- const content = this.getGroup(group) ?? {};
211
- this.setMethod(content, key, value);
212
- return content;
213
- }
214
- /**
215
- * Initialize the asynchronous dependencies.
216
- */
217
- async init() {
218
- await super.init();
219
- if (this.options.defaultGroup) {
220
- this.setDefaultGroup(this.options.defaultGroup);
221
- }
222
- }
223
- }
224
- exports.ConfigGroup = ConfigGroup;
225
- //# sourceMappingURL=configGroup.js.map