'use strict'; const consola = require('consola'); const utils = require('consola/utils'); function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; } const consola__default = /*#__PURE__*/_interopDefaultCompat(consola); function toArray(val) { if (Array.isArray(val)) { return val; } return val === void 0 ? [] : [val]; } function formatLineColumns(lines, linePrefix = "") { const maxLengh = []; for (const line of lines) { for (const [i, element] of line.entries()) { maxLengh[i] = Math.max(maxLengh[i] || 0, element.length); } } return lines.map( (l) => l.map( (c, i) => linePrefix + c[i === 0 ? "padStart" : "padEnd"](maxLengh[i]) ).join(" ") ).join("\n"); } function resolveValue(input) { return typeof input === "function" ? input() : input; } class CLIError extends Error { constructor(message, code) { super(message); this.code = code; this.name = "CLIError"; } } const NUMBER_CHAR_RE = /\d/; const STR_SPLITTERS = ["-", "_", "/", "."]; function isUppercase(char = "") { if (NUMBER_CHAR_RE.test(char)) { return void 0; } return char !== char.toLowerCase(); } function splitByCase(str, separators) { const splitters = separators ?? STR_SPLITTERS; const parts = []; if (!str || typeof str !== "string") { return parts; } let buff = ""; let previousUpper; let previousSplitter; for (const char of str) { const isSplitter = splitters.includes(char); if (isSplitter === true) { parts.push(buff); buff = ""; previousUpper = void 0; continue; } const isUpper = isUppercase(char); if (previousSplitter === false) { if (previousUpper === false && isUpper === true) { parts.push(buff); buff = char; previousUpper = isUpper; continue; } if (previousUpper === true && isUpper === false && buff.length > 1) { const lastChar = buff.at(-1); parts.push(buff.slice(0, Math.max(0, buff.length - 1))); buff = lastChar + char; previousUpper = isUpper; continue; } } buff += char; previousUpper = isUpper; previousSplitter = isSplitter; } parts.push(buff); return parts; } function upperFirst(str) { return str ? str[0].toUpperCase() + str.slice(1) : ""; } function lowerFirst(str) { return str ? str[0].toLowerCase() + str.slice(1) : ""; } function pascalCase(str, opts) { return str ? (Array.isArray(str) ? str : splitByCase(str)).map((p) => upperFirst(opts?.normalize ? p.toLowerCase() : p)).join("") : ""; } function camelCase(str, opts) { return lowerFirst(pascalCase(str || "", opts)); } function kebabCase(str, joiner) { return str ? (Array.isArray(str) ? str : splitByCase(str)).map((p) => p.toLowerCase()).join(joiner ?? "-") : ""; } function toArr(any) { return any == void 0 ? [] : Array.isArray(any) ? any : [any]; } function toVal(out, key, val, opts) { let x; const old = out[key]; const nxt = ~opts.string.indexOf(key) ? val == void 0 || val === true ? "" : String(val) : typeof val === "boolean" ? val : ~opts.boolean.indexOf(key) ? val === "false" ? false : val === "true" || (out._.push((x = +val, x * 0 === 0) ? x : val), !!val) : (x = +val, x * 0 === 0) ? x : val; out[key] = old == void 0 ? nxt : Array.isArray(old) ? old.concat(nxt) : [old, nxt]; } function parseRawArgs(args = [], opts = {}) { let k; let arr; let arg; let name; let val; const out = { _: [] }; let i = 0; let j = 0; let idx = 0; const len = args.length; const alibi = opts.alias !== void 0; const strict = opts.unknown !== void 0; const defaults = opts.default !== void 0; opts.alias = opts.alias || {}; opts.string = toArr(opts.string); opts.boolean = toArr(opts.boolean); if (alibi) { for (k in opts.alias) { arr = opts.alias[k] = toArr(opts.alias[k]); for (i = 0; i < arr.length; i++) { (opts.alias[arr[i]] = arr.concat(k)).splice(i, 1); } } } for (i = opts.boolean.length; i-- > 0; ) { arr = opts.alias[opts.boolean[i]] || []; for (j = arr.length; j-- > 0; ) { opts.boolean.push(arr[j]); } } for (i = opts.string.length; i-- > 0; ) { arr = opts.alias[opts.string[i]] || []; for (j = arr.length; j-- > 0; ) { opts.string.push(arr[j]); } } if (defaults) { for (k in opts.default) { name = typeof opts.default[k]; arr = opts.alias[k] = opts.alias[k] || []; if (opts[name] !== void 0) { opts[name].push(k); for (i = 0; i < arr.length; i++) { opts[name].push(arr[i]); } } } } const keys = strict ? Object.keys(opts.alias) : []; for (i = 0; i < len; i++) { arg = args[i]; if (arg === "--") { out._ = out._.concat(args.slice(++i)); break; } for (j = 0; j < arg.length; j++) { if (arg.charCodeAt(j) !== 45) { break; } } if (j === 0) { out._.push(arg); } else if (arg.substring(j, j + 3) === "no-") { name = arg.slice(Math.max(0, j + 3)); if (strict && !~keys.indexOf(name)) { return opts.unknown(arg); } out[name] = false; } else { for (idx = j + 1; idx < arg.length; idx++) { if (arg.charCodeAt(idx) === 61) { break; } } name = arg.substring(j, idx); val = arg.slice(Math.max(0, ++idx)) || i + 1 === len || ("" + args[i + 1]).charCodeAt(0) === 45 || args[++i]; arr = j === 2 ? [name] : name; for (idx = 0; idx < arr.length; idx++) { name = arr[idx]; if (strict && !~keys.indexOf(name)) { return opts.unknown("-".repeat(j) + name); } toVal(out, name, idx + 1 < arr.length || val, opts); } } } if (defaults) { for (k in opts.default) { if (out[k] === void 0) { out[k] = opts.default[k]; } } } if (alibi) { for (k in out) { arr = opts.alias[k] || []; while (arr.length > 0) { out[arr.shift()] = out[k]; } } } return out; } function parseArgs(rawArgs, argsDef) { const parseOptions = { boolean: [], string: [], mixed: [], alias: {}, default: {} }; const args = resolveArgs(argsDef); for (const arg of args) { if (arg.type === "positional") { continue; } if (arg.type === "string") { parseOptions.string.push(arg.name); } else if (arg.type === "boolean") { parseOptions.boolean.push(arg.name); } if (arg.default !== void 0) { parseOptions.default[arg.name] = arg.default; } if (arg.alias) { parseOptions.alias[arg.name] = arg.alias; } } const parsed = parseRawArgs(rawArgs, parseOptions); const [...positionalArguments] = parsed._; const parsedArgsProxy = new Proxy(parsed, { get(target, prop) { return target[prop] ?? target[camelCase(prop)] ?? target[kebabCase(prop)]; } }); for (const [, arg] of args.entries()) { if (arg.type === "positional") { const nextPositionalArgument = positionalArguments.shift(); if (nextPositionalArgument !== void 0) { parsedArgsProxy[arg.name] = nextPositionalArgument; } else if (arg.default === void 0 && arg.required !== false) { throw new CLIError( `Missing required positional argument: ${arg.name.toUpperCase()}`, "EARG" ); } else { parsedArgsProxy[arg.name] = arg.default; } } else if (arg.required && parsedArgsProxy[arg.name] === void 0) { throw new CLIError(`Missing required argument: --${arg.name}`, "EARG"); } } return parsedArgsProxy; } function resolveArgs(argsDef) { const args = []; for (const [name, argDef] of Object.entries(argsDef || {})) { args.push({ ...argDef, name, alias: toArray(argDef.alias) }); } return args; } function defineCommand(def) { return def; } async function runCommand(cmd, opts) { const cmdArgs = await resolveValue(cmd.args || {}); const parsedArgs = parseArgs(opts.rawArgs, cmdArgs); const context = { rawArgs: opts.rawArgs, args: parsedArgs, data: opts.data, cmd }; if (typeof cmd.setup === "function") { await cmd.setup(context); } let result; try { const subCommands = await resolveValue(cmd.subCommands); if (subCommands && Object.keys(subCommands).length > 0) { const subCommandArgIndex = opts.rawArgs.findIndex( (arg) => !arg.startsWith("-") ); const subCommandName = opts.rawArgs[subCommandArgIndex]; if (subCommandName) { if (!subCommands[subCommandName]) { throw new CLIError( `Unknown command \`${subCommandName}\``, "E_UNKNOWN_COMMAND" ); } const subCommand = await resolveValue(subCommands[subCommandName]); if (subCommand) { await runCommand(subCommand, { rawArgs: opts.rawArgs.slice(subCommandArgIndex + 1) }); } } else if (!cmd.run) { throw new CLIError(`No command specified.`, "E_NO_COMMAND"); } } if (typeof cmd.run === "function") { result = await cmd.run(context); } } finally { if (typeof cmd.cleanup === "function") { await cmd.cleanup(context); } } return { result }; } async function resolveSubCommand(cmd, rawArgs, parent) { const subCommands = await resolveValue(cmd.subCommands); if (subCommands && Object.keys(subCommands).length > 0) { const subCommandArgIndex = rawArgs.findIndex((arg) => !arg.startsWith("-")); const subCommandName = rawArgs[subCommandArgIndex]; const subCommand = await resolveValue(subCommands[subCommandName]); if (subCommand) { return resolveSubCommand( subCommand, rawArgs.slice(subCommandArgIndex + 1), cmd ); } } return [cmd, parent]; } async function showUsage(cmd, parent) { try { consola__default.log(await renderUsage(cmd, parent) + "\n"); } catch (error) { consola__default.error(error); } } async function renderUsage(cmd, parent) { const cmdMeta = await resolveValue(cmd.meta || {}); const cmdArgs = resolveArgs(await resolveValue(cmd.args || {})); const parentMeta = await resolveValue(parent?.meta || {}); const commandName = `${parentMeta.name ? `${parentMeta.name} ` : ""}` + (cmdMeta.name || process.argv[1]); const argLines = []; const posLines = []; const commandsLines = []; const usageLine = []; for (const arg of cmdArgs) { if (arg.type === "positional") { const name = arg.name.toUpperCase(); const isRequired = arg.required !== false && arg.default === void 0; const defaultHint = arg.default ? `="${arg.default}"` : ""; posLines.push([ "`" + name + defaultHint + "`", arg.description || "", arg.valueHint ? `<${arg.valueHint}>` : "" ]); usageLine.push(isRequired ? `<${name}>` : `[${name}]`); } else { const isRequired = arg.required === true && arg.default === void 0; const argStr = (arg.type === "boolean" && arg.default === true ? [ ...(arg.alias || []).map((a) => `--no-${a}`), `--no-${arg.name}` ].join(", ") : [...(arg.alias || []).map((a) => `-${a}`), `--${arg.name}`].join( ", " )) + (arg.type === "string" && (arg.valueHint || arg.default) ? `=${arg.valueHint ? `<${arg.valueHint}>` : `"${arg.default || ""}"`}` : ""); argLines.push([ "`" + argStr + (isRequired ? " (required)" : "") + "`", arg.description || "" ]); if (isRequired) { usageLine.push(argStr); } } } if (cmd.subCommands) { const commandNames = []; const subCommands = await resolveValue(cmd.subCommands); for (const [name, sub] of Object.entries(subCommands)) { const subCmd = await resolveValue(sub); const meta = await resolveValue(subCmd?.meta); commandsLines.push([`\`${name}\``, meta?.description || ""]); commandNames.push(name); } usageLine.push(commandNames.join("|")); } const usageLines = []; const version = cmdMeta.version || parentMeta.version; usageLines.push( utils.colors.gray( `${cmdMeta.description} (${commandName + (version ? ` v${version}` : "")})` ), "" ); const hasOptions = argLines.length > 0 || posLines.length > 0; usageLines.push( `${utils.colors.underline(utils.colors.bold("USAGE"))} \`${commandName}${hasOptions ? " [OPTIONS]" : ""} ${usageLine.join(" ")}\``, "" ); if (posLines.length > 0) { usageLines.push(utils.colors.underline(utils.colors.bold("ARGUMENTS")), ""); usageLines.push(formatLineColumns(posLines, " ")); usageLines.push(""); } if (argLines.length > 0) { usageLines.push(utils.colors.underline(utils.colors.bold("OPTIONS")), ""); usageLines.push(formatLineColumns(argLines, " ")); usageLines.push(""); } if (commandsLines.length > 0) { usageLines.push(utils.colors.underline(utils.colors.bold("COMMANDS")), ""); usageLines.push(formatLineColumns(commandsLines, " ")); usageLines.push( "", `Use \`${commandName} --help\` for more information about a command.` ); } return usageLines.filter((l) => typeof l === "string").join("\n"); } async function runMain(cmd, opts = {}) { const rawArgs = opts.rawArgs || process.argv.slice(2); const showUsage$1 = opts.showUsage || showUsage; try { if (rawArgs.includes("--help") || rawArgs.includes("-h")) { await showUsage$1(...await resolveSubCommand(cmd, rawArgs)); process.exit(0); } else if (rawArgs.length === 1 && rawArgs[0] === "--version") { const meta = typeof cmd.meta === "function" ? await cmd.meta() : await cmd.meta; if (!meta?.version) { throw new CLIError("No version specified", "E_NO_VERSION"); } consola__default.log(meta.version); } else { await runCommand(cmd, { rawArgs }); } } catch (error) { const isCLIError = error instanceof CLIError; if (!isCLIError) { consola__default.error(error, "\n"); } if (isCLIError) { await showUsage$1(...await resolveSubCommand(cmd, rawArgs)); } consola__default.error(error.message); process.exit(1); } } function createMain(cmd) { return (opts = {}) => runMain(cmd, opts); } exports.createMain = createMain; exports.defineCommand = defineCommand; exports.parseArgs = parseArgs; exports.renderUsage = renderUsage; exports.runCommand = runCommand; exports.runMain = runMain; exports.showUsage = showUsage;