@guanghechen/commander 4.7.4 → 4.7.6
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/CHANGELOG.md +16 -0
- package/README.md +46 -39
- package/lib/cjs/browser.cjs +451 -186
- package/lib/cjs/node.cjs +450 -185
- package/lib/esm/browser.mjs +451 -186
- package/lib/esm/node.mjs +450 -185
- package/lib/schema/preset.config.schema.json +152 -0
- package/lib/types/browser.d.ts +43 -7
- package/lib/types/node.d.ts +43 -7
- package/package.json +3 -3
- package/lib/cjs/index.cjs +0 -1237
- package/lib/esm/index.mjs +0 -1208
- package/lib/types/index.d.ts +0 -384
package/lib/cjs/browser.cjs
CHANGED
|
@@ -173,11 +173,9 @@ class CommanderError extends Error {
|
|
|
173
173
|
|
|
174
174
|
const LONG_OPTION_REGEX = /^--[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
175
175
|
const NEGATIVE_OPTION_REGEX = /^--no-[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
176
|
-
const
|
|
177
|
-
const
|
|
178
|
-
const
|
|
179
|
-
const DEFAULT_PRESET_OPTS_FILENAME = '.opt.local';
|
|
180
|
-
const DEFAULT_PRESET_ENVS_FILENAME = '.env.local';
|
|
176
|
+
const PRESET_FILE_FLAG = '--preset-file';
|
|
177
|
+
const PRESET_PROFILE_FLAG = '--preset-profile';
|
|
178
|
+
const PRESET_SELECTOR_DELIMITER = ':';
|
|
181
179
|
function kebabToCamelCase(str) {
|
|
182
180
|
return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
183
181
|
}
|
|
@@ -191,6 +189,8 @@ const DECIMAL_EXPONENT_REGEX = /^[eE][+-]?\d(?:_?\d)*$/;
|
|
|
191
189
|
const BINARY_LITERAL_REGEX = /^0[bB][01](?:_?[01])*$/;
|
|
192
190
|
const OCTAL_LITERAL_REGEX = /^0[oO][0-7](?:_?[0-7])*$/;
|
|
193
191
|
const HEX_LITERAL_REGEX = /^0[xX][0-9a-fA-F](?:_?[0-9a-fA-F])*$/;
|
|
192
|
+
const PRESET_PROFILE_NAME_REGEX = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
193
|
+
const PRESET_VARIANT_NAME_REGEX = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
194
194
|
function stripAnsi(value) {
|
|
195
195
|
return value.replace(ANSI_ESCAPE_REGEX, '');
|
|
196
196
|
}
|
|
@@ -715,8 +715,28 @@ class Command {
|
|
|
715
715
|
const desc = metadata.length > 0 ? `${arg.desc} ${metadata.join(' ')}` : arg.desc;
|
|
716
716
|
argumentsLines.push({ sig, desc });
|
|
717
717
|
}
|
|
718
|
+
const sortedOptions = [...allOptions].sort((a, b) => {
|
|
719
|
+
const optionRank = (option) => {
|
|
720
|
+
if (option.long === 'help') {
|
|
721
|
+
return 0;
|
|
722
|
+
}
|
|
723
|
+
if (option.long === 'version') {
|
|
724
|
+
return 1;
|
|
725
|
+
}
|
|
726
|
+
if (option.required === true) {
|
|
727
|
+
return 2;
|
|
728
|
+
}
|
|
729
|
+
return 3;
|
|
730
|
+
};
|
|
731
|
+
const rankA = optionRank(a);
|
|
732
|
+
const rankB = optionRank(b);
|
|
733
|
+
if (rankA !== rankB) {
|
|
734
|
+
return rankA - rankB;
|
|
735
|
+
}
|
|
736
|
+
return camelToKebabCase(a.long).localeCompare(camelToKebabCase(b.long));
|
|
737
|
+
});
|
|
718
738
|
const options = [];
|
|
719
|
-
for (const opt of
|
|
739
|
+
for (const opt of sortedOptions) {
|
|
720
740
|
const kebabLong = camelToKebabCase(opt.long);
|
|
721
741
|
let sig = opt.short ? `-${opt.short}, ` : ' ';
|
|
722
742
|
sig += `--${kebabLong}`;
|
|
@@ -734,21 +754,13 @@ class Command {
|
|
|
734
754
|
desc += ` [choices: ${opt.choices.map(choice => JSON.stringify(choice)).join(', ')}]`;
|
|
735
755
|
}
|
|
736
756
|
options.push({ sig, desc });
|
|
737
|
-
if (opt.type === 'boolean' &&
|
|
738
|
-
opt.args === 'none' &&
|
|
739
|
-
opt.long !== 'help' &&
|
|
740
|
-
opt.long !== 'version') {
|
|
741
|
-
options.push({
|
|
742
|
-
sig: ` --no-${kebabLong}`,
|
|
743
|
-
desc: `Negate --${kebabLong}`,
|
|
744
|
-
});
|
|
745
|
-
}
|
|
746
757
|
}
|
|
747
758
|
const commands = [];
|
|
748
759
|
if (this.#subcommandsList.length > 0) {
|
|
749
760
|
commands.push({ name: 'help', desc: 'Show help for a command' });
|
|
750
761
|
}
|
|
751
|
-
|
|
762
|
+
const sortedSubcommands = [...this.#subcommandsList].sort((a, b) => a.name.localeCompare(b.name));
|
|
763
|
+
for (const entry of sortedSubcommands) {
|
|
752
764
|
let name = entry.name;
|
|
753
765
|
if (entry.aliases.length > 0) {
|
|
754
766
|
name += `, ${entry.aliases.join(', ')}`;
|
|
@@ -1007,24 +1019,32 @@ class Command {
|
|
|
1007
1019
|
const separatorIndex = controlTailArgv.indexOf('--');
|
|
1008
1020
|
const beforeSeparator = separatorIndex === -1 ? controlTailArgv : controlTailArgv.slice(0, separatorIndex);
|
|
1009
1021
|
const afterSeparator = separatorIndex === -1 ? [] : controlTailArgv.slice(separatorIndex + 1);
|
|
1010
|
-
const
|
|
1011
|
-
const commandPreset = this.#resolveCommandPresetFromChain(ctx.chain);
|
|
1012
|
-
const presetRoot = await this.#resolveEffectivePresetRoot(rootScanResult.cliPresetRoots, commandPreset, commandPath);
|
|
1013
|
-
const fileScanResult = this.#scanPresetFileDirectives(rootScanResult.cleanArgv, commandPath);
|
|
1022
|
+
const profileScanResult = this.#scanPresetProfileDirectives(beforeSeparator, commandPath);
|
|
1014
1023
|
const cleanArgv = separatorIndex === -1
|
|
1015
|
-
?
|
|
1016
|
-
: [...
|
|
1017
|
-
const
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1024
|
+
? profileScanResult.cleanArgv
|
|
1025
|
+
: [...profileScanResult.cleanArgv, '--', ...afterSeparator];
|
|
1026
|
+
const commandChain = ctx.chain;
|
|
1027
|
+
const commandPresetFile = this.#resolveCommandPresetFileFromChain(commandChain);
|
|
1028
|
+
const effectivePresetFile = profileScanResult.presetFile ?? commandPresetFile;
|
|
1029
|
+
const commandPresetProfile = this.#resolveCommandPresetProfileFromChain(commandChain);
|
|
1030
|
+
const useCommandPresetProfile = profileScanResult.presetProfile === undefined && commandPresetProfile !== undefined;
|
|
1031
|
+
if (useCommandPresetProfile) {
|
|
1032
|
+
this.#assertPresetProfileSelectorValue(commandPresetProfile, 'command.preset.profile', commandPath);
|
|
1033
|
+
}
|
|
1034
|
+
const effectivePresetProfile = profileScanResult.presetProfile ?? commandPresetProfile;
|
|
1035
|
+
const effectivePresetProfileSourceName = profileScanResult.presetProfile !== undefined
|
|
1036
|
+
? PRESET_PROFILE_FLAG
|
|
1037
|
+
: commandPresetProfile !== undefined
|
|
1038
|
+
? 'command.preset.profile'
|
|
1039
|
+
: undefined;
|
|
1040
|
+
if (effectivePresetFile === undefined && useCommandPresetProfile) {
|
|
1041
|
+
throw new CommanderError('ConfigurationError', 'cannot use "command.preset.profile" without "command.preset.file" or "--preset-file"', commandPath);
|
|
1042
|
+
}
|
|
1043
|
+
const resolvedProfile = await this.#resolvePresetProfile({
|
|
1044
|
+
presetFile: effectivePresetFile,
|
|
1045
|
+
presetProfile: effectivePresetProfile,
|
|
1046
|
+
presetProfileSourceName: effectivePresetProfileSourceName,
|
|
1047
|
+
commandPath,
|
|
1028
1048
|
});
|
|
1029
1049
|
const userSources = {
|
|
1030
1050
|
cmds: [...ctx.sources.user.cmds],
|
|
@@ -1032,30 +1052,29 @@ class Command {
|
|
|
1032
1052
|
envs: { ...ctx.sources.user.envs },
|
|
1033
1053
|
};
|
|
1034
1054
|
const presetArgv = [];
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
}
|
|
1040
|
-
const tokens = this.#tokenizePresetOptions(content);
|
|
1041
|
-
this.#validatePresetOptionTokens(tokens, file.displayPath, commandPath);
|
|
1042
|
-
this.#assertPresetOptionFragments(tokens, file.displayPath, ctx.chain, optionPolicyMap);
|
|
1043
|
-
presetArgv.push(...tokens);
|
|
1055
|
+
if (resolvedProfile !== undefined && resolvedProfile.optsArgv.length > 0) {
|
|
1056
|
+
this.#validatePresetOptionTokens(resolvedProfile.optsArgv, resolvedProfile.optsSourceLabel, commandPath);
|
|
1057
|
+
this.#assertPresetOptionFragments(resolvedProfile.optsArgv, resolvedProfile.optsSourceLabel, commandChain, optionPolicyMap);
|
|
1058
|
+
presetArgv.push(...resolvedProfile.optsArgv);
|
|
1044
1059
|
}
|
|
1045
1060
|
const presetEnvs = {};
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
parsed = env.parse(content);
|
|
1061
|
+
if (resolvedProfile !== undefined) {
|
|
1062
|
+
if (resolvedProfile.profileEnvFileSource !== undefined) {
|
|
1063
|
+
const content = await this.#readPresetFile(resolvedProfile.profileEnvFileSource, commandPath);
|
|
1064
|
+
if (content !== undefined) {
|
|
1065
|
+
const parsed = this.#parsePresetEnvsContent(content, resolvedProfile.profileEnvFileSource, commandPath);
|
|
1066
|
+
Object.assign(presetEnvs, parsed);
|
|
1067
|
+
}
|
|
1054
1068
|
}
|
|
1055
|
-
|
|
1056
|
-
|
|
1069
|
+
Object.assign(presetEnvs, resolvedProfile.profileInlineEnvs);
|
|
1070
|
+
if (resolvedProfile.variantEnvFileSource !== undefined) {
|
|
1071
|
+
const content = await this.#readPresetFile(resolvedProfile.variantEnvFileSource, commandPath);
|
|
1072
|
+
if (content !== undefined) {
|
|
1073
|
+
const parsed = this.#parsePresetEnvsContent(content, resolvedProfile.variantEnvFileSource, commandPath);
|
|
1074
|
+
Object.assign(presetEnvs, parsed);
|
|
1075
|
+
}
|
|
1057
1076
|
}
|
|
1058
|
-
Object.assign(presetEnvs,
|
|
1077
|
+
Object.assign(presetEnvs, resolvedProfile.variantInlineEnvs);
|
|
1059
1078
|
}
|
|
1060
1079
|
const sources = {
|
|
1061
1080
|
user: userSources,
|
|
@@ -1068,200 +1087,446 @@ class Command {
|
|
|
1068
1087
|
const tailArgv = [...sources.preset.argv, ...sources.user.argv];
|
|
1069
1088
|
return { tailArgv, envs, sources };
|
|
1070
1089
|
}
|
|
1071
|
-
#
|
|
1090
|
+
#resolveCommandPresetFileFromChain(chain) {
|
|
1072
1091
|
for (let index = chain.length - 1; index >= 0; index -= 1) {
|
|
1073
1092
|
const preset = chain[index].#presetConfig;
|
|
1074
|
-
if (preset?.
|
|
1075
|
-
return preset;
|
|
1093
|
+
if (preset?.file !== undefined) {
|
|
1094
|
+
return preset.file;
|
|
1076
1095
|
}
|
|
1077
1096
|
}
|
|
1078
1097
|
return undefined;
|
|
1079
1098
|
}
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
const
|
|
1083
|
-
|
|
1099
|
+
#resolveCommandPresetProfileFromChain(chain) {
|
|
1100
|
+
for (let index = chain.length - 1; index >= 0; index -= 1) {
|
|
1101
|
+
const preset = chain[index].#presetConfig;
|
|
1102
|
+
if (preset?.profile !== undefined) {
|
|
1103
|
+
return preset.profile;
|
|
1104
|
+
}
|
|
1084
1105
|
}
|
|
1085
|
-
|
|
1086
|
-
|
|
1106
|
+
return undefined;
|
|
1107
|
+
}
|
|
1108
|
+
#resolvePresetFileAbsolutePath(filepath, baseDirectory) {
|
|
1109
|
+
if (this.#runtime.isAbsolute(filepath)) {
|
|
1110
|
+
return filepath;
|
|
1087
1111
|
}
|
|
1088
|
-
return
|
|
1112
|
+
return this.#runtime.resolve(baseDirectory ?? this.#runtime.cwd(), filepath);
|
|
1089
1113
|
}
|
|
1090
|
-
async #
|
|
1091
|
-
|
|
1092
|
-
|
|
1114
|
+
async #resolvePresetProfile(params) {
|
|
1115
|
+
const { presetFile, presetProfile, presetProfileSourceName, commandPath } = params;
|
|
1116
|
+
if (presetFile === undefined) {
|
|
1117
|
+
if (presetProfile !== undefined) {
|
|
1118
|
+
throw new CommanderError('ConfigurationError', `cannot use "${PRESET_PROFILE_FLAG}" without "${PRESET_FILE_FLAG}"`, commandPath);
|
|
1119
|
+
}
|
|
1120
|
+
return undefined;
|
|
1121
|
+
}
|
|
1122
|
+
const profileFile = {
|
|
1123
|
+
displayPath: presetFile,
|
|
1124
|
+
absolutePath: this.#resolvePresetFileAbsolutePath(presetFile),
|
|
1125
|
+
explicit: true,
|
|
1126
|
+
};
|
|
1127
|
+
const content = await this.#readPresetFile(profileFile, commandPath);
|
|
1128
|
+
if (content === undefined) {
|
|
1129
|
+
return undefined;
|
|
1093
1130
|
}
|
|
1094
|
-
|
|
1131
|
+
const manifest = this.#parsePresetProfileManifest(content, profileFile.displayPath, commandPath);
|
|
1132
|
+
const resolvedProfileSelector = presetProfile ?? manifest.defaults?.profile;
|
|
1133
|
+
if (resolvedProfileSelector === undefined) {
|
|
1134
|
+
throw new CommanderError('ConfigurationError', `missing profile for preset file "${profileFile.displayPath}": provide "${PRESET_PROFILE_FLAG}" or defaults.profile`, commandPath);
|
|
1135
|
+
}
|
|
1136
|
+
const { profileName: resolvedProfileName, variantName: explicitVariantName } = this.#parsePresetProfileSelector(resolvedProfileSelector, presetProfileSourceName ?? 'defaults.profile', commandPath);
|
|
1137
|
+
const profile = manifest.profiles[resolvedProfileName];
|
|
1138
|
+
if (profile === undefined) {
|
|
1139
|
+
throw new CommanderError('ConfigurationError', `unknown preset profile "${resolvedProfileName}" in "${profileFile.displayPath}"`, commandPath);
|
|
1140
|
+
}
|
|
1141
|
+
const selectedVariantName = explicitVariantName ?? profile.defaultVariant;
|
|
1142
|
+
let selectedVariant;
|
|
1143
|
+
if (selectedVariantName !== undefined) {
|
|
1144
|
+
const variants = profile.variants ?? {};
|
|
1145
|
+
selectedVariant = variants[selectedVariantName];
|
|
1146
|
+
if (selectedVariant === undefined) {
|
|
1147
|
+
const availableVariants = Object.keys(variants);
|
|
1148
|
+
const availableText = availableVariants.length > 0 ? availableVariants.join(', ') : '<none>';
|
|
1149
|
+
throw new CommanderError('ConfigurationError', `unknown preset variant "${selectedVariantName}" for profile "${resolvedProfileName}" in "${profileFile.displayPath}" (available: ${availableText})`, commandPath);
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
const profileSelectorLabel = selectedVariantName === undefined
|
|
1153
|
+
? resolvedProfileName
|
|
1154
|
+
: `${resolvedProfileName}${PRESET_SELECTOR_DELIMITER}${selectedVariantName}`;
|
|
1155
|
+
const mergedOpts = { ...(profile.opts ?? {}), ...(selectedVariant?.opts ?? {}) };
|
|
1156
|
+
const optsArgv = this.#buildPresetArgvFromProfileOptions(mergedOpts, profileSelectorLabel, commandPath);
|
|
1157
|
+
const profileInlineEnvs = this.#normalizePresetProfileEnvs(profile.envs, profileSelectorLabel, commandPath);
|
|
1158
|
+
const variantInlineEnvs = this.#normalizePresetProfileEnvs(selectedVariant?.envs, profileSelectorLabel, commandPath);
|
|
1159
|
+
const profileDir = this.#runtime.resolve(profileFile.absolutePath, '..');
|
|
1160
|
+
let profileEnvFileSource;
|
|
1161
|
+
if (profile.envFile !== undefined) {
|
|
1162
|
+
profileEnvFileSource = {
|
|
1163
|
+
displayPath: profile.envFile,
|
|
1164
|
+
absolutePath: this.#resolvePresetFileAbsolutePath(profile.envFile, profileDir),
|
|
1165
|
+
explicit: true,
|
|
1166
|
+
};
|
|
1167
|
+
}
|
|
1168
|
+
let variantEnvFileSource;
|
|
1169
|
+
if (selectedVariant?.envFile !== undefined) {
|
|
1170
|
+
variantEnvFileSource = {
|
|
1171
|
+
displayPath: selectedVariant.envFile,
|
|
1172
|
+
absolutePath: this.#resolvePresetFileAbsolutePath(selectedVariant.envFile, profileDir),
|
|
1173
|
+
explicit: true,
|
|
1174
|
+
};
|
|
1175
|
+
}
|
|
1176
|
+
return {
|
|
1177
|
+
profileName: resolvedProfileName,
|
|
1178
|
+
variantName: selectedVariantName,
|
|
1179
|
+
optsArgv,
|
|
1180
|
+
optsSourceLabel: `${profileFile.displayPath}#${profileSelectorLabel}.opts`,
|
|
1181
|
+
profileInlineEnvs,
|
|
1182
|
+
variantInlineEnvs,
|
|
1183
|
+
profileEnvFileSource,
|
|
1184
|
+
variantEnvFileSource,
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
#parsePresetProfileManifest(content, filepath, commandPath) {
|
|
1188
|
+
let parsed;
|
|
1095
1189
|
try {
|
|
1096
|
-
|
|
1190
|
+
parsed = JSON.parse(content);
|
|
1097
1191
|
}
|
|
1098
1192
|
catch (error) {
|
|
1099
|
-
throw new CommanderError('ConfigurationError', `
|
|
1193
|
+
throw new CommanderError('ConfigurationError', `failed to parse preset file "${filepath}": ${error.message}`, commandPath);
|
|
1100
1194
|
}
|
|
1101
|
-
if (
|
|
1102
|
-
throw new CommanderError('ConfigurationError', `invalid preset
|
|
1195
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
1196
|
+
throw new CommanderError('ConfigurationError', `invalid preset file "${filepath}": root must be an object`, commandPath);
|
|
1103
1197
|
}
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
if (filepath === undefined) {
|
|
1108
|
-
return undefined;
|
|
1198
|
+
const root = parsed;
|
|
1199
|
+
if (root.version !== 1) {
|
|
1200
|
+
throw new CommanderError('ConfigurationError', `invalid preset file "${filepath}": "version" must be 1`, commandPath);
|
|
1109
1201
|
}
|
|
1110
|
-
|
|
1111
|
-
|
|
1202
|
+
let defaults;
|
|
1203
|
+
const rawDefaults = root.defaults;
|
|
1204
|
+
if (rawDefaults !== undefined) {
|
|
1205
|
+
if (typeof rawDefaults !== 'object' || rawDefaults === null || Array.isArray(rawDefaults)) {
|
|
1206
|
+
throw new CommanderError('ConfigurationError', `invalid preset file "${filepath}": "defaults" must be an object`, commandPath);
|
|
1207
|
+
}
|
|
1208
|
+
const defaultsRecord = rawDefaults;
|
|
1209
|
+
if (defaultsRecord.profile !== undefined) {
|
|
1210
|
+
if (typeof defaultsRecord.profile !== 'string') {
|
|
1211
|
+
throw new CommanderError('ConfigurationError', `invalid preset file "${filepath}": "defaults.profile" must be a string`, commandPath);
|
|
1212
|
+
}
|
|
1213
|
+
this.#assertPresetProfileSelectorValue(defaultsRecord.profile, 'defaults.profile', commandPath);
|
|
1214
|
+
}
|
|
1215
|
+
defaults = { profile: defaultsRecord.profile };
|
|
1216
|
+
}
|
|
1217
|
+
const rawProfiles = root.profiles;
|
|
1218
|
+
if (typeof rawProfiles !== 'object' || rawProfiles === null || Array.isArray(rawProfiles)) {
|
|
1219
|
+
throw new CommanderError('ConfigurationError', `invalid preset file "${filepath}": "profiles" must be an object`, commandPath);
|
|
1112
1220
|
}
|
|
1113
|
-
|
|
1221
|
+
const profilesRecord = {};
|
|
1222
|
+
for (const [profileName, profileValue] of Object.entries(rawProfiles)) {
|
|
1223
|
+
this.#assertPresetProfileName(profileName, `profiles["${profileName}"]`, commandPath);
|
|
1224
|
+
if (typeof profileValue !== 'object' ||
|
|
1225
|
+
profileValue === null ||
|
|
1226
|
+
Array.isArray(profileValue)) {
|
|
1227
|
+
throw new CommanderError('ConfigurationError', `invalid preset file "${filepath}": profile "${profileName}" must be an object`, commandPath);
|
|
1228
|
+
}
|
|
1229
|
+
profilesRecord[profileName] = this.#parsePresetProfileItem(profileValue, profileName, filepath, commandPath);
|
|
1230
|
+
}
|
|
1231
|
+
return {
|
|
1232
|
+
version: 1,
|
|
1233
|
+
defaults,
|
|
1234
|
+
profiles: profilesRecord,
|
|
1235
|
+
};
|
|
1114
1236
|
}
|
|
1115
|
-
#
|
|
1116
|
-
const
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
}));
|
|
1237
|
+
#parsePresetProfileItem(profileValue, profileName, filepath, commandPath) {
|
|
1238
|
+
const labelPrefix = `invalid preset file "${filepath}": profile "${profileName}"`;
|
|
1239
|
+
const envFile = profileValue.envFile;
|
|
1240
|
+
if (envFile !== undefined) {
|
|
1241
|
+
if (typeof envFile !== 'string') {
|
|
1242
|
+
throw new CommanderError('ConfigurationError', `${labelPrefix}.envFile must be a string`, commandPath);
|
|
1243
|
+
}
|
|
1123
1244
|
}
|
|
1124
|
-
|
|
1125
|
-
|
|
1245
|
+
const rawEnvs = profileValue.envs;
|
|
1246
|
+
let envs;
|
|
1247
|
+
if (rawEnvs !== undefined) {
|
|
1248
|
+
if (typeof rawEnvs !== 'object' || rawEnvs === null || Array.isArray(rawEnvs)) {
|
|
1249
|
+
throw new CommanderError('ConfigurationError', `${labelPrefix}.envs must be an object`, commandPath);
|
|
1250
|
+
}
|
|
1251
|
+
envs = {};
|
|
1252
|
+
for (const [key, value] of Object.entries(rawEnvs)) {
|
|
1253
|
+
if (typeof value !== 'string') {
|
|
1254
|
+
throw new CommanderError('ConfigurationError', `${labelPrefix}.envs["${key}"] must be a string`, commandPath);
|
|
1255
|
+
}
|
|
1256
|
+
envs[key] = value;
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
const rawOpts = profileValue.opts;
|
|
1260
|
+
let opts;
|
|
1261
|
+
if (rawOpts !== undefined) {
|
|
1262
|
+
if (typeof rawOpts !== 'object' || rawOpts === null || Array.isArray(rawOpts)) {
|
|
1263
|
+
throw new CommanderError('ConfigurationError', `${labelPrefix}.opts must be an object`, commandPath);
|
|
1264
|
+
}
|
|
1265
|
+
opts = {};
|
|
1266
|
+
for (const [key, value] of Object.entries(rawOpts)) {
|
|
1267
|
+
opts[key] = this.#parsePresetProfileOptionValue(value, `${labelPrefix}.opts["${key}"]`, commandPath);
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
const rawDefaultVariant = profileValue.defaultVariant;
|
|
1271
|
+
let defaultVariant;
|
|
1272
|
+
if (rawDefaultVariant !== undefined) {
|
|
1273
|
+
if (typeof rawDefaultVariant !== 'string') {
|
|
1274
|
+
throw new CommanderError('ConfigurationError', `${labelPrefix}.defaultVariant must be a string`, commandPath);
|
|
1275
|
+
}
|
|
1276
|
+
this.#assertPresetVariantName(rawDefaultVariant, `${labelPrefix}.defaultVariant`, commandPath);
|
|
1277
|
+
defaultVariant = rawDefaultVariant;
|
|
1278
|
+
}
|
|
1279
|
+
const rawVariants = profileValue.variants;
|
|
1280
|
+
let variants;
|
|
1281
|
+
if (rawVariants !== undefined) {
|
|
1282
|
+
if (typeof rawVariants !== 'object' || rawVariants === null || Array.isArray(rawVariants)) {
|
|
1283
|
+
throw new CommanderError('ConfigurationError', `${labelPrefix}.variants must be an object`, commandPath);
|
|
1284
|
+
}
|
|
1285
|
+
variants = {};
|
|
1286
|
+
for (const [variantName, variantValue] of Object.entries(rawVariants)) {
|
|
1287
|
+
this.#assertPresetVariantName(variantName, `${labelPrefix}.variants["${variantName}"]`, commandPath);
|
|
1288
|
+
if (typeof variantValue !== 'object' ||
|
|
1289
|
+
variantValue === null ||
|
|
1290
|
+
Array.isArray(variantValue)) {
|
|
1291
|
+
throw new CommanderError('ConfigurationError', `${labelPrefix}.variants["${variantName}"] must be an object`, commandPath);
|
|
1292
|
+
}
|
|
1293
|
+
variants[variantName] = this.#parsePresetProfileVariantItem(variantValue, `${labelPrefix}.variants["${variantName}"]`, commandPath);
|
|
1294
|
+
}
|
|
1126
1295
|
}
|
|
1127
|
-
if (
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
{
|
|
1139
|
-
displayPath: absolutePath,
|
|
1140
|
-
absolutePath,
|
|
1141
|
-
explicit: false,
|
|
1142
|
-
},
|
|
1143
|
-
];
|
|
1296
|
+
if (defaultVariant !== undefined &&
|
|
1297
|
+
(variants === undefined || variants[defaultVariant] === undefined)) {
|
|
1298
|
+
throw new CommanderError('ConfigurationError', `${labelPrefix}.defaultVariant "${defaultVariant}" is not found in variants`, commandPath);
|
|
1299
|
+
}
|
|
1300
|
+
return {
|
|
1301
|
+
envFile,
|
|
1302
|
+
envs,
|
|
1303
|
+
opts,
|
|
1304
|
+
defaultVariant,
|
|
1305
|
+
variants,
|
|
1306
|
+
};
|
|
1144
1307
|
}
|
|
1145
|
-
#
|
|
1146
|
-
|
|
1147
|
-
|
|
1308
|
+
#parsePresetProfileVariantItem(variantValue, labelPrefix, commandPath) {
|
|
1309
|
+
const envFile = variantValue.envFile;
|
|
1310
|
+
if (envFile !== undefined) {
|
|
1311
|
+
if (typeof envFile !== 'string') {
|
|
1312
|
+
throw new CommanderError('ConfigurationError', `${labelPrefix}.envFile must be a string`, commandPath);
|
|
1313
|
+
}
|
|
1148
1314
|
}
|
|
1149
|
-
|
|
1150
|
-
|
|
1315
|
+
const rawEnvs = variantValue.envs;
|
|
1316
|
+
let envs;
|
|
1317
|
+
if (rawEnvs !== undefined) {
|
|
1318
|
+
if (typeof rawEnvs !== 'object' || rawEnvs === null || Array.isArray(rawEnvs)) {
|
|
1319
|
+
throw new CommanderError('ConfigurationError', `${labelPrefix}.envs must be an object`, commandPath);
|
|
1320
|
+
}
|
|
1321
|
+
envs = {};
|
|
1322
|
+
for (const [key, value] of Object.entries(rawEnvs)) {
|
|
1323
|
+
if (typeof value !== 'string') {
|
|
1324
|
+
throw new CommanderError('ConfigurationError', `${labelPrefix}.envs["${key}"] must be a string`, commandPath);
|
|
1325
|
+
}
|
|
1326
|
+
envs[key] = value;
|
|
1327
|
+
}
|
|
1151
1328
|
}
|
|
1152
|
-
|
|
1329
|
+
const rawOpts = variantValue.opts;
|
|
1330
|
+
let opts;
|
|
1331
|
+
if (rawOpts !== undefined) {
|
|
1332
|
+
if (typeof rawOpts !== 'object' || rawOpts === null || Array.isArray(rawOpts)) {
|
|
1333
|
+
throw new CommanderError('ConfigurationError', `${labelPrefix}.opts must be an object`, commandPath);
|
|
1334
|
+
}
|
|
1335
|
+
opts = {};
|
|
1336
|
+
for (const [key, value] of Object.entries(rawOpts)) {
|
|
1337
|
+
opts[key] = this.#parsePresetProfileOptionValue(value, `${labelPrefix}.opts["${key}"]`, commandPath);
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
return {
|
|
1341
|
+
envFile,
|
|
1342
|
+
envs,
|
|
1343
|
+
opts,
|
|
1344
|
+
};
|
|
1153
1345
|
}
|
|
1154
|
-
#
|
|
1155
|
-
if (
|
|
1156
|
-
return;
|
|
1346
|
+
#parsePresetProfileOptionValue(value, valueLabel, commandPath) {
|
|
1347
|
+
if (typeof value === 'boolean' || typeof value === 'string') {
|
|
1348
|
+
return value;
|
|
1157
1349
|
}
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
void restArgs;
|
|
1162
|
-
const { argTokens } = this.#resolve(chain, optionTokens, optionPolicyMap);
|
|
1163
|
-
if (argTokens.length > 0) {
|
|
1164
|
-
throw new CommanderError('ConfigurationError', `invalid preset options in "${filepath}": token "${argTokens[0].original}" cannot be resolved as an option fragment`, commandPath);
|
|
1350
|
+
if (typeof value === 'number') {
|
|
1351
|
+
if (!Number.isFinite(value)) {
|
|
1352
|
+
throw new CommanderError('ConfigurationError', `${valueLabel} must be a finite number`, commandPath);
|
|
1165
1353
|
}
|
|
1354
|
+
return value;
|
|
1166
1355
|
}
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
if (
|
|
1170
|
-
|
|
1356
|
+
if (Array.isArray(value)) {
|
|
1357
|
+
return value.map((item, index) => {
|
|
1358
|
+
if (typeof item === 'string') {
|
|
1359
|
+
return item;
|
|
1171
1360
|
}
|
|
1172
|
-
|
|
1361
|
+
if (typeof item === 'number' && Number.isFinite(item)) {
|
|
1362
|
+
return item;
|
|
1363
|
+
}
|
|
1364
|
+
throw new CommanderError('ConfigurationError', `${valueLabel}[${index}] must be a string or finite number`, commandPath);
|
|
1365
|
+
});
|
|
1366
|
+
}
|
|
1367
|
+
throw new CommanderError('ConfigurationError', `${valueLabel} must be boolean|string|number|(string|number)[]`, commandPath);
|
|
1368
|
+
}
|
|
1369
|
+
#normalizePresetProfileEnvs(envs, _profileName, _commandPath) {
|
|
1370
|
+
return envs === undefined ? {} : { ...envs };
|
|
1371
|
+
}
|
|
1372
|
+
#normalizePresetOptionName(rawName, profileName, commandPath) {
|
|
1373
|
+
const value = rawName.trim();
|
|
1374
|
+
if (value.length === 0) {
|
|
1375
|
+
throw new CommanderError('ConfigurationError', `invalid option name "" in preset profile "${profileName}"`, commandPath);
|
|
1376
|
+
}
|
|
1377
|
+
const stripped = value.startsWith('--') ? value.slice(2) : value;
|
|
1378
|
+
if (stripped.length === 0) {
|
|
1379
|
+
throw new CommanderError('ConfigurationError', `invalid option name "${rawName}" in preset profile "${profileName}"`, commandPath);
|
|
1380
|
+
}
|
|
1381
|
+
if (stripped.includes('-')) {
|
|
1382
|
+
const lowered = stripped.toLowerCase();
|
|
1383
|
+
if (!/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/.test(lowered)) {
|
|
1384
|
+
throw new CommanderError('ConfigurationError', `invalid option name "${rawName}" in preset profile "${profileName}"`, commandPath);
|
|
1173
1385
|
}
|
|
1174
|
-
|
|
1386
|
+
return kebabToCamelCase(lowered);
|
|
1387
|
+
}
|
|
1388
|
+
if (!/^[a-z][a-zA-Z0-9]*$/.test(stripped)) {
|
|
1389
|
+
throw new CommanderError('ConfigurationError', `invalid option name "${rawName}" in preset profile "${profileName}"`, commandPath);
|
|
1175
1390
|
}
|
|
1391
|
+
return stripped;
|
|
1176
1392
|
}
|
|
1177
|
-
#
|
|
1178
|
-
const
|
|
1179
|
-
const
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
const
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
throw new CommanderError('ConfigurationError', `missing value for "${PRESET_ROOT_FLAG}"`, commandPath);
|
|
1187
|
-
}
|
|
1188
|
-
cliPresetRoots.push(value);
|
|
1189
|
-
index += 2;
|
|
1393
|
+
#buildPresetArgvFromProfileOptions(opts, profileName, commandPath) {
|
|
1394
|
+
const argv = [];
|
|
1395
|
+
for (const [rawName, rawValue] of Object.entries(opts)) {
|
|
1396
|
+
const optionName = this.#normalizePresetOptionName(rawName, profileName, commandPath);
|
|
1397
|
+
const kebabName = camelToKebabCase(optionName);
|
|
1398
|
+
const positiveFlag = `--${kebabName}`;
|
|
1399
|
+
const negativeFlag = `--no-${kebabName}`;
|
|
1400
|
+
if (typeof rawValue === 'boolean') {
|
|
1401
|
+
argv.push(rawValue ? positiveFlag : negativeFlag);
|
|
1190
1402
|
continue;
|
|
1191
1403
|
}
|
|
1192
|
-
if (
|
|
1193
|
-
|
|
1194
|
-
if (value.length === 0) {
|
|
1195
|
-
throw new CommanderError('ConfigurationError', `missing value for "${PRESET_ROOT_FLAG}"`, commandPath);
|
|
1196
|
-
}
|
|
1197
|
-
cliPresetRoots.push(value);
|
|
1198
|
-
index += 1;
|
|
1404
|
+
if (typeof rawValue === 'string') {
|
|
1405
|
+
argv.push(positiveFlag, rawValue);
|
|
1199
1406
|
continue;
|
|
1200
1407
|
}
|
|
1201
|
-
|
|
1202
|
-
|
|
1408
|
+
if (typeof rawValue === 'number') {
|
|
1409
|
+
argv.push(positiveFlag, String(rawValue));
|
|
1410
|
+
continue;
|
|
1411
|
+
}
|
|
1412
|
+
if (rawValue.length === 0) {
|
|
1413
|
+
continue;
|
|
1414
|
+
}
|
|
1415
|
+
argv.push(positiveFlag, ...rawValue.map(value => String(value)));
|
|
1203
1416
|
}
|
|
1204
|
-
return
|
|
1417
|
+
return argv;
|
|
1205
1418
|
}
|
|
1206
|
-
#
|
|
1419
|
+
#scanPresetProfileDirectives(argv, commandPath) {
|
|
1207
1420
|
const cleanArgv = [];
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
const
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
cliPresetOptsFiles.push(value);
|
|
1421
|
+
let presetFile;
|
|
1422
|
+
let presetProfile;
|
|
1423
|
+
const assignDirective = (flag, value) => {
|
|
1424
|
+
if (flag === PRESET_FILE_FLAG) {
|
|
1425
|
+
presetFile = value;
|
|
1214
1426
|
}
|
|
1215
1427
|
else {
|
|
1216
|
-
|
|
1428
|
+
this.#assertPresetProfileSelectorValue(value, PRESET_PROFILE_FLAG, commandPath);
|
|
1429
|
+
presetProfile = value;
|
|
1217
1430
|
}
|
|
1218
1431
|
};
|
|
1219
1432
|
let index = 0;
|
|
1220
1433
|
while (index < argv.length) {
|
|
1221
1434
|
const token = argv[index];
|
|
1222
|
-
if (token ===
|
|
1435
|
+
if (token === PRESET_FILE_FLAG || token === PRESET_PROFILE_FLAG) {
|
|
1223
1436
|
const value = argv[index + 1];
|
|
1224
1437
|
if (value === undefined || value.length === 0) {
|
|
1225
1438
|
throw new CommanderError('ConfigurationError', `missing value for "${token}"`, commandPath);
|
|
1226
1439
|
}
|
|
1227
|
-
|
|
1440
|
+
assignDirective(token, value);
|
|
1228
1441
|
index += 2;
|
|
1229
1442
|
continue;
|
|
1230
1443
|
}
|
|
1231
|
-
if (token.startsWith(`${
|
|
1232
|
-
const value = token.slice(
|
|
1444
|
+
if (token.startsWith(`${PRESET_FILE_FLAG}=`)) {
|
|
1445
|
+
const value = token.slice(PRESET_FILE_FLAG.length + 1);
|
|
1233
1446
|
if (value.length === 0) {
|
|
1234
|
-
throw new CommanderError('ConfigurationError', `missing value for "${
|
|
1447
|
+
throw new CommanderError('ConfigurationError', `missing value for "${PRESET_FILE_FLAG}"`, commandPath);
|
|
1235
1448
|
}
|
|
1236
|
-
|
|
1449
|
+
assignDirective(PRESET_FILE_FLAG, value);
|
|
1237
1450
|
index += 1;
|
|
1238
1451
|
continue;
|
|
1239
1452
|
}
|
|
1240
|
-
if (token.startsWith(`${
|
|
1241
|
-
const value = token.slice(
|
|
1453
|
+
if (token.startsWith(`${PRESET_PROFILE_FLAG}=`)) {
|
|
1454
|
+
const value = token.slice(PRESET_PROFILE_FLAG.length + 1);
|
|
1242
1455
|
if (value.length === 0) {
|
|
1243
|
-
throw new CommanderError('ConfigurationError', `missing value for "${
|
|
1456
|
+
throw new CommanderError('ConfigurationError', `missing value for "${PRESET_PROFILE_FLAG}"`, commandPath);
|
|
1244
1457
|
}
|
|
1245
|
-
|
|
1458
|
+
assignDirective(PRESET_PROFILE_FLAG, value);
|
|
1246
1459
|
index += 1;
|
|
1247
1460
|
continue;
|
|
1248
1461
|
}
|
|
1249
1462
|
cleanArgv.push(token);
|
|
1250
1463
|
index += 1;
|
|
1251
1464
|
}
|
|
1252
|
-
return { cleanArgv,
|
|
1465
|
+
return { cleanArgv, presetFile, presetProfile };
|
|
1466
|
+
}
|
|
1467
|
+
#assertPresetOptionFragments(tokens, filepath, chain, optionPolicyMap) {
|
|
1468
|
+
if (tokens.length === 0) {
|
|
1469
|
+
return;
|
|
1470
|
+
}
|
|
1471
|
+
const commandPath = chain[chain.length - 1].#getCommandPath();
|
|
1472
|
+
try {
|
|
1473
|
+
const { optionTokens, restArgs } = tokenize(tokens, commandPath);
|
|
1474
|
+
void restArgs;
|
|
1475
|
+
const { argTokens } = this.#resolve(chain, optionTokens, optionPolicyMap);
|
|
1476
|
+
if (argTokens.length > 0) {
|
|
1477
|
+
throw new CommanderError('ConfigurationError', `invalid preset options in "${filepath}": token "${argTokens[0].original}" cannot be resolved as an option fragment`, commandPath);
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
catch (error) {
|
|
1481
|
+
if (error instanceof CommanderError) {
|
|
1482
|
+
if (error.kind === 'ConfigurationError') {
|
|
1483
|
+
throw error;
|
|
1484
|
+
}
|
|
1485
|
+
throw new CommanderError('ConfigurationError', `invalid preset options in "${filepath}": ${error.message}`, commandPath);
|
|
1486
|
+
}
|
|
1487
|
+
throw error;
|
|
1488
|
+
}
|
|
1253
1489
|
}
|
|
1254
|
-
#
|
|
1255
|
-
|
|
1490
|
+
#assertPresetProfileSelectorValue(selector, sourceName, commandPath) {
|
|
1491
|
+
void this.#parsePresetProfileSelector(selector, sourceName, commandPath);
|
|
1256
1492
|
}
|
|
1257
|
-
#
|
|
1258
|
-
|
|
1493
|
+
#parsePresetProfileSelector(selector, sourceName, commandPath) {
|
|
1494
|
+
const normalizedSelector = selector.trim();
|
|
1495
|
+
const separatorIndex = normalizedSelector.indexOf(PRESET_SELECTOR_DELIMITER);
|
|
1496
|
+
if (separatorIndex < 0) {
|
|
1497
|
+
this.#assertPresetProfileName(normalizedSelector, sourceName, commandPath);
|
|
1498
|
+
return { profileName: normalizedSelector };
|
|
1499
|
+
}
|
|
1500
|
+
if (normalizedSelector.indexOf(PRESET_SELECTOR_DELIMITER, separatorIndex + 1) >= 0) {
|
|
1501
|
+
throw new CommanderError('ConfigurationError', `invalid value for "${sourceName}": "${selector}" (must be "<profile>" or "<profile>:<variant>")`, commandPath);
|
|
1502
|
+
}
|
|
1503
|
+
const profileName = normalizedSelector.slice(0, separatorIndex);
|
|
1504
|
+
const variantName = normalizedSelector.slice(separatorIndex + 1);
|
|
1505
|
+
if (profileName.length === 0 || variantName.length === 0) {
|
|
1506
|
+
throw new CommanderError('ConfigurationError', `invalid value for "${sourceName}": "${selector}" (must be "<profile>" or "<profile>:<variant>")`, commandPath);
|
|
1507
|
+
}
|
|
1508
|
+
this.#assertPresetProfileName(profileName, sourceName, commandPath);
|
|
1509
|
+
this.#assertPresetVariantName(variantName, sourceName, commandPath);
|
|
1510
|
+
return { profileName, variantName };
|
|
1511
|
+
}
|
|
1512
|
+
#assertPresetProfileName(profileName, sourceName, commandPath) {
|
|
1513
|
+
if (PRESET_PROFILE_NAME_REGEX.test(profileName)) {
|
|
1259
1514
|
return;
|
|
1260
1515
|
}
|
|
1261
|
-
throw new CommanderError('ConfigurationError', `invalid
|
|
1516
|
+
throw new CommanderError('ConfigurationError', `invalid profile name for "${sourceName}": "${profileName}" (must match ${PRESET_PROFILE_NAME_REGEX.source})`, commandPath);
|
|
1517
|
+
}
|
|
1518
|
+
#assertPresetVariantName(variantName, sourceName, commandPath) {
|
|
1519
|
+
if (PRESET_VARIANT_NAME_REGEX.test(variantName)) {
|
|
1520
|
+
return;
|
|
1521
|
+
}
|
|
1522
|
+
throw new CommanderError('ConfigurationError', `invalid variant name for "${sourceName}": "${variantName}" (must match ${PRESET_VARIANT_NAME_REGEX.source})`, commandPath);
|
|
1262
1523
|
}
|
|
1263
1524
|
async #readPresetFile(file, commandPath) {
|
|
1264
1525
|
try {
|
|
1526
|
+
const stats = await this.#runtime.stat(file.absolutePath);
|
|
1527
|
+
if (stats.isDirectory()) {
|
|
1528
|
+
throw new Error('target is a directory');
|
|
1529
|
+
}
|
|
1265
1530
|
return await this.#runtime.readFile(file.absolutePath);
|
|
1266
1531
|
}
|
|
1267
1532
|
catch (error) {
|
|
@@ -1272,11 +1537,13 @@ class Command {
|
|
|
1272
1537
|
throw new CommanderError('ConfigurationError', `failed to read preset file "${file.displayPath}": ${error.message}`, commandPath);
|
|
1273
1538
|
}
|
|
1274
1539
|
}
|
|
1275
|
-
#
|
|
1276
|
-
|
|
1277
|
-
.
|
|
1278
|
-
|
|
1279
|
-
|
|
1540
|
+
#parsePresetEnvsContent(content, file, commandPath) {
|
|
1541
|
+
try {
|
|
1542
|
+
return env.parse(content);
|
|
1543
|
+
}
|
|
1544
|
+
catch (error) {
|
|
1545
|
+
throw new CommanderError('ConfigurationError', `failed to parse preset env file "${file.displayPath}": ${error.message}`, commandPath);
|
|
1546
|
+
}
|
|
1280
1547
|
}
|
|
1281
1548
|
#validatePresetOptionTokens(tokens, filepath, commandPath) {
|
|
1282
1549
|
if (tokens.length === 0) {
|
|
@@ -1292,12 +1559,10 @@ class Command {
|
|
|
1292
1559
|
if (token === 'help' || token === '--help' || token === '--version') {
|
|
1293
1560
|
throw new CommanderError('ConfigurationError', `invalid preset options in "${filepath}": control token "${token}" is not allowed`, commandPath);
|
|
1294
1561
|
}
|
|
1295
|
-
if (token ===
|
|
1296
|
-
token.startsWith(`${
|
|
1297
|
-
token ===
|
|
1298
|
-
token.startsWith(`${
|
|
1299
|
-
token === PRESET_ENVS_FLAG ||
|
|
1300
|
-
token.startsWith(`${PRESET_ENVS_FLAG}=`)) {
|
|
1562
|
+
if (token === PRESET_FILE_FLAG ||
|
|
1563
|
+
token.startsWith(`${PRESET_FILE_FLAG}=`) ||
|
|
1564
|
+
token === PRESET_PROFILE_FLAG ||
|
|
1565
|
+
token.startsWith(`${PRESET_PROFILE_FLAG}=`)) {
|
|
1301
1566
|
throw new CommanderError('ConfigurationError', `invalid preset options in "${filepath}": preset directive "${token}" is not allowed`, commandPath);
|
|
1302
1567
|
}
|
|
1303
1568
|
}
|