@oclif/core 3.0.0-beta.2 → 3.0.0-beta.21

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.
Files changed (112) hide show
  1. package/README.md +10 -6
  2. package/flush.js +1 -1
  3. package/handle.js +1 -1
  4. package/lib/args.d.ts +1 -1
  5. package/lib/args.js +17 -18
  6. package/lib/cli-ux/action/base.d.ts +3 -5
  7. package/lib/cli-ux/action/base.js +32 -26
  8. package/lib/cli-ux/action/simple.js +13 -18
  9. package/lib/cli-ux/action/spinner.d.ts +4 -2
  10. package/lib/cli-ux/action/spinner.js +27 -19
  11. package/lib/cli-ux/action/spinners.js +1 -1
  12. package/lib/cli-ux/action/types.d.ts +5 -0
  13. package/lib/cli-ux/action/types.js +2 -0
  14. package/lib/cli-ux/config.d.ts +0 -1
  15. package/lib/cli-ux/config.js +17 -21
  16. package/lib/cli-ux/exit.d.ts +1 -1
  17. package/lib/cli-ux/exit.js +4 -1
  18. package/lib/cli-ux/flush.d.ts +1 -0
  19. package/lib/cli-ux/flush.js +28 -0
  20. package/lib/cli-ux/index.d.ts +10 -30
  21. package/lib/cli-ux/index.js +32 -75
  22. package/lib/cli-ux/list.js +3 -3
  23. package/lib/cli-ux/prompt.js +32 -22
  24. package/lib/cli-ux/stream.js +1 -0
  25. package/lib/cli-ux/styled/index.d.ts +5 -6
  26. package/lib/cli-ux/styled/index.js +11 -11
  27. package/lib/cli-ux/styled/json.js +8 -5
  28. package/lib/cli-ux/styled/object.js +7 -9
  29. package/lib/cli-ux/styled/table.d.ts +4 -4
  30. package/lib/cli-ux/styled/table.js +61 -64
  31. package/lib/cli-ux/styled/tree.js +1 -3
  32. package/lib/cli-ux/wait.js +3 -5
  33. package/lib/command.d.ts +15 -19
  34. package/lib/command.js +117 -96
  35. package/lib/config/config.d.ts +16 -23
  36. package/lib/config/config.js +180 -334
  37. package/lib/config/index.d.ts +1 -1
  38. package/lib/config/index.js +1 -2
  39. package/lib/config/plugin-loader.d.ts +30 -0
  40. package/lib/config/plugin-loader.js +145 -0
  41. package/lib/config/plugin.d.ts +6 -11
  42. package/lib/config/plugin.js +112 -78
  43. package/lib/config/ts-node.d.ts +2 -1
  44. package/lib/config/ts-node.js +64 -51
  45. package/lib/config/util.d.ts +1 -11
  46. package/lib/config/util.js +6 -59
  47. package/lib/errors/config.js +1 -1
  48. package/lib/errors/errors/cli.d.ts +1 -1
  49. package/lib/errors/errors/cli.js +18 -14
  50. package/lib/errors/errors/exit.d.ts +0 -3
  51. package/lib/errors/errors/exit.js +1 -1
  52. package/lib/errors/errors/module-load.d.ts +0 -3
  53. package/lib/errors/errors/module-load.js +1 -1
  54. package/lib/errors/errors/pretty-print.js +11 -9
  55. package/lib/errors/handle.d.ts +12 -2
  56. package/lib/errors/handle.js +28 -18
  57. package/lib/errors/index.d.ts +2 -2
  58. package/lib/errors/index.js +20 -19
  59. package/lib/errors/logger.js +9 -8
  60. package/lib/execute.d.ts +49 -0
  61. package/lib/execute.js +63 -0
  62. package/lib/flags.d.ts +102 -31
  63. package/lib/flags.js +81 -46
  64. package/lib/help/command.d.ts +2 -0
  65. package/lib/help/command.js +68 -53
  66. package/lib/help/docopts.js +9 -13
  67. package/lib/help/formatter.d.ts +1 -1
  68. package/lib/help/formatter.js +35 -24
  69. package/lib/help/index.d.ts +7 -3
  70. package/lib/help/index.js +77 -55
  71. package/lib/help/root.js +7 -9
  72. package/lib/help/util.d.ts +1 -7
  73. package/lib/help/util.js +8 -28
  74. package/lib/index.d.ts +19 -18
  75. package/lib/index.js +36 -48
  76. package/lib/interfaces/config.d.ts +30 -30
  77. package/lib/interfaces/errors.d.ts +1 -1
  78. package/lib/interfaces/hooks.d.ts +3 -3
  79. package/lib/interfaces/index.d.ts +14 -14
  80. package/lib/interfaces/parser.d.ts +188 -116
  81. package/lib/interfaces/pjson.d.ts +2 -1
  82. package/lib/interfaces/plugin.d.ts +10 -1
  83. package/lib/main.d.ts +0 -48
  84. package/lib/main.js +11 -66
  85. package/lib/module-loader.d.ts +68 -79
  86. package/lib/module-loader.js +183 -150
  87. package/lib/parser/errors.d.ts +3 -3
  88. package/lib/parser/errors.js +17 -10
  89. package/lib/parser/help.js +5 -5
  90. package/lib/parser/parse.d.ts +3 -0
  91. package/lib/parser/parse.js +114 -115
  92. package/lib/parser/validate.js +45 -25
  93. package/lib/performance.d.ts +5 -1
  94. package/lib/performance.js +40 -19
  95. package/lib/util/aggregate-flags.d.ts +2 -0
  96. package/lib/util/aggregate-flags.js +13 -0
  97. package/lib/util/cache-command.d.ts +3 -0
  98. package/lib/util/cache-command.js +109 -0
  99. package/lib/util/cache-default-value.d.ts +2 -0
  100. package/lib/util/cache-default-value.js +28 -0
  101. package/lib/util/ensure-arg-object.d.ts +12 -0
  102. package/lib/util/ensure-arg-object.js +14 -0
  103. package/lib/util/fs.d.ts +7 -0
  104. package/lib/util/fs.js +54 -0
  105. package/lib/util/os.d.ts +19 -0
  106. package/lib/util/os.js +28 -0
  107. package/lib/{util.d.ts → util/util.d.ts} +6 -15
  108. package/lib/util/util.js +98 -0
  109. package/package.json +32 -34
  110. package/lib/cli-ux/action/pride-spinner.d.ts +0 -4
  111. package/lib/cli-ux/action/pride-spinner.js +0 -30
  112. package/lib/util.js +0 -126
