@oclif/core 1.3.6 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/lib/command.d.ts +4 -2
- package/lib/command.js +16 -7
- package/lib/config/config.js +27 -1
- package/lib/flags.d.ts +1 -1
- package/lib/flags.js +3 -1
- package/lib/help/index.d.ts +1 -0
- package/lib/help/index.js +20 -2
- package/lib/interfaces/command.d.ts +3 -0
- package/lib/interfaces/index.d.ts +1 -1
- package/lib/interfaces/parser.d.ts +2 -0
- package/lib/parser/flags.d.ts +6 -0
- package/lib/parser/flags.js +34 -1
- package/lib/parser/index.d.ts +6 -2
- package/lib/parser/index.js +4 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [1.5.1](https://github.com/oclif/core/compare/v1.5.0...v1.5.1) (2022-03-03)
|
|
6
|
+
|
|
7
|
+
## [1.5.0](https://github.com/oclif/core/compare/v1.4.0...v1.5.0) (2022-03-02)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
* dir and file flags that validate existence and type ([#384](https://github.com/oclif/core/issues/384)) ([44dff41](https://github.com/oclif/core/commit/44dff41c5a3ffcdcbf2f10dcefb7c1ab233bfc4f))
|
|
13
|
+
|
|
14
|
+
## [1.4.0](https://github.com/oclif/core/compare/v1.3.6...v1.4.0) (2022-03-01)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
* make global flags settable ([#385](https://github.com/oclif/core/issues/385)) ([e14061c](https://github.com/oclif/core/commit/e14061ca7e6a4c288eb50e0e9954b38e042682df))
|
|
20
|
+
|
|
5
21
|
### [1.3.6](https://github.com/oclif/core/compare/v1.3.5...v1.3.6) (2022-02-28)
|
|
6
22
|
|
|
7
23
|
|
package/lib/command.d.ts
CHANGED
|
@@ -63,9 +63,11 @@ export default abstract class Command {
|
|
|
63
63
|
* @param {Interfaces.LoadOptions} opts options
|
|
64
64
|
*/
|
|
65
65
|
static run: Interfaces.Command.Class['run'];
|
|
66
|
-
|
|
66
|
+
protected static _globalFlags: Interfaces.FlagInput<any>;
|
|
67
|
+
static get globalFlags(): Interfaces.FlagInput<any>;
|
|
68
|
+
static set globalFlags(flags: Interfaces.FlagInput<any>);
|
|
67
69
|
/** A hash of flags for the command */
|
|
68
|
-
|
|
70
|
+
protected static _flags: Interfaces.FlagInput<any>;
|
|
69
71
|
static get flags(): Interfaces.FlagInput<any>;
|
|
70
72
|
static set flags(flags: Interfaces.FlagInput<any>);
|
|
71
73
|
id: string | undefined;
|
package/lib/command.js
CHANGED
|
@@ -17,6 +17,12 @@ process.stdout.on('error', (err) => {
|
|
|
17
17
|
return;
|
|
18
18
|
throw err;
|
|
19
19
|
});
|
|
20
|
+
const jsonFlag = {
|
|
21
|
+
json: Flags.boolean({
|
|
22
|
+
description: 'Format output as json.',
|
|
23
|
+
helpGroup: 'GLOBAL',
|
|
24
|
+
}),
|
|
25
|
+
};
|
|
20
26
|
/**
|
|
21
27
|
* An abstract class which acts as the base for each command
|
|
22
28
|
* in your project.
|
|
@@ -33,11 +39,20 @@ class Command {
|
|
|
33
39
|
this.debug = () => { };
|
|
34
40
|
}
|
|
35
41
|
}
|
|
42
|
+
static get globalFlags() {
|
|
43
|
+
return this._globalFlags;
|
|
44
|
+
}
|
|
45
|
+
static set globalFlags(flags) {
|
|
46
|
+
this._globalFlags = this.enableJsonFlag ?
|
|
47
|
+
Object.assign({}, jsonFlag, this.globalFlags, flags) :
|
|
48
|
+
Object.assign({}, this.globalFlags, flags);
|
|
49
|
+
}
|
|
36
50
|
static get flags() {
|
|
37
51
|
return this._flags;
|
|
38
52
|
}
|
|
39
53
|
static set flags(flags) {
|
|
40
|
-
this.
|
|
54
|
+
this.globalFlags = {};
|
|
55
|
+
this._flags = Object.assign({}, this.globalFlags, flags);
|
|
41
56
|
}
|
|
42
57
|
get ctor() {
|
|
43
58
|
return this.constructor;
|
|
@@ -169,9 +184,3 @@ Command.run = async function (argv, opts) {
|
|
|
169
184
|
const cmd = new this(argv, config);
|
|
170
185
|
return cmd._run(argv);
|
|
171
186
|
};
|
|
172
|
-
Command.globalFlags = {
|
|
173
|
-
json: Flags.boolean({
|
|
174
|
-
description: 'Format output as json.',
|
|
175
|
-
helpGroup: 'GLOBAL',
|
|
176
|
-
}),
|
|
177
|
-
};
|
package/lib/config/config.js
CHANGED
|
@@ -473,6 +473,28 @@ class Config {
|
|
|
473
473
|
}
|
|
474
474
|
}
|
|
475
475
|
exports.Config = Config;
|
|
476
|
+
// when no manifest exists, the default is calculated. This may throw, so we need to catch it
|
|
477
|
+
const defaultToCached = async (flag) => {
|
|
478
|
+
// Prefer the helpDefaultValue function (returns a friendly string for complex types)
|
|
479
|
+
if (typeof flag.defaultHelp === 'function') {
|
|
480
|
+
try {
|
|
481
|
+
return await flag.defaultHelp();
|
|
482
|
+
}
|
|
483
|
+
catch {
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
// if not specified, try the default function
|
|
488
|
+
if (typeof flag.default === 'function') {
|
|
489
|
+
try {
|
|
490
|
+
return await flag.default({ options: {}, flags: {} });
|
|
491
|
+
}
|
|
492
|
+
catch { }
|
|
493
|
+
}
|
|
494
|
+
else {
|
|
495
|
+
return flag.default;
|
|
496
|
+
}
|
|
497
|
+
};
|
|
476
498
|
async function toCached(c, plugin) {
|
|
477
499
|
const flags = {};
|
|
478
500
|
for (const [name, flag] of Object.entries(c.flags || {})) {
|
|
@@ -508,8 +530,12 @@ async function toCached(c, plugin) {
|
|
|
508
530
|
options: flag.options,
|
|
509
531
|
dependsOn: flag.dependsOn,
|
|
510
532
|
exclusive: flag.exclusive,
|
|
511
|
-
default:
|
|
533
|
+
default: await defaultToCached(flag),
|
|
512
534
|
};
|
|
535
|
+
// a command-level placeholder in the manifest so that oclif knows it should regenerate the command during help-time
|
|
536
|
+
if (typeof flag.defaultHelp === 'function') {
|
|
537
|
+
c.hasDynamicHelp = true;
|
|
538
|
+
}
|
|
513
539
|
}
|
|
514
540
|
}
|
|
515
541
|
const argsPromise = (c.args || []).map(async (a) => ({
|
package/lib/flags.d.ts
CHANGED
|
@@ -10,6 +10,6 @@ declare const _enum: <T = string>(opts: EnumFlagOptions<T>) => OptionFlag<T>;
|
|
|
10
10
|
export { _enum as enum };
|
|
11
11
|
declare const stringFlag: Definition<string>;
|
|
12
12
|
export { stringFlag as string };
|
|
13
|
-
export { boolean, integer, url } from './parser';
|
|
13
|
+
export { boolean, integer, url, directory, file } from './parser';
|
|
14
14
|
export declare const version: (opts?: Partial<BooleanFlag<boolean>>) => BooleanFlag<void>;
|
|
15
15
|
export declare const help: (opts?: Partial<BooleanFlag<boolean>>) => BooleanFlag<void>;
|
package/lib/flags.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.help = exports.version = exports.url = exports.integer = exports.boolean = exports.string = exports.enum = exports.option = exports.build = void 0;
|
|
3
|
+
exports.help = exports.version = exports.file = exports.directory = exports.url = exports.integer = exports.boolean = exports.string = exports.enum = exports.option = exports.build = void 0;
|
|
4
4
|
const Parser = require("./parser");
|
|
5
5
|
function build(defaults) {
|
|
6
6
|
return Parser.flags.build(defaults);
|
|
@@ -28,6 +28,8 @@ var parser_1 = require("./parser");
|
|
|
28
28
|
Object.defineProperty(exports, "boolean", { enumerable: true, get: function () { return parser_1.boolean; } });
|
|
29
29
|
Object.defineProperty(exports, "integer", { enumerable: true, get: function () { return parser_1.integer; } });
|
|
30
30
|
Object.defineProperty(exports, "url", { enumerable: true, get: function () { return parser_1.url; } });
|
|
31
|
+
Object.defineProperty(exports, "directory", { enumerable: true, get: function () { return parser_1.directory; } });
|
|
32
|
+
Object.defineProperty(exports, "file", { enumerable: true, get: function () { return parser_1.file; } });
|
|
31
33
|
const version = (opts = {}) => {
|
|
32
34
|
return Parser.flags.boolean({
|
|
33
35
|
description: 'Show CLI version.',
|
package/lib/help/index.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ export declare class Help extends HelpBase {
|
|
|
25
25
|
protected get sortedTopics(): Interfaces.Topic[];
|
|
26
26
|
constructor(config: Interfaces.Config, opts?: Partial<Interfaces.HelpOptions>);
|
|
27
27
|
showHelp(argv: string[]): Promise<void>;
|
|
28
|
+
private getDynamicCommand;
|
|
28
29
|
showCommandHelp(command: Interfaces.Command): Promise<void>;
|
|
29
30
|
protected showRootHelp(): Promise<void>;
|
|
30
31
|
protected showTopicHelp(topic: Interfaces.Topic): Promise<void>;
|
package/lib/help/index.js
CHANGED
|
@@ -8,6 +8,8 @@ const root_1 = require("./root");
|
|
|
8
8
|
const util_1 = require("../util");
|
|
9
9
|
const util_2 = require("./util");
|
|
10
10
|
const formatter_1 = require("./formatter");
|
|
11
|
+
const plugin_1 = require("../config/plugin");
|
|
12
|
+
const config_1 = require("../config/config");
|
|
11
13
|
var command_2 = require("./command");
|
|
12
14
|
Object.defineProperty(exports, "CommandHelp", { enumerable: true, get: function () { return command_2.CommandHelp; } });
|
|
13
15
|
var util_3 = require("./util");
|
|
@@ -89,7 +91,13 @@ class Help extends HelpBase {
|
|
|
89
91
|
}
|
|
90
92
|
const command = this.config.findCommand(subject);
|
|
91
93
|
if (command) {
|
|
92
|
-
|
|
94
|
+
if (command.hasDynamicHelp) {
|
|
95
|
+
const dynamicCommand = await (0, config_1.toCached)(await this.getDynamicCommand(command.id));
|
|
96
|
+
await this.showCommandHelp(dynamicCommand);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
await this.showCommandHelp(command);
|
|
100
|
+
}
|
|
93
101
|
return;
|
|
94
102
|
}
|
|
95
103
|
const topic = this.config.findTopic(subject);
|
|
@@ -99,6 +107,15 @@ class Help extends HelpBase {
|
|
|
99
107
|
}
|
|
100
108
|
(0, errors_1.error)(`Command ${subject} not found.`);
|
|
101
109
|
}
|
|
110
|
+
async getDynamicCommand(cmdName) {
|
|
111
|
+
const plugin = new plugin_1.Plugin({ ignoreManifest: true, root: this.config.root });
|
|
112
|
+
await plugin.load();
|
|
113
|
+
const cmd = await plugin.findCommand(cmdName);
|
|
114
|
+
if (!cmd) {
|
|
115
|
+
throw new Error(`Command ${cmdName} not found.`);
|
|
116
|
+
}
|
|
117
|
+
return cmd;
|
|
118
|
+
}
|
|
102
119
|
async showCommandHelp(command) {
|
|
103
120
|
var _a, _b, _c, _d;
|
|
104
121
|
const name = command.id;
|
|
@@ -110,8 +127,9 @@ class Help extends HelpBase {
|
|
|
110
127
|
if (state)
|
|
111
128
|
console.log(`This command is in ${state}.\n`);
|
|
112
129
|
const summary = this.summary(command);
|
|
113
|
-
if (summary)
|
|
130
|
+
if (summary) {
|
|
114
131
|
console.log(summary + '\n');
|
|
132
|
+
}
|
|
115
133
|
console.log(this.formatCommand(command));
|
|
116
134
|
console.log('');
|
|
117
135
|
if (subTopics.length > 0) {
|
|
@@ -54,6 +54,7 @@ export interface Command extends CommandProps {
|
|
|
54
54
|
};
|
|
55
55
|
args: Command.Arg[];
|
|
56
56
|
strict: boolean;
|
|
57
|
+
hasDynamicHelp?: boolean;
|
|
57
58
|
}
|
|
58
59
|
export declare namespace Command {
|
|
59
60
|
interface Arg {
|
|
@@ -70,6 +71,7 @@ export declare namespace Command {
|
|
|
70
71
|
}
|
|
71
72
|
interface Option extends OptionFlagProps {
|
|
72
73
|
default?: string;
|
|
74
|
+
defaultHelp?: () => Promise<string>;
|
|
73
75
|
}
|
|
74
76
|
}
|
|
75
77
|
interface Base extends CommandProps {
|
|
@@ -80,6 +82,7 @@ export declare namespace Command {
|
|
|
80
82
|
flags?: FlagInput<any>;
|
|
81
83
|
args?: ArgInput;
|
|
82
84
|
strict: boolean;
|
|
85
|
+
hasDynamicHelp?: boolean;
|
|
83
86
|
new (argv: string[], config: Config): Instance;
|
|
84
87
|
run(argv?: string[], config?: LoadOptions): PromiseLike<any>;
|
|
85
88
|
}
|
|
@@ -6,7 +6,7 @@ export { HelpOptions } from './help';
|
|
|
6
6
|
export { Hook, Hooks } from './hooks';
|
|
7
7
|
export { Manifest } from './manifest';
|
|
8
8
|
export { S3Manifest } from './s3-manifest';
|
|
9
|
-
export { ParserArg, Arg, ParseFn, ParserOutput, ParserInput, ArgToken, OptionalArg, FlagOutput, OutputArgs, OutputFlags, FlagUsageOptions, CLIParseErrorOptions, ArgInput, RequiredArg, Metadata, ParsingToken, FlagToken, List, ListItem, BooleanFlag, Flag, FlagBase, OptionFlag, Input, EnumFlagOptions, DefaultContext, Default, Definition, CompletableOptionFlag, Completion, CompletionContext, FlagInput, CompletableFlag, } from './parser';
|
|
9
|
+
export { ParserArg, Arg, ParseFn, ParserOutput, ParserInput, ArgToken, OptionalArg, FlagOutput, OutputArgs, OutputFlags, FlagUsageOptions, CLIParseErrorOptions, ArgInput, RequiredArg, Metadata, ParsingToken, FlagToken, List, ListItem, BooleanFlag, Flag, FlagBase, OptionFlag, Input, EnumFlagOptions, DefaultContext, Default, Definition, CompletableOptionFlag, Completion, CompletionContext, FlagInput, CompletableFlag, OptionFlagProps, } from './parser';
|
|
10
10
|
export { PJSON } from './pjson';
|
|
11
11
|
export { Plugin, PluginOptions, Options } from './plugin';
|
|
12
12
|
export { Topic } from './topic';
|
|
@@ -85,6 +85,7 @@ export declare type DefaultContext<T> = {
|
|
|
85
85
|
};
|
|
86
86
|
};
|
|
87
87
|
export declare type Default<T> = T | ((context: DefaultContext<T>) => Promise<T>);
|
|
88
|
+
export declare type DefaultHelp<T> = T | ((context: DefaultContext<T>) => Promise<string | undefined>);
|
|
88
89
|
export declare type FlagProps = {
|
|
89
90
|
name: string;
|
|
90
91
|
char?: AlphabetLowercase | AlphabetUppercase;
|
|
@@ -139,6 +140,7 @@ export declare type BooleanFlag<T> = FlagBase<T, boolean> & BooleanFlagProps & {
|
|
|
139
140
|
};
|
|
140
141
|
export declare type OptionFlag<T> = FlagBase<T, string> & OptionFlagProps & {
|
|
141
142
|
default?: Default<T | undefined>;
|
|
143
|
+
defaultHelp?: DefaultHelp<T>;
|
|
142
144
|
input: string[];
|
|
143
145
|
};
|
|
144
146
|
export declare type Definition<T> = {
|
package/lib/parser/flags.d.ts
CHANGED
|
@@ -7,6 +7,12 @@ export declare function build<T>(defaults: {
|
|
|
7
7
|
export declare function build(defaults: Partial<OptionFlag<string>>): Definition<string>;
|
|
8
8
|
export declare function boolean<T = boolean>(options?: Partial<BooleanFlag<T>>): BooleanFlag<T>;
|
|
9
9
|
export declare const integer: Definition<number>;
|
|
10
|
+
export declare const directory: (opts?: {
|
|
11
|
+
exists?: boolean;
|
|
12
|
+
} & Partial<OptionFlag<string>>) => OptionFlag<string | undefined>;
|
|
13
|
+
export declare const file: (opts?: {
|
|
14
|
+
exists?: boolean;
|
|
15
|
+
} & Partial<OptionFlag<string>>) => OptionFlag<string | undefined>;
|
|
10
16
|
/**
|
|
11
17
|
* Initializes a string as a URL. Throws an error
|
|
12
18
|
* if the string is not a valid URL.
|
package/lib/parser/flags.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// tslint:disable interface-over-type-literal
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.defaultFlags = exports.string = exports.option = exports.url = exports.integer = exports.boolean = exports.build = void 0;
|
|
4
|
+
exports.defaultFlags = exports.string = exports.option = exports.url = exports.file = exports.directory = exports.integer = exports.boolean = exports.build = void 0;
|
|
5
5
|
const url_1 = require("url");
|
|
6
|
+
const fs = require("fs");
|
|
6
7
|
function build(defaults) {
|
|
7
8
|
return (options = {}) => {
|
|
8
9
|
return {
|
|
@@ -32,6 +33,20 @@ exports.integer = build({
|
|
|
32
33
|
return Number.parseInt(input, 10);
|
|
33
34
|
},
|
|
34
35
|
});
|
|
36
|
+
const directory = (opts = {}) => {
|
|
37
|
+
return build({
|
|
38
|
+
...opts,
|
|
39
|
+
parse: async (input) => opts.exists ? dirExists(input) : input,
|
|
40
|
+
})();
|
|
41
|
+
};
|
|
42
|
+
exports.directory = directory;
|
|
43
|
+
const file = (opts = {}) => {
|
|
44
|
+
return build({
|
|
45
|
+
...opts,
|
|
46
|
+
parse: async (input) => opts.exists ? fileExists(input) : input,
|
|
47
|
+
})();
|
|
48
|
+
};
|
|
49
|
+
exports.file = file;
|
|
35
50
|
/**
|
|
36
51
|
* Initializes a string as a URL. Throws an error
|
|
37
52
|
* if the string is not a valid URL.
|
|
@@ -55,3 +70,21 @@ exports.string = stringFlag;
|
|
|
55
70
|
exports.defaultFlags = {
|
|
56
71
|
color: boolean({ allowNo: true }),
|
|
57
72
|
};
|
|
73
|
+
const dirExists = async (input) => {
|
|
74
|
+
if (!fs.existsSync(input)) {
|
|
75
|
+
throw new Error(`No directory found at ${input}`);
|
|
76
|
+
}
|
|
77
|
+
if (!(await fs.promises.stat(input)).isDirectory()) {
|
|
78
|
+
throw new Error(`${input} exists but is not a directory`);
|
|
79
|
+
}
|
|
80
|
+
return input;
|
|
81
|
+
};
|
|
82
|
+
const fileExists = async (input) => {
|
|
83
|
+
if (!fs.existsSync(input)) {
|
|
84
|
+
throw new Error(`No file found at ${input}`);
|
|
85
|
+
}
|
|
86
|
+
if (!(await fs.promises.stat(input)).isFile()) {
|
|
87
|
+
throw new Error(`${input} exists but is not a file`);
|
|
88
|
+
}
|
|
89
|
+
return input;
|
|
90
|
+
};
|
package/lib/parser/index.d.ts
CHANGED
|
@@ -8,5 +8,9 @@ export { flagUsages } from './help';
|
|
|
8
8
|
export declare function parse<TFlags, TArgs extends {
|
|
9
9
|
[name: string]: string;
|
|
10
10
|
}>(argv: string[], options: Input<TFlags>): Promise<ParserOutput<TFlags, TArgs>>;
|
|
11
|
-
declare const boolean: typeof flags.boolean, integer: import("../interfaces").Definition<number>, url: import("../interfaces").Definition<import("url").URL
|
|
12
|
-
|
|
11
|
+
declare const boolean: typeof flags.boolean, integer: import("../interfaces").Definition<number>, url: import("../interfaces").Definition<import("url").URL>, directory: (opts?: {
|
|
12
|
+
exists?: boolean | undefined;
|
|
13
|
+
} & Partial<import("../interfaces").OptionFlag<string>>) => import("../interfaces").OptionFlag<string | undefined>, file: (opts?: {
|
|
14
|
+
exists?: boolean | undefined;
|
|
15
|
+
} & Partial<import("../interfaces").OptionFlag<string>>) => import("../interfaces").OptionFlag<string | undefined>;
|
|
16
|
+
export { boolean, integer, url, directory, file };
|
package/lib/parser/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// tslint:disable interface-over-type-literal
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.url = exports.integer = exports.boolean = exports.parse = exports.flagUsages = exports.flags = exports.args = void 0;
|
|
4
|
+
exports.file = exports.directory = exports.url = exports.integer = exports.boolean = exports.parse = exports.flagUsages = exports.flags = exports.args = void 0;
|
|
5
5
|
const args = require("./args");
|
|
6
6
|
exports.args = args;
|
|
7
7
|
const deps_1 = require("./deps");
|
|
@@ -32,7 +32,9 @@ async function parse(argv, options) {
|
|
|
32
32
|
return output;
|
|
33
33
|
}
|
|
34
34
|
exports.parse = parse;
|
|
35
|
-
const { boolean, integer, url } = flags;
|
|
35
|
+
const { boolean, integer, url, directory, file } = flags;
|
|
36
36
|
exports.boolean = boolean;
|
|
37
37
|
exports.integer = integer;
|
|
38
38
|
exports.url = url;
|
|
39
|
+
exports.directory = directory;
|
|
40
|
+
exports.file = file;
|