first commit

This commit is contained in:
2025-10-26 23:10:15 +08:00
commit 8f0345b7be
14961 changed files with 2356381 additions and 0 deletions

52
node_modules/@oclif/core/lib/parser/errors.d.ts generated vendored Normal file
View File

@@ -0,0 +1,52 @@
import { CLIError } from '../errors';
import { Arg, ArgInput, CLIParseErrorOptions, OptionFlag } from '../interfaces/parser';
export { CLIError } from '../errors';
export type Validation = {
name: string;
reason?: string | undefined;
status: 'failed' | 'success';
validationFn: string;
};
export declare class CLIParseError extends CLIError {
parse: CLIParseErrorOptions['parse'];
showHelp: boolean;
constructor(options: CLIParseErrorOptions & {
message: string;
});
}
export declare class InvalidArgsSpecError extends CLIParseError {
args: ArgInput;
constructor({ args, exit, parse }: CLIParseErrorOptions & {
args: ArgInput;
});
}
export declare class RequiredArgsError extends CLIParseError {
args: Arg<any>[];
constructor({ args, exit, flagsWithMultiple, parse, }: CLIParseErrorOptions & {
args: Arg<any>[];
flagsWithMultiple?: string[];
});
}
export declare class UnexpectedArgsError extends CLIParseError {
args: unknown[];
constructor({ args, exit, parse }: CLIParseErrorOptions & {
args: unknown[];
});
}
export declare class NonExistentFlagsError extends CLIParseError {
flags: string[];
constructor({ exit, flags, parse }: CLIParseErrorOptions & {
flags: string[];
});
}
export declare class FlagInvalidOptionError extends CLIParseError {
constructor(flag: OptionFlag<any>, input: string);
}
export declare class ArgInvalidOptionError extends CLIParseError {
constructor(arg: Arg<any>, input: string);
}
export declare class FailedFlagValidationError extends CLIParseError {
constructor({ exit, failed, parse }: CLIParseErrorOptions & {
failed: Validation[];
});
}

104
node_modules/@oclif/core/lib/parser/errors.js generated vendored Normal file
View File

@@ -0,0 +1,104 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FailedFlagValidationError = exports.ArgInvalidOptionError = exports.FlagInvalidOptionError = exports.NonExistentFlagsError = exports.UnexpectedArgsError = exports.RequiredArgsError = exports.InvalidArgsSpecError = exports.CLIParseError = exports.CLIError = void 0;
const cache_1 = __importDefault(require("../cache"));
const errors_1 = require("../errors");
const util_1 = require("../util/util");
const list_1 = __importDefault(require("../ux/list"));
const theme_1 = require("../ux/theme");
var errors_2 = require("../errors");
Object.defineProperty(exports, "CLIError", { enumerable: true, get: function () { return errors_2.CLIError; } });
class CLIParseError extends errors_1.CLIError {
parse;
showHelp = false;
constructor(options) {
options.message += '\nSee more help with --help';
super(options.message, { exit: options.exit });
this.parse = options.parse;
}
}
exports.CLIParseError = CLIParseError;
class InvalidArgsSpecError extends CLIParseError {
args;
constructor({ args, exit, parse }) {
let message = 'Invalid argument spec';
const namedArgs = Object.values(args).filter((a) => a.name);
if (namedArgs.length > 0) {
const list = (0, list_1.default)(namedArgs.map((a) => [`${a.name} (${a.required ? 'required' : 'optional'})`, a.description]));
message += `:\n${list}`;
}
super({ exit: cache_1.default.getInstance().get('exitCodes')?.invalidArgsSpec ?? exit, message, parse });
this.args = args;
}
}
exports.InvalidArgsSpecError = InvalidArgsSpecError;
class RequiredArgsError extends CLIParseError {
args;
constructor({ args, exit, flagsWithMultiple, parse, }) {
let message = `Missing ${args.length} required arg${args.length === 1 ? '' : 's'}`;
const namedArgs = args.filter((a) => a.name);
if (namedArgs.length > 0) {
const list = (0, list_1.default)(namedArgs.map((a) => {
const description = a.options ? `(${a.options.join('|')}) ${a.description}` : a.description;
return [a.name, description];
}));
message += `:\n${list}`;
}
if (flagsWithMultiple?.length) {
const flags = flagsWithMultiple.map((f) => `--${f}`).join(', ');
message += `\n\nNote: ${flags} allow${flagsWithMultiple.length === 1 ? 's' : ''} multiple values. Because of this you need to provide all arguments before providing ${flagsWithMultiple.length === 1 ? 'that flag' : 'those flags'}.`;
message += '\nAlternatively, you can use "--" to signify the end of the flags and the beginning of arguments.';
}
super({ exit: cache_1.default.getInstance().get('exitCodes')?.requiredArgs ?? exit, message, parse });
this.args = args;
this.showHelp = true;
}
}
exports.RequiredArgsError = RequiredArgsError;
class UnexpectedArgsError extends CLIParseError {
args;
constructor({ args, exit, parse }) {
const message = `Unexpected argument${args.length === 1 ? '' : 's'}: ${args.join(', ')}`;
super({ exit: cache_1.default.getInstance().get('exitCodes')?.unexpectedArgs ?? exit, message, parse });
this.args = args;
this.showHelp = true;
}
}
exports.UnexpectedArgsError = UnexpectedArgsError;
class NonExistentFlagsError extends CLIParseError {
flags;
constructor({ exit, flags, parse }) {
const message = `Nonexistent flag${flags.length === 1 ? '' : 's'}: ${flags.join(', ')}`;
super({ exit: cache_1.default.getInstance().get('exitCodes')?.nonExistentFlag ?? exit, message, parse });
this.flags = flags;
this.showHelp = true;
}
}
exports.NonExistentFlagsError = NonExistentFlagsError;
class FlagInvalidOptionError extends CLIParseError {
constructor(flag, input) {
const message = `Expected --${flag.name}=${input} to be one of: ${flag.options.join(', ')}`;
super({ message, parse: {} });
}
}
exports.FlagInvalidOptionError = FlagInvalidOptionError;
class ArgInvalidOptionError extends CLIParseError {
constructor(arg, input) {
const message = `Expected ${input} to be one of: ${arg.options.join(', ')}`;
super({ message, parse: {} });
}
}
exports.ArgInvalidOptionError = ArgInvalidOptionError;
class FailedFlagValidationError extends CLIParseError {
constructor({ exit, failed, parse }) {
const reasons = failed.map((r) => r.reason);
const deduped = (0, util_1.uniq)(reasons);
const errString = deduped.length === 1 ? 'error' : 'errors';
const message = `The following ${errString} occurred:\n ${(0, theme_1.colorize)('dim', deduped.join('\n '))}`;
super({ exit: cache_1.default.getInstance().get('exitCodes')?.failedFlagValidation ?? exit, message, parse });
}
}
exports.FailedFlagValidationError = FailedFlagValidationError;

