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