@oclif/core 3.0.0-beta.12 → 3.0.0-beta.14
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/README.md +3 -1
- package/lib/args.d.ts +1 -1
- package/lib/args.js +13 -15
- package/lib/cli-ux/action/base.d.ts +1 -1
- package/lib/cli-ux/action/base.js +20 -15
- package/lib/cli-ux/action/simple.js +10 -8
- package/lib/cli-ux/action/spinner.js +11 -10
- package/lib/cli-ux/config.js +8 -7
- package/lib/cli-ux/flush.js +2 -3
- package/lib/cli-ux/index.d.ts +10 -28
- package/lib/cli-ux/index.js +26 -45
- package/lib/cli-ux/list.js +1 -1
- package/lib/cli-ux/prompt.js +24 -19
- package/lib/cli-ux/styled/index.d.ts +5 -6
- package/lib/cli-ux/styled/index.js +11 -11
- package/lib/cli-ux/styled/json.js +3 -2
- package/lib/cli-ux/styled/object.js +6 -8
- package/lib/cli-ux/styled/table.js +36 -45
- package/lib/cli-ux/wait.js +3 -5
- package/lib/command.d.ts +7 -5
- package/lib/command.js +35 -28
- package/lib/config/config.d.ts +2 -2
- package/lib/config/config.js +57 -43
- package/lib/config/plugin-loader.js +25 -11
- package/lib/config/plugin.d.ts +1 -1
- package/lib/config/plugin.js +66 -56
- package/lib/config/ts-node.d.ts +2 -1
- package/lib/config/ts-node.js +42 -46
- package/lib/config/util.d.ts +1 -5
- package/lib/config/util.js +5 -46
- package/lib/errors/config.js +1 -1
- package/lib/errors/errors/cli.d.ts +1 -1
- package/lib/errors/errors/cli.js +14 -13
- package/lib/errors/errors/exit.d.ts +0 -3
- package/lib/errors/errors/module-load.d.ts +0 -3
- package/lib/errors/errors/pretty-print.js +9 -8
- package/lib/errors/handle.d.ts +12 -2
- package/lib/errors/handle.js +23 -14
- package/lib/errors/index.d.ts +2 -2
- package/lib/errors/index.js +20 -19
- package/lib/errors/logger.js +4 -4
- package/lib/execute.d.ts +5 -5
- package/lib/execute.js +6 -5
- package/lib/flags.d.ts +102 -31
- package/lib/flags.js +75 -42
- package/lib/help/command.d.ts +2 -0
- package/lib/help/command.js +32 -32
- package/lib/help/docopts.js +2 -9
- package/lib/help/formatter.d.ts +1 -1
- package/lib/help/formatter.js +17 -17
- package/lib/help/index.d.ts +2 -2
- package/lib/help/index.js +22 -21
- package/lib/help/root.js +2 -2
- package/lib/help/util.d.ts +1 -1
- package/lib/help/util.js +9 -9
- package/lib/index.d.ts +19 -20
- package/lib/index.js +38 -42
- package/lib/interfaces/config.d.ts +5 -4
- package/lib/interfaces/errors.d.ts +1 -1
- package/lib/interfaces/parser.d.ts +168 -45
- package/lib/interfaces/plugin.d.ts +1 -0
- package/lib/main.d.ts +1 -1
- package/lib/main.js +16 -16
- package/lib/module-loader.d.ts +67 -77
- package/lib/module-loader.js +179 -149
- package/lib/parser/errors.d.ts +2 -2
- package/lib/parser/errors.js +4 -3
- package/lib/parser/help.js +3 -2
- package/lib/parser/parse.d.ts +3 -0
- package/lib/parser/parse.js +56 -52
- package/lib/parser/validate.js +9 -5
- package/lib/performance.d.ts +6 -2
- package/lib/performance.js +23 -12
- package/lib/util.d.ts +25 -1
- package/lib/util.js +93 -29
- package/package.json +10 -15
package/lib/config/config.js
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.toCached = exports.Config = void 0;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const node_os_1 = require("node:os");
|
|
7
|
-
const node_path_1 = require("node:path");
|
|
8
|
-
const ejs = require("ejs");
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const ejs = tslib_1.__importStar(require("ejs"));
|
|
9
6
|
const errors_1 = require("../errors");
|
|
10
7
|
const util_1 = require("./util");
|
|
8
|
+
const node_url_1 = require("node:url");
|
|
9
|
+
const node_os_1 = require("node:os");
|
|
11
10
|
const util_2 = require("../util");
|
|
12
|
-
const
|
|
13
|
-
const help_1 = require("../help");
|
|
14
|
-
const stream_1 = require("../cli-ux/stream");
|
|
11
|
+
const node_path_1 = require("node:path");
|
|
15
12
|
const performance_1 = require("../performance");
|
|
13
|
+
const plugin_loader_1 = tslib_1.__importDefault(require("./plugin-loader"));
|
|
14
|
+
const node_util_1 = require("node:util");
|
|
15
|
+
const help_1 = require("../help");
|
|
16
|
+
const module_loader_1 = require("../module-loader");
|
|
16
17
|
const settings_1 = require("../settings");
|
|
17
|
-
const
|
|
18
|
+
const stream_1 = require("../cli-ux/stream");
|
|
18
19
|
// eslint-disable-next-line new-cap
|
|
19
20
|
const debug = (0, util_1.Debug)();
|
|
20
21
|
const _pjson = (0, util_2.requireJson)(__dirname, '..', '..', 'package.json');
|
|
@@ -105,6 +106,7 @@ class Config {
|
|
|
105
106
|
// eslint-disable-next-line complexity
|
|
106
107
|
async load() {
|
|
107
108
|
settings_1.settings.performanceEnabled = (settings_1.settings.performanceEnabled === undefined ? this.options.enablePerf : settings_1.settings.performanceEnabled) ?? false;
|
|
109
|
+
const marker = performance_1.Performance.mark('config.load');
|
|
108
110
|
this.pluginLoader = new plugin_loader_1.default({ root: this.options.root, plugins: this.options.plugins });
|
|
109
111
|
Config._rootPlugin = await this.pluginLoader.loadRoot();
|
|
110
112
|
this.root = Config._rootPlugin.root;
|
|
@@ -117,7 +119,7 @@ class Config {
|
|
|
117
119
|
this.channel = this.options.channel || channelFromVersion(this.version);
|
|
118
120
|
this.valid = Config._rootPlugin.valid;
|
|
119
121
|
this.arch = ((0, node_os_1.arch)() === 'ia32' ? 'x86' : (0, node_os_1.arch)());
|
|
120
|
-
this.platform = WSL ? 'wsl' : (0,
|
|
122
|
+
this.platform = WSL ? 'wsl' : (0, util_2.getPlatform)();
|
|
121
123
|
this.windows = this.platform === 'win32';
|
|
122
124
|
this.bin = this.pjson.oclif.bin || this.name;
|
|
123
125
|
this.binAliases = this.pjson.oclif.binAliases;
|
|
@@ -132,7 +134,7 @@ class Config {
|
|
|
132
134
|
this.userAgent = `${this.name}/${this.version} ${this.platform}-${this.arch} node-${process.version}`;
|
|
133
135
|
this.shell = this._shell();
|
|
134
136
|
this.debug = this._debug();
|
|
135
|
-
this.home = process.env.HOME || (this.windows && this.windowsHome()) || (0,
|
|
137
|
+
this.home = process.env.HOME || (this.windows && this.windowsHome()) || (0, util_2.getHomeDir)() || (0, node_os_1.tmpdir)();
|
|
136
138
|
this.cacheDir = this.scopedEnvVar('CACHE_DIR') || this.macosCacheDir() || this.dir('cache');
|
|
137
139
|
this.configDir = this.scopedEnvVar('CONFIG_DIR') || this.dir('config');
|
|
138
140
|
this.dataDir = this.scopedEnvVar('DATA_DIR') || this.dir('data');
|
|
@@ -163,7 +165,6 @@ class Config {
|
|
|
163
165
|
...s3.templates && s3.templates.vanilla,
|
|
164
166
|
},
|
|
165
167
|
};
|
|
166
|
-
const marker = performance_1.default.mark('config.load');
|
|
167
168
|
await this.loadPluginsAndCommands();
|
|
168
169
|
debug('config done');
|
|
169
170
|
marker?.addDetails({
|
|
@@ -175,7 +176,7 @@ class Config {
|
|
|
175
176
|
marker?.stop();
|
|
176
177
|
}
|
|
177
178
|
async loadPluginsAndCommands(opts) {
|
|
178
|
-
const
|
|
179
|
+
const pluginsMarker = performance_1.Performance.mark('config.loadAllPlugins');
|
|
179
180
|
const { plugins, errors } = await this.pluginLoader.loadChildren({
|
|
180
181
|
devPlugins: this.options.devPlugins,
|
|
181
182
|
userPlugins: this.options.userPlugins,
|
|
@@ -184,17 +185,19 @@ class Config {
|
|
|
184
185
|
force: opts?.force ?? false,
|
|
185
186
|
});
|
|
186
187
|
this.plugins = plugins;
|
|
188
|
+
pluginsMarker?.stop();
|
|
189
|
+
const commandsMarker = performance_1.Performance.mark('config.loadAllCommands');
|
|
187
190
|
for (const plugin of this.plugins.values()) {
|
|
188
191
|
this.loadCommands(plugin);
|
|
189
192
|
this.loadTopics(plugin);
|
|
190
193
|
}
|
|
194
|
+
commandsMarker?.stop();
|
|
191
195
|
for (const error of errors) {
|
|
192
196
|
this.warn(error);
|
|
193
197
|
}
|
|
194
|
-
marker?.stop();
|
|
195
198
|
}
|
|
196
199
|
async runHook(event, opts, timeout, captureErrors) {
|
|
197
|
-
const marker = performance_1.
|
|
200
|
+
const marker = performance_1.Performance.mark(`config.runHook#${event}`);
|
|
198
201
|
debug('start %s hook', event);
|
|
199
202
|
const search = (m) => {
|
|
200
203
|
if (typeof m === 'function')
|
|
@@ -239,14 +242,14 @@ class Config {
|
|
|
239
242
|
};
|
|
240
243
|
const hooks = p.hooks[event] || [];
|
|
241
244
|
for (const hook of hooks) {
|
|
242
|
-
const marker = performance_1.
|
|
245
|
+
const marker = performance_1.Performance.mark(`config.runHook#${p.name}(${hook})`);
|
|
243
246
|
try {
|
|
244
247
|
/* eslint-disable no-await-in-loop */
|
|
245
|
-
const { isESM, module, filePath } = await module_loader_1.
|
|
248
|
+
const { isESM, module, filePath } = await (0, module_loader_1.loadWithData)(p, (0, node_path_1.join)(p.root, hook));
|
|
246
249
|
debug('start', isESM ? '(import)' : '(require)', filePath);
|
|
247
|
-
const result = timeout
|
|
248
|
-
await withTimeout(timeout, search(module).call(context, { ...opts, config: this }))
|
|
249
|
-
await search(module).call(context, { ...opts, config: this });
|
|
250
|
+
const result = timeout
|
|
251
|
+
? await withTimeout(timeout, search(module).call(context, { ...opts, config: this }))
|
|
252
|
+
: await search(module).call(context, { ...opts, config: this });
|
|
250
253
|
final.successes.push({ plugin: p, result });
|
|
251
254
|
if (p.name === '@oclif/plugin-legacy' && event === 'init') {
|
|
252
255
|
this.insertLegacyPlugins(result);
|
|
@@ -273,14 +276,14 @@ class Config {
|
|
|
273
276
|
return final;
|
|
274
277
|
}
|
|
275
278
|
async runCommand(id, argv = [], cachedCommand = null) {
|
|
276
|
-
const marker = performance_1.
|
|
279
|
+
const marker = performance_1.Performance.mark(`config.runCommand#${id}`);
|
|
277
280
|
debug('runCommand %s %o', id, argv);
|
|
278
281
|
let c = cachedCommand ?? this.findCommand(id);
|
|
279
282
|
if (!c) {
|
|
280
283
|
const matches = this.flexibleTaxonomy ? this.findMatches(id, argv) : [];
|
|
281
|
-
const hookResult = this.flexibleTaxonomy && matches.length > 0
|
|
282
|
-
await this.runHook('command_incomplete', { id, argv, matches })
|
|
283
|
-
await this.runHook('command_not_found', { id, argv });
|
|
284
|
+
const hookResult = this.flexibleTaxonomy && matches.length > 0
|
|
285
|
+
? await this.runHook('command_incomplete', { id, argv, matches })
|
|
286
|
+
: await this.runHook('command_not_found', { id, argv });
|
|
284
287
|
if (hookResult.successes[0])
|
|
285
288
|
return hookResult.successes[0].result;
|
|
286
289
|
if (hookResult.failures[0])
|
|
@@ -335,7 +338,7 @@ class Config {
|
|
|
335
338
|
*/
|
|
336
339
|
scopedEnvVarKey(k) {
|
|
337
340
|
return [this.bin, k]
|
|
338
|
-
.map(p => p.
|
|
341
|
+
.map(p => p.replaceAll('@', '').replaceAll(/[/-]/g, '_'))
|
|
339
342
|
.join('_')
|
|
340
343
|
.toUpperCase();
|
|
341
344
|
}
|
|
@@ -345,7 +348,7 @@ class Config {
|
|
|
345
348
|
* @returns {string[]} e.g. ['SF_DEBUG', 'SFDX_DEBUG']
|
|
346
349
|
*/
|
|
347
350
|
scopedEnvVarKeys(k) {
|
|
348
|
-
return [this.bin, ...this.binAliases ?? []].filter(
|
|
351
|
+
return [this.bin, ...this.binAliases ?? []].filter(Boolean).map(alias => [alias.replaceAll('@', '').replaceAll(/[/-]/g, '_'), k].join('_').toUpperCase());
|
|
349
352
|
}
|
|
350
353
|
findCommand(id, opts = {}) {
|
|
351
354
|
const lookupId = this.getCmdLookupId(id);
|
|
@@ -376,12 +379,10 @@ class Config {
|
|
|
376
379
|
* @returns string[]
|
|
377
380
|
*/
|
|
378
381
|
findMatches(partialCmdId, argv) {
|
|
379
|
-
const flags = argv.filter(arg => !(0, help_1.getHelpFlagAdditions)(this).includes(arg) && arg.startsWith('-')).map(a => a.
|
|
382
|
+
const flags = argv.filter(arg => !(0, help_1.getHelpFlagAdditions)(this).includes(arg) && arg.startsWith('-')).map(a => a.replaceAll('-', ''));
|
|
380
383
|
const possibleMatches = [...this.commandPermutations.get(partialCmdId)].map(k => this._commands.get(k));
|
|
381
384
|
const matches = possibleMatches.filter(command => {
|
|
382
|
-
const cmdFlags = Object.entries(command.flags).flatMap(([flag, def]) =>
|
|
383
|
-
return def.char ? [def.char, flag] : [flag];
|
|
384
|
-
});
|
|
385
|
+
const cmdFlags = Object.entries(command.flags).flatMap(([flag, def]) => def.char ? [def.char, flag] : [flag]);
|
|
385
386
|
// A command is a match if the provided flags belong to the full command
|
|
386
387
|
return flags.every(f => cmdFlags.includes(f));
|
|
387
388
|
});
|
|
@@ -442,7 +443,7 @@ class Config {
|
|
|
442
443
|
return ejs.render(template, { ...this, ...options });
|
|
443
444
|
}
|
|
444
445
|
s3Url(key) {
|
|
445
|
-
const host = this.pjson.oclif.update.s3
|
|
446
|
+
const { host } = this.pjson.oclif.update.s3;
|
|
446
447
|
if (!host)
|
|
447
448
|
throw new Error('no s3 host is set');
|
|
448
449
|
const url = new node_url_1.URL(host);
|
|
@@ -453,9 +454,9 @@ class Config {
|
|
|
453
454
|
return [...this.plugins.values()];
|
|
454
455
|
}
|
|
455
456
|
dir(category) {
|
|
456
|
-
const base = process.env[`XDG_${category.toUpperCase()}_HOME`]
|
|
457
|
-
(this.windows && process.env.LOCALAPPDATA)
|
|
458
|
-
(0, node_path_1.join)(this.home, category === 'data' ? '.local/share' : '.' + category);
|
|
457
|
+
const base = process.env[`XDG_${category.toUpperCase()}_HOME`]
|
|
458
|
+
|| (this.windows && process.env.LOCALAPPDATA)
|
|
459
|
+
|| (0, node_path_1.join)(this.home, category === 'data' ? '.local/share' : '.' + category);
|
|
459
460
|
return (0, node_path_1.join)(base, this.dirname);
|
|
460
461
|
}
|
|
461
462
|
windowsHome() {
|
|
@@ -472,7 +473,7 @@ class Config {
|
|
|
472
473
|
}
|
|
473
474
|
_shell() {
|
|
474
475
|
let shellPath;
|
|
475
|
-
const COMSPEC = process.env
|
|
476
|
+
const { COMSPEC } = process.env;
|
|
476
477
|
const SHELL = process.env.SHELL ?? (0, node_os_1.userInfo)().shell?.split(node_path_1.sep)?.pop();
|
|
477
478
|
if (SHELL) {
|
|
478
479
|
shellPath = SHELL.split('/');
|
|
@@ -483,7 +484,7 @@ class Config {
|
|
|
483
484
|
else {
|
|
484
485
|
shellPath = ['unknown'];
|
|
485
486
|
}
|
|
486
|
-
return shellPath
|
|
487
|
+
return shellPath.at(-1) ?? 'unknown';
|
|
487
488
|
}
|
|
488
489
|
_debug() {
|
|
489
490
|
if (this.scopedEnvVarTrue('DEBUG'))
|
|
@@ -506,7 +507,7 @@ class Config {
|
|
|
506
507
|
if (err instanceof Error) {
|
|
507
508
|
const modifiedErr = err;
|
|
508
509
|
modifiedErr.name = `${err.name} Plugin: ${this.name}`;
|
|
509
|
-
modifiedErr.detail = (0,
|
|
510
|
+
modifiedErr.detail = (0, util_2.compact)([
|
|
510
511
|
err.detail,
|
|
511
512
|
`module: ${this._base}`,
|
|
512
513
|
scope && `task: ${scope}`,
|
|
@@ -520,7 +521,7 @@ class Config {
|
|
|
520
521
|
// err is an object
|
|
521
522
|
process.emitWarning('Config.warn expected either a string or Error, but instead received an object');
|
|
522
523
|
err.name = `${err.name} Plugin: ${this.name}`;
|
|
523
|
-
err.detail = (0,
|
|
524
|
+
err.detail = (0, util_2.compact)([
|
|
524
525
|
err.detail,
|
|
525
526
|
`module: ${this._base}`,
|
|
526
527
|
scope && `task: ${scope}`,
|
|
@@ -552,7 +553,7 @@ class Config {
|
|
|
552
553
|
return id;
|
|
553
554
|
}
|
|
554
555
|
loadCommands(plugin) {
|
|
555
|
-
const marker = performance_1.
|
|
556
|
+
const marker = performance_1.Performance.mark(`config.loadCommands#${plugin.name}`, { plugin: plugin.name });
|
|
556
557
|
for (const command of plugin.commands) {
|
|
557
558
|
// set canonical command id
|
|
558
559
|
if (this._commands.has(command.id)) {
|
|
@@ -562,8 +563,13 @@ class Config {
|
|
|
562
563
|
else {
|
|
563
564
|
this._commands.set(command.id, command);
|
|
564
565
|
}
|
|
566
|
+
// v3 moved command id permutations to the manifest, but some plugins may not have
|
|
567
|
+
// the new manifest yet. For those, we need to calculate the permutations here.
|
|
568
|
+
const permutations = this.flexibleTaxonomy && command.permutations === undefined
|
|
569
|
+
? (0, util_1.getCommandIdPermutations)(command.id)
|
|
570
|
+
: command.permutations ?? [command.id];
|
|
565
571
|
// set every permutation
|
|
566
|
-
for (const permutation of
|
|
572
|
+
for (const permutation of permutations) {
|
|
567
573
|
this.commandPermutations.add(permutation, command.id);
|
|
568
574
|
}
|
|
569
575
|
// set command aliases
|
|
@@ -576,7 +582,13 @@ class Config {
|
|
|
576
582
|
this._commands.set(alias, { ...command, id: alias });
|
|
577
583
|
}
|
|
578
584
|
// set every permutation of the aliases
|
|
579
|
-
|
|
585
|
+
// v3 moved command alias permutations to the manifest, but some plugins may not have
|
|
586
|
+
// the new manifest yet. For those, we need to calculate the permutations here.
|
|
587
|
+
const aliasPermutations = this.flexibleTaxonomy && command.aliasPermutations === undefined
|
|
588
|
+
? (0, util_1.getCommandIdPermutations)(alias)
|
|
589
|
+
: command.permutations ?? [alias];
|
|
590
|
+
// set every permutation
|
|
591
|
+
for (const permutation of aliasPermutations) {
|
|
580
592
|
this.commandPermutations.add(permutation, command.id);
|
|
581
593
|
}
|
|
582
594
|
}
|
|
@@ -585,8 +597,8 @@ class Config {
|
|
|
585
597
|
marker?.stop();
|
|
586
598
|
}
|
|
587
599
|
loadTopics(plugin) {
|
|
588
|
-
const marker = performance_1.
|
|
589
|
-
for (const topic of (0,
|
|
600
|
+
const marker = performance_1.Performance.mark(`config.loadTopics#${plugin.name}`, { plugin: plugin.name });
|
|
601
|
+
for (const topic of (0, util_2.compact)(plugin.topics)) {
|
|
590
602
|
const existing = this._topics.get(topic.name);
|
|
591
603
|
if (existing) {
|
|
592
604
|
existing.description = topic.description || existing.description;
|
|
@@ -750,6 +762,7 @@ async function toCached(c, plugin, respectNoCacheDefault = false) {
|
|
|
750
762
|
deprecated: flag.deprecated,
|
|
751
763
|
deprecateAliases: c.deprecateAliases,
|
|
752
764
|
aliases: flag.aliases,
|
|
765
|
+
charAliases: flag.charAliases,
|
|
753
766
|
delimiter: flag.delimiter,
|
|
754
767
|
noCacheDefault: flag.noCacheDefault,
|
|
755
768
|
};
|
|
@@ -775,6 +788,7 @@ async function toCached(c, plugin, respectNoCacheDefault = false) {
|
|
|
775
788
|
deprecated: flag.deprecated,
|
|
776
789
|
deprecateAliases: c.deprecateAliases,
|
|
777
790
|
aliases: flag.aliases,
|
|
791
|
+
charAliases: flag.charAliases,
|
|
778
792
|
delimiter: flag.delimiter,
|
|
779
793
|
noCacheDefault: flag.noCacheDefault,
|
|
780
794
|
};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const
|
|
4
|
-
const Plugin = require("./plugin");
|
|
5
|
-
const util_1 = require("
|
|
6
|
-
const util_2 = require("
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const Plugin = tslib_1.__importStar(require("./plugin"));
|
|
5
|
+
const util_1 = require("../util");
|
|
6
|
+
const util_2 = require("./util");
|
|
7
7
|
const performance_1 = require("../performance");
|
|
8
|
+
const node_path_1 = require("node:path");
|
|
8
9
|
// eslint-disable-next-line new-cap
|
|
9
|
-
const debug = (0,
|
|
10
|
+
const debug = (0, util_2.Debug)();
|
|
10
11
|
class PluginLoader {
|
|
11
12
|
constructor(options) {
|
|
12
13
|
this.options = options;
|
|
@@ -25,8 +26,18 @@ class PluginLoader {
|
|
|
25
26
|
rootPlugin = plugins.find(p => p.root === this.options.root) ?? plugins[0];
|
|
26
27
|
}
|
|
27
28
|
else {
|
|
29
|
+
const marker = performance_1.Performance.mark('plugin.load#root');
|
|
28
30
|
rootPlugin = new Plugin.Plugin({ root: this.options.root });
|
|
29
31
|
await rootPlugin.load();
|
|
32
|
+
marker?.addDetails({
|
|
33
|
+
hasManifest: rootPlugin.hasManifest ?? false,
|
|
34
|
+
commandCount: rootPlugin.commands.length,
|
|
35
|
+
topicCount: rootPlugin.topics.length,
|
|
36
|
+
type: rootPlugin.type,
|
|
37
|
+
usesMain: Boolean(rootPlugin.pjson.main),
|
|
38
|
+
name: rootPlugin.name,
|
|
39
|
+
});
|
|
40
|
+
marker?.stop();
|
|
30
41
|
}
|
|
31
42
|
this.plugins.set(rootPlugin.name, rootPlugin);
|
|
32
43
|
return rootPlugin;
|
|
@@ -47,10 +58,10 @@ class PluginLoader {
|
|
|
47
58
|
async loadDevPlugins(opts) {
|
|
48
59
|
if (opts.devPlugins !== false) {
|
|
49
60
|
// do not load oclif.devPlugins in production
|
|
50
|
-
if ((0,
|
|
61
|
+
if ((0, util_1.isProd)())
|
|
51
62
|
return;
|
|
52
63
|
try {
|
|
53
|
-
const devPlugins = opts.rootPlugin.pjson.oclif
|
|
64
|
+
const { devPlugins } = opts.rootPlugin.pjson.oclif;
|
|
54
65
|
if (devPlugins)
|
|
55
66
|
await this.loadPlugins(opts.rootPlugin.root, 'dev', devPlugins);
|
|
56
67
|
}
|
|
@@ -62,9 +73,9 @@ class PluginLoader {
|
|
|
62
73
|
async loadUserPlugins(opts) {
|
|
63
74
|
if (opts.userPlugins !== false) {
|
|
64
75
|
try {
|
|
65
|
-
const userPJSONPath =
|
|
76
|
+
const userPJSONPath = (0, node_path_1.join)(opts.dataDir, 'package.json');
|
|
66
77
|
debug('reading user plugins pjson %s', userPJSONPath);
|
|
67
|
-
const pjson = await (0, util_1.
|
|
78
|
+
const pjson = await (0, util_1.readJson)(userPJSONPath);
|
|
68
79
|
if (!pjson.oclif)
|
|
69
80
|
pjson.oclif = { schema: 1 };
|
|
70
81
|
if (!pjson.oclif.plugins)
|
|
@@ -81,7 +92,7 @@ class PluginLoader {
|
|
|
81
92
|
async loadPlugins(root, type, plugins, parent) {
|
|
82
93
|
if (!plugins || plugins.length === 0)
|
|
83
94
|
return;
|
|
84
|
-
const mark = performance_1.
|
|
95
|
+
const mark = performance_1.Performance.mark(`config.loadPlugins#${type}`);
|
|
85
96
|
debug('loading plugins', plugins);
|
|
86
97
|
await Promise.all((plugins || []).map(async (plugin) => {
|
|
87
98
|
try {
|
|
@@ -95,9 +106,12 @@ class PluginLoader {
|
|
|
95
106
|
opts.tag = plugin.tag || opts.tag;
|
|
96
107
|
opts.root = plugin.root || opts.root;
|
|
97
108
|
}
|
|
109
|
+
if (parent) {
|
|
110
|
+
opts.parent = parent;
|
|
111
|
+
}
|
|
98
112
|
if (this.plugins.has(name))
|
|
99
113
|
return;
|
|
100
|
-
const pluginMarker = performance_1.
|
|
114
|
+
const pluginMarker = performance_1.Performance.mark(`plugin.load#${name}`);
|
|
101
115
|
const instance = new Plugin.Plugin(opts);
|
|
102
116
|
await instance.load();
|
|
103
117
|
pluginMarker?.addDetails({
|
package/lib/config/plugin.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Plugin as IPlugin, PluginOptions } from '../interfaces/plugin';
|
|
2
|
+
import { Command } from '../command';
|
|
2
3
|
import { Manifest } from '../interfaces/manifest';
|
|
3
4
|
import { PJSON } from '../interfaces/pjson';
|
|
4
5
|
import { Topic } from '../interfaces/topic';
|
|
5
|
-
import { Command } from '../command';
|
|
6
6
|
export declare class Plugin implements IPlugin {
|
|
7
7
|
options: PluginOptions;
|
|
8
8
|
_base: string;
|
package/lib/config/plugin.js
CHANGED
|
@@ -2,43 +2,42 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Plugin = void 0;
|
|
4
4
|
const errors_1 = require("../errors");
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const config_1 = require("./config");
|
|
9
|
-
const util_2 = require("./util");
|
|
10
|
-
const ts_node_1 = require("./ts-node");
|
|
11
|
-
const util_3 = require("./util");
|
|
12
|
-
const util_4 = require("../util");
|
|
5
|
+
const util_1 = require("./util");
|
|
6
|
+
const util_2 = require("../util");
|
|
7
|
+
const node_path_1 = require("node:path");
|
|
13
8
|
const module_loader_1 = require("../module-loader");
|
|
14
9
|
const performance_1 = require("../performance");
|
|
15
|
-
const
|
|
10
|
+
const node_util_1 = require("node:util");
|
|
11
|
+
const globby_1 = require("globby");
|
|
12
|
+
const config_1 = require("./config");
|
|
13
|
+
const ts_node_1 = require("./ts-node");
|
|
14
|
+
const _pjson = (0, util_2.requireJson)(__dirname, '..', '..', 'package.json');
|
|
16
15
|
function topicsToArray(input, base) {
|
|
17
16
|
if (!input)
|
|
18
17
|
return [];
|
|
19
18
|
base = base ? `${base}:` : '';
|
|
20
19
|
if (Array.isArray(input)) {
|
|
21
|
-
return [...input, ...(0,
|
|
20
|
+
return [...input, ...(0, util_1.flatMap)(input, t => topicsToArray(t.subtopics, `${base}${t.name}`))];
|
|
22
21
|
}
|
|
23
|
-
return (0,
|
|
22
|
+
return (0, util_1.flatMap)(Object.keys(input), k => {
|
|
24
23
|
input[k].name = k;
|
|
25
24
|
return [{ ...input[k], name: `${base}${k}` }, ...topicsToArray(input[k].subtopics, `${base}${input[k].name}`)];
|
|
26
25
|
});
|
|
27
26
|
}
|
|
28
27
|
// essentially just "cd .."
|
|
29
28
|
function* up(from) {
|
|
30
|
-
while (
|
|
29
|
+
while ((0, node_path_1.dirname)(from) !== from) {
|
|
31
30
|
yield from;
|
|
32
|
-
from =
|
|
31
|
+
from = (0, node_path_1.dirname)(from);
|
|
33
32
|
}
|
|
34
33
|
yield from;
|
|
35
34
|
}
|
|
36
35
|
async function findSourcesRoot(root) {
|
|
37
36
|
for (const next of up(root)) {
|
|
38
|
-
const cur =
|
|
37
|
+
const cur = (0, node_path_1.join)(next, 'package.json');
|
|
39
38
|
// eslint-disable-next-line no-await-in-loop
|
|
40
|
-
if (await (0,
|
|
41
|
-
return
|
|
39
|
+
if (await (0, util_2.exists)(cur))
|
|
40
|
+
return (0, node_path_1.dirname)(cur);
|
|
42
41
|
}
|
|
43
42
|
}
|
|
44
43
|
/**
|
|
@@ -56,23 +55,23 @@ async function findRootLegacy(name, root) {
|
|
|
56
55
|
for (const next of up(root)) {
|
|
57
56
|
let cur;
|
|
58
57
|
if (name) {
|
|
59
|
-
cur =
|
|
58
|
+
cur = (0, node_path_1.join)(next, 'node_modules', name, 'package.json');
|
|
60
59
|
// eslint-disable-next-line no-await-in-loop
|
|
61
|
-
if (await (0,
|
|
62
|
-
return
|
|
60
|
+
if (await (0, util_2.exists)(cur))
|
|
61
|
+
return (0, node_path_1.dirname)(cur);
|
|
63
62
|
try {
|
|
64
63
|
// eslint-disable-next-line no-await-in-loop
|
|
65
|
-
const pkg = await (0,
|
|
64
|
+
const pkg = await (0, util_2.readJson)((0, node_path_1.join)(next, 'package.json'));
|
|
66
65
|
if (pkg.name === name)
|
|
67
66
|
return next;
|
|
68
67
|
}
|
|
69
68
|
catch { }
|
|
70
69
|
}
|
|
71
70
|
else {
|
|
72
|
-
cur =
|
|
71
|
+
cur = (0, node_path_1.join)(next, 'package.json');
|
|
73
72
|
// eslint-disable-next-line no-await-in-loop
|
|
74
|
-
if (await (0,
|
|
75
|
-
return
|
|
73
|
+
if (await (0, util_2.exists)(cur))
|
|
74
|
+
return (0, node_path_1.dirname)(cur);
|
|
76
75
|
}
|
|
77
76
|
}
|
|
78
77
|
}
|
|
@@ -80,13 +79,21 @@ async function findRoot(name, root) {
|
|
|
80
79
|
if (name) {
|
|
81
80
|
let pkgPath;
|
|
82
81
|
try {
|
|
83
|
-
pkgPath = (0,
|
|
82
|
+
pkgPath = (0, util_1.resolvePackage)(name, { paths: [root] });
|
|
84
83
|
}
|
|
85
84
|
catch { }
|
|
86
|
-
return pkgPath ? findSourcesRoot(
|
|
85
|
+
return pkgPath ? findSourcesRoot((0, node_path_1.dirname)(pkgPath)) : findRootLegacy(name, root);
|
|
87
86
|
}
|
|
88
87
|
return findSourcesRoot(root);
|
|
89
88
|
}
|
|
89
|
+
const cachedCommandCanBeUsed = (manifest, id) => Boolean(manifest?.commands[id] && ('isESM' in manifest.commands[id] && 'relativePath' in manifest.commands[id]));
|
|
90
|
+
const search = (cmd) => {
|
|
91
|
+
if (typeof cmd.run === 'function')
|
|
92
|
+
return cmd;
|
|
93
|
+
if (cmd.default && cmd.default.run)
|
|
94
|
+
return cmd.default;
|
|
95
|
+
return Object.values(cmd).find((cmd) => typeof cmd.run === 'function');
|
|
96
|
+
};
|
|
90
97
|
class Plugin {
|
|
91
98
|
constructor(options) {
|
|
92
99
|
this.options = options;
|
|
@@ -96,29 +103,34 @@ class Plugin {
|
|
|
96
103
|
this.children = [];
|
|
97
104
|
this.hasManifest = false;
|
|
98
105
|
// eslint-disable-next-line new-cap
|
|
99
|
-
this._debug = (0,
|
|
106
|
+
this._debug = (0, util_1.Debug)();
|
|
100
107
|
this.warned = false;
|
|
101
108
|
}
|
|
102
109
|
async load() {
|
|
103
110
|
this.type = this.options.type || 'core';
|
|
104
111
|
this.tag = this.options.tag;
|
|
105
|
-
|
|
112
|
+
if (this.options.parent)
|
|
113
|
+
this.parent = this.options.parent;
|
|
114
|
+
// Linked plugins already have a root so there's no need to search for it.
|
|
115
|
+
// However there could be child plugins nested inside the linked plugin, in which
|
|
116
|
+
// case we still need to search for the child plugin's root.
|
|
117
|
+
const root = this.type === 'link' && !this.parent ? this.options.root : await findRoot(this.options.name, this.options.root);
|
|
106
118
|
if (!root)
|
|
107
|
-
throw new errors_1.CLIError(`could not find package.json with ${(0,
|
|
119
|
+
throw new errors_1.CLIError(`could not find package.json with ${(0, node_util_1.inspect)(this.options)}`);
|
|
108
120
|
this.root = root;
|
|
109
121
|
this._debug('reading %s plugin %s', this.type, root);
|
|
110
|
-
this.pjson = await (0,
|
|
122
|
+
this.pjson = await (0, util_2.readJson)((0, node_path_1.join)(root, 'package.json'));
|
|
111
123
|
this.flexibleTaxonomy = this.options?.flexibleTaxonomy || this.pjson.oclif?.flexibleTaxonomy || false;
|
|
112
124
|
this.moduleType = this.pjson.type === 'module' ? 'module' : 'commonjs';
|
|
113
125
|
this.name = this.pjson.name;
|
|
114
126
|
this.alias = this.options.name ?? this.pjson.name;
|
|
115
|
-
const pjsonPath =
|
|
127
|
+
const pjsonPath = (0, node_path_1.join)(root, 'package.json');
|
|
116
128
|
if (!this.name)
|
|
117
129
|
throw new errors_1.CLIError(`no name in ${pjsonPath}`);
|
|
118
|
-
if (!(0,
|
|
130
|
+
if (!(0, util_2.isProd)() && !this.pjson.files)
|
|
119
131
|
this.warn(`files attribute must be specified in ${pjsonPath}`);
|
|
120
132
|
// eslint-disable-next-line new-cap
|
|
121
|
-
this._debug = (0,
|
|
133
|
+
this._debug = (0, util_1.Debug)(this.name);
|
|
122
134
|
this.version = this.pjson.version;
|
|
123
135
|
if (this.pjson.oclif) {
|
|
124
136
|
this.valid = true;
|
|
@@ -126,7 +138,7 @@ class Plugin {
|
|
|
126
138
|
else {
|
|
127
139
|
this.pjson.oclif = this.pjson['cli-engine'] || {};
|
|
128
140
|
}
|
|
129
|
-
this.hooks = (0,
|
|
141
|
+
this.hooks = (0, util_1.mapValues)(this.pjson.oclif.hooks || {}, i => Array.isArray(i) ? i : [i]);
|
|
130
142
|
this.manifest = await this._manifest();
|
|
131
143
|
this.commands = Object
|
|
132
144
|
.entries(this.manifest.commands)
|
|
@@ -150,18 +162,18 @@ class Plugin {
|
|
|
150
162
|
get commandIDs() {
|
|
151
163
|
if (!this.commandsDir)
|
|
152
164
|
return [];
|
|
153
|
-
const marker = performance_1.
|
|
165
|
+
const marker = performance_1.Performance.mark(`plugin.commandIDs#${this.name}`, { plugin: this.name });
|
|
154
166
|
this._debug(`loading IDs from ${this.commandsDir}`);
|
|
155
167
|
const patterns = [
|
|
156
168
|
'**/*.+(js|cjs|mjs|ts|tsx)',
|
|
157
169
|
'!**/*.+(d.ts|test.ts|test.js|spec.ts|spec.js)?(x)',
|
|
158
170
|
];
|
|
159
|
-
const ids =
|
|
171
|
+
const ids = (0, globby_1.sync)(patterns, { cwd: this.commandsDir })
|
|
160
172
|
.map(file => {
|
|
161
|
-
const p =
|
|
173
|
+
const p = (0, node_path_1.parse)(file);
|
|
162
174
|
const topics = p.dir.split('/');
|
|
163
175
|
const command = p.name !== 'index' && p.name;
|
|
164
|
-
const id = [...topics, command].filter(
|
|
176
|
+
const id = [...topics, command].filter(Boolean).join(':');
|
|
165
177
|
return id === '' ? '.' : id;
|
|
166
178
|
});
|
|
167
179
|
this._debug('found commands', ids);
|
|
@@ -170,34 +182,31 @@ class Plugin {
|
|
|
170
182
|
return ids;
|
|
171
183
|
}
|
|
172
184
|
async findCommand(id, opts = {}) {
|
|
173
|
-
const marker = performance_1.
|
|
185
|
+
const marker = performance_1.Performance.mark(`plugin.findCommand#${this.name}.${id}`, { id, plugin: this.name });
|
|
174
186
|
const fetch = async () => {
|
|
175
187
|
if (!this.commandsDir)
|
|
176
188
|
return;
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
if (cmd.default && cmd.default.run)
|
|
181
|
-
return cmd.default;
|
|
182
|
-
return Object.values(cmd).find((cmd) => typeof cmd.run === 'function');
|
|
183
|
-
};
|
|
184
|
-
let m;
|
|
189
|
+
let module;
|
|
190
|
+
let isESM;
|
|
191
|
+
let filePath;
|
|
185
192
|
try {
|
|
186
|
-
|
|
187
|
-
|
|
193
|
+
({ isESM, module, filePath } = cachedCommandCanBeUsed(this.manifest, id)
|
|
194
|
+
? await (0, module_loader_1.loadWithDataFromManifest)(this.manifest.commands[id], this.root)
|
|
195
|
+
: await (0, module_loader_1.loadWithData)(this, (0, node_path_1.join)(this.commandsDir ?? this.pjson.oclif.commands, ...id.split(':'))));
|
|
188
196
|
this._debug(isESM ? '(import)' : '(require)', filePath);
|
|
189
|
-
m = module;
|
|
190
197
|
}
|
|
191
198
|
catch (error) {
|
|
192
199
|
if (!opts.must && error.code === 'MODULE_NOT_FOUND')
|
|
193
200
|
return;
|
|
194
201
|
throw error;
|
|
195
202
|
}
|
|
196
|
-
const cmd = search(
|
|
203
|
+
const cmd = search(module);
|
|
197
204
|
if (!cmd)
|
|
198
205
|
return;
|
|
199
206
|
cmd.id = id;
|
|
200
207
|
cmd.plugin = this;
|
|
208
|
+
cmd.isESM = isESM;
|
|
209
|
+
cmd.relativePath = (0, node_path_1.relative)(this.root, filePath || '').split(node_path_1.sep);
|
|
201
210
|
return cmd;
|
|
202
211
|
};
|
|
203
212
|
const cmd = await fetch();
|
|
@@ -212,8 +221,8 @@ class Plugin {
|
|
|
212
221
|
const respectNoCacheDefault = Boolean(this.options.respectNoCacheDefault);
|
|
213
222
|
const readManifest = async (dotfile = false) => {
|
|
214
223
|
try {
|
|
215
|
-
const p =
|
|
216
|
-
const manifest = await (0,
|
|
224
|
+
const p = (0, node_path_1.join)(this.root, `${dotfile ? '.' : ''}oclif.manifest.json`);
|
|
225
|
+
const manifest = await (0, util_2.readJson)(p);
|
|
217
226
|
if (!process.env.OCLIF_NEXT_VERSION && manifest.version.split('-')[0] !== this.version.split('-')[0]) {
|
|
218
227
|
process.emitWarning(`Mismatched version in ${this.name} plugin manifest. Expected: ${this.version} Received: ${manifest.version}\nThis usually means you have an oclif.manifest.json file that should be deleted in development. This file should be automatically generated when publishing.`);
|
|
219
228
|
}
|
|
@@ -233,7 +242,7 @@ class Plugin {
|
|
|
233
242
|
}
|
|
234
243
|
}
|
|
235
244
|
};
|
|
236
|
-
const marker = performance_1.
|
|
245
|
+
const marker = performance_1.Performance.mark(`plugin.manifest#${this.name}`, { plugin: this.name });
|
|
237
246
|
if (!ignoreManifest) {
|
|
238
247
|
const manifest = await readManifest();
|
|
239
248
|
if (manifest) {
|
|
@@ -248,8 +257,8 @@ class Plugin {
|
|
|
248
257
|
try {
|
|
249
258
|
const cached = await (0, config_1.toCached)(await this.findCommand(id, { must: true }), this, respectNoCacheDefault);
|
|
250
259
|
if (this.flexibleTaxonomy) {
|
|
251
|
-
const permutations = (0,
|
|
252
|
-
const aliasPermutations = cached.aliases.flatMap(a => (0,
|
|
260
|
+
const permutations = (0, util_1.getCommandIdPermutations)(id);
|
|
261
|
+
const aliasPermutations = cached.aliases.flatMap(a => (0, util_1.getCommandIdPermutations)(a));
|
|
253
262
|
return [id, { ...cached, permutations, aliasPermutations }];
|
|
254
263
|
}
|
|
255
264
|
return [id, cached];
|
|
@@ -262,6 +271,7 @@ class Plugin {
|
|
|
262
271
|
throw this.addErrorScope(error, scope);
|
|
263
272
|
}
|
|
264
273
|
})))
|
|
274
|
+
// eslint-disable-next-line unicorn/no-await-expression-member, unicorn/prefer-native-coercion-functions
|
|
265
275
|
.filter((f) => Boolean(f))
|
|
266
276
|
.reduce((commands, [id, c]) => {
|
|
267
277
|
commands[id] = c;
|
|
@@ -281,7 +291,7 @@ class Plugin {
|
|
|
281
291
|
}
|
|
282
292
|
addErrorScope(err, scope) {
|
|
283
293
|
err.name = `${err.name} Plugin: ${this.name}`;
|
|
284
|
-
err.detail = (0,
|
|
294
|
+
err.detail = (0, util_2.compact)([err.detail, `module: ${this._base}`, scope && `task: ${scope}`, `plugin: ${this.name}`, `root: ${this.root}`, 'See more details with DEBUG=*']).join('\n');
|
|
285
295
|
return err;
|
|
286
296
|
}
|
|
287
297
|
}
|