@oclif/core 3.0.0-beta.9 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/README.md +4 -2
  2. package/flush.d.ts +3 -0
  3. package/flush.js +1 -0
  4. package/handle.js +1 -0
  5. package/lib/args.d.ts +2 -2
  6. package/lib/args.js +17 -18
  7. package/lib/{ux → cli-ux}/action/base.d.ts +19 -21
  8. package/lib/{ux → cli-ux}/action/base.js +126 -120
  9. package/lib/{ux → cli-ux}/action/simple.js +25 -30
  10. package/lib/{ux → cli-ux}/action/spinner.d.ts +9 -7
  11. package/lib/{ux → cli-ux}/action/spinner.js +45 -37
  12. package/lib/{ux → cli-ux}/action/spinners.js +187 -187
  13. package/lib/cli-ux/action/types.d.ts +5 -0
  14. package/lib/cli-ux/action/types.js +2 -0
  15. package/lib/{ux → cli-ux}/config.d.ts +5 -5
  16. package/lib/{ux → cli-ux}/config.js +17 -17
  17. package/lib/{ux → cli-ux}/exit.js +3 -0
  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 +39 -0
  21. package/lib/{ux → cli-ux}/index.js +74 -88
  22. package/lib/{ux → cli-ux}/list.js +3 -3
  23. package/lib/{ux → cli-ux}/prompt.d.ts +3 -3
  24. package/lib/{ux → cli-ux}/prompt.js +35 -25
  25. package/lib/{ux → cli-ux}/stream.d.ts +6 -6
  26. package/lib/{ux → cli-ux}/stream.js +11 -10
  27. package/lib/cli-ux/styled/index.d.ts +4 -0
  28. package/lib/cli-ux/styled/index.js +11 -0
  29. package/lib/{ux → cli-ux}/styled/object.js +7 -9
  30. package/lib/{ux → cli-ux}/styled/table.d.ts +10 -10
  31. package/lib/{ux → cli-ux}/styled/table.js +130 -133
  32. package/lib/{ux → cli-ux}/styled/tree.js +11 -13
  33. package/lib/cli-ux/wait.js +5 -0
  34. package/lib/command.d.ts +82 -88
  35. package/lib/command.js +196 -175
  36. package/lib/config/config.d.ts +89 -90
  37. package/lib/config/config.js +466 -566
  38. package/lib/config/index.d.ts +0 -1
  39. package/lib/config/index.js +1 -3
  40. package/lib/config/plugin-loader.d.ts +12 -12
  41. package/lib/config/plugin-loader.js +72 -56
  42. package/lib/config/plugin.d.ts +25 -24
  43. package/lib/config/plugin.js +188 -154
  44. package/lib/config/ts-node.d.ts +2 -1
  45. package/lib/config/ts-node.js +71 -58
  46. package/lib/config/util.d.ts +1 -11
  47. package/lib/config/util.js +6 -59
  48. package/lib/errors/config.d.ts +1 -1
  49. package/lib/errors/config.js +6 -6
  50. package/lib/errors/errors/cli.d.ts +7 -7
  51. package/lib/errors/errors/cli.js +20 -16
  52. package/lib/errors/errors/exit.d.ts +1 -4
  53. package/lib/errors/errors/exit.js +1 -1
  54. package/lib/errors/errors/module-load.d.ts +1 -4
  55. package/lib/errors/errors/module-load.js +1 -1
  56. package/lib/errors/errors/pretty-print.d.ts +1 -1
  57. package/lib/errors/errors/pretty-print.js +12 -10
  58. package/lib/errors/handle.d.ts +12 -2
  59. package/lib/errors/handle.js +26 -14
  60. package/lib/errors/index.d.ts +10 -10
  61. package/lib/errors/index.js +25 -24
  62. package/lib/errors/logger.d.ts +2 -2
  63. package/lib/errors/logger.js +14 -13
  64. package/lib/execute.d.ts +6 -6
  65. package/lib/execute.js +10 -9
  66. package/lib/flags.d.ts +103 -32
  67. package/lib/flags.js +79 -45
  68. package/lib/help/command.d.ts +16 -14
  69. package/lib/help/command.js +178 -163
  70. package/lib/help/docopts.d.ts +5 -5
  71. package/lib/help/docopts.js +50 -54
  72. package/lib/help/formatter.d.ts +37 -37
  73. package/lib/help/formatter.js +66 -55
  74. package/lib/help/index.d.ts +25 -21
  75. package/lib/help/index.js +169 -147
  76. package/lib/help/root.d.ts +1 -1
  77. package/lib/help/root.js +15 -17
  78. package/lib/help/util.d.ts +2 -8
  79. package/lib/help/util.js +8 -28
  80. package/lib/index.d.ts +19 -20
  81. package/lib/index.js +37 -43
  82. package/lib/interfaces/config.d.ts +67 -66
  83. package/lib/interfaces/errors.d.ts +5 -5
  84. package/lib/interfaces/help.d.ts +17 -17
  85. package/lib/interfaces/hooks.d.ts +49 -49
  86. package/lib/interfaces/index.d.ts +7 -7
  87. package/lib/interfaces/manifest.d.ts +1 -1
  88. package/lib/interfaces/parser.d.ts +175 -51
  89. package/lib/interfaces/pjson.d.ts +45 -41
  90. package/lib/interfaces/plugin.d.ts +47 -41
  91. package/lib/interfaces/s3-manifest.d.ts +7 -7
  92. package/lib/interfaces/topic.d.ts +1 -1
  93. package/lib/interfaces/ts-config.d.ts +7 -7
  94. package/lib/main.d.ts +2 -2
  95. package/lib/main.js +16 -16
  96. package/lib/module-loader.d.ts +67 -77
  97. package/lib/module-loader.js +183 -150
  98. package/lib/parser/errors.d.ts +7 -7
  99. package/lib/parser/errors.js +29 -22
  100. package/lib/parser/help.js +5 -5
  101. package/lib/parser/index.js +2 -2
  102. package/lib/parser/parse.d.ts +9 -6
  103. package/lib/parser/parse.js +253 -221
  104. package/lib/parser/validate.js +53 -33
  105. package/lib/performance.d.ts +43 -32
  106. package/lib/performance.js +133 -91
  107. package/lib/screen.js +2 -2
  108. package/lib/settings.d.ts +11 -12
  109. package/lib/settings.js +2 -2
  110. package/lib/util/aggregate-flags.d.ts +2 -0
  111. package/lib/util/aggregate-flags.js +13 -0
  112. package/lib/util/cache-command.d.ts +3 -0
  113. package/lib/util/cache-command.js +109 -0
  114. package/lib/util/cache-default-value.d.ts +2 -0
  115. package/lib/util/cache-default-value.js +28 -0
  116. package/lib/util/ensure-arg-object.d.ts +12 -0
  117. package/lib/util/ensure-arg-object.js +14 -0
  118. package/lib/util/fs.d.ts +7 -0
  119. package/lib/util/fs.js +54 -0
  120. package/lib/util/os.d.ts +19 -0
  121. package/lib/util/os.js +28 -0
  122. package/lib/{util.d.ts → util/util.d.ts} +7 -16
  123. package/lib/util/util.js +98 -0
  124. package/package.json +35 -37
  125. package/lib/util.js +0 -126
  126. package/lib/ux/flush.d.ts +0 -1
  127. package/lib/ux/flush.js +0 -27
  128. package/lib/ux/index.d.ts +0 -58
  129. package/lib/ux/styled/index.d.ts +0 -6
  130. package/lib/ux/styled/index.js +0 -13
  131. package/lib/ux/styled/json.d.ts +0 -1
  132. package/lib/ux/styled/json.js +0 -15
  133. package/lib/ux/wait.js +0 -7
  134. package/lib/{ux → cli-ux}/action/simple.d.ts +4 -4
  135. package/lib/{ux → cli-ux}/action/spinners.d.ts +117 -117
  136. package/lib/{ux → cli-ux}/exit.d.ts +2 -2
  137. package/lib/{ux → cli-ux}/list.d.ts +0 -0
  138. package/lib/{ux → cli-ux}/styled/object.d.ts +0 -0
  139. package/lib/{ux → cli-ux}/styled/progress.d.ts +0 -0
  140. package/lib/{ux → cli-ux}/styled/progress.js +0 -0
  141. package/lib/{ux → cli-ux}/styled/tree.d.ts +1 -1
  142. /package/lib/{ux → cli-ux}/wait.d.ts +0 -0