@@ -1,41 +1,40 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toCached = exports.Config = void 0;
3
+ exports.Config = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const ejs = tslib_1.__importStar(require("ejs"));
4
6
  const errors_1 = require("../errors");
5
- const ejs = require("ejs");
6
- const os = require("os");
7
- const path = require("path");
8
- const url_1 = require("url");
9
- const util_1 = require("util");
10
- const Plugin = require("./plugin");
11
- const util_2 = require("./util");
12
- const util_3 = require("../util");
13
- const module_loader_1 = require("../module-loader");
14
- const help_1 = require("../help");
15
- const stream_1 = require("../cli-ux/stream");
16
- const performance_1 = require("../performance");
17
- const settings_1 = require("../settings");
7
+ const util_1 = require("./util");
8
+ const node_url_1 = require("node:url");
18
9
  const node_os_1 = require("node:os");
10
+ const util_2 = require("../util/util");
11
+ const os_1 = require("../util/os");
19
12
  const node_path_1 = require("node:path");
13
+ const performance_1 = require("../performance");
14
+ const plugin_loader_1 = tslib_1.__importDefault(require("./plugin-loader"));
15
+ const is_wsl_1 = tslib_1.__importDefault(require("is-wsl"));
16
+ const node_util_1 = require("node:util");
17
+ const util_3 = require("../help/util");
18
+ const module_loader_1 = require("../module-loader");
19
+ const fs_1 = require("../util/fs");
20
+ const settings_1 = require("../settings");
21
+ const stream_1 = require("../cli-ux/stream");
20
22
  // eslint-disable-next-line new-cap
21
- const debug = (0, util_2.Debug)();
22
- const _pjson = (0, util_3.requireJson)(__dirname, '..', '..', 'package.json');
23
+ const debug = (0, util_1.Debug)();
24
+ const _pjson = (0, fs_1.requireJson)(__dirname, '..', '..', 'package.json');
25
+ const BASE = `${_pjson.name}@${_pjson.version}`;
23
26
  function channelFromVersion(version) {
24
27
  const m = version.match(/[^-]+(?:-([^.]+))?/);
25
28
  return (m && m[1]) || 'stable';
26
29
  }
27
- const WSL = require('is-wsl');
28
30
  function isConfig(o) {
29
31
  return o && Boolean(o._base);
30
32
  }
