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

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,3 +1,3 @@
1
- export { Config, toCached } from './config';
1
+ export { Config } from './config';
2
2
  export { Plugin } from './plugin';
3
3
  export { tsPath } from './ts-node';
@@ -1,9 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.tsPath = exports.Plugin = exports.toCached = exports.Config = void 0;
3
+ exports.tsPath = exports.Plugin = exports.Config = void 0;
4
4
  var config_1 = require("./config");
5
5
  Object.defineProperty(exports, "Config", { enumerable: true, get: function () { return config_1.Config; } });
6
- Object.defineProperty(exports, "toCached", { enumerable: true, get: function () { return config_1.toCached; } });
7
6
  var plugin_1 = require("./plugin");
8
7
  Object.defineProperty(exports, "Plugin", { enumerable: true, get: function () { return plugin_1.Plugin; } });
9
8
  var ts_node_1 = require("./ts-node");
@@ -0,0 +1,30 @@
1
+ import { Plugin as IPlugin } from '../interfaces/plugin';
2
+ type PluginLoaderOptions = {
3
+ root: string;
4
+ plugins?: IPlugin[] | PluginsMap;
5
+ };
6
+ type LoadOpts = {
7
+ devPlugins?: boolean;
8
+ userPlugins?: boolean;
9
+ dataDir: string;
10
+ rootPlugin: IPlugin;
11
+ force?: boolean;
12
+ };
13
+ type PluginsMap = Map<string, IPlugin>;
14
+ export default class PluginLoader {
15
+ options: PluginLoaderOptions;
16
+ plugins: PluginsMap;
17
+ errors: (string | Error)[];
18
+ private pluginsProvided;
19
+ constructor(options: PluginLoaderOptions);
20
+ loadRoot(): Promise<IPlugin>;
21
+ loadChildren(opts: LoadOpts): Promise<{
22
+ plugins: PluginsMap;
23
+ errors: (string | Error)[];
24
+ }>;
25
+ private loadCorePlugins;
26
+ private loadDevPlugins;
27
+ private loadUserPlugins;
28
+ private loadPlugins;
29
+ }
30
+ export {};
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const Plugin = tslib_1.__importStar(require("./plugin"));
5
+ const util_1 = require("./util");
6
+ const performance_1 = require("../performance");
7
+ const util_2 = require("../util/util");
8
+ const node_path_1 = require("node:path");
9
+ const fs_1 = require("../util/fs");
10
+ // eslint-disable-next-line new-cap
11
+ const debug = (0, util_1.Debug)();
12
+ class PluginLoader {
13
+ options;
14
+ plugins = new Map();
15
+ errors = [];
16
+ pluginsProvided = false;
17
+ constructor(options) {
18
+ this.options = options;
19
+ if (options.plugins) {
20
+ this.pluginsProvided = true;
21
+ this.plugins = Array.isArray(options.plugins) ? new Map(options.plugins.map((p) => [p.name, p])) : options.plugins;
22
+ }
23
+ }
24
+ async loadRoot() {
25
+ let rootPlugin;
26
+ if (this.pluginsProvided) {
27
+ const plugins = [...this.plugins.values()];
28
+ rootPlugin = plugins.find((p) => p.root === this.options.root) ?? plugins[0];
29
+ }
30
+ else {
31
+ const marker = performance_1.Performance.mark('plugin.load#root');
32
+ rootPlugin = new Plugin.Plugin({ root: this.options.root, isRoot: true });
33
+ await rootPlugin.load();
34
+ marker?.addDetails({
35
+ hasManifest: rootPlugin.hasManifest ?? false,
36
+ commandCount: rootPlugin.commands.length,
37
+ topicCount: rootPlugin.topics.length,
38
+ type: rootPlugin.type,
39
+ usesMain: Boolean(rootPlugin.pjson.main),
40
+ name: rootPlugin.name,
41
+ });
42
+ marker?.stop();
43
+ }
44
+ this.plugins.set(rootPlugin.name, rootPlugin);
45
+ return rootPlugin;
46
+ }
47
+ async loadChildren(opts) {
48
+ if (!this.pluginsProvided || opts.force) {
49
+ await this.loadUserPlugins(opts);
50
+ await this.loadDevPlugins(opts);
51
+ await this.loadCorePlugins(opts);
52
+ }
53
+ return { plugins: this.plugins, errors: this.errors };
54
+ }
55
+ async loadCorePlugins(opts) {
56
+ if (opts.rootPlugin.pjson.oclif.plugins) {
57
+ await this.loadPlugins(opts.rootPlugin.root, 'core', opts.rootPlugin.pjson.oclif.plugins);
58
+ }
59
+ }
60
+ async loadDevPlugins(opts) {
61
+ if (opts.devPlugins !== false) {
62
+ // do not load oclif.devPlugins in production
63
+ if ((0, util_2.isProd)())
64
+ return;
65
+ try {
66
+ const { devPlugins } = opts.rootPlugin.pjson.oclif;
67
+ if (devPlugins)
68
+ await this.loadPlugins(opts.rootPlugin.root, 'dev', devPlugins);
69
+ }
70
+ catch (error) {
71
+ process.emitWarning(error);
72
+ }
73
+ }
74
+ }
75
+ async loadUserPlugins(opts) {
76
+ if (opts.userPlugins !== false) {
77
+ try {
78
+ const userPJSONPath = (0, node_path_1.join)(opts.dataDir, 'package.json');
79
+ debug('reading user plugins pjson %s', userPJSONPath);
80
+ const pjson = await (0, fs_1.readJson)(userPJSONPath);
81
+ if (!pjson.oclif)
82
+ pjson.oclif = { schema: 1 };
83
+ if (!pjson.oclif.plugins)
84
+ pjson.oclif.plugins = [];
85
+ await this.loadPlugins(userPJSONPath, 'user', pjson.oclif.plugins.filter((p) => p.type === 'user'));
86
+ await this.loadPlugins(userPJSONPath, 'link', pjson.oclif.plugins.filter((p) => p.type === 'link'));
87
+ }
88
+ catch (error) {
89
+ if (error.code !== 'ENOENT')
90
+ process.emitWarning(error);
91
+ }
92
+ }
93
+ }
94
+ async loadPlugins(root, type, plugins, parent) {
95
+ if (!plugins || plugins.length === 0)
96
+ return;
97
+ const mark = performance_1.Performance.mark(`config.loadPlugins#${type}`);
98
+ debug('loading plugins', plugins);
99
+ await Promise.all((plugins || []).map(async (plugin) => {
100
+ try {
101
+ const name = typeof plugin === 'string' ? plugin : plugin.name;
102
+ const opts = {
103
+ name,
104
+ type,
105
+ root,
106
+ };
107
+ if (typeof plugin !== 'string') {
108
+ opts.tag = plugin.tag || opts.tag;
109
+ opts.root = plugin.root || opts.root;
110
+ }
111
+ if (parent) {
112
+ opts.parent = parent;
113
+ }
114
+ if (this.plugins.has(name))
115
+ return;
116
+ const pluginMarker = performance_1.Performance.mark(`plugin.load#${name}`);
117
+ const instance = new Plugin.Plugin(opts);
118
+ await instance.load();
119
+ pluginMarker?.addDetails({
120
+ hasManifest: instance.hasManifest,
121
+ commandCount: instance.commands.length,
122
+ topicCount: instance.topics.length,
123
+ type: instance.type,
124
+ usesMain: Boolean(instance.pjson.main),
125
+ name: instance.name,
126
+ });
127
+ pluginMarker?.stop();
128
+ this.plugins.set(instance.name, instance);
129
+ if (parent) {
130
+ instance.parent = parent;
131
+ if (!parent.children)
132
+ parent.children = [];
133
+ parent.children.push(instance);
134
+ }
135
+ await this.loadPlugins(instance.root, type, instance.pjson.oclif.plugins || [], instance);
136
+ }
137
+ catch (error) {
138
+ this.errors.push(error);
139
+ }
140
+ }));
141
+ mark?.addDetails({ pluginCount: plugins.length });
142
+ mark?.stop();
143
+ }
144
+ }
145
+ exports.default = PluginLoader;
@@ -1,9 +1,8 @@
1
- import { CLIError } from '../errors';
2
1
  import { Plugin as IPlugin, PluginOptions } from '../interfaces/plugin';