@@ -1,42 +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"));
6
+ const is_wsl_1 = tslib_1.__importDefault(require("is-wsl"));
7
+ const node_os_1 = require("node:os");
8
+ const node_path_1 = require("node:path");
9
+ const node_url_1 = require("node:url");
10
+ const node_util_1 = require("node:util");
11
+ const stream_1 = require("../cli-ux/stream");
4
12
  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 util_2 = require("./util");
11
- const util_3 = require("../util");
13
+ const util_1 = require("../help/util");
12
14
  const module_loader_1 = require("../module-loader");
13
- const help_1 = require("../help");
14
- const stream_1 = require("../ux/stream");
15
15
  const performance_1 = require("../performance");
16
16
  const settings_1 = require("../settings");
17
- const node_os_1 = require("node:os");
18
- const node_path_1 = require("node:path");
19
- const plugin_loader_1 = require("./plugin-loader");
17
+ const fs_1 = require("../util/fs");
18
+ const os_1 = require("../util/os");
19
+ const util_2 = require("../util/util");
20
+ const plugin_loader_1 = tslib_1.__importDefault(require("./plugin-loader"));
21
+ const util_3 = require("./util");
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_3.Debug)();
24
+ const _pjson = (0, fs_1.requireJson)(__dirname, '..', '..', 'package.json');
23
25
  const BASE = `${_pjson.name}@${_pjson.version}`;
24
26
  function channelFromVersion(version) {
25
27
  const m = version.match(/[^-]+(?:-([^.]+))?/);
26
28
  return (m && m[1]) || 'stable';
27
29
  }
28
- const WSL = require('is-wsl');
29
30
  function isConfig(o) {
30
31
  return o && Boolean(o._base);
31
32
  }