31
33
  class Permutations extends Map {
32
- constructor() {
33
- super(...arguments);
34
- this.validPermutations = new Map();
35
- }
34
+ validPermutations = new Map();
36
35
  add(permutation, commandId) {
37
36
  this.validPermutations.set(permutation, commandId);
38
- for (const id of (0, util_2.collectUsableIds)([permutation])) {
37
+ for (const id of (0, util_1.collectUsableIds)([permutation])) {
39
38
  if (this.has(id)) {
40
39
  this.set(id, this.get(id).add(commandId));
41
40
  }
@@ -58,27 +57,72 @@ class Permutations extends Map {
58
57
  }
59
58
  }
60
59
  class Config {
60
+ options;
61
+ _base = BASE;
62
+ arch;
63
+ bin;
64
+ binPath;
65
+ cacheDir;
66
+ channel;
67
+ configDir;
68
+ dataDir;
69
+ debug = 0;
70
+ dirname;
71
+ errlog;
72
+ flexibleTaxonomy;
73
+ home;
74
+ name;
75
+ npmRegistry;
76
+ pjson;
77
+ platform;
78
+ plugins = new Map();
79
+ root;
80
+ shell;
81
+ topicSeparator = ':';
82
+ userAgent;
83
+ userPJSON;
84
+ valid;
85
+ version;
86
+ windows;
87
+ binAliases;
88
+ nsisCustomization;
89
+ warned = false;
90
+ commandPermutations = new Permutations();
91
+ topicPermutations = new Permutations();
92
+ _commands = new Map();
93
+ _topics = new Map();
94
+ _commandIDs;
95
+ pluginLoader;
96
+ static _rootPlugin;
61
97
  constructor(options) {
62
98
  this.options = options;
63
- this._base = `${_pjson.name}@${_pjson.version}`;
64
- this.debug = 0;
65
- this.plugins = [];
66
- this.topicSeparator = ':';
67
- this.warned = false;
68
- this.commandPermutations = new Permutations();
69
- this.topicPermutations = new Permutations();
70
- this._commands = new Map();
71
- this._topics = new Map();
72
99
  }
73
100
  static async load(opts = module.filename || __dirname) {
74
101
  // Handle the case when a file URL string is passed in such as 'import.meta.url'; covert to file path.
75
102
  if (typeof opts === 'string' && opts.startsWith('file://')) {
76
- opts = (0, url_1.fileURLToPath)(opts);
103
+ opts = (0, node_url_1.fileURLToPath)(opts);
77
104
  }
78
105
  if (typeof opts === 'string')
79
106
  opts = { root: opts };
80
- if (isConfig(opts))
107
+ if (isConfig(opts)) {
108
+ /**
109
+ * Reload the Config based on the version required by the command.
110
+ * This is needed because the command is given the Config instantiated
111
+ * by the root plugin, which may be a different version than the one
112
+ * required by the command.
113
+ *
114
+ * Doing this ensures that the command can freely use any method on Config that
115
+ * exists in the version of Config required by the command but may not exist on the
116
+ * root's instance of Config.
117
+ */
118
+ if (BASE !== opts._base) {
119
+ debug(`reloading config from ${opts._base} to ${BASE}`);
120
+ const config = new Config({ ...opts.options, plugins: opts.plugins });
121
+ await config.load();
122
+ return config;
123
+ }
81
124
  return opts;
125
+ }
82
126
  const config = new Config(opts);
83
127
  await config.load();
84
128
  return config;
@@ -88,19 +132,22 @@ class Config {
88
132
  }
89
133
  // eslint-disable-next-line complexity
90
134
  async load() {
91
- settings_1.settings.performanceEnabled = (settings_1.settings.performanceEnabled === undefined ? this.options.enablePerf : settings_1.settings.performanceEnabled) ?? false;
92
- const plugin = new Plugin.Plugin({ root: this.options.root });
93
- await plugin.load();
94
- Config._rootPlugin = plugin;
95
- this.plugins.push(plugin);
96
- this.root = plugin.root;
97
- this.pjson = plugin.pjson;
135
+ settings_1.settings.performanceEnabled =
136
+ (settings_1.settings.performanceEnabled === undefined ? this.options.enablePerf : settings_1.settings.performanceEnabled) ?? false;
137
+ const marker = performance_1.Performance.mark('config.load');
138
+ this.pluginLoader = new plugin_loader_1.default({ root: this.options.root, plugins: this.options.plugins });
139
+ Config._rootPlugin = await this.pluginLoader.loadRoot();
140
+ this.root = Config._rootPlugin.root;
141
+ this.pjson = Config._rootPlugin.pjson;
142
+ this.plugins.set(Config._rootPlugin.name, Config._rootPlugin);
143
+ this.root = Config._rootPlugin.root;
144
+ this.pjson = Config._rootPlugin.pjson;
98
145
  this.name = this.pjson.name;
99
146
  this.version = this.options.version || this.pjson.version || '0.0.0';
100
147
  this.channel = this.options.channel || channelFromVersion(this.version);
101
- this.valid = plugin.valid;
102
- this.arch = (os.arch() === 'ia32' ? 'x86' : os.arch());
103
- this.platform = WSL ? 'wsl' : os.platform();
148
+ this.valid = Config._rootPlugin.valid;
149
+ this.arch = (0, node_os_1.arch)() === 'ia32' ? 'x86' : (0, node_os_1.arch)();
150
+ this.platform = is_wsl_1.default ? 'wsl' : (0, os_1.getPlatform)();
104
151
  this.windows = this.platform === 'win32';
105
152
  this.bin = this.pjson.oclif.bin || this.name;
106
153
  this.binAliases = this.pjson.oclif.binAliases;
@@ -115,11 +162,11 @@ class Config {
115
162
  this.userAgent = `${this.name}/${this.version} ${this.platform}-${this.arch} node-${process.version}`;
116
163
  this.shell = this._shell();
117
164
  this.debug = this._debug();
118
- this.home = process.env.HOME || (this.windows && this.windowsHome()) || os.homedir() || os.tmpdir();
165
+ this.home = process.env.HOME || (this.windows && this.windowsHome()) || (0, os_1.getHomeDir)() || (0, node_os_1.tmpdir)();
119
166
  this.cacheDir = this.scopedEnvVar('CACHE_DIR') || this.macosCacheDir() || this.dir('cache');
120
167
  this.configDir = this.scopedEnvVar('CONFIG_DIR') || this.dir('config');
121
168
  this.dataDir = this.scopedEnvVar('DATA_DIR') || this.dir('data');
122
- this.errlog = path.join(this.cacheDir, 'error.log');
169
+ this.errlog = (0, node_path_1.join)(this.cacheDir, 'error.log');
123
170
  this.binPath = this.scopedEnvVar('BINPATH');
124
171
  this.npmRegistry = this.scopedEnvVar('NPM_REGISTRY') || this.pjson.oclif.npmRegistry;
125
172
  this.pjson.oclif.update = this.pjson.oclif.update || {};
@@ -136,76 +183,45 @@ class Config {
136
183
  unversioned: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %><%- bin %>-<%- platform %>-<%- arch %><%- ext %>",
137
184
  versioned: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %><%- bin %>-v<%- version %>/<%- bin %>-v<%- version %>-<%- platform %>-<%- arch %><%- ext %>",
138
185
  manifest: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %><%- platform %>-<%- arch %>",
139
- ...s3.templates && s3.templates.target,
186
+ ...(s3.templates && s3.templates.target),
140
187
  },
141
188
  vanilla: {
142
189
  unversioned: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %><%- bin %><%- ext %>",
143
190
  versioned: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %><%- bin %>-v<%- version %>/<%- bin %>-v<%- version %><%- ext %>",
144
191
  baseDir: '<%- bin %>',
145
192
  manifest: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %>version",
146
- ...s3.templates && s3.templates.vanilla,
193
+ ...(s3.templates && s3.templates.vanilla),
147
194
  },
148
195
  };
149
- const marker = performance_1.Performance.mark('config.load');
150
196
  await this.loadPluginsAndCommands();
151
197
  debug('config done');
152
198
  marker?.addDetails({
153
- plugins: this.plugins.length,
199
+ plugins: this.plugins.size,
154
200
  commandPermutations: this.commands.length,
155
- commands: this.plugins.reduce((acc, p) => acc + p.commands.length, 0),
201
+ commands: [...this.plugins.values()].reduce((acc, p) => acc + p.commands.length, 0),
156
202
  topics: this.topics.length,
157
203
  });
158
204
  marker?.stop();
159
205
  }
160
- async loadPluginsAndCommands() {
161
- const marker = performance_1.Performance.mark('config.loadPluginsAndCommands');
162
- await this.loadUserPlugins();
163
- await this.loadDevPlugins();
164
- await this.loadCorePlugins();
165
- for (const plugin of this.plugins) {
206
+ async loadPluginsAndCommands(opts) {
207
+ const pluginsMarker = performance_1.Performance.mark('config.loadAllPlugins');
208
+ const { plugins, errors } = await this.pluginLoader.loadChildren({
209
+ devPlugins: this.options.devPlugins,
210
+ userPlugins: this.options.userPlugins,
211
+ dataDir: this.dataDir,
212
+ rootPlugin: Config._rootPlugin,
213
+ force: opts?.force ?? false,
214
+ });
215
+ this.plugins = plugins;
216
+ pluginsMarker?.stop();
217
+ const commandsMarker = performance_1.Performance.mark('config.loadAllCommands');
218
+ for (const plugin of this.plugins.values()) {
166
219
  this.loadCommands(plugin);
167
220
  this.loadTopics(plugin);
168
221
  }
169
- marker?.stop();
170
- }
171
- async loadCorePlugins() {
172
- if (this.pjson.oclif.plugins) {
173
- await this.loadPlugins(this.root, 'core', this.pjson.oclif.plugins);
174
- }
175
- }
176
- async loadDevPlugins() {
177
- if (this.options.devPlugins !== false) {
178
- // do not load oclif.devPlugins in production
179
- if (this.isProd)
180
- return;
181
- try {
182
- const devPlugins = this.pjson.oclif.devPlugins;
183
- if (devPlugins)
184
- await this.loadPlugins(this.root, 'dev', devPlugins);
185
- }
186
- catch (error) {
187
- process.emitWarning(error);
188
- }
189
- }
190
- }
191
- async loadUserPlugins() {
192
- if (this.options.userPlugins !== false) {
193
- try {
194
- const userPJSONPath = path.join(this.dataDir, 'package.json');
195
- debug('reading user plugins pjson %s', userPJSONPath);
196
- const pjson = await (0, util_2.loadJSON)(userPJSONPath);
197
- this.userPJSON = pjson;
198
- if (!pjson.oclif)
199
- pjson.oclif = { schema: 1 };
200
- if (!pjson.oclif.plugins)
201
- pjson.oclif.plugins = [];
202
- await this.loadPlugins(userPJSONPath, 'user', pjson.oclif.plugins.filter((p) => p.type === 'user'));
203
- await this.loadPlugins(userPJSONPath, 'link', pjson.oclif.plugins.filter((p) => p.type === 'link'));
204
- }
205
- catch (error) {
206
- if (error.code !== 'ENOENT')
207
- process.emitWarning(error);
208
- }
222
+ commandsMarker?.stop();
223
+ for (const error of errors) {
224
+ this.warn(error);
209
225
  }
210
226
  }
211
227
  async runHook(event, opts, timeout, captureErrors) {
@@ -225,7 +241,7 @@ class Config {
225
241
  reject(new Error(`Timed out after ${ms} ms.`));
226
242
  }, ms).unref();
227
243
  });
228
- return Promise.race([promise, timeout]).then(result => {
244
+ return Promise.race([promise, timeout]).then((result) => {
229
245
  clearTimeout(id);
230
246
  return result;
231
247
  });
@@ -234,7 +250,7 @@ class Config {
234
250
  successes: [],
235
251
  failures: [],
236
252
  };
237
- const promises = this.plugins.map(async (p) => {
253
+ const promises = [...this.plugins.values()].map(async (p) => {
238
254
  const debug = require('debug')([this.bin, p.name, 'hooks', event].join(':'));
239
255
  const context = {
240
256
  config: this,
@@ -243,7 +259,7 @@ class Config {
243
259
  (0, errors_1.exit)(code);
244
260
  },
245
261
  log(message, ...args) {
246
- stream_1.stdout.write((0, util_1.format)(message, ...args) + '\n');
262
+ stream_1.stdout.write((0, node_util_1.format)(message, ...args) + '\n');
247
263
  },
248
264
  error(message, options = {}) {
249
265
  (0, errors_1.error)(message, options);
@@ -257,11 +273,11 @@ class Config {
257
273
  const marker = performance_1.Performance.mark(`config.runHook#${p.name}(${hook})`);
258
274
  try {
259
275
  /* eslint-disable no-await-in-loop */
260
- const { isESM, module, filePath } = await module_loader_1.default.loadWithData(p, hook);
276
+ const { isESM, module, filePath } = await (0, module_loader_1.loadWithData)(p, (0, node_path_1.join)(p.root, hook));
261
277
  debug('start', isESM ? '(import)' : '(require)', filePath);
262
- const result = timeout ?
263
- await withTimeout(timeout, search(module).call(context, { ...opts, config: this })) :
264
- await search(module).call(context, { ...opts, config: this });
278
+ const result = timeout
279
+ ? await withTimeout(timeout, search(module).call(context, { ...opts, config: this }))
280
+ : await search(module).call(context, { ...opts, config: this });
265
281
  final.successes.push({ plugin: p, result });
266
282
  if (p.name === '@oclif/plugin-legacy' && event === 'init') {
267
283
  this.insertLegacyPlugins(result);
@@ -293,9 +309,9 @@ class Config {
293
309
  let c = cachedCommand ?? this.findCommand(id);
294
310
  if (!c) {
295
311
  const matches = this.flexibleTaxonomy ? this.findMatches(id, argv) : [];
296
- const hookResult = this.flexibleTaxonomy && matches.length > 0 ?
297
- await this.runHook('command_incomplete', { id, argv, matches }) :
298
- await this.runHook('command_not_found', { id, argv });
312
+ const hookResult = this.flexibleTaxonomy && matches.length > 0
313
+ ? await this.runHook('command_incomplete', { id, argv, matches })
314
+ : await this.runHook('command_not_found', { id, argv });
299
315
  if (hookResult.successes[0])
300
316
  return hookResult.successes[0].result;
301
317
  if (hookResult.failures[0])
@@ -315,7 +331,7 @@ class Config {
315
331
  if (jitResult.failures[0])
316
332
  throw jitResult.failures[0].error;
317
333
  if (jitResult.successes[0]) {
318
- await this.loadPluginsAndCommands();
334
+ await this.loadPluginsAndCommands({ force: true });
319
335
  c = this.findCommand(id) ?? c;
320
336
  }
321
337
  else {
@@ -337,10 +353,10 @@ class Config {
337
353
  return result;
338
354
  }
339
355
  scopedEnvVar(k) {
340
- return process.env[this.scopedEnvVarKeys(k).find(k => process.env[k])];
356
+ return process.env[this.scopedEnvVarKeys(k).find((k) => process.env[k])];
341
357
  }
342
358
  scopedEnvVarTrue(k) {
343
- const v = process.env[this.scopedEnvVarKeys(k).find(k => process.env[k])];
359
+ const v = process.env[this.scopedEnvVarKeys(k).find((k) => process.env[k])];
344
360
  return v === '1' || v === 'true';
345
361
  }
346
362
  /**
@@ -350,7 +366,7 @@ class Config {
350
366
  */
351
367
  scopedEnvVarKey(k) {
352
368
  return [this.bin, k]
353
- .map(p => p.replace(/@/g, '').replace(/[/-]/g, '_'))
369
+ .map((p) => p.replaceAll('@', '').replaceAll(/[/-]/g, '_'))
354
370
  .join('_')
355
371
  .toUpperCase();
356
372
  }
@@ -360,7 +376,9 @@ class Config {
360
376
  * @returns {string[]} e.g. ['SF_DEBUG', 'SFDX_DEBUG']
361
377
  */
362
378
  scopedEnvVarKeys(k) {
363
- return [this.bin, ...this.binAliases ?? []].filter(alias => Boolean(alias)).map(alias => [alias.replace(/@/g, '').replace(/[/-]/g, '_'), k].join('_').toUpperCase());
379
+ return [this.bin, ...(this.binAliases ?? [])]
380
+ .filter(Boolean)
381
+ .map((alias) => [alias.replaceAll('@', '').replaceAll(/[/-]/g, '_'), k].join('_').toUpperCase());
364
382
  }
365
383
  findCommand(id, opts = {}) {
366
384
  const lookupId = this.getCmdLookupId(id);
@@ -391,14 +409,14 @@ class Config {
391
409
  * @returns string[]
392
410
  */
393
411
  findMatches(partialCmdId, argv) {
394
- const flags = argv.filter(arg => !(0, help_1.getHelpFlagAdditions)(this).includes(arg) && arg.startsWith('-')).map(a => a.replace(/-/g, ''));
395
- const possibleMatches = [...this.commandPermutations.get(partialCmdId)].map(k => this._commands.get(k));
396
- const matches = possibleMatches.filter(command => {
397
- const cmdFlags = Object.entries(command.flags).flatMap(([flag, def]) => {
398
- return def.char ? [def.char, flag] : [flag];
399
- });
412
+ const flags = argv
413
+ .filter((arg) => !(0, util_3.getHelpFlagAdditions)(this).includes(arg) && arg.startsWith('-'))
414
+ .map((a) => a.replaceAll('-', ''));
415
+ const possibleMatches = [...this.commandPermutations.get(partialCmdId)].map((k) => this._commands.get(k));
416
+ const matches = possibleMatches.filter((command) => {
417
+ const cmdFlags = Object.entries(command.flags).flatMap(([flag, def]) => def.char ? [def.char, flag] : [flag]);
400
418
  // A command is a match if the provided flags belong to the full command
401
- return flags.every(f => cmdFlags.includes(f));
419
+ return flags.every((f) => cmdFlags.includes(f));
402
420
  });
403
421
  return matches;
404
422
  }
@@ -422,7 +440,7 @@ class Config {
422
440
  * @returns string[]
423
441
  */
424
442
  getAllCommandIDs() {
425
- return this.getAllCommands().map(c => c.id);
443
+ return this.getAllCommands().map((c) => c.id);
426
444
  }
427
445
  get commands() {
428
446
  return [...this._commands.values()];
@@ -430,7 +448,7 @@ class Config {
430
448
  get commandIDs() {
431
449
  if (this._commandIDs)
432
450
  return this._commandIDs;
433
- this._commandIDs = this.commands.map(c => c.id);
451
+ this._commandIDs = this.commands.map((c) => c.id);
434
452
  return this._commandIDs;
435
453
  }
436
454
  get topics() {
@@ -442,8 +460,8 @@ class Config {
442
460
  cliVersion,
443
461
  architecture,
444
462
  nodeVersion,
445
- pluginVersions: Object.fromEntries(this.plugins.map(p => [p.name, { version: p.version, type: p.type, root: p.root }])),
446
- osVersion: `${os.type()} ${os.release()}`,
463
+ pluginVersions: Object.fromEntries([...this.plugins.values()].map((p) => [p.name, { version: p.version, type: p.type, root: p.root }])),
464
+ osVersion: `${(0, node_os_1.type)()} ${(0, node_os_1.release)()}`,
447
465
  shell: this.shell,
448
466
  rootPath: this.root,
449
467
  };
@@ -457,37 +475,37 @@ class Config {
457
475
  return ejs.render(template, { ...this, ...options });
458
476
  }
459
477
  s3Url(key) {
460
- const host = this.pjson.oclif.update.s3.host;
478
+ const { host } = this.pjson.oclif.update.s3;
461
479
  if (!host)
462
480
  throw new Error('no s3 host is set');
463
- const url = new url_1.URL(host);
464
- url.pathname = path.join(url.pathname, key);
481
+ const url = new node_url_1.URL(host);
482
+ url.pathname = (0, node_path_1.join)(url.pathname, key);
465
483
  return url.toString();
466
484
  }
467
485
  getPluginsList() {
468
- return this.plugins;
486
+ return [...this.plugins.values()];
469
487
  }
470
488
  dir(category) {
471
489
  const base = process.env[`XDG_${category.toUpperCase()}_HOME`] ||
472
490
  (this.windows && process.env.LOCALAPPDATA) ||
473
- path.join(this.home, category === 'data' ? '.local/share' : '.' + category);
474
- return path.join(base, this.dirname);
491
+ (0, node_path_1.join)(this.home, category === 'data' ? '.local/share' : '.' + category);
492
+ return (0, node_path_1.join)(base, this.dirname);
475
493
  }
476
494
  windowsHome() {
477
495
  return this.windowsHomedriveHome() || this.windowsUserprofileHome();
478
496
  }
479
497
  windowsHomedriveHome() {
480
- return (process.env.HOMEDRIVE && process.env.HOMEPATH && path.join(process.env.HOMEDRIVE, process.env.HOMEPATH));
498
+ return process.env.HOMEDRIVE && process.env.HOMEPATH && (0, node_path_1.join)(process.env.HOMEDRIVE, process.env.HOMEPATH);
481
499
  }
482
500
  windowsUserprofileHome() {
483
501
  return process.env.USERPROFILE;
484
502
  }
485
503
  macosCacheDir() {
486
- return (this.platform === 'darwin' && path.join(this.home, 'Library', 'Caches', this.dirname)) || undefined;
504
+ return (this.platform === 'darwin' && (0, node_path_1.join)(this.home, 'Library', 'Caches', this.dirname)) || undefined;
487
505
  }
488
506
  _shell() {
489
507
  let shellPath;
490
- const COMSPEC = process.env.COMSPEC;
508
+ const { COMSPEC } = process.env;
491
509
  const SHELL = process.env.SHELL ?? (0, node_os_1.userInfo)().shell?.split(node_path_1.sep)?.pop();
492
510
  if (SHELL) {
493
511
  shellPath = SHELL.split('/');
@@ -498,7 +516,7 @@ class Config {
498
516
  else {
499
517
  shellPath = ['unknown'];
500
518
  }
501
- return shellPath[shellPath.length - 1];
519
+ return shellPath.at(-1) ?? 'unknown';
502
520
  }
503
521
  _debug() {
504
522
  if (this.scopedEnvVarTrue('DEBUG'))
@@ -511,52 +529,6 @@ class Config {
511
529
  catch { }
512
530
  return 0;
513
531
  }
514
- async loadPlugins(root, type, plugins, parent) {
515
- if (!plugins || plugins.length === 0)
516
- return;
517
- const mark = performance_1.Performance.mark(`config.loadPlugins#${type}`);
518
- debug('loading plugins', plugins);
519
- await Promise.all((plugins || []).map(async (plugin) => {
520
- try {
521
- const opts = { type, root };
522
- if (typeof plugin === 'string') {
523
- opts.name = plugin;
524
- }
525
- else {
526
- opts.name = plugin.name || opts.name;
527
- opts.tag = plugin.tag || opts.tag;
528
- opts.root = plugin.root || opts.root;
529
- }
530
- const pluginMarker = performance_1.Performance.mark(`plugin.load#${opts.name}`);
531
- const instance = new Plugin.Plugin(opts);
532
- await instance.load();
533
- pluginMarker?.addDetails({
534
- hasManifest: instance.hasManifest,
535
- commandCount: instance.commands.length,
536
- topicCount: instance.topics.length,
537
- type: instance.type,
538
- usesMain: Boolean(instance.pjson.main),
539
- name: instance.name,
540
- });
541
- pluginMarker?.stop();
542
- if (this.plugins.find(p => p.name === instance.name))
543
- return;
544
- this.plugins.push(instance);
545
- if (parent) {
546
- instance.parent = parent;
547
- if (!parent.children)
548
- parent.children = [];
549
- parent.children.push(instance);
550
- }
551
- await this.loadPlugins(instance.root, type, instance.pjson.oclif.plugins || [], instance);
552
- }
553
- catch (error) {
554
- this.warn(error, 'loadPlugins');
555
- }
556
- }));
557
- mark?.addDetails({ pluginCount: plugins.length });
558
- mark?.stop();
559
- }
560
532
  warn(err, scope) {
561
533
  if (this.warned)
562
534
  return;
@@ -592,10 +564,12 @@ class Config {
592
564
  process.emitWarning(JSON.stringify(err));
593
565
  }
594
566
  get isProd() {
595
- return (0, util_3.isProd)();
567
+ return (0, util_2.isProd)();
596
568
  }
597
569
  isJitPluginCommand(c) {
598
- return Object.keys(this.pjson.oclif.jitPlugins ?? {}).includes(c.pluginName ?? '') && !this.plugins.find(p => p.name === c?.pluginName);
570
+ // Return true if the command's plugin is listed under oclif.jitPlugins AND if the plugin hasn't been loaded to this.plugins
571
+ return (Object.keys(this.pjson.oclif.jitPlugins ?? {}).includes(c.pluginName ?? '') &&
572
+ Boolean(c?.pluginName && !this.plugins.has(c.pluginName)));
599
573
  }
600
574
  getCmdLookupId(id) {
601
575
  if (this._commands.has(id))
@@ -614,6 +588,7 @@ class Config {
614
588
  loadCommands(plugin) {
615
589
  const marker = performance_1.Performance.mark(`config.loadCommands#${plugin.name}`, { plugin: plugin.name });
616
590
  for (const command of plugin.commands) {
591
+ // set canonical command id
617
592
  if (this._commands.has(command.id)) {
618
593
  const prioritizedCommand = this.determinePriority([this._commands.get(command.id), command]);
619
594
  this._commands.set(prioritizedCommand.id, prioritizedCommand);
@@ -621,10 +596,16 @@ class Config {
621
596
  else {
622
597
  this._commands.set(command.id, command);
623
598
  }
624
- const permutations = this.flexibleTaxonomy ? (0, util_2.getCommandIdPermutations)(command.id) : [command.id];
599
+ // v3 moved command id permutations to the manifest, but some plugins may not have
600
+ // the new manifest yet. For those, we need to calculate the permutations here.
601
+ const permutations = this.flexibleTaxonomy && command.permutations === undefined
602
+ ? (0, util_1.getCommandIdPermutations)(command.id)
603
+ : command.permutations ?? [command.id];
604
+ // set every permutation
625
605
  for (const permutation of permutations) {
626
606
  this.commandPermutations.add(permutation, command.id);
627
607
  }
608
+ // set command aliases
628
609
  for (const alias of command.aliases ?? []) {
629
610
  if (this._commands.has(alias)) {
630
611
  const prioritizedCommand = this.determinePriority([this._commands.get(alias), command]);
@@ -633,7 +614,13 @@ class Config {
633
614
  else {
634
615
  this._commands.set(alias, { ...command, id: alias });
635
616
  }
636
- const aliasPermutations = this.flexibleTaxonomy ? (0, util_2.getCommandIdPermutations)(alias) : [alias];
617
+ // set every permutation of the aliases
618
+ // v3 moved command alias permutations to the manifest, but some plugins may not have
619
+ // the new manifest yet. For those, we need to calculate the permutations here.
620
+ const aliasPermutations = this.flexibleTaxonomy && command.aliasPermutations === undefined
621
+ ? (0, util_1.getCommandIdPermutations)(alias)
622
+ : command.permutations ?? [alias];
623
+ // set every permutation
637
624
  for (const permutation of aliasPermutations) {
638
625
  this.commandPermutations.add(permutation, command.id);
639
626
  }
@@ -653,13 +640,13 @@ class Config {
653
640
  else {
654
641
  this._topics.set(topic.name, topic);
655
642
  }
656
- const permutations = this.flexibleTaxonomy ? (0, util_2.getCommandIdPermutations)(topic.name) : [topic.name];
643
+ const permutations = this.flexibleTaxonomy ? (0, util_1.getCommandIdPermutations)(topic.name) : [topic.name];
657
644
  for (const permutation of permutations) {
658
645
  this.topicPermutations.add(permutation, topic.name);
659
646
  }
660
647
  }
661
648
  // Add missing topics for displaying help when partial commands are entered.
662
- for (const c of plugin.commands.filter(c => !c.hidden)) {
649
+ for (const c of plugin.commands.filter((c) => !c.hidden)) {
663
650
  const parts = c.id.split(':');
664
651
  while (parts.length > 0) {
665
652
  const name = parts.join(':');
@@ -724,160 +711,19 @@ class Config {
724
711
  return commandPlugins[0];
725
712
  }
726
713
  /**
727
- * Insert legacy plugins
728
- *
729
- * Replace invalid CLI plugins (cli-engine plugins, mostly Heroku) loaded via `this.loadPlugins`
730
- * with oclif-compatible ones returned by @oclif/plugin-legacy init hook.
731
- *
732
- * @param plugins array of oclif-compatible plugins
733
- * @returns void
734
- */
714
+ * Insert legacy plugins
715
+ *
716
+ * Replace invalid CLI plugins (cli-engine plugins, mostly Heroku) loaded via `this.loadPlugins`
717
+ * with oclif-compatible ones returned by @oclif/plugin-legacy init hook.
718
+ *
719
+ * @param plugins array of oclif-compatible plugins
720
+ * @returns void
721
+ */
735
722
  insertLegacyPlugins(plugins) {
736
723
  for (const plugin of plugins) {
737
- const idx = this.plugins.findIndex(p => p.name === plugin.name);
738
- if (idx !== -1) {
739
- // invalid plugin instance found in `this.plugins`
740
- // replace with the oclif-compatible one
741
- this.plugins.splice(idx, 1, plugin);
742
- }
724
+ this.plugins.set(plugin.name, plugin);
743
725
  this.loadCommands(plugin);
744
726
  }
745
727
  }
746
728
  }
747
729
  exports.Config = Config;
748
- // when no manifest exists, the default is calculated. This may throw, so we need to catch it
749
- const defaultFlagToCached = async (flag, isWritingManifest = false) => {
750
- // Prefer the helpDefaultValue function (returns a friendly string for complex types)
751
- if (typeof flag.defaultHelp === 'function') {
752
- try {
753
- return await flag.defaultHelp({ options: flag, flags: {} }, isWritingManifest);
754
- }
755
- catch {
756
- return;
757
- }
758
- }
759
- // if not specified, try the default function
760
- if (typeof flag.default === 'function') {
761
- try {
762
- return await flag.default({ options: flag, flags: {} }, isWritingManifest);
763
- }
764
- catch { }
765
- }
766
- else {
767
- return flag.default;
768
- }
769
- };
770
- const defaultArgToCached = async (arg, isWritingManifest = false) => {
771
- // Prefer the helpDefaultValue function (returns a friendly string for complex types)
772
- if (typeof arg.defaultHelp === 'function') {
773
- try {
774
- return await arg.defaultHelp({ options: arg, flags: {} }, isWritingManifest);
775
- }
776
- catch {
777
- return;
778
- }
779
- }
780
- // if not specified, try the default function
781
- if (typeof arg.default === 'function') {
782
- try {
783
- return await arg.default({ options: arg, flags: {} }, isWritingManifest);
784
- }
785
- catch { }
786
- }
787
- else {
788
- return arg.default;
789
- }
790
- };
791
- async function toCached(c, plugin, isWritingManifest) {
792
- const flags = {};
793
- for (const [name, flag] of Object.entries(c.flags || {})) {
794
- if (flag.type === 'boolean') {
795
- flags[name] = {
796
- name,
797
- type: flag.type,
798
- char: flag.char,
799
- summary: flag.summary,
800
- description: flag.description,
801
- hidden: flag.hidden,
802
- required: flag.required,
803
- helpLabel: flag.helpLabel,
804
- helpGroup: flag.helpGroup,
805
- allowNo: flag.allowNo,
806
- dependsOn: flag.dependsOn,
807
- relationships: flag.relationships,
808
- exclusive: flag.exclusive,
809
- deprecated: flag.deprecated,
810
- deprecateAliases: c.deprecateAliases,
811
- aliases: flag.aliases,
812
- delimiter: flag.delimiter,
813
- };
814
- }
815
- else {
816
- flags[name] = {
817
- name,
818
- type: flag.type,
819
- char: flag.char,
820
- summary: flag.summary,
821
- description: flag.description,
822
- hidden: flag.hidden,
823
- required: flag.required,
824
- helpLabel: flag.helpLabel,
825
- helpValue: flag.helpValue,
826
- helpGroup: flag.helpGroup,
827
- multiple: flag.multiple,
828
- options: flag.options,
829
- dependsOn: flag.dependsOn,
830
- relationships: flag.relationships,
831
- exclusive: flag.exclusive,
832
- default: await defaultFlagToCached(flag, isWritingManifest),
833
- deprecated: flag.deprecated,
834
- deprecateAliases: c.deprecateAliases,
835
- aliases: flag.aliases,
836
- delimiter: flag.delimiter,
837
- };
838
- // a command-level placeholder in the manifest so that oclif knows it should regenerate the command during help-time
839
- if (typeof flag.defaultHelp === 'function') {
840
- c.hasDynamicHelp = true;
841
- }
842
- }
843
- }
844
- const args = {};
845
- for (const [name, arg] of Object.entries((0, util_3.ensureArgObject)(c.args))) {
846
- args[name] = {
847
- name,
848
- description: arg.description,
849
- required: arg.required,
850
- options: arg.options,
851
- default: await defaultArgToCached(arg, isWritingManifest),
852
- hidden: arg.hidden,
853
- };
854
- }
855
- const stdProperties = {
856
- id: c.id,
857
- summary: c.summary,
858
- description: c.description,
859
- strict: c.strict,
860
- usage: c.usage,
861
- pluginName: plugin && plugin.name,
862
- pluginAlias: plugin && plugin.alias,
863
- pluginType: plugin && plugin.type,
864
- hidden: c.hidden,
865
- state: c.state,
866
- aliases: c.aliases || [],
867
- examples: c.examples || c.example,
868
- deprecationOptions: c.deprecationOptions,
869
- deprecateAliases: c.deprecateAliases,
870
- flags,
871
- args,
872
- };
873
- // do not include these properties in manifest
874
- const ignoreCommandProperties = ['plugin', '_flags', '_enableJsonFlag', '_globalFlags', '_baseFlags'];
875
- const stdKeys = Object.keys(stdProperties);
876
- const keysToAdd = Object.keys(c).filter(property => ![...stdKeys, ...ignoreCommandProperties].includes(property));
877
- const additionalProperties = {};
878
- for (const key of keysToAdd) {
879
- additionalProperties[key] = c[key];
880
- }
881
- return { ...stdProperties, ...additionalProperties };
882
- }
883
- exports.toCached = toCached;