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