123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- import process from 'node:process';
- import { decamelizeFlagKey } from './utils.js';
- const validateFlags = (flags, options) => {
- for (const [flagKey, flagValue] of Object.entries(options.flags)) {
- if (flagKey !== '--' && !flagValue.isMultiple && Array.isArray(flags[flagKey])) {
- throw new Error(`The flag --${flagKey} can only be set once.`);
- }
- }
- };
- const validateChoicesByFlag = (flagKey, flagValue, receivedInput) => {
- const {choices, isRequired} = flagValue;
- if (!choices) {
- return;
- }
- const valueMustBeOneOf = `Value must be one of: [\`${choices.join('`, `')}\`]`;
- if (!receivedInput) {
- if (isRequired) {
- return `Flag \`${decamelizeFlagKey(flagKey)}\` has no value. ${valueMustBeOneOf}`;
- }
- return;
- }
- if (Array.isArray(receivedInput)) {
- const unknownValues = receivedInput.filter(index => !choices.includes(index));
- if (unknownValues.length > 0) {
- const valuesText = unknownValues.length > 1 ? 'values' : 'value';
- return `Unknown ${valuesText} for flag \`${decamelizeFlagKey(flagKey)}\`: \`${unknownValues.join('`, `')}\`. ${valueMustBeOneOf}`;
- }
- } else if (!choices.includes(receivedInput)) {
- return `Unknown value for flag \`${decamelizeFlagKey(flagKey)}\`: \`${receivedInput}\`. ${valueMustBeOneOf}`;
- }
- };
- const validateChoices = (flags, receivedFlags) => {
- const errors = [];
- for (const [flagKey, flagValue] of Object.entries(flags)) {
- const receivedInput = receivedFlags[flagKey];
- const errorMessage = validateChoicesByFlag(flagKey, flagValue, receivedInput);
- if (errorMessage) {
- errors.push(errorMessage);
- }
- }
- if (errors.length > 0) {
- throw new Error(`${errors.join('\n')}`);
- }
- };
- const validate = (flags, options) => {
- validateFlags(flags, options);
- validateChoices(options.flags, flags);
- };
- const reportUnknownFlags = unknownFlags => {
- console.error([
- `Unknown flag${unknownFlags.length > 1 ? 's' : ''}`,
- ...unknownFlags,
- ].join('\n'));
- };
- const checkUnknownFlags = input => {
- const unknownFlags = input.filter(item => typeof item === 'string' && item.startsWith('-'));
- if (unknownFlags.length > 0) {
- reportUnknownFlags(unknownFlags);
- process.exit(2);
- }
- };
- const isFlagMissing = (flagName, definedFlags, receivedFlags, input) => {
- const flag = definedFlags[flagName];
- let isFlagRequired = true;
- if (typeof flag.isRequired === 'function') {
- isFlagRequired = flag.isRequired(receivedFlags, input);
- if (typeof isFlagRequired !== 'boolean') {
- throw new TypeError(`Return value for isRequired callback should be of type boolean, but ${typeof isFlagRequired} was returned.`);
- }
- }
- if (receivedFlags[flagName] === undefined) {
- return isFlagRequired;
- }
- return flag.isMultiple && receivedFlags[flagName].length === 0 && isFlagRequired;
- };
- const reportMissingRequiredFlags = missingRequiredFlags => {
- console.error(`Missing required flag${missingRequiredFlags.length > 1 ? 's' : ''}`);
- for (const flag of missingRequiredFlags) {
- console.error(`\t${decamelizeFlagKey(flag.key)}${flag.shortFlag ? `, -${flag.shortFlag}` : ''}`);
- }
- };
- const checkMissingRequiredFlags = (flags, receivedFlags, input) => {
- const missingRequiredFlags = [];
- if (flags === undefined) {
- return [];
- }
- for (const flagName of Object.keys(flags)) {
- if (flags[flagName].isRequired && isFlagMissing(flagName, flags, receivedFlags, input)) {
- missingRequiredFlags.push({key: flagName, ...flags[flagName]});
- }
- }
- if (missingRequiredFlags.length > 0) {
- reportMissingRequiredFlags(missingRequiredFlags);
- process.exit(2);
- }
- };
- export { checkMissingRequiredFlags, checkUnknownFlags, validate };
|