@oclif/core 2.14.0 → 2.15.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.
@@ -1,7 +1,6 @@
1
1
  import { Options, Plugin as IPlugin } from '../interfaces/plugin';
2
2
  import { Config as IConfig, ArchTypes, PlatformTypes, LoadOptions, VersionDetails } from '../interfaces/config';
3
3
  import { Hook, Hooks, PJSON, Topic } from '../interfaces';
4
- import * as Plugin from './plugin';
5
4
  import { Command } from '../command';
6
5
  export declare class Config implements IConfig {
7
6
  options: Options;
@@ -39,13 +38,14 @@ export declare class Config implements IConfig {
39
38
  private _commands;
40
39
  private _topics;
41
40
  private _commandIDs;
41
+ private pluginLoader;
42
+ private rootPlugin;
42
43
  constructor(options: Options);
43
44
  static load(opts?: LoadOptions): Promise<Config>;
44
45
  load(): Promise<void>;
45
- loadPluginsAndCommands(): Promise<void>;
46
- loadCorePlugins(): Promise<void>;
47
- loadDevPlugins(): Promise<void>;
48
- loadUserPlugins(): Promise<void>;
46
+ loadPluginsAndCommands(opts?: {
47
+ force: boolean;
48
+ }): Promise<void>;
49
49
  runHook<T extends keyof Hooks>(event: T, opts: Hooks[T]['options'], timeout?: number, captureErrors?: boolean): Promise<Hook.Result<Hooks[T]['return']>>;
50
50
  runCommand<T = unknown>(id: string, argv?: string[], cachedCommand?: Command.Loadable | null): Promise<T>;
51
51
  scopedEnvVar(k: string): string | undefined;
@@ -112,11 +112,6 @@ export declare class Config implements IConfig {
112
112
  protected macosCacheDir(): string | undefined;
113
113
  protected _shell(): string;
114
114
  protected _debug(): number;
115
- protected loadPlugins(root: string, type: string, plugins: (string | {
116
- root?: string;
117
- name?: string;
118
- tag?: string;
119
- })[], parent?: Plugin.Plugin): Promise<void>;
120
115
  protected warn(err: string | Error | {
121
116
  name: string;
122
117
  detail: string;
@@ -7,7 +7,6 @@ const os = require("os");
7
7
  const path = require("path");
8
8
  const url_1 = require("url");
9
9
  const util_1 = require("util");
10
- const Plugin = require("./plugin");
11
10
  const util_2 = require("./util");
12
11
  const util_3 = require("../util");
13
12
  const module_loader_1 = require("../module-loader");
@@ -17,6 +16,7 @@ const performance_1 = require("../performance");
17
16
  const settings_1 = require("../settings");
18
17
  const os_1 = require("os");
19
18
  const path_1 = require("path");
19
+ const plugin_loader_1 = require("./plugin-loader");
20
20
  // eslint-disable-next-line new-cap
21
21
  const debug = (0, util_2.Debug)();
22
22
  const _pjson = (0, util_3.requireJson)(__dirname, '..', '..', 'package.json');
@@ -70,24 +70,6 @@ class Config {
70
70
  this.topicPermutations = new Permutations();
71
71
  this._commands = new Map();
72
72
  this._topics = new Map();
73
- if (options.config) {
74
- if (Array.isArray(options.config.plugins) && Array.isArray(this.plugins)) {
75
- // incoming config is v2 with plugins array and this config is v2 with plugins array
76
- Object.assign(this, options.config);
77
- }
78
- else if (Array.isArray(options.config.plugins) && !Array.isArray(this.plugins)) {
79
- // incoming config is v2 with plugins array and this config is v3 with plugin Map
80
- Object.assign(this, options.config, { plugins: new Map(options.config.plugins.map(p => [p.name, p])) });
81
- }
82
- else if (!Array.isArray(options.config.plugins) && Array.isArray(this.plugins)) {
83
- // incoming config is v3 with plugin Map and this config is v2 with plugins array
84
- Object.assign(this, options.config, { plugins: options.config.getPluginsList() });
85
- }
86
- else {
87
- // incoming config is v3 with plugin Map and this config is v3 with plugin Map
88
- Object.assign(this, options.config);
89
- }
90
- }
91
73
  }
92
74
  static async load(opts = module.filename || __dirname) {
93
75
  // Handle the case when a file URL string is passed in such as 'import.meta.url'; covert to file path.
@@ -97,9 +79,6 @@ class Config {
97
79
  if (typeof opts === 'string')
98
80
  opts = { root: opts };
99
81
  if (isConfig(opts)) {
100
- const { lt } = await import('semver');
101
- const currentConfigBase = BASE.replace('@oclif/core@', '');
102
- const incomingConfigBase = opts._base.replace('@oclif/core@', '');
103
82
  /**
104
83
  * Reload the Config based on the version required by the command.
105
84
  * This is needed because the command is given the Config instantiated
@@ -110,9 +89,11 @@ class Config {
110
89
  * exists in the version of Config required by the command but may not exist on the
111
90
  * root's instance of Config.
112
91
  */
113
- if (lt(incomingConfigBase, currentConfigBase)) {
92
+ if (BASE !== opts._base) {
114
93
  debug(`reloading config from ${opts._base} to ${BASE}`);
115
- return new Config({ ...opts.options, config: opts });
94
+ const config = new Config({ ...opts.options, plugins: opts.plugins });
95
+ await config.load();
96
+ return config;
116
97
  }
117
98
  return opts;
118
99
  }
@@ -122,18 +103,15 @@ class Config {
122
103
  }
123
104
  // eslint-disable-next-line complexity
124
105
  async load() {
125
- if (this.options.config)
126
- return;
127
106
  settings_1.settings.performanceEnabled = (settings_1.settings.performanceEnabled === undefined ? this.options.enablePerf : settings_1.settings.performanceEnabled) ?? false;
128
- const plugin = new Plugin.Plugin({ root: this.options.root });
129
- await plugin.load();
130
- this.plugins.push(plugin);
131
- this.root = plugin.root;
132
- this.pjson = plugin.pjson;
107
+ this.pluginLoader = new plugin_loader_1.default({ root: this.options.root, plugins: this.options.plugins });
108
+ this.rootPlugin = await this.pluginLoader.loadRoot();
109
+ this.root = this.rootPlugin.root;
110
+ this.pjson = this.rootPlugin.pjson;
133
111
  this.name = this.pjson.name;
134
112
  this.version = this.options.version || this.pjson.version || '0.0.0';
135
113
  this.channel = this.options.channel || channelFromVersion(this.version);
136
- this.valid = plugin.valid;
114
+ this.valid = this.rootPlugin.valid;
137
115
  this.arch = (os.arch() === 'ia32' ? 'x86' : os.arch());
138
116
  this.platform = WSL ? 'wsl' : os.platform();
139
117
  this.windows = this.platform === 'win32';
@@ -192,56 +170,24 @@ class Config {
192
170
  });
193
171
  marker?.stop();
194
172
  }
195
- async loadPluginsAndCommands() {
173
+ async loadPluginsAndCommands(opts) {
196
174
  const marker = performance_1.Performance.mark('config.loadPluginsAndCommands');
197
- await this.loadUserPlugins();
198
- await this.loadDevPlugins();
199
- await this.loadCorePlugins();
175
+ const { plugins, errors } = await this.pluginLoader.loadChildren({
176
+ devPlugins: this.options.devPlugins,
177
+ userPlugins: this.options.userPlugins,
178
+ dataDir: this.dataDir,
179
+ rootPlugin: this.rootPlugin,
180
+ force: opts?.force ?? false,
181
+ });
182
+ this.plugins = [...plugins.values()];
200
183
  for (const plugin of this.plugins) {
201
184
  this.loadCommands(plugin);
202
185
  this.loadTopics(plugin);
203
186
  }
204
- marker?.stop();
205
- }
206
- async loadCorePlugins() {
207
- if (this.pjson.oclif.plugins) {
208
- await this.loadPlugins(this.root, 'core', this.pjson.oclif.plugins);
209
- }
210
- }
211
- async loadDevPlugins() {
212
- if (this.options.devPlugins !== false) {
213
- // do not load oclif.devPlugins in production
214
- if (this.isProd)
215
- return;
216
- try {
217
- const devPlugins = this.pjson.oclif.devPlugins;
218
- if (devPlugins)
219
- await this.loadPlugins(this.root, 'dev', devPlugins);
220
- }
221
- catch (error) {
222
- process.emitWarning(error);
223
- }
224
- }
225
- }
226
- async loadUserPlugins() {
227
- if (this.options.userPlugins !== false) {
228
- try {
229
- const userPJSONPath = path.join(this.dataDir, 'package.json');
230
- debug('reading user plugins pjson %s', userPJSONPath);
231
- const pjson = await (0, util_2.loadJSON)(userPJSONPath);
232
- this.userPJSON = pjson;
233
- if (!pjson.oclif)
234
- pjson.oclif = { schema: 1 };
235
- if (!pjson.oclif.plugins)
236
- pjson.oclif.plugins = [];
237
- await this.loadPlugins(userPJSONPath, 'user', pjson.oclif.plugins.filter((p) => p.type === 'user'));
238
- await this.loadPlugins(userPJSONPath, 'link', pjson.oclif.plugins.filter((p) => p.type === 'link'));
239
- }
240
- catch (error) {
241
- if (error.code !== 'ENOENT')
242
- process.emitWarning(error);
243
- }
187
+ for (const error of errors) {
188
+ this.warn(error);
244
189
  }
190
+ marker?.stop();
245
191
  }
246
192
  async runHook(event, opts, timeout, captureErrors) {
247
193
  const marker = performance_1.Performance.mark(`config.runHook#${event}`);
@@ -350,7 +296,7 @@ class Config {
350
296
  if (jitResult.failures[0])
351
297
  throw jitResult.failures[0].error;
352
298
  if (jitResult.successes[0]) {
353
- await this.loadPluginsAndCommands();
299
+ await this.loadPluginsAndCommands({ force: true });
354
300
  c = this.findCommand(id) ?? c;
355
301
  }
356
302
  else {
@@ -546,52 +492,6 @@ class Config {
546
492
  catch { }
547
493
  return 0;
548
494
  }
549
- async loadPlugins(root, type, plugins, parent) {
550
- if (!plugins || plugins.length === 0)
551
- return;
552
- const mark = performance_1.Performance.mark(`config.loadPlugins#${type}`);
553
- debug('loading plugins', plugins);
554
- await Promise.all((plugins || []).map(async (plugin) => {
555
- try {
556
- const opts = { type, root };
557
- if (typeof plugin === 'string') {
558
- opts.name = plugin;
559
- }
560
- else {
561
- opts.name = plugin.name || opts.name;
562
- opts.tag = plugin.tag || opts.tag;
563
- opts.root = plugin.root || opts.root;
564
- }
565
- const pluginMarker = performance_1.Performance.mark(`plugin.load#${opts.name}`);
566
- const instance = new Plugin.Plugin(opts);
567
- await instance.load();
568
- pluginMarker?.addDetails({
569
- hasManifest: instance.hasManifest,
570
- commandCount: instance.commands.length,
571
- topicCount: instance.topics.length,
572
- type: instance.type,
573
- usesMain: Boolean(instance.pjson.main),
574
- name: instance.name,
575
- });
576
- pluginMarker?.stop();
577
- if (this.plugins.find(p => p.name === instance.name))
578
- return;
579
- this.plugins.push(instance);
580
- if (parent) {
581
- instance.parent = parent;
582
- if (!parent.children)
583
- parent.children = [];
584
- parent.children.push(instance);
585
- }
586
- await this.loadPlugins(instance.root, type, instance.pjson.oclif.plugins || [], instance);
587
- }
588
- catch (error) {
589
- this.warn(error, 'loadPlugins');
590
- }
591
- }));
592
- mark?.addDetails({ pluginCount: plugins.length });
593
- mark?.stop();
594
- }
595
495
  warn(err, scope) {
596
496
  if (this.warned)
597
497
  return;
@@ -0,0 +1,30 @@
1
+ import { Plugin as IPlugin } from '../interfaces/plugin';
2
+ type PluginLoaderOptions = {
3
+ root: string;
4
+ plugins?: IPlugin[] | PluginsMap;
5
+ };
6
+ type LoadOpts = {
7
+ devPlugins?: boolean;
8
+ userPlugins?: boolean;
9
+ dataDir: string;
10
+ rootPlugin: IPlugin;
11
+ force?: boolean;
12
+ };
13
+ type PluginsMap = Map<string, IPlugin>;
14
+ export default class PluginLoader {
15
+ options: PluginLoaderOptions;
16
+ plugins: PluginsMap;
17
+ errors: (string | Error)[];
18
+ private pluginsProvided;
19
+ constructor(options: PluginLoaderOptions);
20
+ loadRoot(): Promise<IPlugin>;
21
+ loadChildren(opts: LoadOpts): Promise<{
22
+ plugins: PluginsMap;
23
+ errors: (string | Error)[];
24
+ }>;
25
+ private loadCorePlugins;
26
+ private loadDevPlugins;
27
+ private loadUserPlugins;
28
+ private loadPlugins;
29
+ }
30
+ export {};
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const path = require("path");
4
+ const Plugin = require("./plugin");
5
+ const util_1 = require("./util");
6
+ const util_2 = require("../util");
7
+ const performance_1 = require("../performance");
8
+ // eslint-disable-next-line new-cap
9
+ const debug = (0, util_1.Debug)();
10
+ class PluginLoader {
11
+ constructor(options) {
12
+ this.options = options;
13
+ this.plugins = new Map();
14
+ this.errors = [];
15
+ this.pluginsProvided = false;
16
+ if (options.plugins) {
17
+ this.pluginsProvided = true;
18
+ this.plugins = Array.isArray(options.plugins) ? new Map(options.plugins.map(p => [p.name, p])) : options.plugins;
19
+ }
20
+ }
21
+ async loadRoot() {
22
+ let rootPlugin;
23
+ if (this.pluginsProvided) {
24
+ const plugins = [...this.plugins.values()];
25
+ rootPlugin = plugins.find(p => p.root === this.options.root) ?? plugins[0];
26
+ }
27
+ else {
28
+ rootPlugin = new Plugin.Plugin({ root: this.options.root });
29
+ await rootPlugin.load();
30
+ }
31
+ this.plugins.set(rootPlugin.name, rootPlugin);
32
+ return rootPlugin;
33
+ }
34
+ async loadChildren(opts) {
35
+ if (!this.pluginsProvided || opts.force) {
36
+ await this.loadUserPlugins(opts);
37
+ await this.loadDevPlugins(opts);
38
+ await this.loadCorePlugins(opts);
39
+ }
40
+ return { plugins: this.plugins, errors: this.errors };
41
+ }
42
+ async loadCorePlugins(opts) {
43
+ if (opts.rootPlugin.pjson.oclif.plugins) {
44
+ await this.loadPlugins(opts.rootPlugin.root, 'core', opts.rootPlugin.pjson.oclif.plugins);
45
+ }
46
+ }
47
+ async loadDevPlugins(opts) {
48
+ if (opts.devPlugins !== false) {
49
+ // do not load oclif.devPlugins in production
50
+ if ((0, util_2.isProd)())
51
+ return;
52
+ try {
53
+ const devPlugins = opts.rootPlugin.pjson.oclif.devPlugins;
54
+ if (devPlugins)
55
+ await this.loadPlugins(opts.rootPlugin.root, 'dev', devPlugins);
56
+ }
57
+ catch (error) {
58
+ process.emitWarning(error);
59
+ }
60
+ }
61
+ }
62
+ async loadUserPlugins(opts) {
63
+ if (opts.userPlugins !== false) {
64
+ try {
65
+ const userPJSONPath = path.join(opts.dataDir, 'package.json');
66
+ debug('reading user plugins pjson %s', userPJSONPath);
67
+ const pjson = await (0, util_1.loadJSON)(userPJSONPath);
68
+ if (!pjson.oclif)
69
+ pjson.oclif = { schema: 1 };
70
+ if (!pjson.oclif.plugins)
71
+ pjson.oclif.plugins = [];
72
+ await this.loadPlugins(userPJSONPath, 'user', pjson.oclif.plugins.filter((p) => p.type === 'user'));
73
+ await this.loadPlugins(userPJSONPath, 'link', pjson.oclif.plugins.filter((p) => p.type === 'link'));
74
+ }
75
+ catch (error) {
76
+ if (error.code !== 'ENOENT')
77
+ process.emitWarning(error);
78
+ }
79
+ }
80
+ }
81
+ async loadPlugins(root, type, plugins, parent) {
82
+ if (!plugins || plugins.length === 0)
83
+ return;
84
+ const mark = performance_1.Performance.mark(`config.loadPlugins#${type}`);
85
+ debug('loading plugins', plugins);
86
+ await Promise.all((plugins || []).map(async (plugin) => {
87
+ try {
88
+ const name = typeof plugin === 'string' ? plugin : plugin.name;
89
+ const opts = {
90
+ name,
91
+ type,
92
+ root,
93
+ };
94
+ if (typeof plugin !== 'string') {
95
+ opts.tag = plugin.tag || opts.tag;
96
+ opts.root = plugin.root || opts.root;
97
+ }
98
+ if (this.plugins.has(name))
99
+ return;
100
+ const pluginMarker = performance_1.Performance.mark(`plugin.load#${name}`);
101
+ const instance = new Plugin.Plugin(opts);
102
+ await instance.load();
103
+ pluginMarker?.addDetails({
104
+ hasManifest: instance.hasManifest,
105
+ commandCount: instance.commands.length,
106
+ topicCount: instance.topics.length,
107
+ type: instance.type,
108
+ usesMain: Boolean(instance.pjson.main),
109
+ name: instance.name,
110
+ });
111
+ pluginMarker?.stop();
112
+ this.plugins.set(instance.name, instance);
113
+ if (parent) {
114
+ instance.parent = parent;
115
+ if (!parent.children)
116
+ parent.children = [];
117
+ parent.children.push(instance);
118
+ }
119
+ await this.loadPlugins(instance.root, type, instance.pjson.oclif.plugins || [], instance);
120
+ }
121
+ catch (error) {
122
+ this.errors.push(error);
123
+ }
124
+ }));
125
+ mark?.addDetails({ pluginCount: plugins.length });
126
+ mark?.stop();
127
+ }
128
+ }
129
+ exports.default = PluginLoader;
@@ -96,7 +96,6 @@ export interface Config {
96
96
  * npm registry to use for installing plugins
97
97
  */
98
98
  npmRegistry?: string;
99
- userPJSON?: PJSON.User;
100
99
  plugins: Plugin[];
101
100
  binPath?: string;
102
101
  /**
@@ -1,4 +1,3 @@
1
- import { Config } from './config';
2
1
  import { Command } from '../command';
3
2
  import { PJSON } from './pjson';
4
3
  import { Topic } from './topic';
@@ -19,7 +18,7 @@ export interface Options extends PluginOptions {
19
18
  channel?: string;
20
19
  version?: string;
21
20
  enablePerf?: boolean;
22
- config?: Config;
21
+ plugins?: Plugin[];
23
22
  }
24
23
  export interface Plugin {
25
24
  /**
@@ -76,5 +75,5 @@ export interface Plugin {
76
75
  findCommand(id: string, opts?: {
77
76
  must: boolean;
78
77
  }): Promise<Command.Class> | undefined;
79
- load(isWritingManifest: boolean): Promise<void>;
78
+ load(isWritingManifest?: boolean): Promise<void>;
80
79
  }
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.14.0",
4
+ "version": "2.15.0",
5
5
  "author": "Salesforce",
6
6
  "bugs": "https://github.com/oclif/core/issues",
7
7
  "dependencies": {
@@ -23,7 +23,6 @@
23
23
  "natural-orderby": "^2.0.3",
24
24
  "object-treeify": "^1.1.33",
25
25
  "password-prompt": "^1.1.2",
26
- "semver": "^7.5.4",
27
26
  "slice-ansi": "^4.0.0",
28
27
  "string-width": "^4.2.3",
29
28
  "strip-ansi": "^6.0.1",
@@ -53,7 +52,6 @@
53
52
  "@types/node": "^16",
54
53
  "@types/node-notifier": "^8.0.2",
55
54
  "@types/proxyquire": "^1.3.28",
56
- "@types/semver": "^7.5.1",
57
55
  "@types/shelljs": "^0.8.11",
58
56
  "@types/slice-ansi": "^4.0.0",
59
57
  "@types/strip-ansi": "^5.2.1",