🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@oclif/core

Package Overview
Dependencies
Maintainers
2
Versions
470
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@oclif/core - npm Package Compare versions

Comparing version
4.9.0
to
4.10.0
+3
-2
lib/help/command.js

@@ -60,4 +60,5 @@ "use strict";

return args.map((a) => {
// Add ellipsis to indicate that the argument takes multiple values if strict is false
let name = this.command.strict === false ? `${a.name.toUpperCase()}...` : a.name.toUpperCase();
// Add ellipsis for variadic args, or for all args when strict is false (backward compat)
const suffix = a.multiple ? '...' : this.command.strict === false ? '...' : '';
let name = `${a.name.toUpperCase()}${suffix}`;
name = a.required ? `${name}` : `[${name}]`;

@@ -64,0 +65,0 @@ let description = a.description || '';

+4
-3

@@ -103,7 +103,8 @@ "use strict";

if (this.cmd.args) {
// If strict is false, add ellipsis to indicate that the argument takes multiple values
const suffix = this.cmd.strict === false ? '...' : '';
const a = Object.values((0, ensure_arg_object_1.ensureArgObject)(this.cmd.args))
.filter((arg) => !arg.hidden)
.map((arg) => arg.required ? `${arg.name.toUpperCase()}${suffix}` : `[${arg.name.toUpperCase()}${suffix}]`) || [];
.map((arg) => {
const suffix = arg.multiple ? '...' : this.cmd.strict === false ? '...' : '';
return arg.required ? `${arg.name.toUpperCase()}${suffix}` : `[${arg.name.toUpperCase()}${suffix}]`;
}) || [];
opts.push(...a);

@@ -110,0 +111,0 @@ }

@@ -195,2 +195,7 @@ import { Command } from '../command';

required?: boolean;
/**
* If true, the arg accepts multiple values. Only one arg per command can have multiple: true.
* All args after a variadic arg must be required.
*/
multiple?: boolean;
options?: string[];

@@ -249,2 +254,16 @@ ignoreStdin?: boolean;

export type ArgDefinition<T, P = CustomOptions> = {
(options: P & {
multiple: true;
} & ({
required: true;
} | {
default: ArgDefault<T[]>;
}) & Omit<Partial<Arg<T, P>>, 'default'> & {
default?: ArgDefault<T[] | undefined>;
}): Arg<T[], P>;
(options: P & {
multiple: true;
} & Omit<Partial<Arg<T, P>>, 'default'> & {
default?: ArgDefault<T[] | undefined>;
}): Arg<T[] | undefined, P>;
(options: P & ({

@@ -251,0 +270,0 @@ required: true;

@@ -19,4 +19,5 @@ import { CLIError } from '../errors';

args: ArgInput;
constructor({ args, exit, parse }: CLIParseErrorOptions & {
constructor({ args, exit, parse, reason }: CLIParseErrorOptions & {
args: ArgInput;
reason?: string;
});

@@ -23,0 +24,0 @@ }

@@ -26,4 +26,7 @@ "use strict";

args;
constructor({ args, exit, parse }) {
constructor({ args, exit, parse, reason }) {
let message = 'Invalid argument spec';
if (reason) {
message += `: ${reason}`;
}
const namedArgs = Object.values(args).filter((a) => a.name);

@@ -30,0 +33,0 @@ if (namedArgs.length > 0) {

@@ -204,40 +204,90 @@ "use strict";

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;
const parseArgInput = async (name, arg, input) => {
if (arg.options && !arg.options.includes(input)) {
throw new errors_1.ArgInvalidOptionError(arg, input);
}
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;
ctx.token = { arg: name, input, type: 'arg' };
const parsed = await arg.parse(input, ctx, arg);
argv.push(parsed);
args[name] = parsed;
};
const applyDefault = async (name, arg) => {
if (args[name] !== undefined)
return;
if (!arg.default && arg.default !== false)
return;
const value = typeof arg.default === 'function' ? await arg.default() : arg.default;
if (Array.isArray(value)) {
for (const v of value)
argv.push(v);
}
else {
argv.push(value);
}
args[name] = value;
};
const tryStdin = async (name, arg) => {
if (arg.ignoreStdin || stdinRead)
return;
let stdin = await (0, exports.readStdin)();
stdinRead = true;
if (!stdin)
return;
stdin = stdin.trim();
await parseArgInput(name, arg, stdin);
};
const argEntries = Object.entries(this.input.args);
const variadicIndex = argEntries.findIndex(([, arg]) => arg.multiple);
if (variadicIndex === -1) {
for (const [name, arg] of argEntries) {
const token = tokens.find((t) => t.arg === name);
ctx.token = token;
await (token ? parseArgInput(name, arg, token.input) : tryStdin(name, arg));
await applyDefault(name, arg);
}
// Append unmatched tokens to argv (for strict: false)
for (const token of tokens) {
if (args[token.arg] !== undefined)
continue;
argv.push(token.input);
}
}
else {
const tokenInputs = tokens.map((t) => t.input);
// Consume pre-variadic args from the front
for (let i = 0; i < variadicIndex; i++) {
const [name, arg] = argEntries[i];
const input = tokenInputs.shift();
await (input === undefined ? tryStdin(name, arg) : parseArgInput(name, arg, input));
await applyDefault(name, arg);
}
// Consume post-variadic args from the back
const postVariadicParsing = [];
for (let i = argEntries.length - 1; i > variadicIndex; i--) {
const [name, arg] = argEntries[i];
const input = tokenInputs.pop();
if (input !== undefined) {
postVariadicParsing.unshift({ arg, input, name });
}
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;
// Everything remaining goes to the variadic arg
const [variadicName, variadicArg] = argEntries[variadicIndex];
if (tokenInputs.length > 0) {
const parsedValues = [];
for (const input of tokenInputs) {
await parseArgInput(variadicName, variadicArg, input);
parsedValues.push(args[variadicName]);
}
else {
argv.push(arg.default);
args[name] = arg.default;
}
args[variadicName] = parsedValues;
}
for (const { arg, input, name } of postVariadicParsing) {
await parseArgInput(name, arg, input);
}
// Apply defaults for any args that didn't receive values
await applyDefault(variadicName, variadicArg);
for (let i = variadicIndex + 1; i < argEntries.length; i++) {
const [name, arg] = argEntries[i];
await applyDefault(name, arg);
}
}
for (const token of tokens) {
if (args[token.arg] !== undefined)
continue;
argv.push(token.input);
}
return { args, argv };

@@ -244,0 +294,0 @@ }

@@ -9,2 +9,37 @@ "use strict";

function validateArgs() {
// Validate variadic arg constraints (definition-time checks)
const argEntries = Object.entries(parse.input.args);
const variadicIndex = argEntries.findIndex(([, arg]) => arg.multiple);
if (variadicIndex !== -1) {
// Only one variadic arg is allowed
const secondVariadic = argEntries.findIndex(([, arg], i) => i > variadicIndex && arg.multiple);
if (secondVariadic !== -1) {
throw new errors_1.InvalidArgsSpecError({
args: parse.input.args,
parse,
reason: 'only one variadic arg (multiple: true) is allowed',
});
}
// All args before a variadic arg must be required (otherwise assignment is ambiguous)
for (let i = 0; i < variadicIndex; i++) {
if (!argEntries[i][1].required) {
throw new errors_1.InvalidArgsSpecError({
args: parse.input.args,
parse,
reason: `args before a variadic arg must be required, but "${argEntries[i][0]}" is optional`,
});
}
}
// All args after a variadic arg must be required (otherwise assignment is ambiguous)
for (let i = variadicIndex + 1; i < argEntries.length; i++) {
if (!argEntries[i][1].required) {
throw new errors_1.InvalidArgsSpecError({
args: parse.input.args,
parse,
reason: `args after a variadic arg must be required, but "${argEntries[i][0]}" is optional`,
});
}
}
}
const variadicArgFound = variadicIndex !== -1;
if (parse.output.nonExistentFlags?.length > 0) {

@@ -17,3 +52,4 @@ throw new errors_1.NonExistentFlagsError({

const maxArgs = Object.keys(parse.input.args).length;
if (parse.input.strict && parse.output.argv.length > maxArgs) {
const hasVariadicArg = Object.values(parse.input.args).some((arg) => arg.multiple);
if (parse.input.strict && !hasVariadicArg && parse.output.argv.length > maxArgs) {
const extras = parse.output.argv.slice(maxArgs);

@@ -31,5 +67,7 @@ throw new errors_1.UnexpectedArgsError({

}
else if (hasOptional) {
else if (hasOptional && !variadicArgFound) {
// (required arg) check whether an optional has occurred before
// optionals should follow required, not before
// Skip this check when a variadic arg is present, since the variadic
// validation above already enforces that args after a variadic are required
throw new errors_1.InvalidArgsSpecError({

@@ -36,0 +74,0 @@ args: parse.input.args,

@@ -63,2 +63,3 @@ "use strict";

hidden: arg.hidden,
multiple: arg.multiple,
name,

@@ -65,0 +66,0 @@ noCacheDefault: arg.noCacheDefault,

{
"name": "@oclif/core",
"description": "base library for oclif CLIs",
"version": "4.9.0",
"version": "4.10.0",
"author": "Salesforce",

@@ -6,0 +6,0 @@ "bugs": "https://github.com/oclif/core/issues",