@oclif/core 3.19.5-dev.0 → 3.19.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/cache.d.ts CHANGED
@@ -2,23 +2,15 @@ import { PJSON, Plugin } from './interfaces';
2
2
  type CacheContents = {
3
3
  rootPlugin: Plugin;
4
4
  exitCodes: PJSON.Plugin['oclif']['exitCodes'];
5
- '@oclif/core': OclifCoreInfo;
6
5
  };
7
6
  type ValueOf<T> = T[keyof T];
8
- type OclifCoreInfo = {
9
- name: string;
10
- version: string;
11
- };
12
7
  /**
13
8
  * A simple cache for storing values that need to be accessed globally.
14
9
  */
15
10
  export default class Cache extends Map<keyof CacheContents, ValueOf<CacheContents>> {
16
11
  static instance: Cache;
17
- constructor();
18
12
  static getInstance(): Cache;
19
- get(key: '@oclif/core'): OclifCoreInfo;
20
13
  get(key: 'rootPlugin'): Plugin | undefined;
21
14
  get(key: 'exitCodes'): PJSON.Plugin['oclif']['exitCodes'] | undefined;
22
- private getOclifCoreMeta;
23
15
  }
24
16
  export {};
package/lib/cache.js CHANGED
@@ -1,16 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const node_fs_1 = require("node:fs");
4
- const node_path_1 = require("node:path");
5
3
  /**
6
4
  * A simple cache for storing values that need to be accessed globally.
7
5
  */
