generated from salesforcecli/plugin-template-sf
-
Notifications
You must be signed in to change notification settings - Fork 0
/
set.ts
112 lines (99 loc) · 4.61 KB
/
set.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/*
* Copyright (c) 2020, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import { parseVarArgs, Flags, loglevel, Ux, SfCommand } from '@salesforce/sf-plugins-core';
import { Config, Messages, Org, SfError, OrgConfigProperties } from '@salesforce/core';
import { CONFIG_HELP_SECTION, Msg, buildFailureMsg, calculateSuggestion, output } from '../../config.js';
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('@salesforce/plugin-settings', 'config.set');
export type SetOrUnsetConfigCommandResult = { successes: Msg[]; failures: Msg[] };
export class Set extends SfCommand<SetOrUnsetConfigCommandResult> {
public static readonly description = messages.getMessage('description');
public static readonly summary = messages.getMessage('summary');
public static readonly examples = messages.getMessages('examples');
public static readonly aliases = ['force:config:set'];
public static readonly deprecateAliases = true;
public static readonly strict = false;
public static readonly flags = {
loglevel,
global: Flags.boolean({
char: 'g',
summary: messages.getMessage('flags.global.summary'),
}),
};
public static configurationVariablesSection = CONFIG_HELP_SECTION;
public async run(): Promise<SetOrUnsetConfigCommandResult> {
const { args, argv, flags } = await this.parse(Set);
const config: Config = await loadConfig(flags.global);
const responses: SetOrUnsetConfigCommandResult = { successes: [], failures: [] };
if (!argv.length) throw messages.createError('error.ArgumentsRequired');
const parsed = parseVarArgs(args, argv as string[]);
for (const [name, value] of Object.entries(parsed)) {
let resolvedName = name;
try {
// this needs to be inside the try/catch because it can throw an error
resolvedName = this.configAggregator.getPropertyMeta(name)?.newKey ?? name;
if (!value) {
// Push a failure if users are try to unset a value with `set=`.
responses.failures.push(buildFailureMsg(name, messages.createError('error.ValueRequired'), value));
} else {
// core's builtin config validation requires synchronous functions but there's
// currently no way to validate an org synchronously. Therefore, we have to manually
// validate the org here and manually set the error message if it fails
// eslint-disable-next-line no-await-in-loop
if (isOrgKey(resolvedName) && value) await validateOrg(value);
config.set(resolvedName, value);
responses.successes.push({ name: resolvedName, value, success: true });
}
} catch (error) {
if (error instanceof Error && error.name.includes('UnknownConfigKeyError')) {
if (this.jsonEnabled()) {
responses.failures.push(buildFailureMsg(resolvedName, error, value));
} else {
const suggestion = calculateSuggestion(name);
// eslint-disable-next-line no-await-in-loop
const answer = (await this.confirm({ message: messages.getMessage('didYouMean', [suggestion]) })) ?? false;
if (answer && value) {
const key = Config.getPropertyConfigMeta(suggestion)?.key ?? suggestion;
config.set(key, value);
responses.successes.push({ name: key, value, success: true });
}
}
} else {
responses.failures.push(buildFailureMsg(resolvedName, error, value));
}
}
}
await config.write();
if (responses.failures.length) {
process.exitCode = 1;
}
output(new Ux({ jsonEnabled: this.jsonEnabled() }), [...responses.successes, ...responses.failures], 'set');
return responses;
}
}
const loadConfig = async (global: boolean): Promise<Config> => {
try {
const config = await Config.create(Config.getDefaultOptions(global));
await config.read();
return config;
} catch (error) {
if (error instanceof SfError) {
error.actions = error.actions ?? [];
error.actions.push('Run with --global to set for your entire workspace.');
}
throw error;
}
};
const isOrgKey = (name: string): boolean =>
[OrgConfigProperties.TARGET_DEV_HUB as string, OrgConfigProperties.TARGET_ORG as string].includes(name);
const validateOrg = async (value: string): Promise<void> => {
try {
await Org.create({ aliasOrUsername: value });
} catch {
throw new Error(`Invalid config value: org "${value}" is not authenticated.`);
}
};