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