3
node_modules/@oclif/core/lib/parser/help.d.ts generated vendored Normal file
View File

@@ -0,0 +1,3 @@
import { Flag, FlagUsageOptions } from '../interfaces/parser';
export declare function flagUsage(flag: Flag<any>, options?: FlagUsageOptions): [string, string | undefined];
export declare function flagUsages(flags: Flag<any>[], options?: FlagUsageOptions): [string, string | undefined][];

29
node_modules/@oclif/core/lib/parser/help.js generated vendored Normal file
View File

@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.flagUsage = flagUsage;
exports.flagUsages = flagUsages;
const util_1 = require("../util/util");
const ux_1 = require("../ux");
function flagUsage(flag, options = {}) {
const label = [];
if (flag.helpLabel) {
label.push(flag.helpLabel);
}
else {
if (flag.char)
label.push(`-${flag.char}`);
if (flag.name)
label.push(` --${flag.name}`);
}
const usage = flag.type === 'option' ? ` ${flag.name.toUpperCase()}` : '';
let description = flag.summary || flag.description || '';
if (options.displayRequired && flag.required)
description = `(required) ${description}`;
description = description ? (0, ux_1.colorize)('dim', description) : undefined;
return [` ${label.join(',').trim()}${usage}`, description];
}
function flagUsages(flags, options = {}) {
if (flags.length === 0)
return [];
return (0, util_1.sortBy)(flags, (f) => [f.char ? -1 : 1, f.char, f.name]).map((f) => flagUsage(f, options));
}

5
node_modules/@oclif/core/lib/parser/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,5 @@
import type { Input, OutputArgs, OutputFlags, ParserOutput } from '../interfaces/parser';
export type { ArgInput, FlagInput, Input, OutputArgs, OutputFlags, ParserOutput } from '../interfaces/parser';
export { flagUsages } from './help';
export { validate } from './validate';
export declare function parse<TFlags extends OutputFlags<any>, BFlags extends OutputFlags<any>, TArgs extends OutputArgs<any>>(argv: string[], options: Input<TFlags, BFlags, TArgs>): Promise<ParserOutput<TFlags, BFlags, TArgs>>;

24
node_modules/@oclif/core/lib/parser/index.js generated vendored Normal file
View File

@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validate = exports.flagUsages = void 0;
exports.parse = parse;
const parse_1 = require("./parse");
const validate_1 = require("./validate");
var help_1 = require("./help");
Object.defineProperty(exports, "flagUsages", { enumerable: true, get: function () { return help_1.flagUsages; } });
var validate_2 = require("./validate");
Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return validate_2.validate; } });
async function parse(argv, options) {
const input = {
'--': options['--'],
args: (options.args ?? {}),
argv,
context: options.context,
flags: (options.flags ?? {}),
strict: options.strict !== false,
};
const parser = new parse_1.Parser(input);
const output = await parser.parse();
await (0, validate_1.validate)({ input, output });
return output;
}