2
+ import { Command } from '../command';
3
3
  import { Manifest } from '../interfaces/manifest';
4
4
  import { PJSON } from '../interfaces/pjson';
5
5
  import { Topic } from '../interfaces/topic';
6
- import { Command } from '../command';
7
6
  export declare class Plugin implements IPlugin {
8
7
  options: PluginOptions;
9
8
  _base: string;
@@ -25,17 +24,13 @@ export declare class Plugin implements IPlugin {
25
24
  parent: Plugin | undefined;
26
25
  children: Plugin[];
27
26
  hasManifest: boolean;
27
+ isRoot: boolean;
28
28
  private _commandsDir;
29
+ private flexibleTaxonomy;
29
30
  protected _debug: (..._: any) => void;
30
31
  protected warned: boolean;
31
32
  constructor(options: PluginOptions);
32
- /**
33
- * Loads a plugin
34
- * @param isWritingManifest - if true, exclude selected data from manifest
35
- * default is false to maintain backwards compatibility
36
- * @returns Promise<void>
37
- */
38
- load(isWritingManifest?: boolean): Promise<void>;
33
+ load(): Promise<void>;
39
34
  get topics(): Topic[];
40
35
  get commandsDir(): string | undefined;
41
36
  get commandIDs(): string[];
@@ -45,7 +40,7 @@ export declare class Plugin implements IPlugin {
45
40
  findCommand(id: string, opts?: {
46
41
  must: boolean;
47
42
  }): Promise<Command.Class | undefined>;
48
- protected _manifest(ignoreManifest: boolean, errorOnManifestCreate?: boolean, isWritingManifest?: boolean): Promise<Manifest>;
49
- protected warn(err: string | Error | CLIError, scope?: string): void;
43
+ private _manifest;
44
+ private warn;
50
45
  private addErrorScope;
51
46
  }
@@ -2,43 +2,43 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Plugin = void 0;
4
4
  const errors_1 = require("../errors");
5
- const globby = require("globby");
6
- const path = require("path");
7
- const util_1 = require("util");
8
- const config_1 = require("./config");
9
- const util_2 = require("./util");
10
- const ts_node_1 = require("./ts-node");
11
- const util_3 = require("./util");
12
- const util_4 = require("../util");
5
+ const util_1 = require("./util");
6
+ const util_2 = require("../util/util");
7
+ const node_path_1 = require("node:path");
8
+ const fs_1 = require("../util/fs");
13
9
  const module_loader_1 = require("../module-loader");
14
10
  const performance_1 = require("../performance");
15
- const _pjson = (0, util_4.requireJson)(__dirname, '..', '..', 'package.json');
11
+ const cache_command_1 = require("../util/cache-command");
12
+ const node_util_1 = require("node:util");
13
+ const globby_1 = require("globby");
14
+ const ts_node_1 = require("./ts-node");
15
+ const _pjson = (0, fs_1.requireJson)(__dirname, '..', '..', 'package.json');
16
16
  function topicsToArray(input, base) {
17
17
  if (!input)
18
18
  return [];
19
19
  base = base ? `${base}:` : '';
20
20
  if (Array.isArray(input)) {
21
- return [...input, ...(0, util_3.flatMap)(input, t => topicsToArray(t.subtopics, `${base}${t.name}`))];
21
+ return [...input, input.flatMap((t) => topicsToArray(t.subtopics, `${base}${t.name}`))];
22
22
  }
23
- return (0, util_3.flatMap)(Object.keys(input), k => {
23
+ return Object.keys(input).flatMap((k) => {
24
24
  input[k].name = k;
25
25
  return [{ ...input[k], name: `${base}${k}` }, ...topicsToArray(input[k].subtopics, `${base}${input[k].name}`)];
26
26
  });
27
27
  }
28
28
  // essentially just "cd .."
29
29
  function* up(from) {
30
- while (path.dirname(from) !== from) {
30
+ while ((0, node_path_1.dirname)(from) !== from) {
31
31
  yield from;
32
- from = path.dirname(from);
32
+ from = (0, node_path_1.dirname)(from);
33
33
  }
34
34
  yield from;
35
35
  }
36
36
  async function findSourcesRoot(root) {
37
37
  for (const next of up(root)) {
38
- const cur = path.join(next, 'package.json');
38
+ const cur = (0, node_path_1.join)(next, 'package.json');
39
39
  // eslint-disable-next-line no-await-in-loop
40
- if (await (0, util_3.exists)(cur))
41
- return path.dirname(cur);
40
+ if (await (0, fs_1.exists)(cur))
41
+ return (0, node_path_1.dirname)(cur);
42
42
  }
43
43
  }
44
44
  /**
@@ -56,23 +56,23 @@ async function findRootLegacy(name, root) {
56
56
  for (const next of up(root)) {
57
57
  let cur;
58
58
  if (name) {
59
- cur = path.join(next, 'node_modules', name, 'package.json');
59
+ cur = (0, node_path_1.join)(next, 'node_modules', name, 'package.json');
60
60
  // eslint-disable-next-line no-await-in-loop
61
- if (await (0, util_3.exists)(cur))
62
- return path.dirname(cur);
61
+ if (await (0, fs_1.exists)(cur))
62
+ return (0, node_path_1.dirname)(cur);
63
63
  try {
64
64
  // eslint-disable-next-line no-await-in-loop
65
- const pkg = await (0, util_3.loadJSON)(path.join(next, 'package.json'));
65
+ const pkg = await (0, fs_1.readJson)((0, node_path_1.join)(next, 'package.json'));
66
66
  if (pkg.name === name)
67
67
  return next;
68
68
  }
69
69
  catch { }
70
70
  }
71
71
  else {
72
- cur = path.join(next, 'package.json');
72
+ cur = (0, node_path_1.join)(next, 'package.json');
73
73
  // eslint-disable-next-line no-await-in-loop
74
- if (await (0, util_3.exists)(cur))
75
- return path.dirname(cur);
74
+ if (await (0, fs_1.exists)(cur))
75
+ return (0, node_path_1.dirname)(cur);
76
76
  }
77
77
  }
78
78
  }
@@ -80,51 +80,75 @@ async function findRoot(name, root) {
80
80
  if (name) {
81
81
  let pkgPath;
82
82
  try {
83
- pkgPath = (0, util_3.resolvePackage)(name, { paths: [root] });
83
+ pkgPath = (0, util_1.resolvePackage)(name, { paths: [root] });
84
84
  }
85
85
  catch { }
86
- return pkgPath ? findSourcesRoot(path.dirname(pkgPath)) : findRootLegacy(name, root);
86
+ return pkgPath ? findSourcesRoot((0, node_path_1.dirname)(pkgPath)) : findRootLegacy(name, root);
87
87
  }
88
88
  return findSourcesRoot(root);
89
89
  }
90
+ const cachedCommandCanBeUsed = (manifest, id) => Boolean(manifest?.commands[id] && 'isESM' in manifest.commands[id] && 'relativePath' in manifest.commands[id]);
91
+ const search = (cmd) => {
92
+ if (typeof cmd.run === 'function')
93
+ return cmd;
94
+ if (cmd.default && cmd.default.run)
95
+ return cmd.default;
96
+ return Object.values(cmd).find((cmd) => typeof cmd.run === 'function');
97
+ };
90
98
  class Plugin {
99
+ options;
100
+ _base = `${_pjson.name}@${_pjson.version}`;
101
+ name;
102
+ version;
103
+ pjson;
104
+ type;
105
+ moduleType;
106
+ root;
107
+ alias;
108
+ tag;
109
+ manifest;
110
+ commands;
111
+ hooks;
112
+ valid = false;
113
+ alreadyLoaded = false;
114
+ parent;
115
+ children = [];
116
+ hasManifest = false;
117
+ isRoot = false;
118
+ _commandsDir;
119
+ flexibleTaxonomy;
120
+ // eslint-disable-next-line new-cap
121
+ _debug = (0, util_1.Debug)();
122
+ warned = false;
91
123
  constructor(options) {
92
124
  this.options = options;
93
- // static loadedPlugins: {[name: string]: Plugin} = {}
94
- this._base = `${_pjson.name}@${_pjson.version}`;
95
- this.valid = false;
96
- this.alreadyLoaded = false;
97
- this.children = [];
98
- this.hasManifest = false;
99
- // eslint-disable-next-line new-cap
100
- this._debug = (0, util_2.Debug)();
101
- this.warned = false;
102
125
  }
103
- /**
104
- * Loads a plugin
105
- * @param isWritingManifest - if true, exclude selected data from manifest
106
- * default is false to maintain backwards compatibility
107
- * @returns Promise<void>
108
- */
109
- async load(isWritingManifest) {
126
+ async load() {
110
127
  this.type = this.options.type || 'core';
111
128
  this.tag = this.options.tag;
112
- const root = await findRoot(this.options.name, this.options.root);
129
+ this.isRoot = this.options.isRoot ?? false;
130
+ if (this.options.parent)
131
+ this.parent = this.options.parent;
132
+ // Linked plugins already have a root so there's no need to search for it.
133
+ // However there could be child plugins nested inside the linked plugin, in which
134
+ // case we still need to search for the child plugin's root.
135
+ const root = this.type === 'link' && !this.parent ? this.options.root : await findRoot(this.options.name, this.options.root);
113
136
  if (!root)
114
- throw new Error(`could not find package.json with ${(0, util_1.inspect)(this.options)}`);
137
+ throw new errors_1.CLIError(`could not find package.json with ${(0, node_util_1.inspect)(this.options)}`);
115
138
  this.root = root;
116
139
  this._debug('reading %s plugin %s', this.type, root);
117
- this.pjson = await (0, util_3.loadJSON)(path.join(root, 'package.json'));
140
+ this.pjson = await (0, fs_1.readJson)((0, node_path_1.join)(root, 'package.json'));
141
+ this.flexibleTaxonomy = this.options?.flexibleTaxonomy || this.pjson.oclif?.flexibleTaxonomy || false;
118
142
  this.moduleType = this.pjson.type === 'module' ? 'module' : 'commonjs';
119
143
  this.name = this.pjson.name;
120
144
  this.alias = this.options.name ?? this.pjson.name;
121
- const pjsonPath = path.join(root, 'package.json');
145
+ const pjsonPath = (0, node_path_1.join)(root, 'package.json');
122
146
  if (!this.name)
123
- throw new Error(`no name in ${pjsonPath}`);
124
- if (!(0, util_4.isProd)() && !this.pjson.files)
147
+ throw new errors_1.CLIError(`no name in ${pjsonPath}`);
148
+ if (!(0, util_2.isProd)() && !this.pjson.files)
125
149
  this.warn(`files attribute must be specified in ${pjsonPath}`);
126
150
  // eslint-disable-next-line new-cap
127
- this._debug = (0, util_2.Debug)(this.name);
151
+ this._debug = (0, util_1.Debug)(this.name);
128
152
  this.version = this.pjson.version;
129
153
  if (this.pjson.oclif) {
130
154
  this.valid = true;
@@ -132,10 +156,9 @@ class Plugin {
132
156
  else {
133
157
  this.pjson.oclif = this.pjson['cli-engine'] || {};
134
158
  }
135
- this.hooks = (0, util_3.mapValues)(this.pjson.oclif.hooks || {}, i => Array.isArray(i) ? i : [i]);
136
- this.manifest = await this._manifest(Boolean(this.options.ignoreManifest), Boolean(this.options.errorOnManifestCreate), isWritingManifest);
137
- this.commands = Object
138
- .entries(this.manifest.commands)
159
+ this.hooks = (0, util_2.mapValues)(this.pjson.oclif.hooks || {}, (i) => (Array.isArray(i) ? i : [i]));
160
+ this.manifest = await this._manifest();
161
+ this.commands = Object.entries(this.manifest.commands)
139
162
  .map(([id, c]) => ({
140
163
  ...c,
141
164
  pluginAlias: this.alias,
@@ -158,16 +181,12 @@ class Plugin {
158
181
  return [];
159
182
  const marker = performance_1.Performance.mark(`plugin.commandIDs#${this.name}`, { plugin: this.name });
160
183
  this._debug(`loading IDs from ${this.commandsDir}`);
161
- const patterns = [
162
- '**/*.+(js|cjs|mjs|ts|tsx)',
163
- '!**/*.+(d.ts|test.ts|test.js|spec.ts|spec.js)?(x)',
164
- ];
165
- const ids = globby.sync(patterns, { cwd: this.commandsDir })
166
- .map(file => {
167
- const p = path.parse(file);
184
+ const patterns = ['**/*.+(js|cjs|mjs|ts|tsx)', '!**/*.+(d.ts|test.ts|test.js|spec.ts|spec.js)?(x)'];
185
+ const ids = (0, globby_1.sync)(patterns, { cwd: this.commandsDir }).map((file) => {
186
+ const p = (0, node_path_1.parse)(file);
168
187
  const topics = p.dir.split('/');
169
188
  const command = p.name !== 'index' && p.name;
170
- const id = [...topics, command].filter(f => f).join(':');
189
+ const id = [...topics, command].filter(Boolean).join(':');
171
190
  return id === '' ? '.' : id;
172
191
  });
173
192
  this._debug('found commands', ids);
@@ -180,30 +199,28 @@ class Plugin {
180
199
  const fetch = async () => {
181
200
  if (!this.commandsDir)
182
201
  return;
183
- const search = (cmd) => {
184
- if (typeof cmd.run === 'function')
185
- return cmd;
186
- if (cmd.default && cmd.default.run)
187
- return cmd.default;
188
- return Object.values(cmd).find((cmd) => typeof cmd.run === 'function');
189
- };
190
- let m;
202
+ let module;
203
+ let isESM;
204
+ let filePath;
191
205
  try {
192
- const p = path.join(this.commandsDir ?? this.pjson.oclif.commands, ...id.split(':'));
193
- const { isESM, module, filePath } = await module_loader_1.default.loadWithData(this, p);
206
+ ;
207
+ ({ isESM, module, filePath } = cachedCommandCanBeUsed(this.manifest, id)
208
+ ? await (0, module_loader_1.loadWithDataFromManifest)(this.manifest.commands[id], this.root)
209
+ : await (0, module_loader_1.loadWithData)(this, (0, node_path_1.join)(this.commandsDir ?? this.pjson.oclif.commands, ...id.split(':'))));
194
210
  this._debug(isESM ? '(import)' : '(require)', filePath);
195
- m = module;
196
211
  }
197
212
  catch (error) {
198
213
  if (!opts.must && error.code === 'MODULE_NOT_FOUND')
199
214
  return;
200
215
  throw error;
201
216
  }
202
- const cmd = search(m);
217
+ const cmd = search(module);
203
218
  if (!cmd)
204
219
  return;
205
220
  cmd.id = id;
206
221
  cmd.plugin = this;
222
+ cmd.isESM = isESM;
223
+ cmd.relativePath = (0, node_path_1.relative)(this.root, filePath || '').split(node_path_1.sep);
207
224
  return cmd;
208
225
  };
209
226
  const cmd = await fetch();
@@ -212,11 +229,14 @@ class Plugin {
212
229
  marker?.stop();
213
230
  return cmd;
214
231
  }
215
- async _manifest(ignoreManifest, errorOnManifestCreate = false, isWritingManifest = false) {
232
+ async _manifest() {
233
+ const ignoreManifest = Boolean(this.options.ignoreManifest);
234
+ const errorOnManifestCreate = Boolean(this.options.errorOnManifestCreate);
235
+ const respectNoCacheDefault = Boolean(this.options.respectNoCacheDefault);
216
236
  const readManifest = async (dotfile = false) => {
217
237
  try {
218
- const p = path.join(this.root, `${dotfile ? '.' : ''}oclif.manifest.json`);
219
- const manifest = await (0, util_3.loadJSON)(p);
238
+ const p = (0, node_path_1.join)(this.root, `${dotfile ? '.' : ''}oclif.manifest.json`);
239
+ const manifest = await (0, fs_1.readJson)(p);
220
240
  if (!process.env.OCLIF_NEXT_VERSION && manifest.version.split('-')[0] !== this.version.split('-')[0]) {
221
241
  process.emitWarning(`Mismatched version in ${this.name} plugin manifest. Expected: ${this.version} Received: ${manifest.version}\nThis usually means you have an oclif.manifest.json file that should be deleted in development. This file should be automatically generated when publishing.`);
222
242
  }
@@ -249,16 +269,23 @@ class Plugin {
249
269
  version: this.version,
250
270
  commands: (await Promise.all(this.commandIDs.map(async (id) => {
251
271
  try {
252
- return [id, await (0, config_1.toCached)(await this.findCommand(id, { must: true }), this, isWritingManifest)];
272
+ const cached = await (0, cache_command_1.cacheCommand)(await this.findCommand(id, { must: true }), this, respectNoCacheDefault);
273
+ if (this.flexibleTaxonomy) {
274
+ const permutations = (0, util_1.getCommandIdPermutations)(id);
275
+ const aliasPermutations = cached.aliases.flatMap((a) => (0, util_1.getCommandIdPermutations)(a));
276
+ return [id, { ...cached, permutations, aliasPermutations }];
277
+ }
278
+ return [id, cached];
253
279
  }
254
280
  catch (error) {
255
- const scope = 'toCached';
281
+ const scope = 'cacheCommand';
256
282
  if (Boolean(errorOnManifestCreate) === false)
257
283
  this.warn(error, scope);
258
284
  else
259
285
  throw this.addErrorScope(error, scope);
260
286
  }
261
287
  })))
288
+ // eslint-disable-next-line unicorn/no-await-expression-member, unicorn/prefer-native-coercion-functions
262
289
  .filter((f) => Boolean(f))
263
290
  .reduce((commands, [id, c]) => {
264
291
  commands[id] = c;
@@ -278,7 +305,14 @@ class Plugin {
278
305
  }
279
306
  addErrorScope(err, scope) {
280
307
  err.name = `${err.name} Plugin: ${this.name}`;
281
- err.detail = (0, util_3.compact)([err.detail, `module: ${this._base}`, scope && `task: ${scope}`, `plugin: ${this.name}`, `root: ${this.root}`, 'See more details with DEBUG=*']).join('\n');
308
+ err.detail = (0, util_2.compact)([
309
+ err.detail,
310
+ `module: ${this._base}`,
311
+ scope && `task: ${scope}`,
312
+ `plugin: ${this.name}`,
313
+ `root: ${this.root}`,
314
+ 'See more details with DEBUG=*',
315
+ ]).join('\n');
282
316
  return err;
283
317
  }
284
318
  }
@@ -1,4 +1,5 @@
1
- import { Plugin } from '../interfaces';
1
+ import { Plugin, TSConfig } from '../interfaces';
2
+ export declare const TS_CONFIGS: Record<string, TSConfig>;
2
3
  /**
3
4
  * Convert a path from the compiled ./lib files to the ./src typescript source
4
5
  * this is for developing typescript plugins/CLIs