@oclif/core 2.6.5 → 2.7.0
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/lib/config/config.d.ts +1 -1
- package/lib/config/config.js +9 -9
- package/lib/config/plugin.d.ts +8 -2
- package/lib/config/plugin.js +10 -4
- package/lib/help/index.js +1 -1
- package/lib/interfaces/parser.d.ts +86 -4
- package/lib/interfaces/plugin.d.ts +1 -1
- package/lib/parser/parse.js +8 -2
- package/lib/parser/validate.js +2 -1
- package/package.json +4 -4
package/lib/config/config.d.ts
CHANGED
|
@@ -136,4 +136,4 @@ export declare class Config implements IConfig {
|
|
|
136
136
|
private determinePriority;
|
|
137
137
|
private insertLegacyPlugins;
|
|
138
138
|
}
|
|
139
|
-
export declare function toCached(c: Command.Class, plugin?: IPlugin): Promise<Command.Cached>;
|
|
139
|
+
export declare function toCached(c: Command.Class, plugin?: IPlugin | undefined, isWritingManifest?: boolean): Promise<Command.Cached>;
|
package/lib/config/config.js
CHANGED
|
@@ -713,11 +713,11 @@ class Config {
|
|
|
713
713
|
}
|
|
714
714
|
exports.Config = Config;
|
|
715
715
|
// when no manifest exists, the default is calculated. This may throw, so we need to catch it
|
|
716
|
-
const defaultFlagToCached = async (flag) => {
|
|
716
|
+
const defaultFlagToCached = async (flag, isWritingManifest = false) => {
|
|
717
717
|
// Prefer the helpDefaultValue function (returns a friendly string for complex types)
|
|
718
718
|
if (typeof flag.defaultHelp === 'function') {
|
|
719
719
|
try {
|
|
720
|
-
return await flag.defaultHelp();
|
|
720
|
+
return await flag.defaultHelp({ options: flag, flags: {} }, isWritingManifest);
|
|
721
721
|
}
|
|
722
722
|
catch {
|
|
723
723
|
return;
|
|
@@ -726,7 +726,7 @@ const defaultFlagToCached = async (flag) => {
|
|
|
726
726
|
// if not specified, try the default function
|
|
727
727
|
if (typeof flag.default === 'function') {
|
|
728
728
|
try {
|
|
729
|
-
return await flag.default({ options: {}, flags: {} });
|
|
729
|
+
return await flag.default({ options: {}, flags: {} }, isWritingManifest);
|
|
730
730
|
}
|
|
731
731
|
catch { }
|
|
732
732
|
}
|
|
@@ -734,11 +734,11 @@ const defaultFlagToCached = async (flag) => {
|
|
|
734
734
|
return flag.default;
|
|
735
735
|
}
|
|
736
736
|
};
|
|
737
|
-
const defaultArgToCached = async (arg) => {
|
|
737
|
+
const defaultArgToCached = async (arg, isWritingManifest = false) => {
|
|
738
738
|
// Prefer the helpDefaultValue function (returns a friendly string for complex types)
|
|
739
739
|
if (typeof arg.defaultHelp === 'function') {
|
|
740
740
|
try {
|
|
741
|
-
return await arg.defaultHelp();
|
|
741
|
+
return await arg.defaultHelp({ options: arg, flags: {} }, isWritingManifest);
|
|
742
742
|
}
|
|
743
743
|
catch {
|
|
744
744
|
return;
|
|
@@ -747,7 +747,7 @@ const defaultArgToCached = async (arg) => {
|
|
|
747
747
|
// if not specified, try the default function
|
|
748
748
|
if (typeof arg.default === 'function') {
|
|
749
749
|
try {
|
|
750
|
-
return await arg.default({ options:
|
|
750
|
+
return await arg.default({ options: arg, flags: {} }, isWritingManifest);
|
|
751
751
|
}
|
|
752
752
|
catch { }
|
|
753
753
|
}
|
|
@@ -755,7 +755,7 @@ const defaultArgToCached = async (arg) => {
|
|
|
755
755
|
return arg.default;
|
|
756
756
|
}
|
|
757
757
|
};
|
|
758
|
-
async function toCached(c, plugin) {
|
|
758
|
+
async function toCached(c, plugin, isWritingManifest) {
|
|
759
759
|
const flags = {};
|
|
760
760
|
for (const [name, flag] of Object.entries(c.flags || {})) {
|
|
761
761
|
if (flag.type === 'boolean') {
|
|
@@ -796,7 +796,7 @@ async function toCached(c, plugin) {
|
|
|
796
796
|
dependsOn: flag.dependsOn,
|
|
797
797
|
relationships: flag.relationships,
|
|
798
798
|
exclusive: flag.exclusive,
|
|
799
|
-
default: await defaultFlagToCached(flag),
|
|
799
|
+
default: await defaultFlagToCached(flag, isWritingManifest),
|
|
800
800
|
deprecated: flag.deprecated,
|
|
801
801
|
deprecateAliases: c.deprecateAliases,
|
|
802
802
|
aliases: flag.aliases,
|
|
@@ -815,7 +815,7 @@ async function toCached(c, plugin) {
|
|
|
815
815
|
description: arg.description,
|
|
816
816
|
required: arg.required,
|
|
817
817
|
options: arg.options,
|
|
818
|
-
default: await defaultArgToCached(arg),
|
|
818
|
+
default: await defaultArgToCached(arg, isWritingManifest),
|
|
819
819
|
hidden: arg.hidden,
|
|
820
820
|
};
|
|
821
821
|
}
|
package/lib/config/plugin.d.ts
CHANGED
|
@@ -28,7 +28,13 @@ export declare class Plugin implements IPlugin {
|
|
|
28
28
|
protected _debug: (..._: any) => void;
|
|
29
29
|
protected warned: boolean;
|
|
30
30
|
constructor(options: PluginOptions);
|
|
31
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Loads a plugin
|
|
33
|
+
* @param isWritingManifest - if true, exclude selected data from manifest
|
|
34
|
+
* default is false to maintain backwards compatibility
|
|
35
|
+
* @returns Promise<void>
|
|
36
|
+
*/
|
|
37
|
+
load(isWritingManifest?: boolean): Promise<void>;
|
|
32
38
|
get topics(): Topic[];
|
|
33
39
|
get commandsDir(): string | undefined;
|
|
34
40
|
get commandIDs(): string[];
|
|
@@ -38,7 +44,7 @@ export declare class Plugin implements IPlugin {
|
|
|
38
44
|
findCommand(id: string, opts?: {
|
|
39
45
|
must: boolean;
|
|
40
46
|
}): Promise<Command.Class | undefined>;
|
|
41
|
-
protected _manifest(ignoreManifest: boolean, errorOnManifestCreate?: boolean): Promise<Manifest>;
|
|
47
|
+
protected _manifest(ignoreManifest: boolean, errorOnManifestCreate?: boolean, isWritingManifest?: boolean): Promise<Manifest>;
|
|
42
48
|
protected warn(err: string | Error | CLIError, scope?: string): void;
|
|
43
49
|
private addErrorScope;
|
|
44
50
|
}
|
package/lib/config/plugin.js
CHANGED
|
@@ -100,7 +100,13 @@ class Plugin {
|
|
|
100
100
|
this._debug = (0, util_2.Debug)();
|
|
101
101
|
this.warned = false;
|
|
102
102
|
}
|
|
103
|
-
|
|
103
|
+
/**
|
|
104
|
+
* Loads a plugin
|
|
105
|
+
* @param isWritingManifest - if true, exclude selected data from manifest
|
|
106
|
+
* default is false to maintain backwards compatibility
|
|
107
|
+
* @returns Promise<void>
|
|
108
|
+
*/
|
|
109
|
+
async load(isWritingManifest) {
|
|
104
110
|
this.type = this.options.type || 'core';
|
|
105
111
|
this.tag = this.options.tag;
|
|
106
112
|
const root = await findRoot(this.options.name, this.options.root);
|
|
@@ -126,7 +132,7 @@ class Plugin {
|
|
|
126
132
|
this.pjson.oclif = this.pjson['cli-engine'] || {};
|
|
127
133
|
}
|
|
128
134
|
this.hooks = (0, util_3.mapValues)(this.pjson.oclif.hooks || {}, i => Array.isArray(i) ? i : [i]);
|
|
129
|
-
this.manifest = await this._manifest(Boolean(this.options.ignoreManifest), Boolean(this.options.errorOnManifestCreate));
|
|
135
|
+
this.manifest = await this._manifest(Boolean(this.options.ignoreManifest), Boolean(this.options.errorOnManifestCreate), isWritingManifest);
|
|
130
136
|
this.commands = Object
|
|
131
137
|
.entries(this.manifest.commands)
|
|
132
138
|
.map(([id, c]) => ({
|
|
@@ -205,7 +211,7 @@ class Plugin {
|
|
|
205
211
|
marker?.stop();
|
|
206
212
|
return cmd;
|
|
207
213
|
}
|
|
208
|
-
async _manifest(ignoreManifest, errorOnManifestCreate = false) {
|
|
214
|
+
async _manifest(ignoreManifest, errorOnManifestCreate = false, isWritingManifest = false) {
|
|
209
215
|
const readManifest = async (dotfile = false) => {
|
|
210
216
|
try {
|
|
211
217
|
const p = path.join(this.root, `${dotfile ? '.' : ''}oclif.manifest.json`);
|
|
@@ -242,7 +248,7 @@ class Plugin {
|
|
|
242
248
|
version: this.version,
|
|
243
249
|
commands: (await Promise.all(this.commandIDs.map(async (id) => {
|
|
244
250
|
try {
|
|
245
|
-
return [id, await (0, config_1.toCached)(await this.findCommand(id, { must: true }), this)];
|
|
251
|
+
return [id, await (0, config_1.toCached)(await this.findCommand(id, { must: true }), this, isWritingManifest)];
|
|
246
252
|
}
|
|
247
253
|
catch (error) {
|
|
248
254
|
const scope = 'toCached';
|
package/lib/help/index.js
CHANGED
|
@@ -91,7 +91,7 @@ class Help extends HelpBase {
|
|
|
91
91
|
const command = this.config.findCommand(subject);
|
|
92
92
|
if (command) {
|
|
93
93
|
if (command.hasDynamicHelp && command.pluginType !== 'jit') {
|
|
94
|
-
const dynamicCommand = await (0, config_1.toCached)(await command.load());
|
|
94
|
+
const dynamicCommand = await (0, config_1.toCached)(await command.load(), undefined, false);
|
|
95
95
|
await this.showCommandHelp(dynamicCommand);
|
|
96
96
|
}
|
|
97
97
|
else {
|
|
@@ -50,6 +50,7 @@ export type Metadata = {
|
|
|
50
50
|
};
|
|
51
51
|
type MetadataFlag = {
|
|
52
52
|
setFromDefault?: boolean;
|
|
53
|
+
defaultHelp?: unknown;
|
|
53
54
|
};
|
|
54
55
|
export type ListItem = [string, string | undefined];
|
|
55
56
|
export type List = ListItem[];
|
|
@@ -58,10 +59,91 @@ export type DefaultContext<T> = {
|
|
|
58
59
|
options: T;
|
|
59
60
|
flags: Record<string, string>;
|
|
60
61
|
};
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Type to define a default value for a flag.
|
|
64
|
+
* @param context The context of the flag.
|
|
65
|
+
* @param isWritingManifest Informs the function that a manifest file is being written.
|
|
66
|
+
* The manifest file is used to store the flag definitions, with a default value if present, for a command and is published to npm.
|
|
67
|
+
* When a manifest file is being written, the default value may contain data that should not be included in the manifest.
|
|
68
|
+
* The plugin developer can use isWritingManifest to determine if the default value should be omitted from the manifest.
|
|
69
|
+
* in the function's implementation.
|
|
70
|
+
* @example
|
|
71
|
+
* static flags = {
|
|
72
|
+
* foo: flags.string({
|
|
73
|
+
* defaultHelp: async (context, isWritingManifest) => {
|
|
74
|
+
* if (isWritingManifest) {
|
|
75
|
+
* return undefined
|
|
76
|
+
* }
|
|
77
|
+
* return 'value that is used outside a manifest'
|
|
78
|
+
* },
|
|
79
|
+
* }),
|
|
80
|
+
* }
|
|
81
|
+
*/
|
|
82
|
+
export type FlagDefault<T, P = CustomOptions> = T | ((context: DefaultContext<P & OptionFlag<T, P>>, isWritingManifest?: boolean) => Promise<T>);
|
|
83
|
+
/**
|
|
84
|
+
* Type to define a defaultHelp value for a flag.
|
|
85
|
+
* The defaultHelp value is used in the help output for the flag and when writing a manifest.
|
|
86
|
+
* It is also can be used to provide a value for the flag when issuing certain error messages.
|
|
87
|
+
*
|
|
88
|
+
* @param context The context of the flag.
|
|
89
|
+
* @param isWritingManifest Informs the function that a manifest file is being written.
|
|
90
|
+
* The manifest file is used to store the flag definitions, with a default value if present via defaultHelp, for a command and is published to npm.
|
|
91
|
+
* When a manifest file is being written, the default value may contain data that should not be included in the manifest.
|
|
92
|
+
* The plugin developer can use isWritingManifest to determine if the defaultHelp value should be omitted from the manifest.
|
|
93
|
+
* in the function's implementation.
|
|
94
|
+
* @example
|
|
95
|
+
* static flags = {
|
|
96
|
+
* foo: flags.string({
|
|
97
|
+
* defaultHelp: async (context, isWritingManifest) => {
|
|
98
|
+
* if (isWritingManifest) {
|
|
99
|
+
* return undefined
|
|
100
|
+
* }
|
|
101
|
+
* return 'value that is used outside a manifest'
|
|
102
|
+
* },
|
|
103
|
+
* }),
|
|
104
|
+
* }
|
|
105
|
+
*/
|
|
106
|
+
export type FlagDefaultHelp<T, P = CustomOptions> = T | ((context: DefaultContext<P & OptionFlag<T, P>>, isWritingManifest?: boolean) => Promise<string | undefined>);
|
|
107
|
+
/**
|
|
108
|
+
* Type to define a default value for an arg.
|
|
109
|
+
* @param context The context of the arg.
|
|
110
|
+
* @param isWritingManifest Informs the function that a manifest file is being written.
|
|
111
|
+
* The manifest file is used to store the arg definitions, with a default value if present, for a command and is published to npm.
|
|
112
|
+
* When a manifest file is being written, the default value may contain data that should not be included in the manifest.
|
|
113
|
+
* The plugin developer can use isWritingManifest to determine if the default value should be omitted from the manifest.
|
|
114
|
+
* in the function's implementation.
|
|
115
|
+
* @example
|
|
116
|
+
* public static readonly args = {
|
|
117
|
+
* one: Args.string({
|
|
118
|
+
* default: async (context, isWritingManifest) => {
|
|
119
|
+
* if (isWritingManifest) {
|
|
120
|
+
* return undefined
|
|
121
|
+
* }
|
|
122
|
+
* return 'value that is used outside a manifest'
|
|
123
|
+
* }),
|
|
124
|
+
* };
|
|
125
|
+
*/
|
|
126
|
+
export type ArgDefault<T, P = CustomOptions> = T | ((context: DefaultContext<Arg<T, P>>, isWritingManifest?: boolean) => Promise<T>);
|
|
127
|
+
/**
|
|
128
|
+
* Type to define a defaultHelp value for an arg.
|
|
129
|
+
* @param context The context of the arg.
|
|
130
|
+
* @param isWritingManifest Informs the function that a manifest file is being written.
|
|
131
|
+
* The manifest file is used to store the arg definitions, with a default value if present via defaultHelp, for a command and is published to npm.
|
|
132
|
+
* When a manifest file is being written, the default value may contain data that should not be included in the manifest.
|
|
133
|
+
* The plugin developer can use isWritingManifest to determine if the default value should be omitted from the manifest.
|
|
134
|
+
* in the function's implementation.
|
|
135
|
+
* @example
|
|
136
|
+
* public static readonly args = {
|
|
137
|
+
* one: Args.string({
|
|
138
|
+
* defaultHelp: async (context, isWritingManifest) => {
|
|
139
|
+
* if (isWritingManifest) {
|
|
140
|
+
* return undefined
|
|
141
|
+
* }
|
|
142
|
+
* return 'value that is used outside a manifest'
|
|
143
|
+
* }),
|
|
144
|
+
* };
|
|
145
|
+
*/
|
|
146
|
+
export type ArgDefaultHelp<T, P = CustomOptions> = T | ((context: DefaultContext<Arg<T, P>>, isWritingManifest?: boolean) => Promise<string | undefined>);
|
|
65
147
|
export type FlagRelationship = string | {
|
|
66
148
|
name: string;
|
|
67
149
|
when: (flags: Record<string, unknown>) => Promise<boolean>;
|
package/lib/parser/parse.js
CHANGED
|
@@ -178,6 +178,12 @@ class Parser {
|
|
|
178
178
|
const flag = this.input.flags[token.flag];
|
|
179
179
|
if (!flag)
|
|
180
180
|
throw new errors_1.CLIError(`Unexpected flag ${token.flag}`);
|
|
181
|
+
// if flag has defaultHelp, capture its value into metadata
|
|
182
|
+
if (Reflect.has(flag, 'defaultHelp')) {
|
|
183
|
+
const defaultHelpProperty = Reflect.get(flag, 'defaultHelp');
|
|
184
|
+
const defaultHelp = (typeof defaultHelpProperty === 'function' ? await defaultHelpProperty({ options: flag, flags, ...this.context }) : defaultHelpProperty);
|
|
185
|
+
this.metaData.flags[token.flag] = { ...this.metaData.flags[token.flag], defaultHelp };
|
|
186
|
+
}
|
|
181
187
|
if (flag.type === 'boolean') {
|
|
182
188
|
if (token.input === `--no-${flag.name}`) {
|
|
183
189
|
flags[token.flag] = false;
|
|
@@ -216,7 +222,7 @@ class Parser {
|
|
|
216
222
|
const flag = this.input.flags[k];
|
|
217
223
|
if (flags[k])
|
|
218
224
|
continue;
|
|
219
|
-
if (flag.env &&
|
|
225
|
+
if (flag.env && Reflect.has(process.env, flag.env)) {
|
|
220
226
|
const input = process.env[flag.env];
|
|
221
227
|
if (flag.type === 'option') {
|
|
222
228
|
if (input) {
|
|
@@ -230,7 +236,7 @@ class Parser {
|
|
|
230
236
|
}
|
|
231
237
|
}
|
|
232
238
|
if (!(k in flags) && flag.default !== undefined) {
|
|
233
|
-
this.metaData.flags[k] = { setFromDefault: true };
|
|
239
|
+
this.metaData.flags[k] = { ...this.metaData.flags[k], setFromDefault: true };
|
|
234
240
|
const defaultValue = (typeof flag.default === 'function' ? await flag.default({ options: flag, flags, ...this.context }) : flag.default);
|
|
235
241
|
flags[k] = defaultValue;
|
|
236
242
|
}
|
package/lib/parser/validate.js
CHANGED
|
@@ -94,7 +94,8 @@ async function validate(parse) {
|
|
|
94
94
|
if (parse.output.metadata.flags && parse.output.metadata.flags[name]?.setFromDefault)
|
|
95
95
|
continue;
|
|
96
96
|
if (parse.output.flags[flag] !== undefined) {
|
|
97
|
-
|
|
97
|
+
const flagValue = parse.output.metadata.flags?.[flag]?.defaultHelp ?? parse.output.flags[flag];
|
|
98
|
+
return { ...base, status: 'failed', reason: `--${flag}=${flagValue} cannot also be provided when using --${name}` };
|
|
98
99
|
}
|
|
99
100
|
}
|
|
100
101
|
return { ...base, status: 'success' };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oclif/core",
|
|
3
3
|
"description": "base library for oclif CLIs",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.7.0",
|
|
5
5
|
"author": "Salesforce",
|
|
6
6
|
"bugs": "https://github.com/oclif/core/issues",
|
|
7
7
|
"dependencies": {
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@commitlint/config-conventional": "^12.1.4",
|
|
40
|
-
"@oclif/plugin-help": "^5.2.
|
|
40
|
+
"@oclif/plugin-help": "^5.2.8",
|
|
41
41
|
"@oclif/plugin-plugins": "^2.4.1",
|
|
42
|
-
"@oclif/test": "^2.3.
|
|
42
|
+
"@oclif/test": "^2.3.11",
|
|
43
43
|
"@types/ansi-styles": "^3.2.1",
|
|
44
44
|
"@types/chai": "^4.3.4",
|
|
45
45
|
"@types/chai-as-promised": "^7.1.5",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"eslint": "^7.32.0",
|
|
66
66
|
"eslint-config-oclif": "^4.0.0",
|
|
67
67
|
"eslint-config-oclif-typescript": "^1.0.3",
|
|
68
|
-
"fancy-test": "^2.0.
|
|
68
|
+
"fancy-test": "^2.0.15",
|
|
69
69
|
"globby": "^11.1.0",
|
|
70
70
|
"husky": "6",
|
|
71
71
|
"mocha": "^8.4.0",
|