37
node_modules/@oclif/core/lib/parser/parse.d.ts generated vendored Normal file
View File

@@ -0,0 +1,37 @@
import { OutputArgs, OutputFlags, ParserInput, ParserOutput } from '../interfaces/parser';
declare global {
/**
* Cache the stdin so that it can be read multiple times.
*
* This fixes a bug where the stdin would be read multiple times (because Parser.parse() was called more than once)
* but only the first read would be successful - all other reads would return null.
*
* Storing in global is necessary because we want the cache to be shared across all versions of @oclif/core in
* in the dependency tree. Storing in a variable would only share the cache within the same version of @oclif/core.
*/
var oclif: {
stdinCache?: string;
};
}
export declare const readStdin: () => Promise<null | string>;
export declare class Parser<T extends ParserInput, TFlags extends OutputFlags<T['flags']>, BFlags extends OutputFlags<T['flags']>, TArgs extends OutputArgs<T['args']>> {
private readonly input;
private readonly argv;
private readonly booleanFlags;
private readonly context;
private currentFlag?;
private readonly flagAliases;
private readonly raw;
constructor(input: T);
private get _argTokens();
parse(): Promise<ParserOutput<TFlags, BFlags, TArgs>>;
private _args;
private _debugInput;
private _debugOutput;
private _flags;
private _setNames;
private findFlag;
private findLongFlag;
private findShortFlag;
private mapAndValidateFlags;
}

495
node_modules/@oclif/core/lib/parser/parse.js generated vendored Normal file
View File