8
6
  class Cache extends Map {
9
7
  static instance;
10
- constructor() {
11
- super();
12
- this.set('@oclif/core', this.getOclifCoreMeta());
13
- }
14
8
  static getInstance() {
15
9
  if (!Cache.instance) {
16
10
  Cache.instance = new Cache();
@@ -20,22 +14,5 @@ class Cache extends Map {
20
14
  get(key) {
21
15
  return super.get(key);
22
16
  }
23
- getOclifCoreMeta() {
24
- try {
25
- // eslint-disable-next-line node/no-extraneous-require
26
- return { name: '@oclif/core', version: require('@oclif/core/package.json').version };
27
- }
28
- catch {
29
- try {
30
- return {
31
- name: '@oclif/core',
32
- version: JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(__dirname, '..', 'package.json'), 'utf8')),
33
- };
34
- }
35
- catch {
36
- return { name: '@oclif/core', version: 'unknown' };
37
- }
38
- }
39
- }
40
17
  }
41
18
  exports.default = Cache;
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.config = exports.Config = void 0;
7
- const cache_1 = __importDefault(require("../cache"));
7
+ const fs_1 = require("../util/fs");
8
8
  const simple_1 = __importDefault(require("./action/simple"));
9
9
  const spinner_1 = __importDefault(require("./action/spinner"));
10
10
  const g = global;
@@ -35,8 +35,7 @@ class Config {
35
35
  }
36
36
  exports.Config = Config;
37
37
  function fetch() {
38
- const core = cache_1.default.getInstance().get('@oclif/core');
39
- const major = core?.version.split('.')[0] || 'unknown';
38
+ const major = (0, fs_1.requireJson)(__dirname, '..', '..', 'package.json').version.split('.')[0];
40
39
  if (globals[major])
41
40
  return globals[major];
42
41
  globals[major] = new Config();
@@ -42,7 +42,8 @@ function normal(options, retries = 100) {
42
42
  output: process.stdout,
43
43
  });
44
44
  let timeout;
45
- if (options.timeout) {
45
+ // Only set the timeout if the input is a TTY
46
+ if (options.timeout && options.isTTY) {
46
47
  timeout = setTimeout(() => ac.abort(), options.timeout);
47
48
  signal.addEventListener('abort', () => {
48
49
  rl.close();
package/lib/command.js CHANGED
@@ -30,16 +30,16 @@ exports.Command = void 0;
30
30
  const chalk_1 = __importDefault(require("chalk"));
31
31
  const node_url_1 = require("node:url");
32
32
  const node_util_1 = require("node:util");
33
- const cache_1 = __importDefault(require("./cache"));
34
33
  const cli_ux_1 = require("./cli-ux");
35
34
  const config_1 = require("./config");
36
35
  const Errors = __importStar(require("./errors"));
37
36
  const util_1 = require("./help/util");
38
37
  const Parser = __importStar(require("./parser"));
39
38
  const aggregate_flags_1 = require("./util/aggregate-flags");
39
+ const fs_1 = require("./util/fs");
40
40
  const ids_1 = require("./util/ids");
41
41
  const util_2 = require("./util/util");
42
- const pjson = cache_1.default.getInstance().get('@oclif/core');
42
+ const pjson = (0, fs_1.requireJson)(__dirname, '..', 'package.json');
43
43
  /**
44
44
  * swallows stdout epipe errors
45
45
  * this occurs when stdout closes such as when piping to head
@@ -18,7 +18,6 @@ export declare class Config implements IConfig {
18
18
  errlog: string;
19
19
  flexibleTaxonomy: boolean;
20
20
  home: string;
21
- isSingleCommandCLI: boolean;
22
21
  name: string;
23
22
  npmRegistry?: string;
24
23
  nsisCustomization?: string;
@@ -48,7 +48,7 @@ const ts_node_1 = require("./ts-node");
48
48
  const util_3 = require("./util");
49
49
  // eslint-disable-next-line new-cap
50
50
  const debug = (0, util_3.Debug)();
51
- const _pjson = cache_1.default.getInstance().get('@oclif/core');
51
+ const _pjson = (0, fs_1.requireJson)(__dirname, '..', '..', 'package.json');
52
52
  const BASE = `${_pjson.name}@${_pjson.version}`;
53
53
  function channelFromVersion(version) {
54
54
  const m = version.match(/[^-]+(?:-([^.]+))?/);
@@ -98,7 +98,6 @@ class Config {
98
98
  errlog;
99
99
  flexibleTaxonomy;
100
100
  home;
101
- isSingleCommandCLI = false;
102
101
  name;
103
102
  npmRegistry;
104
103
  nsisCustomization;
@@ -329,10 +328,6 @@ class Config {
329
328
  ...(s3.templates && s3.templates.vanilla),
330
329
  },
331
330
  };
332
- this.isSingleCommandCLI = Boolean(this.pjson.oclif.default ||
333
- (typeof this.pjson.oclif.commands !== 'string' &&
334
- this.pjson.oclif.commands?.strategy === 'single' &&
335
- this.pjson.oclif.commands?.target));
336
331
  await this.loadPluginsAndCommands();
337
332
  debug('config done');
338
333
  marker?.addDetails({
@@ -487,15 +482,14 @@ class Config {
487
482
  };
488
483
  const hooks = p.hooks[event] || [];
489
484
  for (const hook of hooks) {
490
- const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `config.runHook#${p.name}(${hook.target})`);
485
+ const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `config.runHook#${p.name}(${hook})`);
491
486
  try {
492
487
  /* eslint-disable no-await-in-loop */
493
- const { filePath, isESM, module } = await (0, module_loader_1.loadWithData)(p, await (0, ts_node_1.tsPath)(p.root, hook.target, p));
488
+ const { filePath, isESM, module } = await (0, module_loader_1.loadWithData)(p, await (0, ts_node_1.tsPath)(p.root, hook, p));
494
489
  debug('start', isESM ? '(import)' : '(require)', filePath);
495
- const hookFn = module[hook.identifier] ?? search(module);
496
490
  const result = timeout
497
- ? await withTimeout(timeout, hookFn.call(context, { ...opts, config: this, context }))
498
- : await hookFn.call(context, { ...opts, config: this, context });
491
+ ? await withTimeout(timeout, search(module).call(context, { ...opts, config: this, context }))
492
+ : await search(module).call(context, { ...opts, config: this, context });
499
493
  final.successes.push({ plugin: p, result });
500
494
  if (p.name === '@oclif/plugin-legacy' && event === 'init') {
501
495
  this.insertLegacyPlugins(result);
@@ -517,7 +511,7 @@ class Config {
517
511
  }
518
512
  marker?.addDetails({
519
513
  event,
520
- hook: hook.target,
514
+ hook,
521
515
  plugin: p.name,
522
516
  });
523
517
  marker?.stop();
@@ -1,6 +1,6 @@
1
1
  import { Command } from '../command';
2
2
  import { Manifest } from '../interfaces/manifest';
3
- import { HookOptions, PJSON } from '../interfaces/pjson';
3
+ import { PJSON } from '../interfaces/pjson';
4
4
  import { Plugin as IPlugin, PluginOptions } from '../interfaces/plugin';
5
5
  import { Topic } from '../interfaces/topic';
6
6
  export declare class Plugin implements IPlugin {
@@ -13,7 +13,7 @@ export declare class Plugin implements IPlugin {
13
13
  commandsDir: string | undefined;
14
14
  hasManifest: boolean;
15
15
  hooks: {
16
- [key: string]: HookOptions[];
16
+ [k: string]: string[];
17
17
  };
18
18
  isRoot: boolean;
19
19
  manifest: Manifest;
@@ -29,8 +29,6 @@ export declare class Plugin implements IPlugin {
29
29
  protected warned: boolean;
30
30
  _base: string;
31
31
  protected _debug: (..._: any) => void;
32
- private commandCache;
33
- private commandDiscoveryOpts;
34
32
  private flexibleTaxonomy;
35
33
  constructor(options: PluginOptions);
36
34
  get topics(): Topic[];
@@ -44,9 +42,6 @@ export declare class Plugin implements IPlugin {
44
42
  private _manifest;
45
43
  private addErrorScope;
46
44
  private getCommandIDs;
47
- private getCommandIdsFromPattern;
48
- private getCommandIdsFromTarget;
49
45
  private getCommandsDir;
50
- private loadCommandsFromTarget;
51
46
  private warn;
52
47
  }
@@ -7,18 +7,16 @@ exports.Plugin = void 0;
7
7
  const globby_1 = __importDefault(require("globby"));
8
8
  const node_path_1 = require("node:path");
9
9
  const node_util_1 = require("node:util");
10
- const cache_1 = __importDefault(require("../cache"));
11
10
  const errors_1 = require("../errors");
12
11
  const module_loader_1 = require("../module-loader");
13
12
  const performance_1 = require("../performance");
14
- const symbols_1 = require("../symbols");
15
13
  const cache_command_1 = require("../util/cache-command");
16
14
  const find_root_1 = require("../util/find-root");
17
15
  const fs_1 = require("../util/fs");
18
16
  const util_1 = require("../util/util");
19
17
  const ts_node_1 = require("./ts-node");
20
18
  const util_2 = require("./util");
21
- const _pjson = cache_1.default.getInstance().get('@oclif/core');
19
+ const _pjson = (0, fs_1.requireJson)(__dirname, '..', '..', 'package.json');
22
20
  function topicsToArray(input, base) {
23
21
  if (!input)
24
22
  return [];
@@ -32,7 +30,7 @@ function topicsToArray(input, base) {
32
30
  });
33
31
  }
34
32
  const cachedCommandCanBeUsed = (manifest, id) => Boolean(manifest?.commands[id] && 'isESM' in manifest.commands[id] && 'relativePath' in manifest.commands[id]);
35
- const searchForCommandClass = (cmd) => {
33
+ const search = (cmd) => {
36
34
  if (typeof cmd.run === 'function')
37
35
  return cmd;
38
36
  if (cmd.default && cmd.default.run)
@@ -49,34 +47,9 @@ function processCommandIds(files) {
49
47
  const topics = p.dir.split('/');
50
48
  const command = p.name !== 'index' && p.name;
51
49
  const id = [...topics, command].filter(Boolean).join(':');
52
- return id === '' ? symbols_1.SINGLE_COMMAND_CLI_SYMBOL : id;
50
+ return id === '' ? '.' : id;
53
51
  });
54
52
  }
55
- function determineCommandDiscoveryOptions(commandDiscovery, defaultCmdId) {
56
- if (!commandDiscovery)
57
- return;
58
- if (typeof commandDiscovery === 'string' && defaultCmdId) {
59
- return { strategy: 'single', target: commandDiscovery };
60
- }
61
- if (typeof commandDiscovery === 'string') {
62
- return { globPatterns: GLOB_PATTERNS, strategy: 'pattern', target: commandDiscovery };
63
- }
64
- if (!commandDiscovery.target)
65
- throw new errors_1.CLIError('`oclif.commandDiscovery.target` is required.');
66
- if (!commandDiscovery.strategy)
67
- throw new errors_1.CLIError('`oclif.commandDiscovery.strategy` is required.');
68
- if (commandDiscovery.strategy === 'explicit' && !commandDiscovery.identifier) {
69
- commandDiscovery.identifier = 'default';
70
- }
71
- return commandDiscovery;
72
- }
73
- function determineHookOptions(hook) {
74
- if (typeof hook === 'string')
75
- return { identifier: 'default', target: hook };
76
- if (!hook.identifier)
77
- return { ...hook, identifier: 'default' };
78
- return hook;
79
- }
80
53
  class Plugin {
81
54
  options;
82
55
  alias;
@@ -103,8 +76,6 @@ class Plugin {
103
76
  _base = `${_pjson.name}@${_pjson.version}`;
104
77
  // eslint-disable-next-line new-cap
105
78
  _debug = (0, util_2.Debug)();
106
- commandCache;
107
- commandDiscoveryOpts;
108
79
  flexibleTaxonomy;
109
80
  constructor(options) {
110
81
  this.options = options;
@@ -118,43 +89,32 @@ class Plugin {
118
89
  plugin: this.name,
119
90
  });
120
91
  const fetch = async () => {
121
- if (this.commandDiscoveryOpts?.strategy === 'pattern') {
122
- const commandsDir = await this.getCommandsDir();
123
- if (!commandsDir)
124
- return;
125
- let module;
126
- let isESM;
127
- let filePath;
128
- try {
129
- ;
130
- ({ filePath, isESM, module } = cachedCommandCanBeUsed(this.manifest, id)
131
- ? await (0, module_loader_1.loadWithDataFromManifest)(this.manifest.commands[id], this.root)
132
- : await (0, module_loader_1.loadWithData)(this, (0, node_path_1.join)(commandsDir ?? this.pjson.oclif.commands, ...id.split(':'))));
133
- this._debug(isESM ? '(import)' : '(require)', filePath);
134
- }
135
- catch (error) {
136
- if (!opts.must && error.code === 'MODULE_NOT_FOUND')
137
- return;
138
- throw error;
139
- }
140
- const cmd = searchForCommandClass(module);
141
- if (!cmd)
142
- return;
143
- cmd.id = id;
144
- cmd.plugin = this;
145
- cmd.isESM = isESM;
146
- cmd.relativePath = (0, node_path_1.relative)(this.root, filePath || '').split(node_path_1.sep);
147
- return cmd;
92
+ const commandsDir = await this.getCommandsDir();
93
+ if (!commandsDir)
94
+ return;
95
+ let module;
96
+ let isESM;
97
+ let filePath;
98
+ try {
99
+ ;
100
+ ({ filePath, isESM, module } = cachedCommandCanBeUsed(this.manifest, id)
101
+ ? await (0, module_loader_1.loadWithDataFromManifest)(this.manifest.commands[id], this.root)
102
+ : await (0, module_loader_1.loadWithData)(this, (0, node_path_1.join)(commandsDir ?? this.pjson.oclif.commands, ...id.split(':'))));
103
+ this._debug(isESM ? '(import)' : '(require)', filePath);
148
104
  }
149
- if (this.commandDiscoveryOpts?.strategy === 'single' || this.commandDiscoveryOpts?.strategy === 'explicit') {
150
- const commandCache = await this.loadCommandsFromTarget();
151
- const cmd = commandCache?.[id];
152
- if (!cmd)
105
+ catch (error) {
106
+ if (!opts.must && error.code === 'MODULE_NOT_FOUND')
153
107
  return;
154
- cmd.id = id;
155
- cmd.plugin = this;
156
- return cmd;
108
+ throw error;
157
109
  }
110
+ const cmd = search(module);
111
+ if (!cmd)
112
+ return;
113
+ cmd.id = id;
114
+ cmd.plugin = this;
115
+ cmd.isESM = isESM;
116
+ cmd.relativePath = (0, node_path_1.relative)(this.root, filePath || '').split(node_path_1.sep);
117
+ return cmd;
158
118
  };
159
119
  const cmd = await fetch();
160
120
  if (!cmd && opts.must)
@@ -193,12 +153,7 @@ class Plugin {
193
153
  else {
194
154
  this.pjson.oclif = this.pjson['cli-engine'] || {};
195
155
  }
196
- this.hooks = Object.fromEntries(Object.entries(this.pjson.oclif.hooks ?? {}).map(([k, v]) => [
197
- k,
198
- (0, util_1.castArray)(v).map((v) => determineHookOptions(v)),
199
- ]));
200
- this.commandDiscoveryOpts = determineCommandDiscoveryOptions(this.pjson.oclif?.commands, this.pjson.oclif?.default);
201
- this._debug('command discovery options', this.commandDiscoveryOpts);
156
+ this.hooks = Object.fromEntries(Object.entries(this.pjson.oclif.hooks ?? {}).map(([k, v]) => [k, (0, util_1.castArray)(v)]));
202
157
  this.manifest = await this._manifest();
203
158
  this.commands = Object.entries(this.manifest.commands)
204
159
  .map(([id, c]) => ({
@@ -250,13 +205,7 @@ class Plugin {
250
205
  const manifest = {
251
206
  commands: (await Promise.all(this.commandIDs.map(async (id) => {
252
207
  try {
253
- const found = await this.findCommand(id, { must: true });
254
- const cached = await (0, cache_command_1.cacheCommand)(found, this, respectNoCacheDefault);
255
- // Ensure that id is set to the id being processed
256
- // This is necessary because the id is set by findCommand but if there
257
- // are multiple instances of a Command, then the id will be set to the
258
- // last one found.
259
- cached.id = id;
208
+ const cached = await (0, cache_command_1.cacheCommand)(await this.findCommand(id, { must: true }), this, respectNoCacheDefault);
260
209
  if (this.flexibleTaxonomy) {
261
210
  const permutations = (0, util_2.getCommandIdPermutations)(id);
262
211
  const aliasPermutations = cached.aliases.flatMap((a) => (0, util_2.getCommandIdPermutations)(a));
@@ -297,66 +246,24 @@ class Plugin {
297
246
  return err;
298
247
  }
299
248
  async getCommandIDs() {
249
+ const commandsDir = await this.getCommandsDir();
250
+ if (!commandsDir)
251
+ return [];
300
252
  const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `plugin.getCommandIDs#${this.name}`, { plugin: this.name });
301
- let ids;
302
- switch (this.commandDiscoveryOpts?.strategy) {
303
- case 'explicit': {
304
- ids = (await this.getCommandIdsFromTarget()) ?? [];
305
- break;
306
- }
307
- case 'pattern': {
308
- ids = await this.getCommandIdsFromPattern();
309
- break;
310
- }
311
- case 'single': {
312
- ids = (await this.getCommandIdsFromTarget()) ?? [];
313
- break;
314
- }
315
- default: {
316
- ids = [];
317
- }
318
- }
253
+ this._debug(`loading IDs from ${commandsDir}`);
254
+ const files = await (0, globby_1.default)(GLOB_PATTERNS, { cwd: commandsDir });
255
+ const ids = processCommandIds(files);
319
256
  this._debug('found commands', ids);
320
257
  marker?.addDetails({ count: ids.length });
321
258
  marker?.stop();
322
259
  return ids;
323
260
  }
324
- async getCommandIdsFromPattern() {
325
- const commandsDir = await this.getCommandsDir();
326
- if (!commandsDir)
327
- return [];
328
- this._debug(`loading IDs from ${commandsDir}`);
329
- const files = await (0, globby_1.default)(this.commandDiscoveryOpts?.globPatterns ?? GLOB_PATTERNS, { cwd: commandsDir });
330
- return processCommandIds(files);
331
- }
332
- async getCommandIdsFromTarget() {
333
- const commandsFromExport = await this.loadCommandsFromTarget();
334
- if (commandsFromExport) {
335
- return Object.keys(commandsFromExport);
336
- }
337
- }
338
261
  async getCommandsDir() {
339
262
  if (this.commandsDir)
340
263
  return this.commandsDir;
341
- this.commandsDir = await (0, ts_node_1.tsPath)(this.root, this.commandDiscoveryOpts?.target, this);
264
+ this.commandsDir = await (0, ts_node_1.tsPath)(this.root, this.pjson.oclif.commands, this);
342
265
  return this.commandsDir;
343
266
  }
344
- async loadCommandsFromTarget() {
345
- if (this.commandCache)
346
- return this.commandCache;
347
- if (this.commandDiscoveryOpts?.strategy === 'explicit' && this.commandDiscoveryOpts.target) {
348
- const filePath = await (0, ts_node_1.tsPath)(this.root, this.commandDiscoveryOpts.target, this);
349
- const module = await (0, module_loader_1.load)(this, filePath);
350
- this.commandCache = module[this.commandDiscoveryOpts?.identifier ?? 'default'] ?? {};
351
- return this.commandCache;
352
- }
353
- if (this.commandDiscoveryOpts?.strategy === 'single' && this.commandDiscoveryOpts.target) {
354
- const filePath = await (0, ts_node_1.tsPath)(this.root, this.commandDiscoveryOpts?.target ?? this.root, this);
355
- const module = await (0, module_loader_1.load)(this, filePath);
356
- this.commandCache = { [symbols_1.SINGLE_COMMAND_CLI_SYMBOL]: searchForCommandClass(module) };
357
- return this.commandCache;
358
- }
359
- }
360
267
  warn(err, scope) {
361
268
  if (this.warned)
362
269
  return;
@@ -77,7 +77,7 @@ class DocOpts {
77
77
  return new DocOpts(cmd).toString();
78
78
  }
79
79
  toString() {
80
- const opts = ['<%= command.id %>'];
80
+ const opts = this.cmd.id === '.' || this.cmd.id === '' ? [] : ['<%= command.id %>'];
81
81
  if (this.cmd.args) {
82
82
  const a = Object.values((0, ensure_arg_object_1.ensureArgObject)(this.cmd.args)).map((arg) => arg.required ? arg.name.toUpperCase() : `[${arg.name.toUpperCase()}]`) || [];
83
83
  opts.push(...a);
package/lib/help/index.js CHANGED
@@ -10,7 +10,6 @@ const theme_1 = require("../cli-ux/theme");
10
10
  const write_1 = __importDefault(require("../cli-ux/write"));
11
11
  const errors_1 = require("../errors");
12
12
  const module_loader_1 = require("../module-loader");
13
- const symbols_1 = require("../symbols");
14
13
  const cache_default_value_1 = require("../util/cache-default-value");
15
14
  const ids_1 = require("../util/ids");
16
15
  const util_1 = require("../util/util");
@@ -190,8 +189,8 @@ class Help extends HelpBase {
190
189
  argv = (0, util_2.standardizeIDFromArgv)(argv, this.config);
191
190
  const subject = getHelpSubject(argv, this.config);
192
191
  if (!subject) {
193
- if (this.config.isSingleCommandCLI) {
194
- const rootCmd = this.config.findCommand(symbols_1.SINGLE_COMMAND_CLI_SYMBOL);
192
+ if (this.config.pjson.oclif.default) {
193
+ const rootCmd = this.config.findCommand(this.config.pjson.oclif.default);
195
194
  if (rootCmd) {
196
195
  await this.showCommandHelp(rootCmd);
197
196
  return;
@@ -202,12 +201,6 @@ class Help extends HelpBase {
202
201
  }
203
202
  const command = this.config.findCommand(subject);
204
203
  if (command) {
205
- if (command.id === symbols_1.SINGLE_COMMAND_CLI_SYMBOL) {
206
- // If the command is the root command of a single command CLI,
207
- // then set the command id to an empty string to prevent the
208
- // the SINGLE_COMMAND_CLI_SYMBOL from being displayed in the help output.
209
- command.id = '';
210
- }
211
204
  if (command.hasDynamicHelp && command.pluginType !== 'jit') {
212
205
  const loaded = await command.load();
213
206
  for (const [name, flag] of Object.entries(loaded.flags ?? {})) {
@@ -96,7 +96,6 @@ export interface Config {
96
96
  * example: /home/myuser
97
97
  */
98
98
  readonly home: string;
99
- readonly isSingleCommandCLI: boolean;
100
99
  readonly name: string;
101
100
  /**
102
101
  * npm registry to use for installing plugins
@@ -16,84 +16,6 @@ export interface PJSON {
16
16
  };
17
17
  version: string;
18
18
  }
19
- export type CommandDiscovery = {
20
- /**
21
- * The strategy to use for loading commands.
22
- *
23
- * - `pattern` will use glob patterns to find command files in the specified `target`.
24
- * - `explicit` will use `import` (or `require` for CJS) to load the commands from the
25
- * specified `target`.
26
- * - `single` will use the `target` which should export a command class. This is for CLIs that
27
- * only have a single command.
28
- *
29
- * In both cases, the `oclif.manifest.json` file will be used to find the commands if it exists.
30
- */
31
- strategy: 'pattern' | 'explicit' | 'single';
32
- /**
33
- * If the `strategy` is `pattern`, this is the **directory** to use to find command files.
34
- *
35
- * If the `strategy` is `explicit`, this is the **file** that exports the commands.
36
- * - This export must be an object with keys that are the command names and values that are the command classes.
37
- * - Unless `identifier` is specified, the default export will be used.
38
- *
39
- * @example
40
- * ```typescript
41
- * // in src/commands.ts
42
- * import Hello from './commands/hello/index.js'
43
- * import HelloWorld from './commands/hello/world.js'
44
- *
45
- * export default {
46
- * hello: Hello,
47
- * 'hello:world': HelloWorld,
48
- * }
49
- * ```
50
- */
51
- target: string;
52
- /**
53
- * The glob patterns to use to find command files when no `oclif.manifest.json` is present.
54
- * This is only used when `strategy` is `pattern`.
55
- */
56
- globPatterns?: string[];
57
- /**
58
- * The name of the export to used when loading the command object from the `target` file. Only
59
- * used when `strategy` is `explicit`. Defaults to `default`.
60
- *
61
- * @example
62
- * ```typescript
63
- * // in src/commands.ts
64
- * import Hello from './commands/hello/index.js'
65
- * import HelloWorld from './commands/hello/world.js'
66
- *
67
- * export const MY_COMMANDS = {
68
- * hello: Hello,
69
- * 'hello:world': HelloWorld,
70
- * }
71
- * ```
72
- *
73
- * In the package.json:
74
- * ```json
75
- * {
76
- * "oclif": {
77
- * "commands": {
78
- * "strategy": "explicit",
79
- * "target": "./dist/index.js",
80
- * "identifier": "MY_COMMANDS"
81
- * }
82
- * }
83
- * ```
84
- */
85
- identifier?: string;
86
- };
87
- export type HookOptions = {
88
- /**
89
- * The file path containing hook.
90
- */
91
- target: string;
92
- /**
93
- * The name of the export to use when loading the hook function from the `target` file. Defaults to `default`.
94
- */
95
- identifier: string;
96
- };
97
19
  export declare namespace PJSON {
98
20
  interface Plugin extends PJSON {
99
21
  name: string;
@@ -103,13 +25,7 @@ export declare namespace PJSON {
103
25
  aliases?: {
104
26
  [name: string]: null | string;
105
27
  };
106
- commands?: string | CommandDiscovery;
107
- /**
108
- * Default command id when no command is found. This is used to support single command CLIs.
109
- * Only supported value is "."
110
- *
111
- * @deprecated Use `commands.strategy: 'single'` instead.
112
- */
28
+ commands?: string;
113
29
  default?: string;
114
30
  description?: string;
115
31
  devPlugins?: string[];
@@ -126,7 +42,7 @@ export declare namespace PJSON {
126
42
  helpClass?: string;
127
43
  helpOptions?: HelpOptions;
128
44
  hooks?: {
129
- [name: string]: string | string[] | HookOptions | HookOptions[];
45
+ [name: string]: string | string[];
130
46
  };
131
47
  jitPlugins?: Record<string, string>;
132
48
  macos?: {
@@ -1,5 +1,5 @@
1
1
  import { Command } from '../command';
2
- import { HookOptions, PJSON } from './pjson';
2
+ import { PJSON } from './pjson';
3
3
  import { Topic } from './topic';
4
4
  export interface PluginOptions {
5
5
  children?: Plugin[];
@@ -44,7 +44,7 @@ export interface Plugin {
44
44
  }): Promise<Command.Class> | undefined;
45
45
  readonly hasManifest: boolean;
46
46
  hooks: {
47
- [key: string]: HookOptions[];
47
+ [k: string]: string[];
48
48
  };
49
49
  /**
50
50
  * True if the plugin is the root plugin.
package/lib/main.js CHANGED
@@ -6,10 +6,9 @@ const cli_ux_1 = require("./cli-ux");
6
6
  const config_1 = require("./config");
7
7
  const help_1 = require("./help");
8
8
  const performance_1 = require("./performance");
9
- const symbols_1 = require("./symbols");
10
9
  const debug = require('debug')('oclif:main');
11
10
  const helpAddition = (argv, config) => {
12
- if (argv.length === 0 && !config.isSingleCommandCLI)
11
+ if (argv.length === 0 && !config.pjson.oclif.default)
13
12
  return true;
14
13
  const mergedHelpFlags = (0, help_1.getHelpFlagAdditions)(config);
15
14
  for (const arg of argv) {
@@ -48,11 +47,7 @@ async function run(argv, options) {
48
47
  options = (0, node_url_1.fileURLToPath)(options);
49
48
  }
50
49
  const config = await config_1.Config.load(options ?? require.main?.filename ?? __dirname);
51
- // If this is a single command CLI, then insert the SINGLE_COMMAND_CLI_SYMBOL into the argv array to serve as the command id.
52
- if (config.isSingleCommandCLI) {
53
- argv = [symbols_1.SINGLE_COMMAND_CLI_SYMBOL, ...argv];
54
- }
55
- const [id, ...argvSlice] = (0, help_1.normalizeArgv)(config, argv);
50
+ let [id, ...argvSlice] = (0, help_1.normalizeArgv)(config, argv);
56
51
  // run init hook
57
52
  await config.runHook('init', { argv: argvSlice, id });
58
53
  // display version if applicable
@@ -75,8 +70,17 @@ async function run(argv, options) {
75
70
  const topic = config.flexibleTaxonomy ? null : config.findTopic(id);
76
71
  if (topic)
77
72
  return config.runCommand('help', [id]);
73
+ if (config.pjson.oclif.default) {
74
+ id = config.pjson.oclif.default;
75
+ argvSlice = argv;
76
+ }
78
77
  }
79
78
  initMarker?.stop();
79
+ // If the the default command is '.' (signifying that the CLI is a single command CLI) and '.' is provided
80
+ // as an argument, we need to add back the '.' to argv since it was stripped out earlier as part of the
81
+ // command id.
82
+ if (config.pjson.oclif.default === '.' && id === '.' && argv[0] === '.')
83
+ argvSlice = ['.', ...argvSlice];
80
84
  try {
81
85
  return await config.runCommand(id, argvSlice, cmd);
82
86
  }
package/lib/util/fs.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export declare function requireJson<T>(...pathParts: string[]): T;
1
2
  /**
2
3
  * Parser for Args.directory and Flags.directory. Checks that the provided path
3
4
  * exists and is a directory.
package/lib/util/fs.js CHANGED
@@ -1,8 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.existsSync = exports.safeReadJson = exports.readJsonSync = exports.readJson = exports.fileExists = exports.dirExists = void 0;
3
+ exports.existsSync = exports.safeReadJson = exports.readJsonSync = exports.readJson = exports.fileExists = exports.dirExists = exports.requireJson = void 0;
4
4
  const node_fs_1 = require("node:fs");
5
5
  const promises_1 = require("node:fs/promises");
6
+ const node_path_1 = require("node:path");
7
+ function requireJson(...pathParts) {
8
+ return JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(...pathParts), 'utf8'));
9
+ }
10
+ exports.requireJson = requireJson;
6
11
  /**
7
12
  * Parser for Args.directory and Flags.directory. Checks that the provided path
8
13
  * exists and is a directory.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@oclif/core",
3
3
  "description": "base library for oclif CLIs",
4
- "version": "3.19.5-dev.0",
4
+ "version": "3.19.5",
5
5
  "author": "Salesforce",
6
6
  "bugs": "https://github.com/oclif/core/issues",
7
7
  "dependencies": {
@@ -114,6 +114,7 @@
114
114
  "access": "public"
115
115
  },
116
116
  "scripts": {
117
+ "build:dev": "shx rm -rf lib && tsc --sourceMap",
117
118
  "build": "shx rm -rf lib && tsc",
118
119
  "commitlint": "commitlint",
119
120
  "compile": "tsc",
@@ -126,8 +127,9 @@
126
127
  "test:circular-deps": "madge lib/ -c",
127
128
  "test:debug": "nyc mocha --debug-brk --inspect \"test/**/*.test.ts\"",
128
129
  "test:integration": "mocha --forbid-only \"test/**/*.integration.ts\" --parallel --timeout 1200000",
129
- "test:interoperability": "cross-env DEBUG=integration:* ts-node test/integration/interop.ts",
130
+ "test:esm-cjs": "cross-env DEBUG=integration:* ts-node test/integration/esm-cjs.ts",
130
131
  "test:perf": "ts-node test/perf/parser.perf.ts",
132
+ "test:dev": "nyc mocha \"test/**/*.test.ts\"",
131
133
  "test": "nyc mocha --forbid-only \"test/**/*.test.ts\""
132
134
  },
133
135
  "types": "lib/index.d.ts"
package/lib/symbols.d.ts DELETED
@@ -1 +0,0 @@
1
- export declare const SINGLE_COMMAND_CLI_SYMBOL: string;
package/lib/symbols.js DELETED
@@ -1,4 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SINGLE_COMMAND_CLI_SYMBOL = void 0;
4
- exports.SINGLE_COMMAND_CLI_SYMBOL = Symbol('SINGLE_COMMAND_CLI').toString();