32
33
  class Permutations extends Map {
33
- constructor() {
34
- super(...arguments);
35
- this.validPermutations = new Map();
36
- }
34
+ validPermutations = new Map();
37
35
  add(permutation, commandId) {
38
36
  this.validPermutations.set(permutation, commandId);
39
- for (const id of (0, util_2.collectUsableIds)([permutation])) {
37
+ for (const id of (0, util_3.collectUsableIds)([permutation])) {
40
38
  if (this.has(id)) {
41
39
  this.set(id, this.get(id).add(commandId));
42
40
  }
@@ -48,33 +46,61 @@ class Permutations extends Map {
48
46
  get(key) {
49
47
  return super.get(key) ?? new Set();
50
48
  }
51
- getValid(key) {
52
- return this.validPermutations.get(key);
53
- }
54
49
  getAllValid() {
55
50
  return [...this.validPermutations.keys()];
56
51
  }
52
+ getValid(key) {
53
+ return this.validPermutations.get(key);
54
+ }
57
55
  hasValid(key) {
58
56
  return this.validPermutations.has(key);
59
57
  }
60
58
  }
61
59
  class Config {
60
+ options;
61
+ _base = BASE;
62
+ _commandIDs;
63
+ _commands = new Map();
64
+ static _rootPlugin;
65
+ _topics = new Map();
66
+ commandPermutations = new Permutations();
67
+ pluginLoader;
68
+ topicPermutations = new Permutations();
69
+ arch;
70
+ bin;
71
+ binAliases;
72
+ binPath;
73
+ cacheDir;
74
+ channel;
75
+ configDir;
76
+ dataDir;
77
+ debug = 0;
78
+ dirname;
79
+ errlog;
80
+ flexibleTaxonomy;
81
+ home;
82
+ name;
83
+ npmRegistry;
84
+ nsisCustomization;
85
+ pjson;
86
+ platform;
87
+ plugins = new Map();
88
+ root;
89
+ shell;
90
+ topicSeparator = ':';
91
+ userAgent;
92
+ userPJSON;
93
+ valid;
94
+ version;
95
+ warned = false;
96
+ windows;
62
97
  constructor(options) {
63
98
  this.options = options;
64
- this._base = BASE;
65
- this.debug = 0;
66
- this.plugins = new Map();
67
- this.topicSeparator = ':';
68
- this.warned = false;
69
- this.commandPermutations = new Permutations();
70
- this.topicPermutations = new Permutations();
71
- this._commands = new Map();
72
- this._topics = new Map();
73
99
  }
74
100
  static async load(opts = module.filename || __dirname) {
75
101
  // Handle the case when a file URL string is passed in such as 'import.meta.url'; covert to file path.
76
102
  if (typeof opts === 'string' && opts.startsWith('file://')) {
77
- opts = (0, url_1.fileURLToPath)(opts);
103
+ opts = (0, node_url_1.fileURLToPath)(opts);
78
104
  }
79
105
  if (typeof opts === 'string')
80
106
  opts = { root: opts };
@@ -104,10 +130,268 @@ class Config {
104
130
  static get rootPlugin() {
105
131
  return Config._rootPlugin;
106
132
  }
133
+ _debug() {
134
+ if (this.scopedEnvVarTrue('DEBUG'))
135
+ return 1;
136
+ try {
137
+ const { enabled } = require('debug')(this.bin);
138
+ if (enabled)
139
+ return 1;
140
+ }
141
+ catch { }
142
+ return 0;
143
+ }
144
+ _shell() {
145
+ let shellPath;
146
+ const { COMSPEC } = process.env;
147
+ const SHELL = process.env.SHELL ?? (0, node_os_1.userInfo)().shell?.split(node_path_1.sep)?.pop();
148
+ if (SHELL) {
149
+ shellPath = SHELL.split('/');
150
+ }
151
+ else if (this.windows && COMSPEC) {
152
+ shellPath = COMSPEC.split(/\\|\//);
153
+ }
154
+ else {
155
+ shellPath = ['unknown'];
156
+ }
157
+ return shellPath.at(-1) ?? 'unknown';
158
+ }
159
+ /**
160
+ * This method is responsible for locating the correct plugin to use for a named command id
161
+ * It searches the {Config} registered commands to match either the raw command id or the command alias
162
+ * It is possible that more than one command will be found. This is due the ability of two distinct plugins to
163
+ * create the same command or command alias.
164
+ *
165
+ * In the case of more than one found command, the function will select the command based on the order in which
166
+ * the plugin is included in the package.json `oclif.plugins` list. The command that occurs first in the list
167
+ * is selected as the command to run.
168
+ *
169
+ * Commands can also be present from either an install or a link. When a command is one of these and a core plugin
170
+ * is present, this function defers to the core plugin.
171
+ *
172
+ * If there is not a core plugin command present, this function will return the first
173
+ * plugin as discovered (will not change the order)
174
+ *
175
+ * @param commands commands to determine the priority of
176
+ * @returns command instance {Command.Loadable} or undefined
177
+ */
178
+ determinePriority(commands) {
179
+ const oclifPlugins = this.pjson.oclif?.plugins ?? [];
180
+ const commandPlugins = commands.sort((a, b) => {
181
+ const pluginAliasA = a.pluginAlias ?? 'A-Cannot-Find-This';
182
+ const pluginAliasB = b.pluginAlias ?? 'B-Cannot-Find-This';
183
+ const aIndex = oclifPlugins.indexOf(pluginAliasA);
184
+ const bIndex = oclifPlugins.indexOf(pluginAliasB);
185
+ // When both plugin types are 'core' plugins sort based on index
186
+ if (a.pluginType === 'core' && b.pluginType === 'core') {
187
+ // If b appears first in the pjson.plugins sort it first
188
+ return aIndex - bIndex;
189
+ }
190
+ // if b is a core plugin and a is not sort b first
191
+ if (b.pluginType === 'core' && a.pluginType !== 'core') {
192
+ return 1;
193
+ }
194
+ // if a is a core plugin and b is not sort a first
195
+ if (a.pluginType === 'core' && b.pluginType !== 'core') {
196
+ return -1;
197
+ }
198
+ // if a is a jit plugin and b is not sort b first
199
+ if (a.pluginType === 'jit' && b.pluginType !== 'jit') {
200
+ return 1;
201
+ }
202
+ // if b is a jit plugin and a is not sort a first
203
+ if (b.pluginType === 'jit' && a.pluginType !== 'jit') {
204
+ return -1;
205
+ }
206
+ // neither plugin is core, so do not change the order
207
+ return 0;
208
+ });
209
+ return commandPlugins[0];
210
+ }
211
+ getCmdLookupId(id) {
212
+ if (this._commands.has(id))
213
+ return id;
214
+ if (this.commandPermutations.hasValid(id))
215
+ return this.commandPermutations.getValid(id);
216
+ return id;
217
+ }
218
+ getTopicLookupId(id) {
219
+ if (this._topics.has(id))
220
+ return id;
221
+ if (this.topicPermutations.hasValid(id))
222
+ return this.topicPermutations.getValid(id);
223
+ return id;
224
+ }
225
+ /**
226
+ * Insert legacy plugins
227
+ *
228
+ * Replace invalid CLI plugins (cli-engine plugins, mostly Heroku) loaded via `this.loadPlugins`
229
+ * with oclif-compatible ones returned by @oclif/plugin-legacy init hook.
230
+ *
231
+ * @param plugins array of oclif-compatible plugins
232
+ * @returns void
233
+ */
234
+ insertLegacyPlugins(plugins) {
235
+ for (const plugin of plugins) {
236
+ this.plugins.set(plugin.name, plugin);
237
+ this.loadCommands(plugin);
238
+ }
239
+ }
240
+ isJitPluginCommand(c) {
241
+ // Return true if the command's plugin is listed under oclif.jitPlugins AND if the plugin hasn't been loaded to this.plugins
242
+ return (Object.keys(this.pjson.oclif.jitPlugins ?? {}).includes(c.pluginName ?? '') &&
243
+ Boolean(c?.pluginName && !this.plugins.has(c.pluginName)));
244
+ }
245
+ loadCommands(plugin) {
246
+ const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `config.loadCommands#${plugin.name}`, { plugin: plugin.name });
247
+ for (const command of plugin.commands) {
248
+ // set canonical command id
249
+ if (this._commands.has(command.id)) {
250
+ const prioritizedCommand = this.determinePriority([this._commands.get(command.id), command]);
251
+ this._commands.set(prioritizedCommand.id, prioritizedCommand);
252
+ }
253
+ else {
254
+ this._commands.set(command.id, command);
255
+ }
256
+ // v3 moved command id permutations to the manifest, but some plugins may not have
257
+ // the new manifest yet. For those, we need to calculate the permutations here.
258
+ const permutations = this.flexibleTaxonomy && command.permutations === undefined
259
+ ? (0, util_3.getCommandIdPermutations)(command.id)
260
+ : command.permutations ?? [command.id];
261
+ // set every permutation
262
+ for (const permutation of permutations) {
263
+ this.commandPermutations.add(permutation, command.id);
264
+ }
265
+ // set command aliases
266
+ for (const alias of command.aliases ?? []) {
267
+ if (this._commands.has(alias)) {
268
+ const prioritizedCommand = this.determinePriority([this._commands.get(alias), command]);
269
+ this._commands.set(alias, { ...prioritizedCommand, id: alias });
270
+ }
271
+ else {
272
+ this._commands.set(alias, { ...command, id: alias });
273
+ }
274
+ // set every permutation of the aliases
275
+ // v3 moved command alias permutations to the manifest, but some plugins may not have
276
+ // the new manifest yet. For those, we need to calculate the permutations here.
277
+ const aliasPermutations = this.flexibleTaxonomy && command.aliasPermutations === undefined
278
+ ? (0, util_3.getCommandIdPermutations)(alias)
279
+ : command.permutations ?? [alias];
280
+ // set every permutation
281
+ for (const permutation of aliasPermutations) {
282
+ this.commandPermutations.add(permutation, command.id);
283
+ }
284
+ }
285
+ }
286
+ marker?.addDetails({ commandCount: plugin.commands.length });
287
+ marker?.stop();
288
+ }
289
+ loadTopics(plugin) {
290
+ const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `config.loadTopics#${plugin.name}`, { plugin: plugin.name });
291
+ for (const topic of (0, util_2.compact)(plugin.topics)) {
292
+ const existing = this._topics.get(topic.name);
293
+ if (existing) {
294
+ existing.description = topic.description || existing.description;
295
+ existing.hidden = existing.hidden || topic.hidden;
296
+ }
297
+ else {
298
+ this._topics.set(topic.name, topic);
299
+ }
300
+ const permutations = this.flexibleTaxonomy ? (0, util_3.getCommandIdPermutations)(topic.name) : [topic.name];
301
+ for (const permutation of permutations) {
302
+ this.topicPermutations.add(permutation, topic.name);
303
+ }
304
+ }
305
+ // Add missing topics for displaying help when partial commands are entered.
306
+ for (const c of plugin.commands.filter((c) => !c.hidden)) {
307
+ const parts = c.id.split(':');
308
+ while (parts.length > 0) {
309
+ const name = parts.join(':');
310
+ if (name && !this._topics.has(name)) {
311
+ this._topics.set(name, { description: c.summary || c.description, name });
312
+ }
313
+ parts.pop();
314
+ }
315
+ }
316
+ marker?.stop();
317
+ }
318
+ dir(category) {
319
+ const base = process.env[`XDG_${category.toUpperCase()}_HOME`] ||
320
+ (this.windows && process.env.LOCALAPPDATA) ||
321
+ (0, node_path_1.join)(this.home, category === 'data' ? '.local/share' : '.' + category);
322
+ return (0, node_path_1.join)(base, this.dirname);
323
+ }
324
+ findCommand(id, opts = {}) {
325
+ const lookupId = this.getCmdLookupId(id);
326
+ const command = this._commands.get(lookupId);
327
+ if (opts.must && !command)
328
+ (0, errors_1.error)(`command ${lookupId} not found`);
329
+ return command;
330
+ }
331
+ /**
332
+ * Find all command ids that include the provided command id.
333
+ *
334
+ * For example, if the command ids are:
335
+ * - foo:bar:baz
336
+ * - one:two:three
337
+ *
338
+ * `bar` would return `foo:bar:baz`
339
+ *
340
+ * @param partialCmdId string
341
+ * @param argv string[] process.argv containing the flags and arguments provided by the user
342
+ * @returns string[]
343
+ */
344
+ findMatches(partialCmdId, argv) {
345
+ const flags = argv
346
+ .filter((arg) => !(0, util_1.getHelpFlagAdditions)(this).includes(arg) && arg.startsWith('-'))
347
+ .map((a) => a.replaceAll('-', ''));
348
+ const possibleMatches = [...this.commandPermutations.get(partialCmdId)].map((k) => this._commands.get(k));
349
+ const matches = possibleMatches.filter((command) => {
350
+ const cmdFlags = Object.entries(command.flags).flatMap(([flag, def]) => def.char ? [def.char, flag] : [flag]);
351
+ // A command is a match if the provided flags belong to the full command
352
+ return flags.every((f) => cmdFlags.includes(f));
353
+ });
354
+ return matches;
355
+ }
356
+ findTopic(name, opts = {}) {
357
+ const lookupId = this.getTopicLookupId(name);
358
+ const topic = this._topics.get(lookupId);
359
+ if (topic)
360
+ return topic;
361
+ if (opts.must)
362
+ throw new Error(`topic ${name} not found`);
363
+ }
364
+ /**
365
+ * Returns an array of all command ids. If flexible taxonomy is enabled then all permutations will be appended to the array.
366
+ * @returns string[]
367
+ */
368
+ getAllCommandIDs() {
369
+ return this.getAllCommands().map((c) => c.id);
370
+ }
371
+ /**
372
+ * Returns an array of all commands. If flexible taxonomy is enabled then all permutations will be appended to the array.
373
+ * @returns Command.Loadable[]
374
+ */
375
+ getAllCommands() {
376
+ const commands = [...this._commands.values()];
377
+ const validPermutations = [...this.commandPermutations.getAllValid()];
378
+ for (const permutation of validPermutations) {
379
+ if (!this._commands.has(permutation)) {
380
+ const cmd = this._commands.get(this.getCmdLookupId(permutation));
381
+ commands.push({ ...cmd, id: permutation });
382
+ }
383
+ }
384
+ return commands;
385
+ }
386
+ getPluginsList() {
387
+ return [...this.plugins.values()];
388
+ }
107
389
  // eslint-disable-next-line complexity
108
390
  async load() {
109
- settings_1.default.performanceEnabled = (settings_1.default.performanceEnabled === undefined ? this.options.enablePerf : settings_1.default.performanceEnabled) ?? false;
110
- this.pluginLoader = new plugin_loader_1.default({ root: this.options.root, plugins: this.options.plugins });
391
+ settings_1.settings.performanceEnabled =
392
+ (settings_1.settings.performanceEnabled === undefined ? this.options.enablePerf : settings_1.settings.performanceEnabled) ?? false;
393
+ const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, 'config.load');
394
+ this.pluginLoader = new plugin_loader_1.default({ plugins: this.options.plugins, root: this.options.root });
111
395
  Config._rootPlugin = await this.pluginLoader.loadRoot();
112
396
  this.root = Config._rootPlugin.root;
113
397
  this.pjson = Config._rootPlugin.pjson;
@@ -118,8 +402,8 @@ class Config {
118
402
  this.version = this.options.version || this.pjson.version || '0.0.0';
119
403
  this.channel = this.options.channel || channelFromVersion(this.version);
120
404
  this.valid = Config._rootPlugin.valid;
121
- this.arch = (os.arch() === 'ia32' ? 'x86' : os.arch());
122
- this.platform = WSL ? 'wsl' : os.platform();
405
+ this.arch = (0, node_os_1.arch)() === 'ia32' ? 'x86' : (0, node_os_1.arch)();
406
+ this.platform = is_wsl_1.default ? 'wsl' : (0, os_1.getPlatform)();
123
407
  this.windows = this.platform === 'win32';
124
408
  this.bin = this.pjson.oclif.bin || this.name;
125
409
  this.binAliases = this.pjson.oclif.binAliases;
@@ -127,18 +411,18 @@ class Config {
127
411
  this.dirname = this.pjson.oclif.dirname || this.name;
128
412
  this.flexibleTaxonomy = this.pjson.oclif.flexibleTaxonomy || false;
129
413
  // currently, only colons or spaces are valid separators
130
- if (this.pjson.oclif.topicSeparator && [':', ' '].includes(this.pjson.oclif.topicSeparator))
414
+ if (this.pjson.oclif.topicSeparator && [' ', ':'].includes(this.pjson.oclif.topicSeparator))
131
415
  this.topicSeparator = this.pjson.oclif.topicSeparator;
132
416
  if (this.platform === 'win32')
133
417
  this.dirname = this.dirname.replace('/', '\\');
134
418
  this.userAgent = `${this.name}/${this.version} ${this.platform}-${this.arch} node-${process.version}`;
135
419
  this.shell = this._shell();
136
420
  this.debug = this._debug();
137
- this.home = process.env.HOME || (this.windows && this.windowsHome()) || os.homedir() || os.tmpdir();
421
+ this.home = process.env.HOME || (this.windows && this.windowsHome()) || (0, os_1.getHomeDir)() || (0, node_os_1.tmpdir)();
138
422
  this.cacheDir = this.scopedEnvVar('CACHE_DIR') || this.macosCacheDir() || this.dir('cache');
139
423
  this.configDir = this.scopedEnvVar('CONFIG_DIR') || this.dir('config');
140
424
  this.dataDir = this.scopedEnvVar('DATA_DIR') || this.dir('data');
141
- this.errlog = path.join(this.cacheDir, 'error.log');
425
+ this.errlog = (0, node_path_1.join)(this.cacheDir, 'error.log');
142
426
  this.binPath = this.scopedEnvVar('BINPATH');
143
427
  this.npmRegistry = this.scopedEnvVar('NPM_REGISTRY') || this.pjson.oclif.npmRegistry;
144
428
  this.pjson.oclif.update = this.pjson.oclif.update || {};
@@ -152,88 +436,141 @@ class Config {
152
436
  ...s3.templates,
153
437
  target: {
154
438
  baseDir: '<%- bin %>',
439
+ manifest: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %><%- platform %>-<%- arch %>",
155
440
  unversioned: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %><%- bin %>-<%- platform %>-<%- arch %><%- ext %>",
156
441
  versioned: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %><%- bin %>-v<%- version %>/<%- bin %>-v<%- version %>-<%- platform %>-<%- arch %><%- ext %>",
157
- manifest: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %><%- platform %>-<%- arch %>",
158
- ...s3.templates && s3.templates.target,
442
+ ...(s3.templates && s3.templates.target),
159
443
  },
160
444
  vanilla: {
161
- unversioned: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %><%- bin %><%- ext %>",
162
- versioned: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %><%- bin %>-v<%- version %>/<%- bin %>-v<%- version %><%- ext %>",
163
445
  baseDir: '<%- bin %>',
164
446
  manifest: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %>version",
165
- ...s3.templates && s3.templates.vanilla,
447
+ unversioned: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %><%- bin %><%- ext %>",
448
+ versioned: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %><%- bin %>-v<%- version %>/<%- bin %>-v<%- version %><%- ext %>",
449
+ ...(s3.templates && s3.templates.vanilla),
166
450
  },
167
451
  };
168
- const marker = performance_1.default.mark('config.load');
169
452
  await this.loadPluginsAndCommands();
170
453
  debug('config done');
171
454
  marker?.addDetails({
172
- plugins: this.plugins.size,
173
455
  commandPermutations: this.commands.length,
174
456
  commands: [...this.plugins.values()].reduce((acc, p) => acc + p.commands.length, 0),
457
+ plugins: this.plugins.size,
175
458
  topics: this.topics.length,
176
459
  });
177
460
  marker?.stop();
178
461
  }
179
462
  async loadPluginsAndCommands(opts) {
180
- const marker = performance_1.default.mark('config.loadPluginsAndCommands');
181
- const { plugins, errors } = await this.pluginLoader.loadChildren({
182
- devPlugins: this.options.devPlugins,
183
- userPlugins: this.options.userPlugins,
463
+ const pluginsMarker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, 'config.loadAllPlugins');
464
+ const { errors, plugins } = await this.pluginLoader.loadChildren({
184
465
  dataDir: this.dataDir,
185
- rootPlugin: Config._rootPlugin,
466
+ devPlugins: this.options.devPlugins,
186
467
  force: opts?.force ?? false,
468
+ rootPlugin: Config._rootPlugin,
469
+ userPlugins: this.options.userPlugins,
187
470
  });
188
471
  this.plugins = plugins;
472
+ pluginsMarker?.stop();
473
+ const commandsMarker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, 'config.loadAllCommands');
189
474
  for (const plugin of this.plugins.values()) {
190
475
  this.loadCommands(plugin);
191
476
  this.loadTopics(plugin);
192
477
  }
478
+ commandsMarker?.stop();
193
479
  for (const error of errors) {
194
480
  this.warn(error);
195
481
  }
196
- marker?.stop();
197
482
  }
198
- async runHook(event, opts, timeout, captureErrors) {
199
- const marker = performance_1.default.mark(`config.runHook#${event}`);
200
- debug('start %s hook', event);
201
- const search = (m) => {
202
- if (typeof m === 'function')
203
- return m;
204
- if (m.default && typeof m.default === 'function')
205
- return m.default;
206
- return Object.values(m).find((m) => typeof m === 'function');
207
- };
208
- const withTimeout = async (ms, promise) => {
483
+ macosCacheDir() {
484
+ return (this.platform === 'darwin' && (0, node_path_1.join)(this.home, 'Library', 'Caches', this.dirname)) || undefined;
485
+ }
486
+ async runCommand(id, argv = [], cachedCommand = null) {
487
+ const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `config.runCommand#${id}`);
488
+ debug('runCommand %s %o', id, argv);
489
+ let c = cachedCommand ?? this.findCommand(id);
490
+ if (!c) {
491
+ const matches = this.flexibleTaxonomy ? this.findMatches(id, argv) : [];
492
+ const hookResult = this.flexibleTaxonomy && matches.length > 0
493
+ ? await this.runHook('command_incomplete', { argv, id, matches })
494
+ : await this.runHook('command_not_found', { argv, id });
495
+ if (hookResult.successes[0])
496
+ return hookResult.successes[0].result;
497
+ if (hookResult.failures[0])
498
+ throw hookResult.failures[0].error;
499
+ throw new errors_1.CLIError(`command ${id} not found`);
500
+ }
501
+ if (this.isJitPluginCommand(c)) {
502
+ const pluginName = c.pluginName;
503
+ const pluginVersion = this.pjson.oclif.jitPlugins[pluginName];
504
+ const jitResult = await this.runHook('jit_plugin_not_installed', {
505
+ argv,
506
+ command: c,
507
+ id,
508
+ pluginName,
509
+ pluginVersion,
510
+ });
511
+ if (jitResult.failures[0])
512
+ throw jitResult.failures[0].error;
513
+ if (jitResult.successes[0]) {
514
+ await this.loadPluginsAndCommands({ force: true });
515
+ c = this.findCommand(id) ?? c;
516
+ }
517
+ else {
518
+ // this means that no jit_plugin_not_installed hook exists, so we should run the default behavior
519
+ const result = await this.runHook('command_not_found', { argv, id });
520
+ if (result.successes[0])
521
+ return result.successes[0].result;
522
+ if (result.failures[0])
523
+ throw result.failures[0].error;
524
+ throw new errors_1.CLIError(`command ${id} not found`);
525
+ }
526
+ }
527
+ const command = await c.load();
528
+ await this.runHook('prerun', { Command: command, argv });
529
+ const result = (await command.run(argv, this));
530
+ await this.runHook('postrun', { Command: command, argv, result });
531
+ marker?.addDetails({ command: id, plugin: c.pluginName });
532
+ marker?.stop();
533
+ return result;
534
+ }
535
+ async runHook(event, opts, timeout, captureErrors) {
536
+ const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `config.runHook#${event}`);
537
+ debug('start %s hook', event);
538
+ const search = (m) => {
539
+ if (typeof m === 'function')
540
+ return m;
541
+ if (m.default && typeof m.default === 'function')
542
+ return m.default;
543
+ return Object.values(m).find((m) => typeof m === 'function');
544
+ };
545
+ const withTimeout = async (ms, promise) => {
209
546
  let id;
210
547
  const timeout = new Promise((_, reject) => {
211
548
  id = setTimeout(() => {
212
549
  reject(new Error(`Timed out after ${ms} ms.`));
213
550
  }, ms).unref();
214
551
  });
215
- return Promise.race([promise, timeout]).then(result => {
552
+ return Promise.race([promise, timeout]).then((result) => {
216
553
  clearTimeout(id);
217
554
  return result;
218
555
  });
219
556
  };
220
557
  const final = {
221
- successes: [],
222
558
  failures: [],
559
+ successes: [],
223
560
  };
224
561
  const promises = [...this.plugins.values()].map(async (p) => {
225
562
  const debug = require('debug')([this.bin, p.name, 'hooks', event].join(':'));
226
563
  const context = {
227
564
  config: this,
228
565
  debug,
566
+ error(message, options = {}) {
567
+ (0, errors_1.error)(message, options);
568
+ },
229
569
  exit(code = 0) {
230
570
  (0, errors_1.exit)(code);
231
571
  },
232
572
  log(message, ...args) {
233
- stream_1.stdout.write((0, util_1.format)(message, ...args) + '\n');
234
- },
235
- error(message, options = {}) {
236
- (0, errors_1.error)(message, options);
573
+ stream_1.stdout.write((0, node_util_1.format)(message, ...args) + '\n');
237
574
  },
238
575
  warn(message) {
239
576
  (0, errors_1.warn)(message);
@@ -241,14 +578,14 @@ class Config {
241
578
  };
242
579
  const hooks = p.hooks[event] || [];
243
580
  for (const hook of hooks) {
244
- const marker = performance_1.default.mark(`config.runHook#${p.name}(${hook})`);
581
+ const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `config.runHook#${p.name}(${hook})`);
245
582
  try {
246
583
  /* eslint-disable no-await-in-loop */
247
- const { isESM, module, filePath } = await module_loader_1.default.loadWithData(p, hook);
584
+ const { filePath, isESM, module } = await (0, module_loader_1.loadWithData)(p, (0, node_path_1.join)(p.root, hook));
248
585
  debug('start', isESM ? '(import)' : '(require)', filePath);
249
- const result = timeout ?
250
- await withTimeout(timeout, search(module).call(context, { ...opts, config: this })) :
251
- await search(module).call(context, { ...opts, config: this });
586
+ const result = timeout
587
+ ? await withTimeout(timeout, search(module).call(context, { ...opts, config: this }))
588
+ : await search(module).call(context, { ...opts, config: this });
252
589
  final.successes.push({ plugin: p, result });
253
590
  if (p.name === '@oclif/plugin-legacy' && event === 'init') {
254
591
  this.insertLegacyPlugins(result);
@@ -256,15 +593,15 @@ class Config {
256
593
  debug('done');
257
594
  }
258
595
  catch (error) {
259
- final.failures.push({ plugin: p, error: error });
596
+ final.failures.push({ error: error, plugin: p });
260
597
  debug(error);
261
598
  if (!captureErrors && error.oclif?.exit !== undefined)
262
599
  throw error;
263
600
  }
264
601
  marker?.addDetails({
265
- plugin: p.name,
266
602
  event,
267
603
  hook,
604
+ plugin: p.name,
268
605
  });
269
606
  marker?.stop();
270
607
  }
@@ -274,61 +611,24 @@ class Config {
274
611
  marker?.stop();
275
612
  return final;
276
613
  }
277
- async runCommand(id, argv = [], cachedCommand = null) {
278
- const marker = performance_1.default.mark(`config.runCommand#${id}`);
279
- debug('runCommand %s %o', id, argv);
280
- let c = cachedCommand ?? this.findCommand(id);
281
- if (!c) {
282
- const matches = this.flexibleTaxonomy ? this.findMatches(id, argv) : [];
283
- const hookResult = this.flexibleTaxonomy && matches.length > 0 ?
284
- await this.runHook('command_incomplete', { id, argv, matches }) :
285
- await this.runHook('command_not_found', { id, argv });
286
- if (hookResult.successes[0])
287
- return hookResult.successes[0].result;
288
- if (hookResult.failures[0])
289
- throw hookResult.failures[0].error;
290
- throw new errors_1.CLIError(`command ${id} not found`);
291
- }
292
- if (this.isJitPluginCommand(c)) {
293
- const pluginName = c.pluginName;
294
- const pluginVersion = this.pjson.oclif.jitPlugins[pluginName];
295
- const jitResult = await this.runHook('jit_plugin_not_installed', {
296
- id,
297
- argv,
298
- command: c,
299
- pluginName,
300
- pluginVersion,
301
- });
302
- if (jitResult.failures[0])
303
- throw jitResult.failures[0].error;
304
- if (jitResult.successes[0]) {
305
- await this.loadPluginsAndCommands({ force: true });
306
- c = this.findCommand(id) ?? c;
307
- }
308
- else {
309
- // this means that no jit_plugin_not_installed hook exists, so we should run the default behavior
310
- const result = await this.runHook('command_not_found', { id, argv });
311
- if (result.successes[0])
312
- return result.successes[0].result;
313
- if (result.failures[0])
314
- throw result.failures[0].error;
315
- throw new errors_1.CLIError(`command ${id} not found`);
316
- }
317
- }
318
- const command = await c.load();
319
- await this.runHook('prerun', { Command: command, argv });
320
- const result = (await command.run(argv, this));
321
- await this.runHook('postrun', { Command: command, result, argv });
322
- marker?.addDetails({ command: id, plugin: c.pluginName });
323
- marker?.stop();
324
- return result;
614
+ s3Key(type, ext, options = {}) {
615
+ if (typeof ext === 'object')
616
+ options = ext;
617
+ else if (ext)
618
+ options.ext = ext;
619
+ const template = this.pjson.oclif.update.s3.templates[options.platform ? 'target' : 'vanilla'][type] ?? '';
620
+ return ejs.render(template, { ...this, ...options });
325
621
  }
326
- scopedEnvVar(k) {
327
- return process.env[this.scopedEnvVarKeys(k).find(k => process.env[k])];
622
+ s3Url(key) {
623
+ const { host } = this.pjson.oclif.update.s3;
624
+ if (!host)
625
+ throw new Error('no s3 host is set');
626
+ const url = new node_url_1.URL(host);
627
+ url.pathname = (0, node_path_1.join)(url.pathname, key);
628
+ return url.toString();
328
629
  }
329
- scopedEnvVarTrue(k) {
330
- const v = process.env[this.scopedEnvVarKeys(k).find(k => process.env[k])];
331
- return v === '1' || v === 'true';
630
+ scopedEnvVar(k) {
631
+ return process.env[this.scopedEnvVarKeys(k).find((k) => process.env[k])];
332
632
  }
333
633
  /**
334
634
  * this DOES NOT account for bin aliases, use scopedEnvVarKeys instead which will account for bin aliases
@@ -337,7 +637,7 @@ class Config {
337
637
  */
338
638
  scopedEnvVarKey(k) {
339
639
  return [this.bin, k]
340
- .map(p => p.replace(/@/g, '').replace(/[/-]/g, '_'))
640
+ .map((p) => p.replaceAll('@', '').replaceAll(/[/-]/g, '_'))
341
641
  .join('_')
342
642
  .toUpperCase();
343
643
  }
@@ -347,156 +647,13 @@ class Config {
347
647
  * @returns {string[]} e.g. ['SF_DEBUG', 'SFDX_DEBUG']
348
648
  */
349
649
  scopedEnvVarKeys(k) {
350
- return [this.bin, ...this.binAliases ?? []].filter(alias => Boolean(alias)).map(alias => [alias.replace(/@/g, '').replace(/[/-]/g, '_'), k].join('_').toUpperCase());
351
- }
352
- findCommand(id, opts = {}) {
353
- const lookupId = this.getCmdLookupId(id);
354
- const command = this._commands.get(lookupId);
355
- if (opts.must && !command)
356
- (0, errors_1.error)(`command ${lookupId} not found`);
357
- return command;
358
- }
359
- findTopic(name, opts = {}) {
360
- const lookupId = this.getTopicLookupId(name);
361
- const topic = this._topics.get(lookupId);
362
- if (topic)
363
- return topic;
364
- if (opts.must)
365
- throw new Error(`topic ${name} not found`);
366
- }
367
- /**
368
- * Find all command ids that include the provided command id.
369
- *
370
- * For example, if the command ids are:
371
- * - foo:bar:baz
372
- * - one:two:three
373
- *
374
- * `bar` would return `foo:bar:baz`
375
- *
376
- * @param partialCmdId string
377
- * @param argv string[] process.argv containing the flags and arguments provided by the user
378
- * @returns string[]
379
- */
380
- findMatches(partialCmdId, argv) {
381
- const flags = argv.filter(arg => !(0, help_1.getHelpFlagAdditions)(this).includes(arg) && arg.startsWith('-')).map(a => a.replace(/-/g, ''));
382
- const possibleMatches = [...this.commandPermutations.get(partialCmdId)].map(k => this._commands.get(k));
383
- const matches = possibleMatches.filter(command => {
384
- const cmdFlags = Object.entries(command.flags).flatMap(([flag, def]) => {
385
- return def.char ? [def.char, flag] : [flag];
386
- });
387
- // A command is a match if the provided flags belong to the full command
388
- return flags.every(f => cmdFlags.includes(f));
389
- });
390
- return matches;
391
- }
392
- /**
393
- * Returns an array of all commands. If flexible taxonomy is enabled then all permutations will be appended to the array.
394
- * @returns Command.Loadable[]
395
- */
396
- getAllCommands() {
397
- const commands = [...this._commands.values()];
398
- const validPermutations = [...this.commandPermutations.getAllValid()];
399
- for (const permutation of validPermutations) {
400
- if (!this._commands.has(permutation)) {
401
- const cmd = this._commands.get(this.getCmdLookupId(permutation));
402
- commands.push({ ...cmd, id: permutation });
403
- }
404
- }
405
- return commands;
406
- }
407
- /**
408
- * Returns an array of all command ids. If flexible taxonomy is enabled then all permutations will be appended to the array.
409
- * @returns string[]
410
- */
411
- getAllCommandIDs() {
412
- return this.getAllCommands().map(c => c.id);
413
- }
414
- get commands() {
415
- return [...this._commands.values()];
416
- }
417
- get commandIDs() {
418
- if (this._commandIDs)
419
- return this._commandIDs;
420
- this._commandIDs = this.commands.map(c => c.id);
421
- return this._commandIDs;
422
- }
423
- get topics() {
424
- return [...this._topics.values()];
425
- }
426
- get versionDetails() {
427
- const [cliVersion, architecture, nodeVersion] = this.userAgent.split(' ');
428
- return {
429
- cliVersion,
430
- architecture,
431
- nodeVersion,
432
- pluginVersions: Object.fromEntries([...this.plugins.values()].map(p => [p.name, { version: p.version, type: p.type, root: p.root }])),
433
- osVersion: `${os.type()} ${os.release()}`,
434
- shell: this.shell,
435
- rootPath: this.root,
436
- };
437
- }
438
- s3Key(type, ext, options = {}) {
439
- if (typeof ext === 'object')
440
- options = ext;
441
- else if (ext)
442
- options.ext = ext;
443
- const template = this.pjson.oclif.update.s3.templates[options.platform ? 'target' : 'vanilla'][type] ?? '';
444
- return ejs.render(template, { ...this, ...options });
445
- }
446
- s3Url(key) {
447
- const host = this.pjson.oclif.update.s3.host;
448
- if (!host)
449
- throw new Error('no s3 host is set');
450
- const url = new url_1.URL(host);
451
- url.pathname = path.join(url.pathname, key);
452
- return url.toString();
453
- }
454
- getPluginsList() {
455
- return [...this.plugins.values()];
456
- }
457
- dir(category) {
458
- const base = process.env[`XDG_${category.toUpperCase()}_HOME`] ||
459
- (this.windows && process.env.LOCALAPPDATA) ||
460
- path.join(this.home, category === 'data' ? '.local/share' : '.' + category);
461
- return path.join(base, this.dirname);
462
- }
463
- windowsHome() {
464
- return this.windowsHomedriveHome() || this.windowsUserprofileHome();
465
- }
466
- windowsHomedriveHome() {
467
- return (process.env.HOMEDRIVE && process.env.HOMEPATH && path.join(process.env.HOMEDRIVE, process.env.HOMEPATH));
468
- }
469
- windowsUserprofileHome() {
470
- return process.env.USERPROFILE;
650
+ return [this.bin, ...(this.binAliases ?? [])]
651
+ .filter(Boolean)
652
+ .map((alias) => [alias.replaceAll('@', '').replaceAll(/[/-]/g, '_'), k].join('_').toUpperCase());
471
653
  }
472
- macosCacheDir() {
473
- return (this.platform === 'darwin' && path.join(this.home, 'Library', 'Caches', this.dirname)) || undefined;
474
- }
475
- _shell() {
476
- let shellPath;
477
- const COMSPEC = process.env.COMSPEC;
478
- const SHELL = process.env.SHELL ?? (0, node_os_1.userInfo)().shell?.split(node_path_1.sep)?.pop();
479
- if (SHELL) {
480
- shellPath = SHELL.split('/');
481
- }
482
- else if (this.windows && COMSPEC) {
483
- shellPath = COMSPEC.split(/\\|\//);
484
- }
485
- else {
486
- shellPath = ['unknown'];
487
- }
488
- return shellPath[shellPath.length - 1];
489
- }
490
- _debug() {
491
- if (this.scopedEnvVarTrue('DEBUG'))
492
- return 1;
493
- try {
494
- const { enabled } = require('debug')(this.bin);
495
- if (enabled)
496
- return 1;
497
- }
498
- catch { }
499
- return 0;
654
+ scopedEnvVarTrue(k) {
655
+ const v = process.env[this.scopedEnvVarKeys(k).find((k) => process.env[k])];
656
+ return v === '1' || v === 'true';
500
657
  }
501
658
  warn(err, scope) {
502
659
  if (this.warned)
@@ -532,298 +689,41 @@ class Config {
532
689
  ]).join('\n');
533
690
  process.emitWarning(JSON.stringify(err));
534
691
  }
535
- get isProd() {
536
- return (0, util_3.isProd)();
537
- }
538
- isJitPluginCommand(c) {
539
- // Return true if the command's plugin is listed under oclif.jitPlugins AND if the plugin hasn't been loaded to this.plugins
540
- return Object.keys(this.pjson.oclif.jitPlugins ?? {}).includes(c.pluginName ?? '') && Boolean(c?.pluginName && !this.plugins.has(c.pluginName));
541
- }
542
- getCmdLookupId(id) {
543
- if (this._commands.has(id))
544
- return id;
545
- if (this.commandPermutations.hasValid(id))
546
- return this.commandPermutations.getValid(id);
547
- return id;
548
- }
549
- getTopicLookupId(id) {
550
- if (this._topics.has(id))
551
- return id;
552
- if (this.topicPermutations.hasValid(id))
553
- return this.topicPermutations.getValid(id);
554
- return id;
555
- }
556
- loadCommands(plugin) {
557
- const marker = performance_1.default.mark(`config.loadCommands#${plugin.name}`, { plugin: plugin.name });
558
- for (const command of plugin.commands) {
559
- // set canonical command id
560
- if (this._commands.has(command.id)) {
561
- const prioritizedCommand = this.determinePriority([this._commands.get(command.id), command]);
562
- this._commands.set(prioritizedCommand.id, prioritizedCommand);
563
- }
564
- else {
565
- this._commands.set(command.id, command);
566
- }
567
- // set every permutation
568
- for (const permutation of command.permutations ?? [command.id]) {
569
- this.commandPermutations.add(permutation, command.id);
570
- }
571
- // set command aliases
572
- for (const alias of command.aliases ?? []) {
573
- if (this._commands.has(alias)) {
574
- const prioritizedCommand = this.determinePriority([this._commands.get(alias), command]);
575
- this._commands.set(alias, { ...prioritizedCommand, id: alias });
576
- }
577
- else {
578
- this._commands.set(alias, { ...command, id: alias });
579
- }
580
- // set every permutation of the aliases
581
- for (const permutation of command.aliasPermutations ?? [alias]) {
582
- this.commandPermutations.add(permutation, command.id);
583
- }
584
- }
585
- }
586
- marker?.addDetails({ commandCount: plugin.commands.length });
587
- marker?.stop();
588
- }
589
- loadTopics(plugin) {
590
- const marker = performance_1.default.mark(`config.loadTopics#${plugin.name}`, { plugin: plugin.name });
591
- for (const topic of (0, util_2.compact)(plugin.topics)) {
592
- const existing = this._topics.get(topic.name);
593
- if (existing) {
594
- existing.description = topic.description || existing.description;
595
- existing.hidden = existing.hidden || topic.hidden;
596
- }
597
- else {
598
- this._topics.set(topic.name, topic);
599
- }
600
- const permutations = this.flexibleTaxonomy ? (0, util_2.getCommandIdPermutations)(topic.name) : [topic.name];
601
- for (const permutation of permutations) {
602
- this.topicPermutations.add(permutation, topic.name);
603
- }
604
- }
605
- // Add missing topics for displaying help when partial commands are entered.
606
- for (const c of plugin.commands.filter(c => !c.hidden)) {
607
- const parts = c.id.split(':');
608
- while (parts.length > 0) {
609
- const name = parts.join(':');
610
- if (name && !this._topics.has(name)) {
611
- this._topics.set(name, { name, description: c.summary || c.description });
612
- }
613
- parts.pop();
614
- }
615
- }
616
- marker?.stop();
617
- }
618
- /**
619
- * This method is responsible for locating the correct plugin to use for a named command id
620
- * It searches the {Config} registered commands to match either the raw command id or the command alias
621
- * It is possible that more than one command will be found. This is due the ability of two distinct plugins to
622
- * create the same command or command alias.
623
- *
624
- * In the case of more than one found command, the function will select the command based on the order in which
625
- * the plugin is included in the package.json `oclif.plugins` list. The command that occurs first in the list
626
- * is selected as the command to run.
627
- *
628
- * Commands can also be present from either an install or a link. When a command is one of these and a core plugin
629
- * is present, this function defers to the core plugin.
630
- *
631
- * If there is not a core plugin command present, this function will return the first
632
- * plugin as discovered (will not change the order)
633
- *
634
- * @param commands commands to determine the priority of
635
- * @returns command instance {Command.Loadable} or undefined
636
- */
637
- determinePriority(commands) {
638
- const oclifPlugins = this.pjson.oclif?.plugins ?? [];
639
- const commandPlugins = commands.sort((a, b) => {
640
- const pluginAliasA = a.pluginAlias ?? 'A-Cannot-Find-This';
641
- const pluginAliasB = b.pluginAlias ?? 'B-Cannot-Find-This';
642
- const aIndex = oclifPlugins.indexOf(pluginAliasA);
643
- const bIndex = oclifPlugins.indexOf(pluginAliasB);
644
- // When both plugin types are 'core' plugins sort based on index
645
- if (a.pluginType === 'core' && b.pluginType === 'core') {
646
- // If b appears first in the pjson.plugins sort it first
647
- return aIndex - bIndex;
648
- }
649
- // if b is a core plugin and a is not sort b first
650
- if (b.pluginType === 'core' && a.pluginType !== 'core') {
651
- return 1;
652
- }
653
- // if a is a core plugin and b is not sort a first
654
- if (a.pluginType === 'core' && b.pluginType !== 'core') {
655
- return -1;
656
- }
657
- // if a is a jit plugin and b is not sort b first
658
- if (a.pluginType === 'jit' && b.pluginType !== 'jit') {
659
- return 1;
660
- }
661
- // if b is a jit plugin and a is not sort a first
662
- if (b.pluginType === 'jit' && a.pluginType !== 'jit') {
663
- return -1;
664
- }
665
- // neither plugin is core, so do not change the order
666
- return 0;
667
- });
668
- return commandPlugins[0];
669
- }
670
- /**
671
- * Insert legacy plugins
672
- *
673
- * Replace invalid CLI plugins (cli-engine plugins, mostly Heroku) loaded via `this.loadPlugins`
674
- * with oclif-compatible ones returned by @oclif/plugin-legacy init hook.
675
- *
676
- * @param plugins array of oclif-compatible plugins
677
- * @returns void
678
- */
679
- insertLegacyPlugins(plugins) {
680
- for (const plugin of plugins) {
681
- this.plugins.set(plugin.name, plugin);
682
- this.loadCommands(plugin);
683
- }
692
+ windowsHome() {
693
+ return this.windowsHomedriveHome() || this.windowsUserprofileHome();
684
694
  }
685
- }
686
- exports.Config = Config;
687
- // when no manifest exists, the default is calculated. This may throw, so we need to catch it
688
- const defaultFlagToCached = async (flag, respectNoCacheDefault) => {
689
- if (respectNoCacheDefault && flag.noCacheDefault)
690
- return;
691
- // Prefer the defaultHelp function (returns a friendly string for complex types)
692
- if (typeof flag.defaultHelp === 'function') {
693
- try {
694
- return await flag.defaultHelp({ options: flag, flags: {} });
695
- }
696
- catch {
697
- return;
698
- }
695
+ windowsHomedriveHome() {
696
+ return process.env.HOMEDRIVE && process.env.HOMEPATH && (0, node_path_1.join)(process.env.HOMEDRIVE, process.env.HOMEPATH);
699
697
  }
700
- // if not specified, try the default function
701
- if (typeof flag.default === 'function') {
702
- try {
703
- return await flag.default({ options: flag, flags: {} });
704
- }
705
- catch { }
698
+ windowsUserprofileHome() {
699
+ return process.env.USERPROFILE;
706
700
  }
707
- else {
708
- return flag.default;
701
+ get commandIDs() {
702
+ if (this._commandIDs)
703
+ return this._commandIDs;
704
+ this._commandIDs = this.commands.map((c) => c.id);
705
+ return this._commandIDs;
709
706
  }
710
- };
711
- const defaultArgToCached = async (arg, respectNoCacheDefault) => {
712
- if (respectNoCacheDefault && arg.noCacheDefault)
713
- return;
714
- // Prefer the defaultHelp function (returns a friendly string for complex types)
715
- if (typeof arg.defaultHelp === 'function') {
716
- try {
717
- return await arg.defaultHelp({ options: arg, flags: {} });
718
- }
719
- catch {
720
- return;
721
- }
707
+ get commands() {
708
+ return [...this._commands.values()];
722
709
  }
723
- // if not specified, try the default function
724
- if (typeof arg.default === 'function') {
725
- try {
726
- return await arg.default({ options: arg, flags: {} });
727
- }
728
- catch { }
710
+ get isProd() {
711
+ return (0, util_2.isProd)();
729
712
  }
730
- else {
731
- return arg.default;
732
- }
733
- };
734
- async function toCached(c, plugin, respectNoCacheDefault = false) {
735
- const flags = {};
736
- for (const [name, flag] of Object.entries(c.flags || {})) {
737
- if (flag.type === 'boolean') {
738
- flags[name] = {
739
- name,
740
- type: flag.type,
741
- char: flag.char,
742
- summary: flag.summary,
743
- description: flag.description,
744
- hidden: flag.hidden,
745
- required: flag.required,
746
- helpLabel: flag.helpLabel,
747
- helpGroup: flag.helpGroup,
748
- allowNo: flag.allowNo,
749
- dependsOn: flag.dependsOn,
750
- relationships: flag.relationships,
751
- exclusive: flag.exclusive,
752
- deprecated: flag.deprecated,
753
- deprecateAliases: c.deprecateAliases,
754
- aliases: flag.aliases,
755
- delimiter: flag.delimiter,
756
- noCacheDefault: flag.noCacheDefault,
757
- };
758
- }
759
- else {
760
- flags[name] = {
761
- name,
762
- type: flag.type,
763
- char: flag.char,
764
- summary: flag.summary,
765
- description: flag.description,
766
- hidden: flag.hidden,
767
- required: flag.required,
768
- helpLabel: flag.helpLabel,
769
- helpValue: flag.helpValue,
770
- helpGroup: flag.helpGroup,
771
- multiple: flag.multiple,
772
- options: flag.options,
773
- dependsOn: flag.dependsOn,
774
- relationships: flag.relationships,
775
- exclusive: flag.exclusive,
776
- default: await defaultFlagToCached(flag, respectNoCacheDefault),
777
- deprecated: flag.deprecated,
778
- deprecateAliases: c.deprecateAliases,
779
- aliases: flag.aliases,
780
- delimiter: flag.delimiter,
781
- noCacheDefault: flag.noCacheDefault,
782
- };
783
- // a command-level placeholder in the manifest so that oclif knows it should regenerate the command during help-time
784
- if (typeof flag.defaultHelp === 'function') {
785
- c.hasDynamicHelp = true;
786
- }
787
- }
713
+ get topics() {
714
+ return [...this._topics.values()];
788
715
  }
789
- const args = {};
790
- for (const [name, arg] of Object.entries((0, util_3.ensureArgObject)(c.args))) {
791
- args[name] = {
792
- name,
793
- description: arg.description,
794
- required: arg.required,
795
- options: arg.options,
796
- default: await defaultArgToCached(arg, respectNoCacheDefault),
797
- hidden: arg.hidden,
798
- noCacheDefault: arg.noCacheDefault,
716
+ get versionDetails() {
717
+ const [cliVersion, architecture, nodeVersion] = this.userAgent.split(' ');
718
+ return {
719
+ architecture,
720
+ cliVersion,
721
+ nodeVersion,
722
+ osVersion: `${(0, node_os_1.type)()} ${(0, node_os_1.release)()}`,
723
+ pluginVersions: Object.fromEntries([...this.plugins.values()].map((p) => [p.name, { root: p.root, type: p.type, version: p.version }])),
724
+ rootPath: this.root,
725
+ shell: this.shell,
799
726
  };
800
727
  }
801
- const stdProperties = {
802
- id: c.id,
803
- summary: c.summary,
804
- description: c.description,
805
- strict: c.strict,
806
- usage: c.usage,
807
- pluginName: plugin && plugin.name,
808
- pluginAlias: plugin && plugin.alias,
809
- pluginType: plugin && plugin.type,
810
- hidden: c.hidden,
811
- state: c.state,
812
- aliases: c.aliases || [],
813
- examples: c.examples || c.example,
814
- deprecationOptions: c.deprecationOptions,
815
- deprecateAliases: c.deprecateAliases,
816
- flags,
817
- args,
818
- };
819
- // do not include these properties in manifest
820
- const ignoreCommandProperties = ['plugin', '_flags', '_enableJsonFlag', '_globalFlags', '_baseFlags'];
821
- const stdKeys = Object.keys(stdProperties);
822
- const keysToAdd = Object.keys(c).filter(property => ![...stdKeys, ...ignoreCommandProperties].includes(property));
823
- const additionalProperties = {};
824
- for (const key of keysToAdd) {
825
- additionalProperties[key] = c[key];
826
- }
827
- return { ...stdProperties, ...additionalProperties };
828
728
  }
829
- exports.toCached = toCached;
729
+ exports.Config = Config;