@@ -0,0 +1,495 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Parser = exports.readStdin = void 0;
/* eslint-disable no-await-in-loop */
const node_os_1 = require("node:os");
const node_readline_1 = require("node:readline");
const cache_1 = __importDefault(require("../cache"));
const logger_1 = require("../logger");
const util_1 = require("../util/util");
const errors_1 = require("./errors");
let debug;
try {
debug =
process.env.CLI_FLAGS_DEBUG === '1'
? (0, logger_1.makeDebug)('parser')
: () => {
// noop
};
}
catch {
debug = () => {
// noop
};
}
const readStdin = async () => {
const { stdin, stdout } = process;
// process.stdin.isTTY is true whenever it's running in a terminal.
// process.stdin.isTTY is undefined when it's running in a pipe, e.g. echo 'foo' | my-cli command
// process.stdin.isTTY is undefined when it's running in a spawned process, even if there's no pipe.
// This means that reading from stdin could hang indefinitely while waiting for a non-existent pipe.
// Because of this, we have to set a timeout to prevent the process from hanging.
if (stdin.isTTY)
return null;
if (globalThis.oclif?.stdinCache) {
debug('resolved stdin from global cache', globalThis.oclif.stdinCache);
return globalThis.oclif.stdinCache;
}
return new Promise((resolve) => {
const lines = [];
const ac = new AbortController();
const { signal } = ac;
const timeout = setTimeout(() => ac.abort(), 10);
const rl = (0, node_readline_1.createInterface)({
input: stdin,
output: stdout,
terminal: false,
});
rl.on('line', (line) => {
lines.push(line);
});
rl.once('close', () => {
const result = lines.join(node_os_1.EOL);
clearTimeout(timeout);
debug('resolved from stdin', result);
globalThis.oclif = { ...globalThis.oclif, stdinCache: result };
resolve(result);
});
signal.addEventListener('abort', () => {
debug('stdin aborted');
clearTimeout(timeout);
rl.close();
resolve(null);
}, { once: true });
});
};
exports.readStdin = readStdin;
function isNegativeNumber(input) {
return /^-\d/g.test(input);
}
const validateOptions = (flag, input) => {
if (flag.options && !flag.options.includes(input))
throw new errors_1.FlagInvalidOptionError(flag, input);
return input;
};
const NEGATION = '--no-';
class Parser {
input;
argv;
booleanFlags;
context;
currentFlag;
flagAliases;
raw = [];
constructor(input) {
this.input = input;
this.context = input.context ?? {};
this.argv = [...input.argv];
this._setNames();
this.booleanFlags = (0, util_1.pickBy)(input.flags, (f) => f.type === 'boolean');
this.flagAliases = Object.fromEntries(Object.values(input.flags).flatMap((flag) => [...(flag.aliases ?? []), ...(flag.charAliases ?? [])].map((a) => [a, flag])));
}
get _argTokens() {
return this.raw.filter((o) => o.type === 'arg');
}
async parse() {
this._debugInput();
// eslint-disable-next-line complexity
const parseFlag = async (arg) => {
const { isLong, name } = this.findFlag(arg);
if (!name) {
const i = arg.indexOf('=');
if (i !== -1) {
const sliced = arg.slice(i + 1);
this.argv.unshift(sliced);
const equalsParsed = await parseFlag(arg.slice(0, i));
if (!equalsParsed) {
this.argv.shift();
}
return equalsParsed;
}
return false;
}
const flag = this.input.flags[name];
if (flag.type === 'option') {
if (!flag.multiple && this.raw.some((o) => o.type === 'flag' && o.flag === name)) {
throw new errors_1.CLIError(`Flag --${name} can only be specified once`);
}
this.currentFlag = flag;
let input = isLong || arg.length < 3 ? this.argv.shift() : arg.slice(arg[2] === '=' ? 3 : 2);
if (flag.allowStdin === 'only' && input !== '-' && input !== undefined && !this.findFlag(input).name) {
throw new errors_1.CLIError(`Flag --${name} can only be read from stdin. The value must be "-" or not provided at all.`);
}
if ((flag.allowStdin && input === '-') || flag.allowStdin === 'only') {
const stdin = await (0, exports.readStdin)();
if (stdin) {
input = stdin.trim();
}
}
// if the value ends up being one of the command's flags, the user didn't provide an input
if (typeof input !== 'string' || this.findFlag(input).name) {
if (flag.options) {
throw new errors_1.CLIError(`Flag --${name} expects one of these values: ${flag.options.join(', ')}`);
}
throw new errors_1.CLIError(`Flag --${name} expects a value`);
}
this.raw.push({ flag: flag.name, input, type: 'flag' });
}
else {
this.raw.push({ flag: flag.name, input: arg, type: 'flag' });
// push the rest of the short characters back on the stack
if (!isLong && arg.length > 2) {
this.argv.unshift(`-${arg.slice(2)}`);
}
}
return true;
};
let parsingFlags = true;
const nonExistentFlags = [];
let dashdash = false;
const originalArgv = [...this.argv];
while (this.argv.length > 0) {
const input = this.argv.shift();
if (parsingFlags && input.startsWith('-') && input !== '-') {
// attempt to parse as arg
if (this.input['--'] !== false && input === '--') {
parsingFlags = false;
continue;
}
if (await parseFlag(input)) {
continue;
}
if (input === '--') {
dashdash = true;
continue;
}
if (this.input['--'] !== false && !isNegativeNumber(input)) {
// At this point we have a value that begins with '-' or '--'
// but doesn't match up to a flag definition. So we assume that
// this is a misspelled flag or a non-existent flag,
// e.g. --hekp instead of --help
nonExistentFlags.push(input);
continue;
}
}
if (parsingFlags && this.currentFlag && this.currentFlag.multiple && !this.currentFlag.multipleNonGreedy) {
this.raw.push({ flag: this.currentFlag.name, input, type: 'flag' });
continue;
}
// not a flag, parse as arg
const arg = Object.keys(this.input.args)[this._argTokens.length];
this.raw.push({ arg, input, type: 'arg' });
}
const [{ args, argv }, { flags, metadata }] = await Promise.all([this._args(), this._flags()]);
this._debugOutput(argv, args, flags);
const unsortedArgv = (dashdash ? [...argv, ...nonExistentFlags, '--'] : [...argv, ...nonExistentFlags]);
return {
args: args,
argv: unsortedArgv.sort((a, b) => originalArgv.indexOf(a) - originalArgv.indexOf(b)),
flags,
metadata,
nonExistentFlags,
raw: this.raw,
};
}
async _args() {
const argv = [];
const args = {};
const tokens = this._argTokens;
let stdinRead = false;
const ctx = this.context;
for (const [name, arg] of Object.entries(this.input.args)) {
const token = tokens.find((t) => t.arg === name);
ctx.token = token;
if (token) {
if (arg.options && !arg.options.includes(token.input)) {
throw new errors_1.ArgInvalidOptionError(arg, token.input);
}
const parsed = await arg.parse(token.input, ctx, arg);
argv.push(parsed);
args[token.arg] = parsed;
}
else if (!arg.ignoreStdin && !stdinRead) {
let stdin = await (0, exports.readStdin)();
if (stdin) {
stdin = stdin.trim();
const parsed = await arg.parse(stdin, ctx, arg);
argv.push(parsed);
args[name] = parsed;
}
stdinRead = true;
}
if (!args[name] && (arg.default || arg.default === false)) {
if (typeof arg.default === 'function') {
const f = await arg.default();
argv.push(f);
args[name] = f;
}
else {
argv.push(arg.default);
args[name] = arg.default;
}
}
}
for (const token of tokens) {
if (args[token.arg] !== undefined)
continue;
argv.push(token.input);
}
return { args, argv };
}
_debugInput() {
debug('input: %s', this.argv.join(' '));
const args = Object.keys(this.input.args);
if (args.length > 0) {
debug('available args: %s', args.join(' '));
}
if (Object.keys(this.input.flags).length === 0)
return;
debug('available flags: %s', Object.keys(this.input.flags)
.map((f) => `--${f}`)
.join(' '));
}
_debugOutput(args, flags, argv) {
if (argv.length > 0) {
debug('argv: %o', argv);
}
if (Object.keys(args).length > 0) {
debug('args: %o', args);
}
if (Object.keys(flags).length > 0) {
debug('flags: %o', flags);
}
}
async _flags() {
const parseFlagOrThrowError = async (input, flag, context, token) => {
if (!flag.parse)
return input;
const ctx = {
...context,
error: context?.error,
exit: context?.exit,
jsonEnabled: context?.jsonEnabled,
log: context?.log,
logToStderr: context?.logToStderr,
token,
warn: context?.warn,
};
try {
if (flag.type === 'boolean') {
return await flag.parse(input, ctx, flag);
}
return await flag.parse(input, ctx, flag);
}
catch (error) {
error.message = `Parsing --${flag.name} \n\t${error.message}\nSee more help with --help`;
if (cache_1.default.getInstance().get('exitCodes')?.failedFlagParsing)
error.oclif = { exit: cache_1.default.getInstance().get('exitCodes')?.failedFlagParsing };
throw error;
}
};
/* Could add a valueFunction (if there is a value/env/default) and could metadata.
* Value function can be resolved later.
*/
const addValueFunction = (fws) => {
const tokenLength = fws.tokens?.length;
// user provided some input
if (tokenLength) {
// boolean
if (fws.inputFlag.flag.type === 'boolean' && (0, util_1.last)(fws.tokens)?.input) {
const doesNotContainNegation = (i) => {
const possibleNegations = [i.inputFlag.name, ...(i.inputFlag.flag.aliases ?? [])].map((n) => `${NEGATION}${n}`);
const input = (0, util_1.last)(i.tokens)?.input;
if (!input)
return true;
return !possibleNegations.includes(input);
};
return {
...fws,
valueFunction: async (i) => parseFlagOrThrowError(doesNotContainNegation(i), i.inputFlag.flag, this.context, (0, util_1.last)(i.tokens)),
};
}
// multiple with custom delimiter
if (fws.inputFlag.flag.type === 'option' && fws.inputFlag.flag.delimiter && fws.inputFlag.flag.multiple) {
// regex that will identify unescaped delimiters
const makeDelimiter = (delimiter) => new RegExp(`(?<!\\\\)${delimiter}`);
return {
...fws,
valueFunction: async (i) => (await Promise.all((i.tokens ?? [])
.flatMap((token) => token.input.split(makeDelimiter(i.inputFlag.flag.delimiter ?? ',')))
// trim, and remove surrounding doubleQuotes (which would hav been needed if the elements contain spaces)
.map((v) => v
.trim()
// remove escaped characters from delimiter
// example: --opt="a\,b,c" -> ["a,b", "c"]
.replaceAll(new RegExp(`\\\\${i.inputFlag.flag.delimiter}`, 'g'), i.inputFlag.flag.delimiter ?? ',')
.replace(/^"(.*)"$/, '$1')
.replace(/^'(.*)'$/, '$1'))
.map(async (v) => parseFlagOrThrowError(v, i.inputFlag.flag, this.context, {
...(0, util_1.last)(i.tokens),
input: v,
})))).map((v) => validateOptions(i.inputFlag.flag, v)),
};
}
// multiple in the oclif-core style
if (fws.inputFlag.flag.type === 'option' && fws.inputFlag.flag.multiple) {
return {
...fws,
valueFunction: async (i) => Promise.all((fws.tokens ?? []).map((token) => parseFlagOrThrowError(validateOptions(i.inputFlag.flag, token.input), i.inputFlag.flag, this.context, token))),
};
}
// simple option flag
if (fws.inputFlag.flag.type === 'option') {
return {
...fws,
valueFunction: async (i) => parseFlagOrThrowError(validateOptions(i.inputFlag.flag, (0, util_1.last)(fws.tokens)?.input), i.inputFlag.flag, this.context, (0, util_1.last)(fws.tokens)),
};
}
}
// no input: env flags
if (fws.inputFlag.flag.env && process.env[fws.inputFlag.flag.env]) {
const valueFromEnv = process.env[fws.inputFlag.flag.env];
if (fws.inputFlag.flag.type === 'option' && valueFromEnv) {
return {
...fws,
valueFunction: async (i) => parseFlagOrThrowError(validateOptions(i.inputFlag.flag, valueFromEnv), i.inputFlag.flag, this.context),
};
}
if (fws.inputFlag.flag.type === 'boolean') {
return {
...fws,
valueFunction: async (i) => (0, util_1.isTruthy)(process.env[i.inputFlag.flag.env] ?? 'false'),
};
}
}
// no input, but flag has default value
// eslint-disable-next-line no-constant-binary-expression, valid-typeof
if (typeof fws.inputFlag.flag.default !== undefined) {
return {
...fws,
metadata: { setFromDefault: true },
valueFunction: typeof fws.inputFlag.flag.default === 'function'
? (i, allFlags = {}) => fws.inputFlag.flag.default({ flags: allFlags, options: i.inputFlag.flag })
: async () => fws.inputFlag.flag.default,
};
}
// base case (no value function)
return fws;
};
const addHelpFunction = (fws) => {
if (fws.inputFlag.flag.type === 'option' && fws.inputFlag.flag.defaultHelp) {
return {
...fws,
helpFunction: typeof fws.inputFlag.flag.defaultHelp === 'function'
? (i, flags, ...context) =>
// @ts-expect-error flag type isn't specific enough to know defaultHelp will definitely be there
i.inputFlag.flag.defaultHelp({ flags, options: i.inputFlag }, ...context)
: // @ts-expect-error flag type isn't specific enough to know defaultHelp will definitely be there
(i) => i.inputFlag.flag.defaultHelp,
};
}
return fws;
};
const addDefaultHelp = async (fwsArray) => {
const valueReferenceForHelp = fwsArrayToObject(flagsWithAllValues.filter((fws) => !fws.metadata?.setFromDefault));
return Promise.all(fwsArray.map(async (fws) => {
try {
if (fws.helpFunction) {
return {
...fws,
metadata: {
...fws.metadata,
defaultHelp: await fws.helpFunction?.(fws, valueReferenceForHelp, this.context),
},
};
}
}
catch {
// no-op
}
return fws;
}));
};
const fwsArrayToObject = (fwsArray) => Object.fromEntries(fwsArray.filter((fws) => fws.value !== undefined).map((fws) => [fws.inputFlag.name, fws.value]));
const flagTokenMap = this.mapAndValidateFlags();
const flagsWithValues = await Promise.all(Object.entries(this.input.flags)
// we check them if they have a token, or might have env, default, or defaultHelp. Also include booleans so they get their default value
.filter(([name, flag]) => flag.type === 'boolean' ||
flag.env ||
flag.default !== undefined ||
'defaultHelp' in flag ||
flagTokenMap.has(name))
// match each possible flag to its token, if there is one
.map(([name, flag]) => ({ inputFlag: { flag, name }, tokens: flagTokenMap.get(name) }))
.map((fws) => addValueFunction(fws))
.filter((fws) => fws.valueFunction !== undefined)
.map((fws) => addHelpFunction(fws))
// we can't apply the default values until all the other flags are resolved because `flag.default` can reference other flags
.map(async (fws) => (fws.metadata?.setFromDefault ? fws : { ...fws, value: await fws.valueFunction?.(fws) })));
const valueReference = fwsArrayToObject(flagsWithValues.filter((fws) => !fws.metadata?.setFromDefault));
const flagsWithAllValues = await Promise.all(flagsWithValues.map(async (fws) => fws.metadata?.setFromDefault ? { ...fws, value: await fws.valueFunction?.(fws, valueReference) } : fws));
const finalFlags = flagsWithAllValues.some((fws) => typeof fws.helpFunction === 'function')
? await addDefaultHelp(flagsWithAllValues)
: flagsWithAllValues;
return {
flags: fwsArrayToObject(finalFlags),
metadata: {
flags: Object.fromEntries(finalFlags.filter((fws) => fws.metadata).map((fws) => [fws.inputFlag.name, fws.metadata])),
},
};
}
_setNames() {
for (const k of Object.keys(this.input.flags)) {
this.input.flags[k].name = k;
}
for (const k of Object.keys(this.input.args)) {
this.input.args[k].name = k;
}
}
findFlag(arg) {
const isLong = arg.startsWith('--');
const short = isLong ? false : arg.startsWith('-');
const name = isLong ? this.findLongFlag(arg) : short ? this.findShortFlag(arg) : undefined;
return { isLong, name };
}
findLongFlag(arg) {
const name = arg.slice(2);
if (this.input.flags[name]) {
return name;
}
if (this.flagAliases[name]) {
return this.flagAliases[name].name;
}
if (arg.startsWith(NEGATION)) {
const flag = this.booleanFlags[arg.slice(NEGATION.length)];
if (flag && flag.allowNo)
return flag.name;
const flagAlias = this.flagAliases[arg.slice(NEGATION.length)];
if (flagAlias && flagAlias.type === 'boolean' && flagAlias.allowNo) {
return flagAlias.name;
}
}
}
findShortFlag([_, char]) {
if (this.flagAliases[char]) {
return this.flagAliases[char].name;
}
return Object.keys(this.input.flags).find((k) => this.input.flags[k].char === char && char !== undefined && this.input.flags[k].char !== undefined);
}
mapAndValidateFlags() {
const flagTokenMap = new Map();
for (const token of this.raw.filter((o) => o.type === 'flag')) {
// fail fast if there are any invalid flags
if (!(token.flag in this.input.flags)) {
throw new errors_1.CLIError(`Unexpected flag ${token.flag}`);
}
const existing = flagTokenMap.get(token.flag) ?? [];
flagTokenMap.set(token.flag, [...existing, token]);
}
return flagTokenMap;
}
}
exports.Parser = Parser;

