@oclif/core 3.0.0-beta.1 → 3.0.0-beta.3
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/README.md +9 -7
- package/lib/command.d.ts +2 -0
- package/lib/command.js +4 -4
- package/lib/config/config.d.ts +9 -12
- package/lib/config/config.js +90 -137
- package/lib/config/index.d.ts +2 -1
- package/lib/config/index.js +2 -1
- package/lib/config/plugin-loader.d.ts +30 -0
- package/lib/config/plugin-loader.js +129 -0
- package/lib/config/plugin.d.ts +5 -10
- package/lib/config/plugin.js +21 -17
- package/lib/config/ts-node.d.ts +3 -2
- package/lib/config/ts-node.js +83 -36
- package/lib/errors/config.js +5 -5
- package/lib/errors/errors/cli.d.ts +1 -0
- package/lib/errors/errors/cli.js +1 -0
- package/lib/errors/handle.d.ts +2 -2
- package/lib/errors/handle.js +4 -5
- package/lib/errors/index.d.ts +2 -1
- package/lib/errors/index.js +9 -2
- package/lib/errors/logger.js +3 -3
- package/lib/execute.d.ts +49 -0
- package/lib/execute.js +62 -0
- package/lib/flags.js +6 -4
- package/lib/help/index.js +3 -3
- package/lib/index.d.ts +9 -7
- package/lib/index.js +13 -19
- package/lib/interfaces/config.d.ts +26 -26
- package/lib/interfaces/parser.d.ts +14 -66
- package/lib/interfaces/pjson.d.ts +2 -0
- package/lib/interfaces/plugin.d.ts +8 -1
- package/lib/interfaces/ts-config.d.ts +9 -0
- package/lib/main.d.ts +1 -54
- package/lib/main.js +11 -73
- package/lib/module-loader.d.ts +1 -2
- package/lib/module-loader.js +9 -9
- package/lib/parser/errors.js +1 -1
- package/lib/parser/parse.js +1 -34
- package/lib/performance.d.ts +1 -1
- package/lib/performance.js +2 -3
- package/lib/screen.js +2 -2
- package/lib/settings.d.ts +2 -1
- package/lib/settings.js +2 -2
- package/lib/{cli-ux → ux}/action/base.js +2 -2
- package/lib/{cli-ux → ux}/action/spinner.js +1 -1
- package/lib/{cli-ux → ux}/config.d.ts +0 -1
- package/lib/{cli-ux → ux}/config.js +6 -10
- package/lib/{cli-ux → ux}/exit.d.ts +1 -1
- package/lib/{cli-ux → ux}/exit.js +1 -1
- package/lib/ux/flush.d.ts +1 -0
- package/lib/ux/flush.js +27 -0
- package/lib/{cli-ux → ux}/index.d.ts +8 -27
- package/lib/{cli-ux → ux}/index.js +21 -80
- package/lib/{cli-ux → ux}/prompt.js +2 -2
- package/lib/{cli-ux → ux}/styled/json.js +3 -3
- package/package.json +24 -19
- package/flush.d.ts +0 -3
- package/flush.js +0 -1
- package/handle.js +0 -1
- package/lib/cli-ux/action/pride-spinner.d.ts +0 -4
- package/lib/cli-ux/action/pride-spinner.js +0 -30
- /package/lib/{cli-ux → ux}/action/base.d.ts +0 -0
- /package/lib/{cli-ux → ux}/action/simple.d.ts +0 -0
- /package/lib/{cli-ux → ux}/action/simple.js +0 -0
- /package/lib/{cli-ux → ux}/action/spinner.d.ts +0 -0
- /package/lib/{cli-ux → ux}/action/spinners.d.ts +0 -0
- /package/lib/{cli-ux → ux}/action/spinners.js +0 -0
- /package/lib/{cli-ux → ux}/list.d.ts +0 -0
- /package/lib/{cli-ux → ux}/list.js +0 -0
- /package/lib/{cli-ux → ux}/prompt.d.ts +0 -0
- /package/lib/{cli-ux → ux}/stream.d.ts +0 -0
- /package/lib/{cli-ux → ux}/stream.js +0 -0
- /package/lib/{cli-ux → ux}/styled/index.d.ts +0 -0
- /package/lib/{cli-ux → ux}/styled/index.js +0 -0
- /package/lib/{cli-ux → ux}/styled/json.d.ts +0 -0
- /package/lib/{cli-ux → ux}/styled/object.d.ts +0 -0
- /package/lib/{cli-ux → ux}/styled/object.js +0 -0
- /package/lib/{cli-ux → ux}/styled/progress.d.ts +0 -0
- /package/lib/{cli-ux → ux}/styled/progress.js +0 -0
- /package/lib/{cli-ux → ux}/styled/table.d.ts +0 -0
- /package/lib/{cli-ux → ux}/styled/table.js +0 -0
- /package/lib/{cli-ux → ux}/styled/tree.d.ts +0 -0
- /package/lib/{cli-ux → ux}/styled/tree.js +0 -0
- /package/lib/{cli-ux → ux}/wait.d.ts +0 -0
- /package/lib/{cli-ux → ux}/wait.js +0 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const Plugin = require("./plugin");
|
|
5
|
+
const util_1 = require("./util");
|
|
6
|
+
const util_2 = require("../util");
|
|
7
|
+
const performance_1 = require("../performance");
|
|
8
|
+
// eslint-disable-next-line new-cap
|
|
9
|
+
const debug = (0, util_1.Debug)();
|
|
10
|
+
class PluginLoader {
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.options = options;
|
|
13
|
+
this.plugins = new Map();
|
|
14
|
+
this.errors = [];
|
|
15
|
+
this.pluginsProvided = false;
|
|
16
|
+
if (options.plugins) {
|
|
17
|
+
this.pluginsProvided = true;
|
|
18
|
+
this.plugins = Array.isArray(options.plugins) ? new Map(options.plugins.map(p => [p.name, p])) : options.plugins;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async loadRoot() {
|
|
22
|
+
let rootPlugin;
|
|
23
|
+
if (this.pluginsProvided) {
|
|
24
|
+
const plugins = [...this.plugins.values()];
|
|
25
|
+
rootPlugin = plugins.find(p => p.root === this.options.root) ?? plugins[0];
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
rootPlugin = new Plugin.Plugin({ root: this.options.root });
|
|
29
|
+
await rootPlugin.load();
|
|
30
|
+
}
|
|
31
|
+
this.plugins.set(rootPlugin.name, rootPlugin);
|
|
32
|
+
return rootPlugin;
|
|
33
|
+
}
|
|
34
|
+
async loadChildren(opts) {
|
|
35
|
+
if (!this.pluginsProvided || opts.force) {
|
|
36
|
+
await this.loadUserPlugins(opts);
|
|
37
|
+
await this.loadDevPlugins(opts);
|
|
38
|
+
await this.loadCorePlugins(opts);
|
|
39
|
+
}
|
|
40
|
+
return { plugins: this.plugins, errors: this.errors };
|
|
41
|
+
}
|
|
42
|
+
async loadCorePlugins(opts) {
|
|
43
|
+
if (opts.rootPlugin.pjson.oclif.plugins) {
|
|
44
|
+
await this.loadPlugins(opts.rootPlugin.root, 'core', opts.rootPlugin.pjson.oclif.plugins);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async loadDevPlugins(opts) {
|
|
48
|
+
if (opts.devPlugins !== false) {
|
|
49
|
+
// do not load oclif.devPlugins in production
|
|
50
|
+
if ((0, util_2.isProd)())
|
|
51
|
+
return;
|
|
52
|
+
try {
|
|
53
|
+
const devPlugins = opts.rootPlugin.pjson.oclif.devPlugins;
|
|
54
|
+
if (devPlugins)
|
|
55
|
+
await this.loadPlugins(opts.rootPlugin.root, 'dev', devPlugins);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
process.emitWarning(error);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async loadUserPlugins(opts) {
|
|
63
|
+
if (opts.userPlugins !== false) {
|
|
64
|
+
try {
|
|
65
|
+
const userPJSONPath = path.join(opts.dataDir, 'package.json');
|
|
66
|
+
debug('reading user plugins pjson %s', userPJSONPath);
|
|
67
|
+
const pjson = await (0, util_1.loadJSON)(userPJSONPath);
|
|
68
|
+
if (!pjson.oclif)
|
|
69
|
+
pjson.oclif = { schema: 1 };
|
|
70
|
+
if (!pjson.oclif.plugins)
|
|
71
|
+
pjson.oclif.plugins = [];
|
|
72
|
+
await this.loadPlugins(userPJSONPath, 'user', pjson.oclif.plugins.filter((p) => p.type === 'user'));
|
|
73
|
+
await this.loadPlugins(userPJSONPath, 'link', pjson.oclif.plugins.filter((p) => p.type === 'link'));
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (error.code !== 'ENOENT')
|
|
77
|
+
process.emitWarning(error);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async loadPlugins(root, type, plugins, parent) {
|
|
82
|
+
if (!plugins || plugins.length === 0)
|
|
83
|
+
return;
|
|
84
|
+
const mark = performance_1.default.mark(`config.loadPlugins#${type}`);
|
|
85
|
+
debug('loading plugins', plugins);
|
|
86
|
+
await Promise.all((plugins || []).map(async (plugin) => {
|
|
87
|
+
try {
|
|
88
|
+
const name = typeof plugin === 'string' ? plugin : plugin.name;
|
|
89
|
+
const opts = {
|
|
90
|
+
name,
|
|
91
|
+
type,
|
|
92
|
+
root,
|
|
93
|
+
};
|
|
94
|
+
if (typeof plugin !== 'string') {
|
|
95
|
+
opts.tag = plugin.tag || opts.tag;
|
|
96
|
+
opts.root = plugin.root || opts.root;
|
|
97
|
+
}
|
|
98
|
+
if (this.plugins.has(name))
|
|
99
|
+
return;
|
|
100
|
+
const pluginMarker = performance_1.default.mark(`plugin.load#${name}`);
|
|
101
|
+
const instance = new Plugin.Plugin(opts);
|
|
102
|
+
await instance.load();
|
|
103
|
+
pluginMarker?.addDetails({
|
|
104
|
+
hasManifest: instance.hasManifest,
|
|
105
|
+
commandCount: instance.commands.length,
|
|
106
|
+
topicCount: instance.topics.length,
|
|
107
|
+
type: instance.type,
|
|
108
|
+
usesMain: Boolean(instance.pjson.main),
|
|
109
|
+
name: instance.name,
|
|
110
|
+
});
|
|
111
|
+
pluginMarker?.stop();
|
|
112
|
+
this.plugins.set(instance.name, instance);
|
|
113
|
+
if (parent) {
|
|
114
|
+
instance.parent = parent;
|
|
115
|
+
if (!parent.children)
|
|
116
|
+
parent.children = [];
|
|
117
|
+
parent.children.push(instance);
|
|
118
|
+
}
|
|
119
|
+
await this.loadPlugins(instance.root, type, instance.pjson.oclif.plugins || [], instance);
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
this.errors.push(error);
|
|
123
|
+
}
|
|
124
|
+
}));
|
|
125
|
+
mark?.addDetails({ pluginCount: plugins.length });
|
|
126
|
+
mark?.stop();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
exports.default = PluginLoader;
|
package/lib/config/plugin.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { CLIError } from '../errors';
|
|
2
1
|
import { Plugin as IPlugin, PluginOptions } from '../interfaces/plugin';
|
|
3
2
|
import { Manifest } from '../interfaces/manifest';
|
|
4
3
|
import { PJSON } from '../interfaces/pjson';
|
|
@@ -11,6 +10,7 @@ export declare class Plugin implements IPlugin {
|
|
|
11
10
|
version: string;
|
|
12
11
|
pjson: PJSON.Plugin;
|
|
13
12
|
type: string;
|
|
13
|
+
moduleType: 'module' | 'commonjs';
|
|
14
14
|
root: string;
|
|
15
15
|
alias: string;
|
|
16
16
|
tag?: string;
|
|
@@ -25,16 +25,11 @@ export declare class Plugin implements IPlugin {
|
|
|
25
25
|
children: Plugin[];
|
|
26
26
|
hasManifest: boolean;
|
|
27
27
|
private _commandsDir;
|
|
28
|
+
private flexibleTaxonomy;
|
|
28
29
|
protected _debug: (..._: any) => void;
|
|
29
30
|
protected warned: boolean;
|
|
30
31
|
constructor(options: PluginOptions);
|
|
31
|
-
|
|
32
|
-
* Loads a plugin
|
|
33
|
-
* @param isWritingManifest - if true, exclude selected data from manifest
|
|
34
|
-
* default is false to maintain backwards compatibility
|
|
35
|
-
* @returns Promise<void>
|
|
36
|
-
*/
|
|
37
|
-
load(isWritingManifest?: boolean): Promise<void>;
|
|
32
|
+
load(): Promise<void>;
|
|
38
33
|
get topics(): Topic[];
|
|
39
34
|
get commandsDir(): string | undefined;
|
|
40
35
|
get commandIDs(): string[];
|
|
@@ -44,7 +39,7 @@ export declare class Plugin implements IPlugin {
|
|
|
44
39
|
findCommand(id: string, opts?: {
|
|
45
40
|
must: boolean;
|
|
46
41
|
}): Promise<Command.Class | undefined>;
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
private _manifest;
|
|
43
|
+
private warn;
|
|
49
44
|
private addErrorScope;
|
|
50
45
|
}
|
package/lib/config/plugin.js
CHANGED
|
@@ -90,7 +90,6 @@ async function findRoot(name, root) {
|
|
|
90
90
|
class Plugin {
|
|
91
91
|
constructor(options) {
|
|
92
92
|
this.options = options;
|
|
93
|
-
// static loadedPlugins: {[name: string]: Plugin} = {}
|
|
94
93
|
this._base = `${_pjson.name}@${_pjson.version}`;
|
|
95
94
|
this.valid = false;
|
|
96
95
|
this.alreadyLoaded = false;
|
|
@@ -100,26 +99,22 @@ class Plugin {
|
|
|
100
99
|
this._debug = (0, util_2.Debug)();
|
|
101
100
|
this.warned = false;
|
|
102
101
|
}
|
|
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) {
|
|
102
|
+
async load() {
|
|
110
103
|
this.type = this.options.type || 'core';
|
|
111
104
|
this.tag = this.options.tag;
|
|
112
105
|
const root = await findRoot(this.options.name, this.options.root);
|
|
113
106
|
if (!root)
|
|
114
|
-
throw new
|
|
107
|
+
throw new errors_1.CLIError(`could not find package.json with ${(0, util_1.inspect)(this.options)}`);
|
|
115
108
|
this.root = root;
|
|
116
109
|
this._debug('reading %s plugin %s', this.type, root);
|
|
117
110
|
this.pjson = await (0, util_3.loadJSON)(path.join(root, 'package.json'));
|
|
111
|
+
this.flexibleTaxonomy = this.options?.flexibleTaxonomy || this.pjson.oclif?.flexibleTaxonomy || false;
|
|
112
|
+
this.moduleType = this.pjson.type === 'module' ? 'module' : 'commonjs';
|
|
118
113
|
this.name = this.pjson.name;
|
|
119
114
|
this.alias = this.options.name ?? this.pjson.name;
|
|
120
115
|
const pjsonPath = path.join(root, 'package.json');
|
|
121
116
|
if (!this.name)
|
|
122
|
-
throw new
|
|
117
|
+
throw new errors_1.CLIError(`no name in ${pjsonPath}`);
|
|
123
118
|
if (!(0, util_4.isProd)() && !this.pjson.files)
|
|
124
119
|
this.warn(`files attribute must be specified in ${pjsonPath}`);
|
|
125
120
|
// eslint-disable-next-line new-cap
|
|
@@ -132,7 +127,7 @@ class Plugin {
|
|
|
132
127
|
this.pjson.oclif = this.pjson['cli-engine'] || {};
|
|
133
128
|
}
|
|
134
129
|
this.hooks = (0, util_3.mapValues)(this.pjson.oclif.hooks || {}, i => Array.isArray(i) ? i : [i]);
|
|
135
|
-
this.manifest = await this._manifest(
|
|
130
|
+
this.manifest = await this._manifest();
|
|
136
131
|
this.commands = Object
|
|
137
132
|
.entries(this.manifest.commands)
|
|
138
133
|
.map(([id, c]) => ({
|
|
@@ -149,13 +144,13 @@ class Plugin {
|
|
|
149
144
|
get commandsDir() {
|
|
150
145
|
if (this._commandsDir)
|
|
151
146
|
return this._commandsDir;
|
|
152
|
-
this._commandsDir = (0, ts_node_1.tsPath)(this.root, this.pjson.oclif.commands, this
|
|
147
|
+
this._commandsDir = (0, ts_node_1.tsPath)(this.root, this.pjson.oclif.commands, this);
|
|
153
148
|
return this._commandsDir;
|
|
154
149
|
}
|
|
155
150
|
get commandIDs() {
|
|
156
151
|
if (!this.commandsDir)
|
|
157
152
|
return [];
|
|
158
|
-
const marker = performance_1.
|
|
153
|
+
const marker = performance_1.default.mark(`plugin.commandIDs#${this.name}`, { plugin: this.name });
|
|
159
154
|
this._debug(`loading IDs from ${this.commandsDir}`);
|
|
160
155
|
const patterns = [
|
|
161
156
|
'**/*.+(js|cjs|mjs|ts|tsx)',
|
|
@@ -175,7 +170,7 @@ class Plugin {
|
|
|
175
170
|
return ids;
|
|
176
171
|
}
|
|
177
172
|
async findCommand(id, opts = {}) {
|
|
178
|
-
const marker = performance_1.
|
|
173
|
+
const marker = performance_1.default.mark(`plugin.findCommand#${this.name}.${id}`, { id, plugin: this.name });
|
|
179
174
|
const fetch = async () => {
|
|
180
175
|
if (!this.commandsDir)
|
|
181
176
|
return;
|
|
@@ -211,7 +206,10 @@ class Plugin {
|
|
|
211
206
|
marker?.stop();
|
|
212
207
|
return cmd;
|
|
213
208
|
}
|
|
214
|
-
async _manifest(
|
|
209
|
+
async _manifest() {
|
|
210
|
+
const ignoreManifest = Boolean(this.options.ignoreManifest);
|
|
211
|
+
const errorOnManifestCreate = Boolean(this.options.errorOnManifestCreate);
|
|
212
|
+
const respectNoCacheDefault = Boolean(this.options.respectNoCacheDefault);
|
|
215
213
|
const readManifest = async (dotfile = false) => {
|
|
216
214
|
try {
|
|
217
215
|
const p = path.join(this.root, `${dotfile ? '.' : ''}oclif.manifest.json`);
|
|
@@ -235,7 +233,7 @@ class Plugin {
|
|
|
235
233
|
}
|
|
236
234
|
}
|
|
237
235
|
};
|
|
238
|
-
const marker = performance_1.
|
|
236
|
+
const marker = performance_1.default.mark(`plugin.manifest#${this.name}`, { plugin: this.name });
|
|
239
237
|
if (!ignoreManifest) {
|
|
240
238
|
const manifest = await readManifest();
|
|
241
239
|
if (manifest) {
|
|
@@ -248,7 +246,13 @@ class Plugin {
|
|
|
248
246
|
version: this.version,
|
|
249
247
|
commands: (await Promise.all(this.commandIDs.map(async (id) => {
|
|
250
248
|
try {
|
|
251
|
-
|
|
249
|
+
const cached = await (0, config_1.toCached)(await this.findCommand(id, { must: true }), this, respectNoCacheDefault);
|
|
250
|
+
if (this.flexibleTaxonomy) {
|
|
251
|
+
const permutations = (0, util_2.getCommandIdPermutations)(id);
|
|
252
|
+
const aliasPermutations = cached.aliases.flatMap(a => (0, util_2.getCommandIdPermutations)(a));
|
|
253
|
+
return [id, { ...cached, permutations, aliasPermutations }];
|
|
254
|
+
}
|
|
255
|
+
return [id, cached];
|
|
252
256
|
}
|
|
253
257
|
catch (error) {
|
|
254
258
|
const scope = 'toCached';
|
package/lib/config/ts-node.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { Plugin } from '../interfaces';
|
|
1
2
|
/**
|
|
2
3
|
* Convert a path from the compiled ./lib files to the ./src typescript source
|
|
3
4
|
* this is for developing typescript plugins/CLIs
|
|
4
5
|
* if there is a tsconfig and the original sources exist, it attempts to require ts-node
|
|
5
6
|
*/
|
|
6
|
-
export declare function tsPath(root: string, orig: string,
|
|
7
|
-
export declare function tsPath(root: string, orig: string | undefined,
|
|
7
|
+
export declare function tsPath(root: string, orig: string, plugin: Plugin): string;
|
|
8
|
+
export declare function tsPath(root: string, orig: string | undefined, plugin?: Plugin): string | undefined;
|
package/lib/config/ts-node.js
CHANGED
|
@@ -6,11 +6,15 @@ const path = require("path");
|
|
|
6
6
|
const settings_1 = require("../settings");
|
|
7
7
|
const util_1 = require("../util");
|
|
8
8
|
const util_2 = require("./util");
|
|
9
|
+
const config_1 = require("./config");
|
|
10
|
+
const errors_1 = require("../errors");
|
|
9
11
|
// eslint-disable-next-line new-cap
|
|
10
12
|
const debug = (0, util_2.Debug)('ts-node');
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
+
const TS_CONFIGS = {};
|
|
14
|
+
const REGISTERED = new Set();
|
|
13
15
|
function loadTSConfig(root) {
|
|
16
|
+
if (TS_CONFIGS[root])
|
|
17
|
+
return TS_CONFIGS[root];
|
|
14
18
|
const tsconfigPath = path.join(root, 'tsconfig.json');
|
|
15
19
|
let typescript;
|
|
16
20
|
try {
|
|
@@ -18,7 +22,7 @@ function loadTSConfig(root) {
|
|
|
18
22
|
}
|
|
19
23
|
catch {
|
|
20
24
|
try {
|
|
21
|
-
typescript = require(root
|
|
25
|
+
typescript = require(path.join(root, 'node_modules', 'typescript'));
|
|
22
26
|
}
|
|
23
27
|
catch { }
|
|
24
28
|
}
|
|
@@ -28,6 +32,7 @@ function loadTSConfig(root) {
|
|
|
28
32
|
throw new Error(`Could not read and parse tsconfig.json at ${tsconfigPath}, or it ` +
|
|
29
33
|
'did not contain a "compilerOptions" section.');
|
|
30
34
|
}
|
|
35
|
+
TS_CONFIGS[root] = tsconfig;
|
|
31
36
|
return tsconfig;
|
|
32
37
|
}
|
|
33
38
|
}
|
|
@@ -35,54 +40,96 @@ function registerTSNode(root) {
|
|
|
35
40
|
const tsconfig = loadTSConfig(root);
|
|
36
41
|
if (!tsconfig)
|
|
37
42
|
return;
|
|
43
|
+
if (REGISTERED.has(root))
|
|
44
|
+
return tsconfig;
|
|
38
45
|
debug('registering ts-node at', root);
|
|
39
46
|
const tsNodePath = require.resolve('ts-node', { paths: [root, __dirname] });
|
|
47
|
+
debug('ts-node path:', tsNodePath);
|
|
40
48
|
const tsNode = require(tsNodePath);
|
|
41
|
-
|
|
49
|
+
const typeRoots = [
|
|
50
|
+
path.join(root, 'node_modules', '@types'),
|
|
51
|
+
];
|
|
52
|
+
const rootDirs = [];
|
|
42
53
|
if (tsconfig.compilerOptions.rootDirs) {
|
|
43
|
-
|
|
54
|
+
for (const r of tsconfig.compilerOptions.rootDirs) {
|
|
55
|
+
rootDirs.push(path.join(root, r));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else if (tsconfig.compilerOptions.rootDir) {
|
|
59
|
+
rootDirs.push(path.join(root, tsconfig.compilerOptions.rootDir));
|
|
44
60
|
}
|
|
45
61
|
else {
|
|
46
|
-
|
|
62
|
+
rootDirs.push(path.join(root, 'src'));
|
|
47
63
|
}
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
const conf = {
|
|
65
|
+
compilerOptions: {
|
|
66
|
+
esModuleInterop: tsconfig.compilerOptions.esModuleInterop,
|
|
67
|
+
target: tsconfig.compilerOptions.target ?? 'es2019',
|
|
68
|
+
experimentalDecorators: tsconfig.compilerOptions.experimentalDecorators ?? false,
|
|
69
|
+
emitDecoratorMetadata: tsconfig.compilerOptions.emitDecoratorMetadata ?? false,
|
|
70
|
+
module: tsconfig.compilerOptions.module ?? 'commonjs',
|
|
71
|
+
sourceMap: tsconfig.compilerOptions.sourceMap ?? true,
|
|
72
|
+
rootDirs,
|
|
73
|
+
typeRoots,
|
|
74
|
+
},
|
|
75
|
+
skipProject: true,
|
|
76
|
+
transpileOnly: true,
|
|
77
|
+
esm: tsconfig['ts-node']?.esm ?? true,
|
|
78
|
+
scope: true,
|
|
79
|
+
scopeDir: root,
|
|
80
|
+
cwd: root,
|
|
81
|
+
experimentalSpecifierResolution: tsconfig['ts-node']?.experimentalSpecifierResolution ?? 'explicit',
|
|
82
|
+
};
|
|
83
|
+
if (tsconfig.compilerOptions.moduleResolution) {
|
|
84
|
+
// @ts-expect-error TSNode.RegisterOptions.compilerOptions is typed as a plain object
|
|
85
|
+
conf.compilerOptions.moduleResolution = tsconfig.compilerOptions.moduleResolution;
|
|
67
86
|
}
|
|
68
|
-
|
|
69
|
-
|
|
87
|
+
if (tsconfig.compilerOptions.jsx) {
|
|
88
|
+
// @ts-expect-error TSNode.RegisterOptions.compilerOptions is typed as a plain object
|
|
89
|
+
conf.compilerOptions.jsx = tsconfig.compilerOptions.jsx;
|
|
70
90
|
}
|
|
91
|
+
tsNode.register(conf);
|
|
92
|
+
REGISTERED.add(root);
|
|
93
|
+
return tsconfig;
|
|
71
94
|
}
|
|
72
|
-
|
|
95
|
+
// eslint-disable-next-line complexity
|
|
96
|
+
function tsPath(root, orig, plugin) {
|
|
73
97
|
if (!orig)
|
|
74
98
|
return orig;
|
|
75
99
|
orig = orig.startsWith(root) ? orig : path.join(root, orig);
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
//
|
|
82
|
-
if (
|
|
100
|
+
// NOTE: The order of these checks matter!
|
|
101
|
+
if (settings_1.default.tsnodeEnabled === false) {
|
|
102
|
+
debug(`Skipping ts-node registration for ${root} because tsNodeEnabled is explicitly set to false`);
|
|
103
|
+
return orig;
|
|
104
|
+
}
|
|
105
|
+
// Skip ts-node registration if plugin is an ESM plugin executing from a CJS plugin
|
|
106
|
+
if (plugin?.moduleType === 'module' && config_1.Config.rootPlugin?.moduleType === 'commonjs') {
|
|
107
|
+
debug(`Skipping ts-node registration for ${root} because it's an ESM module but the root plugin is CommonJS`);
|
|
108
|
+
if (plugin.type === 'link')
|
|
109
|
+
(0, errors_1.memoizedWarn)(`${plugin.name} is a linked ESM module and cannot be auto-compiled from a CommonJS root plugin. Existing compiled source will be used instead.`);
|
|
83
110
|
return orig;
|
|
111
|
+
}
|
|
112
|
+
// If plugin is an ESM plugin being executed from an ESM root plugin, check to see if ts-node/esm loader has been set
|
|
113
|
+
// either in the NODE_OPTIONS env var or from the exec args. If the ts-node/esm loader has NOT been loaded then we want
|
|
114
|
+
// to skip ts-node registration so that it falls back on the compiled source.
|
|
115
|
+
if (plugin?.moduleType === 'module') {
|
|
116
|
+
const tsNodeEsmLoaderInExecArgv = process.execArgv.includes('--loader') && process.execArgv.includes('ts-node/esm');
|
|
117
|
+
const tsNodeEsmLoaderInNodeOptions = process.env.NODE_OPTIONS?.includes('--loader=ts-node/esm') ?? false;
|
|
118
|
+
if (!tsNodeEsmLoaderInExecArgv && !tsNodeEsmLoaderInNodeOptions) {
|
|
119
|
+
debug(`Skipping ts-node registration for ${root} because it's an ESM module but the ts-node/esm loader hasn't been run`);
|
|
120
|
+
debug('try setting NODE_OPTIONS="--loader ts-node/esm" in your environment.');
|
|
121
|
+
if (plugin.type === 'link') {
|
|
122
|
+
(0, errors_1.memoizedWarn)(`${plugin.name} is a linked ESM module and cannot be auto-compiled without setting NODE_OPTIONS="--loader=ts-node/esm" in the environment. Existing compiled source will be used instead.`);
|
|
123
|
+
}
|
|
124
|
+
return orig;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (settings_1.default.tsnodeEnabled === undefined && (0, util_1.isProd)() && plugin?.type !== 'link') {
|
|
128
|
+
debug(`Skipping ts-node registration for ${root} because NODE_ENV is NOT "test" or "development"`);
|
|
129
|
+
return orig;
|
|
130
|
+
}
|
|
84
131
|
try {
|
|
85
|
-
const tsconfig =
|
|
132
|
+
const tsconfig = registerTSNode(root);
|
|
86
133
|
if (!tsconfig)
|
|
87
134
|
return orig;
|
|
88
135
|
const { rootDir, rootDirs, outDir } = tsconfig.compilerOptions;
|
package/lib/errors/config.js
CHANGED
|
@@ -15,24 +15,24 @@ function displayWarnings() {
|
|
|
15
15
|
exports.config = {
|
|
16
16
|
errorLogger: undefined,
|
|
17
17
|
get debug() {
|
|
18
|
-
return Boolean(settings_1.
|
|
18
|
+
return Boolean(settings_1.default.debug);
|
|
19
19
|
},
|
|
20
20
|
set debug(enabled) {
|
|
21
|
-
settings_1.
|
|
21
|
+
settings_1.default.debug = enabled;
|
|
22
22
|
if (enabled)
|
|
23
23
|
displayWarnings();
|
|
24
24
|
},
|
|
25
25
|
get errlog() {
|
|
26
|
-
return settings_1.
|
|
26
|
+
return settings_1.default.errlog;
|
|
27
27
|
},
|
|
28
28
|
set errlog(errlog) {
|
|
29
29
|
if (errlog) {
|
|
30
30
|
this.errorLogger = new logger_1.Logger(errlog);
|
|
31
|
-
settings_1.
|
|
31
|
+
settings_1.default.errlog = errlog;
|
|
32
32
|
}
|
|
33
33
|
else {
|
|
34
34
|
delete this.errorLogger;
|
|
35
|
-
delete settings_1.
|
|
35
|
+
delete settings_1.default.errlog;
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
};
|
|
@@ -8,6 +8,7 @@ export declare function addOclifExitCode(error: Record<string, any>, options?: {
|
|
|
8
8
|
export declare class CLIError extends Error implements OclifError {
|
|
9
9
|
oclif: OclifError['oclif'];
|
|
10
10
|
code?: string;
|
|
11
|
+
suggestions?: string[];
|
|
11
12
|
constructor(error: string | Error, options?: {
|
|
12
13
|
exit?: number | false;
|
|
13
14
|
} & PrettyPrintableError);
|
package/lib/errors/errors/cli.js
CHANGED
package/lib/errors/handle.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { OclifError, PrettyPrintableError } from '../interfaces';
|
|
2
|
-
export
|
|
2
|
+
export default function handle(err: Error & Partial<PrettyPrintableError> & Partial<OclifError> & {
|
|
3
3
|
skipOclifErrorHandling?: boolean;
|
|
4
|
-
})
|
|
4
|
+
}): Promise<void>;
|
package/lib/errors/handle.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handle = void 0;
|
|
4
3
|
/* eslint-disable no-process-exit */
|
|
5
4
|
/* eslint-disable unicorn/no-process-exit */
|
|
6
5
|
const config_1 = require("./config");
|
|
@@ -8,7 +7,7 @@ const pretty_print_1 = require("./errors/pretty-print");
|
|
|
8
7
|
const _1 = require(".");
|
|
9
8
|
const clean = require("clean-stack");
|
|
10
9
|
const cli_1 = require("./errors/cli");
|
|
11
|
-
|
|
10
|
+
async function handle(err) {
|
|
12
11
|
try {
|
|
13
12
|
if (!err)
|
|
14
13
|
err = new cli_1.CLIError('no error?');
|
|
@@ -25,7 +24,7 @@ const handle = (err) => {
|
|
|
25
24
|
if (stack) {
|
|
26
25
|
config_1.config.errorLogger.log(stack);
|
|
27
26
|
}
|
|
28
|
-
config_1.config.errorLogger.flush()
|
|
27
|
+
await config_1.config.errorLogger.flush()
|
|
29
28
|
.then(() => process.exit(exitCode))
|
|
30
29
|
.catch(console.error);
|
|
31
30
|
}
|
|
@@ -37,5 +36,5 @@ const handle = (err) => {
|
|
|
37
36
|
console.error(error.stack);
|
|
38
37
|
process.exit(1);
|
|
39
38
|
}
|
|
40
|
-
}
|
|
41
|
-
exports.
|
|
39
|
+
}
|
|
40
|
+
exports.default = handle;
|
package/lib/errors/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { handle } from './handle';
|
|
1
|
+
export { default as handle } from './handle';
|
|
2
2
|
export { ExitError } from './errors/exit';
|
|
3
3
|
export { ModuleLoadError } from './errors/module-load';
|
|
4
4
|
export { CLIError } from './errors/cli';
|
|
@@ -14,3 +14,4 @@ export declare function error(input: string | Error, options?: {
|
|
|
14
14
|
exit?: number;
|
|
15
15
|
} & PrettyPrintableError): never;
|
|
16
16
|
export declare function warn(input: string | Error): void;
|
|
17
|
+
export declare function memoizedWarn(input: string | Error): void;
|
package/lib/errors/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.warn = exports.error = exports.exit = exports.config = exports.Logger = exports.CLIError = exports.ModuleLoadError = exports.ExitError = exports.handle = void 0;
|
|
3
|
+
exports.memoizedWarn = exports.warn = exports.error = exports.exit = exports.config = exports.Logger = exports.CLIError = exports.ModuleLoadError = exports.ExitError = exports.handle = void 0;
|
|
4
4
|
var handle_1 = require("./handle");
|
|
5
|
-
Object.defineProperty(exports, "handle", { enumerable: true, get: function () { return handle_1.
|
|
5
|
+
Object.defineProperty(exports, "handle", { enumerable: true, get: function () { return handle_1.default; } });
|
|
6
6
|
var exit_1 = require("./errors/exit");
|
|
7
7
|
Object.defineProperty(exports, "ExitError", { enumerable: true, get: function () { return exit_1.ExitError; } });
|
|
8
8
|
var module_load_1 = require("./errors/module-load");
|
|
@@ -60,3 +60,10 @@ function warn(input) {
|
|
|
60
60
|
config_2.config.errorLogger.log(err?.stack ?? '');
|
|
61
61
|
}
|
|
62
62
|
exports.warn = warn;
|
|
63
|
+
const WARNINGS = new Set();
|
|
64
|
+
function memoizedWarn(input) {
|
|
65
|
+
if (!WARNINGS.has(input))
|
|
66
|
+
warn(input);
|
|
67
|
+
WARNINGS.add(input);
|
|
68
|
+
}
|
|
69
|
+
exports.memoizedWarn = memoizedWarn;
|
package/lib/errors/logger.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Logger = void 0;
|
|
4
|
-
const fs = require("fs
|
|
5
|
-
const
|
|
4
|
+
const fs = require("fs/promises");
|
|
5
|
+
const path_1 = require("path");
|
|
6
6
|
const stripAnsi = require("strip-ansi");
|
|
7
7
|
const timestamp = () => new Date().toISOString();
|
|
8
8
|
let timer;
|
|
@@ -35,7 +35,7 @@ class Logger {
|
|
|
35
35
|
return;
|
|
36
36
|
const mylines = this.buffer;
|
|
37
37
|
this.buffer = [];
|
|
38
|
-
await fs.
|
|
38
|
+
await fs.mkdir((0, path_1.dirname)(this.file), { recursive: true });
|
|
39
39
|
await fs.appendFile(this.file, mylines.join('\n') + '\n');
|
|
40
40
|
});
|
|
41
41
|
await this.flushing;
|
package/lib/execute.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as Interfaces from './interfaces';
|
|
2
|
+
/**
|
|
3
|
+
* Load and run oclif CLI
|
|
4
|
+
*
|
|
5
|
+
* @param options - options to load the CLI
|
|
6
|
+
* @returns Promise<void>
|
|
7
|
+
*
|
|
8
|
+
* @example For ESM dev.js
|
|
9
|
+
* ```
|
|
10
|
+
* #!/usr/bin/env node
|
|
11
|
+
* void (async () => {
|
|
12
|
+
* const oclif = await import('@oclif/core')
|
|
13
|
+
* await oclif.execute({development: true, dir: import.meta.url})
|
|
14
|
+
* })()
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @example For ESM run.js
|
|
18
|
+
* ```
|
|
19
|
+
* #!/usr/bin/env node
|
|
20
|
+
* void (async () => {
|
|
21
|
+
* const oclif = await import('@oclif/core')
|
|
22
|
+
* await oclif.execute({dir: import.meta.url})
|
|
23
|
+
* })()
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @example For CJS dev.js
|
|
27
|
+
* ```
|
|
28
|
+
* #!/usr/bin/env node
|
|
29
|
+
* void (async () => {
|
|
30
|
+
* const oclif = await import('@oclif/core')
|
|
31
|
+
* await oclif.execute({development: true, dir: __dirname})
|
|
32
|
+
* })()
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @example For CJS run.js
|
|
36
|
+
* ```
|
|
37
|
+
* #!/usr/bin/env node
|
|
38
|
+
* void (async () => {
|
|
39
|
+
* const oclif = await import('@oclif/core')
|
|
40
|
+
* await oclif.execute({dir: __dirname})
|
|
41
|
+
* })()
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export default function execute(options: {
|
|
45
|
+
dir: string;
|
|
46
|
+
args?: string[];
|
|
47
|
+
loadOptions?: Interfaces.LoadOptions;
|
|
48
|
+
development?: boolean;
|
|
49
|
+
}): Promise<unknown>;
|