|
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- 'use strict';
-
- const _ = require('lodash');
- const chalk = require('chalk');
- const EOL = require('os').EOL;
- const levenshtein = require('fastest-levenshtein');
-
- /**
- * @param {{ [key: string]: { alias?: string } }} allowedOptions
- * @return {string[]}
- */
- const buildAllowedOptions = (allowedOptions) => {
- let options = Object.keys(allowedOptions);
-
- options = options.reduce((opts, opt) => {
- const alias = allowedOptions[opt].alias;
-
- if (alias) {
- opts.push(alias);
- }
-
- return opts;
- }, options);
- options.sort();
-
- return options;
- };
-
- /**
- * @param {string[]} all
- * @param {string} invalid
- * @return {null|string}
- */
- const suggest = (all, invalid) => {
- const maxThreshold = 10;
-
- for (let threshold = 1; threshold <= maxThreshold; threshold++) {
- const suggestion = all.find((option) => levenshtein.distance(option, invalid) <= threshold);
-
- if (suggestion) {
- return suggestion;
- }
- }
-
- return null;
- };
-
- /**
- * @param {string} opt
- * @return {string}
- */
- const cliOption = (opt) => {
- if (opt.length === 1) {
- return `"-${opt}"`;
- }
-
- return `"--${_.kebabCase(opt)}"`;
- };
-
- /**
- * @param {string} invalid
- * @param {string|null} suggestion
- * @return {string}
- */
- const buildMessageLine = (invalid, suggestion) => {
- let line = `Invalid option ${chalk.red(cliOption(invalid))}.`;
-
- if (suggestion) {
- line += ` Did you mean ${chalk.cyan(cliOption(suggestion))}?`;
- }
-
- return line + EOL;
- };
-
- /**
- * @param {{ [key: string]: any }} allowedOptions
- * @param {{ [key: string]: any }} inputOptions
- * @return {string}
- */
- module.exports = function checkInvalidCLIOptions(allowedOptions, inputOptions) {
- const allOptions = buildAllowedOptions(allowedOptions);
-
- return Object.keys(inputOptions)
- .filter((opt) => !allOptions.includes(opt))
- .map(_.kebabCase)
- .reduce((msg, invalid) => {
- // NOTE: No suggestion for shortcut options because it's too difficult
- const suggestion = invalid.length >= 2 ? suggest(allOptions, invalid) : null;
-
- return msg + buildMessageLine(invalid, suggestion);
- }, '');
- };
|