5
node_modules/@oclif/core/lib/parser/validate.d.ts generated vendored Normal file
View File

@@ -0,0 +1,5 @@
import { ParserInput, ParserOutput } from '../interfaces/parser';
export declare function validate(parse: {
input: ParserInput;
output: ParserOutput;
}): Promise<void>;

236
node_modules/@oclif/core/lib/parser/validate.js generated vendored Normal file
View File

@@ -0,0 +1,236 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validate = validate;
const util_1 = require("../util/util");
const errors_1 = require("./errors");
async function validate(parse) {
let cachedResolvedFlags;
function validateArgs() {
if (parse.output.nonExistentFlags?.length > 0) {
throw new errors_1.NonExistentFlagsError({
flags: parse.output.nonExistentFlags,
parse,
});
}
const maxArgs = Object.keys(parse.input.args).length;
if (parse.input.strict && parse.output.argv.length > maxArgs) {
const extras = parse.output.argv.slice(maxArgs);
throw new errors_1.UnexpectedArgsError({
args: extras,
parse,
});
}
const missingRequiredArgs = [];
let hasOptional = false;
for (const [name, arg] of Object.entries(parse.input.args)) {
if (!arg.required) {
hasOptional = true;
}
else if (hasOptional) {
// (required arg) check whether an optional has occurred before
// optionals should follow required, not before
throw new errors_1.InvalidArgsSpecError({
args: parse.input.args,
parse,
});
}
// Only add if it's required and undefined. Allow falsy values like empty strings and 0.
if (arg.required && parse.output.args[name] === undefined) {
missingRequiredArgs.push(arg);
}
}
if (missingRequiredArgs.length > 0) {
const flagsWithMultiple = Object.entries(parse.input.flags)
.filter(([_, flagDef]) => flagDef.type === 'option' && Boolean(flagDef.multiple))
.map(([name]) => name);
throw new errors_1.RequiredArgsError({
args: missingRequiredArgs,
flagsWithMultiple,
parse,
});
}
}
async function validateFlags() {
const promises = Object.entries(parse.input.flags).flatMap(([name, flag]) => {
if (parse.output.flags[name] !== undefined) {
return [
...(flag.relationships ? validateRelationships(name, flag) : []),
...(flag.dependsOn ? [validateDependsOn(name, flag.dependsOn)] : []),
...(flag.exclusive ? [validateExclusive(name, flag.exclusive)] : []),
...(flag.combinable ? [validateCombinable(name, flag.combinable)] : []),
...(flag.exactlyOne ? [validateExactlyOne(name, flag.exactlyOne)] : []),
];
}
if (flag.required) {
return [{ name, reason: `Missing required flag ${name}`, status: 'failed', validationFn: 'required' }];
}
if (flag.exactlyOne && flag.exactlyOne.length > 0) {
return [validateExactlyOneAcrossFlags(flag)];
}
if (flag.atLeastOne && flag.atLeastOne.length > 0) {
return [validateAtLeastOneAcrossFlags(flag)];
}
return [];
});
const results = await Promise.all(promises);
const failed = results.filter((r) => r.status === 'failed');
if (failed.length > 0)
throw new errors_1.FailedFlagValidationError({
failed,
parse,
});
}
async function resolveFlags(flags) {
if (cachedResolvedFlags)
return cachedResolvedFlags;
const promises = flags.map(async (flag) => {
if (typeof flag === 'string') {
return [flag, parse.output.flags[flag]];
}
const result = await flag.when(parse.output.flags);
return result ? [flag.name, parse.output.flags[flag.name]] : null;
});
const resolved = await Promise.all(promises);
cachedResolvedFlags = Object.fromEntries(resolved.filter((r) => r !== null));
return cachedResolvedFlags;
}
const getPresentFlags = (flags) => Object.keys(flags).filter((key) => key !== undefined);
function validateExactlyOneAcrossFlags(flag) {
const base = { name: flag.name, validationFn: 'validateExactlyOneAcrossFlags' };
const intersection = Object.entries(parse.input.flags)
.map((entry) => entry[0]) // array of flag names
.filter((flagName) => parse.output.flags[flagName] !== undefined) // with values
.filter((flagName) => flag.exactlyOne && flag.exactlyOne.includes(flagName)); // and in the exactlyOne list
if (intersection.length === 0) {
// the command's exactlyOne may or may not include itself, so we'll use Set to add + de-dupe
const deduped = (0, util_1.uniq)(flag.exactlyOne?.map((flag) => `--${flag}`) ?? []).join(', ');
const reason = `Exactly one of the following must be provided: ${deduped}`;
return { ...base, reason, status: 'failed' };
}
return { ...base, status: 'success' };
}
function validateAtLeastOneAcrossFlags(flag) {
const base = { name: flag.name, validationFn: 'validateAtLeastOneAcrossFlags' };
const intersection = Object.entries(parse.input.flags)
.map((entry) => entry[0]) // array of flag names
.filter((flagName) => parse.output.flags[flagName] !== undefined) // with values
.filter((flagName) => flag.atLeastOne && flag.atLeastOne.includes(flagName)); // and in the atLeastOne list
if (intersection.length === 0) {
// the command's atLeastOne may or may not include itself, so we'll use Set to add + de-dupe
const deduped = (0, util_1.uniq)(flag.atLeastOne?.map((flag) => `--${flag}`) ?? []).join(', ');
const reason = `At least one of the following must be provided: ${deduped}`;
return { ...base, reason, status: 'failed' };
}
return { ...base, status: 'success' };
}
async function validateExclusive(name, flags) {
const base = { name, validationFn: 'validateExclusive' };
const resolved = await resolveFlags(flags);
const keys = getPresentFlags(resolved);
for (const flag of keys) {
// do not enforce exclusivity for flags that were defaulted
if (parse.output.metadata.flags && parse.output.metadata.flags[flag]?.setFromDefault)
continue;
if (parse.output.metadata.flags && parse.output.metadata.flags[name]?.setFromDefault)
continue;
if (parse.output.flags[flag] !== undefined) {
const flagValue = parse.output.metadata.flags?.[flag]?.defaultHelp ?? parse.output.flags[flag];
return {
...base,
reason: `--${flag}=${flagValue} cannot also be provided when using --${name}`,
status: 'failed',
};
}
}
return { ...base, status: 'success' };
}
async function validateCombinable(name, flags) {
const base = { name, validationFn: 'validateCombinable' };
const combinableFlags = new Set(flags.map((flag) => (typeof flag === 'string' ? flag : flag.name)));
const resolved = await resolveFlags(flags);
for (const flag of Object.keys(parse.output.flags)) {
// do not enforce exclusivity for flags that were defaulted
if (parse.output.metadata.flags && parse.output.metadata.flags[flag]?.setFromDefault)
continue;
if (parse.output.metadata.flags && parse.output.metadata.flags[name]?.setFromDefault)
continue;
if (flag !== name && parse.output.flags[flag] !== undefined && !combinableFlags.has(flag)) {
const formattedFlags = Object.keys(resolved)
.map((f) => `--${f}`)
.join(', ');
return {
...base,
reason: `Only the following can be provided when using --${name}: ${formattedFlags}`,
status: 'failed',
};
}
}
return { ...base, status: 'success' };
}
async function validateExactlyOne(name, flags) {
const base = { name, validationFn: 'validateExactlyOne' };
const resolved = await resolveFlags(flags);
const keys = getPresentFlags(resolved);
for (const flag of keys) {
if (flag !== name && parse.output.flags[flag] !== undefined) {
return { ...base, reason: `--${flag} cannot also be provided when using --${name}`, status: 'failed' };
}
}
return { ...base, status: 'success' };
}
async function validateDependsOn(name, flags) {
const base = { name, validationFn: 'validateDependsOn' };
const resolved = await resolveFlags(flags);
const foundAll = Object.values(resolved).every((val) => val !== undefined);
if (!foundAll) {
const formattedFlags = Object.keys(resolved)
.map((f) => `--${f}`)
.join(', ');
return {
...base,
reason: `All of the following must be provided when using --${name}: ${formattedFlags}`,
status: 'failed',
};
}
return { ...base, status: 'success' };
}
async function validateSome(name, flags) {
const base = { name, validationFn: 'validateSome' };
const resolved = await resolveFlags(flags);
const foundAtLeastOne = Object.values(resolved).some(Boolean);
if (!foundAtLeastOne) {
const formattedFlags = Object.keys(resolved)
.map((f) => `--${f}`)
.join(', ');
return {
...base,
reason: `One of the following must be provided when using --${name}: ${formattedFlags}`,
status: 'failed',
};
}
return { ...base, status: 'success' };
}
function validateRelationships(name, flag) {
return (flag.relationships ?? []).map((relationship) => {
switch (relationship.type) {
case 'all': {
return validateDependsOn(name, relationship.flags);
}
case 'none': {
return validateExclusive(name, relationship.flags);
}
case 'only': {
return validateCombinable(name, relationship.flags);
}
case 'some': {
return validateSome(name, relationship.flags);
}
default: {
throw new Error(`Unknown relationship type: ${relationship.type}`);
}
}
});
}
validateArgs();
return validateFlags();
}