awais-tool
Version:
Get to know via `npx itishaawais`
145 lines (120 loc) • 3.82 kB
JavaScript
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")}`);
}
};
export 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"
)
);
};
export 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}` : ""}`
);
}
};
export 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);
}
};