@oclif/core 3.9.2 → 3.10.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.
- package/lib/config/plugin.d.ts +4 -3
- package/lib/config/plugin.js +42 -32
- package/lib/config/ts-node.d.ts +2 -2
- package/lib/config/ts-node.js +30 -40
- package/lib/errors/index.js +8 -2
- package/lib/interfaces/plugin.d.ts +1 -0
- package/lib/interfaces/ts-config.d.ts +2 -0
- package/lib/module-loader.js +5 -4
- package/lib/util/find-root.js +29 -5
- package/lib/util/fs.d.ts +1 -0
- package/lib/util/fs.js +8 -3
- package/package.json +3 -1
package/lib/config/plugin.d.ts
CHANGED
|
@@ -8,7 +8,9 @@ export declare class Plugin implements IPlugin {
|
|
|
8
8
|
alias: string;
|
|
9
9
|
alreadyLoaded: boolean;
|
|
10
10
|
children: Plugin[];
|
|
11
|
+
commandIDs: string[];
|
|
11
12
|
commands: Command.Loadable[];
|
|
13
|
+
commandsDir: string | undefined;
|
|
12
14
|
hasManifest: boolean;
|
|
13
15
|
hooks: {
|
|
14
16
|
[k: string]: string[];
|
|
@@ -26,12 +28,9 @@ export declare class Plugin implements IPlugin {
|
|
|
26
28
|
version: string;
|
|
27
29
|
protected warned: boolean;
|
|
28
30
|
_base: string;
|
|
29
|
-
private _commandsDir;
|
|
30
31
|
protected _debug: (..._: any) => void;
|
|
31
32
|
private flexibleTaxonomy;
|
|
32
33
|
constructor(options: PluginOptions);
|
|
33
|
-
get commandIDs(): string[];
|
|
34
|
-
get commandsDir(): string | undefined;
|
|
35
34
|
get topics(): Topic[];
|
|
36
35
|
findCommand(id: string, opts: {
|
|
37
36
|
must: true;
|
|
@@ -42,5 +41,7 @@ export declare class Plugin implements IPlugin {
|
|
|
42
41
|
load(): Promise<void>;
|
|
43
42
|
private _manifest;
|
|
44
43
|
private addErrorScope;
|
|
44
|
+
private getCommandIDs;
|
|
45
|
+
private getCommandsDir;
|
|
45
46
|
private warn;
|
|
46
47
|
}
|
package/lib/config/plugin.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.Plugin = void 0;
|
|
4
|
-
const globby_1 = require("globby");
|
|
7
|
+
const globby_1 = __importDefault(require("globby"));
|
|
5
8
|
const node_path_1 = require("node:path");
|
|
6
9
|
const node_util_1 = require("node:util");
|
|
7
10
|
const errors_1 = require("../errors");
|
|
@@ -34,12 +37,27 @@ const search = (cmd) => {
|
|
|
34
37
|
return cmd.default;
|
|
35
38
|
return Object.values(cmd).find((cmd) => typeof cmd.run === 'function');
|
|
36
39
|
};
|
|
40
|
+
const GLOB_PATTERNS = [
|
|
41
|
+
'**/*.+(js|cjs|mjs|ts|tsx|mts|cts)',
|
|
42
|
+
'!**/*.+(d.ts|test.ts|test.js|spec.ts|spec.js|d.mts|d.cts)?(x)',
|
|
43
|
+
];
|
|
44
|
+
function processCommandIds(files) {
|
|
45
|
+
return files.map((file) => {
|
|
46
|
+
const p = (0, node_path_1.parse)(file);
|
|
47
|
+
const topics = p.dir.split('/');
|
|
48
|
+
const command = p.name !== 'index' && p.name;
|
|
49
|
+
const id = [...topics, command].filter(Boolean).join(':');
|
|
50
|
+
return id === '' ? '.' : id;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
37
53
|
class Plugin {
|
|
38
54
|
options;
|
|
39
55
|
alias;
|
|
40
56
|
alreadyLoaded = false;
|
|
41
57
|
children = [];
|
|
58
|
+
commandIDs = [];
|
|
42
59
|
commands;
|
|
60
|
+
commandsDir;
|
|
43
61
|
hasManifest = false;
|
|
44
62
|
hooks;
|
|
45
63
|
isRoot = false;
|
|
@@ -55,40 +73,12 @@ class Plugin {
|
|
|
55
73
|
version;
|
|
56
74
|
warned = false;
|
|
57
75
|
_base = `${_pjson.name}@${_pjson.version}`;
|
|
58
|
-
_commandsDir;
|
|
59
76
|
// eslint-disable-next-line new-cap
|
|
60
77
|
_debug = (0, util_2.Debug)();
|
|
61
78
|
flexibleTaxonomy;
|
|
62
79
|
constructor(options) {
|
|
63
80
|
this.options = options;
|
|
64
81
|
}
|
|
65
|
-
get commandIDs() {
|
|
66
|
-
if (!this.commandsDir)
|
|
67
|
-
return [];
|
|
68
|
-
const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `plugin.commandIDs#${this.name}`, { plugin: this.name });
|
|
69
|
-
this._debug(`loading IDs from ${this.commandsDir}`);
|
|
70
|
-
const patterns = [
|
|
71
|
-
'**/*.+(js|cjs|mjs|ts|tsx|mts|cts)',
|
|
72
|
-
'!**/*.+(d.ts|test.ts|test.js|spec.ts|spec.js|d.mts|d.cts)?(x)',
|
|
73
|
-
];
|
|
74
|
-
const ids = (0, globby_1.sync)(patterns, { cwd: this.commandsDir }).map((file) => {
|
|
75
|
-
const p = (0, node_path_1.parse)(file);
|
|
76
|
-
const topics = p.dir.split('/');
|
|
77
|
-
const command = p.name !== 'index' && p.name;
|
|
78
|
-
const id = [...topics, command].filter(Boolean).join(':');
|
|
79
|
-
return id === '' ? '.' : id;
|
|
80
|
-
});
|
|
81
|
-
this._debug('found commands', ids);
|
|
82
|
-
marker?.addDetails({ count: ids.length });
|
|
83
|
-
marker?.stop();
|
|
84
|
-
return ids;
|
|
85
|
-
}
|
|
86
|
-
get commandsDir() {
|
|
87
|
-
if (this._commandsDir)
|
|
88
|
-
return this._commandsDir;
|
|
89
|
-
this._commandsDir = (0, ts_node_1.tsPath)(this.root, this.pjson.oclif.commands, this);
|
|
90
|
-
return this._commandsDir;
|
|
91
|
-
}
|
|
92
82
|
get topics() {
|
|
93
83
|
return topicsToArray(this.pjson.oclif.topics || {});
|
|
94
84
|
}
|
|
@@ -131,7 +121,7 @@ class Plugin {
|
|
|
131
121
|
return cmd;
|
|
132
122
|
}
|
|
133
123
|
async load() {
|
|
134
|
-
this.type = this.options.type
|
|
124
|
+
this.type = this.options.type ?? 'core';
|
|
135
125
|
this.tag = this.options.tag;
|
|
136
126
|
this.isRoot = this.options.isRoot ?? false;
|
|
137
127
|
if (this.options.parent)
|
|
@@ -143,7 +133,7 @@ class Plugin {
|
|
|
143
133
|
if (!root)
|
|
144
134
|
throw new errors_1.CLIError(`could not find package.json with ${(0, node_util_1.inspect)(this.options)}`);
|
|
145
135
|
this.root = root;
|
|
146
|
-
this._debug(
|
|
136
|
+
this._debug(`loading ${this.type} plugin from ${root}`);
|
|
147
137
|
this.pjson = await (0, fs_1.readJson)((0, node_path_1.join)(root, 'package.json'));
|
|
148
138
|
this.flexibleTaxonomy = this.options?.flexibleTaxonomy || this.pjson.oclif?.flexibleTaxonomy || false;
|
|
149
139
|
this.moduleType = this.pjson.type === 'module' ? 'module' : 'commonjs';
|
|
@@ -163,7 +153,12 @@ class Plugin {
|
|
|
163
153
|
else {
|
|
164
154
|
this.pjson.oclif = this.pjson['cli-engine'] || {};
|
|
165
155
|
}
|
|
166
|
-
this.
|
|
156
|
+
this.commandsDir = await this.getCommandsDir();
|
|
157
|
+
this.commandIDs = await this.getCommandIDs();
|
|
158
|
+
this.hooks = Object.fromEntries(await Promise.all(Object.entries(this.pjson.oclif.hooks ?? {}).map(async ([k, v]) => [
|
|
159
|
+
k,
|
|
160
|
+
await Promise.all((0, util_1.castArray)(v).map(async (i) => (0, ts_node_1.tsPath)(this.root, i, this))),
|
|
161
|
+
])));
|
|
167
162
|
this.manifest = await this._manifest();
|
|
168
163
|
this.commands = Object.entries(this.manifest.commands)
|
|
169
164
|
.map(([id, c]) => ({
|
|
@@ -253,6 +248,21 @@ class Plugin {
|
|
|
253
248
|
]).join('\n');
|
|
254
249
|
return err;
|
|
255
250
|
}
|
|
251
|
+
async getCommandIDs() {
|
|
252
|
+
if (!this.commandsDir)
|
|
253
|
+
return [];
|
|
254
|
+
const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `plugin.getCommandIDs#${this.name}`, { plugin: this.name });
|
|
255
|
+
this._debug(`loading IDs from ${this.commandsDir}`);
|
|
256
|
+
const files = await (0, globby_1.default)(GLOB_PATTERNS, { cwd: this.commandsDir });
|
|
257
|
+
const ids = processCommandIds(files);
|
|
258
|
+
this._debug('found commands', ids);
|
|
259
|
+
marker?.addDetails({ count: ids.length });
|
|
260
|
+
marker?.stop();
|
|
261
|
+
return ids;
|
|
262
|
+
}
|
|
263
|
+
async getCommandsDir() {
|
|
264
|
+
return (0, ts_node_1.tsPath)(this.root, this.pjson.oclif.commands, this);
|
|
265
|
+
}
|
|
256
266
|
warn(err, scope) {
|
|
257
267
|
if (this.warned)
|
|
258
268
|
return;
|
package/lib/config/ts-node.d.ts
CHANGED
|
@@ -5,5 +5,5 @@ export declare const TS_CONFIGS: Record<string, TSConfig>;
|
|
|
5
5
|
* this is for developing typescript plugins/CLIs
|
|
6
6
|
* if there is a tsconfig and the original sources exist, it attempts to require ts-node
|
|
7
7
|
*/
|
|
8
|
-
export declare function tsPath(root: string, orig: string, plugin: Plugin): string
|
|
9
|
-
export declare function tsPath(root: string, orig: string | undefined, plugin?: Plugin): string | undefined
|
|
8
|
+
export declare function tsPath(root: string, orig: string, plugin: Plugin): Promise<string>;
|
|
9
|
+
export declare function tsPath(root: string, orig: string | undefined, plugin?: Plugin): Promise<string | undefined>;
|
package/lib/config/ts-node.js
CHANGED
|
@@ -15,36 +15,25 @@ const util_2 = require("./util");
|
|
|
15
15
|
const debug = (0, util_2.Debug)('ts-node');
|
|
16
16
|
exports.TS_CONFIGS = {};
|
|
17
17
|
const REGISTERED = new Set();
|
|
18
|
-
function
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
let typescript;
|
|
18
|
+
function isErrno(error) {
|
|
19
|
+
return 'code' in error && error.code === 'ENOENT';
|
|
20
|
+
}
|
|
21
|
+
async function loadTSConfig(root) {
|
|
23
22
|
try {
|
|
24
|
-
|
|
23
|
+
if (exports.TS_CONFIGS[root])
|
|
24
|
+
return exports.TS_CONFIGS[root];
|
|
25
|
+
exports.TS_CONFIGS[root] = await (0, fs_1.readTSConfig)((0, node_path_1.join)(root, 'tsconfig.json'));
|
|
26
|
+
return exports.TS_CONFIGS[root];
|
|
25
27
|
}
|
|
26
|
-
catch {
|
|
27
|
-
|
|
28
|
-
typescript = require(require.resolve('typescript', { paths: [root, __dirname] }));
|
|
29
|
-
}
|
|
30
|
-
catch {
|
|
31
|
-
debug(`Could not find typescript dependency. Skipping ts-node registration for ${root}.`);
|
|
32
|
-
(0, errors_1.memoizedWarn)('Could not find typescript. Please ensure that typescript is a devDependency. Falling back to compiled source.');
|
|
28
|
+
catch (error) {
|
|
29
|
+
if (isErrno(error))
|
|
33
30
|
return;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if ((0, fs_1.existsSync)(tsconfigPath) && typescript) {
|
|
37
|
-
const tsconfig = typescript.parseConfigFileTextToJson(tsconfigPath, (0, fs_1.readJsonSync)(tsconfigPath, false)).config;
|
|
38
|
-
if (!tsconfig || !tsconfig.compilerOptions) {
|
|
39
|
-
throw new Error(`Could not read and parse tsconfig.json at ${tsconfigPath}, or it ` +
|
|
40
|
-
'did not contain a "compilerOptions" section.');
|
|
41
|
-
}
|
|
42
|
-
exports.TS_CONFIGS[root] = tsconfig;
|
|
43
|
-
return tsconfig;
|
|
31
|
+
debug(`Could not parse tsconfig.json. Skipping ts-node registration for ${root}.`);
|
|
32
|
+
(0, errors_1.memoizedWarn)(`Could not parse tsconfig.json for ${root}. Falling back to compiled source.`);
|
|
44
33
|
}
|
|
45
34
|
}
|
|
46
|
-
function registerTSNode(root) {
|
|
47
|
-
const tsconfig = loadTSConfig(root);
|
|
35
|
+
async function registerTSNode(root) {
|
|
36
|
+
const tsconfig = await loadTSConfig(root);
|
|
48
37
|
if (!tsconfig)
|
|
49
38
|
return;
|
|
50
39
|
if (REGISTERED.has(root))
|
|
@@ -71,24 +60,24 @@ function registerTSNode(root) {
|
|
|
71
60
|
else if (tsconfig.compilerOptions.rootDir) {
|
|
72
61
|
rootDirs.push((0, node_path_1.join)(root, tsconfig.compilerOptions.rootDir));
|
|
73
62
|
}
|
|
63
|
+
else if (tsconfig.compilerOptions.baseUrl) {
|
|
64
|
+
rootDirs.push((0, node_path_1.join)(root, tsconfig.compilerOptions.baseUrl));
|
|
65
|
+
}
|
|
74
66
|
else {
|
|
75
67
|
rootDirs.push((0, node_path_1.join)(root, 'src'));
|
|
76
68
|
}
|
|
69
|
+
// Because we need to provide a modified `rootDirs` to ts-node, we need to
|
|
70
|
+
// remove `baseUrl` and `rootDir` from `compilerOptions` so that they
|
|
71
|
+
// don't conflict.
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
73
|
+
const { baseUrl, rootDir, ...rest } = tsconfig.compilerOptions;
|
|
77
74
|
const conf = {
|
|
78
75
|
compilerOptions: {
|
|
79
|
-
|
|
80
|
-
esModuleInterop: tsconfig.compilerOptions.esModuleInterop,
|
|
81
|
-
experimentalDecorators: tsconfig.compilerOptions.experimentalDecorators ?? false,
|
|
82
|
-
module: tsconfig.compilerOptions.module ?? 'commonjs',
|
|
76
|
+
...rest,
|
|
83
77
|
rootDirs,
|
|
84
|
-
sourceMap: tsconfig.compilerOptions.sourceMap ?? true,
|
|
85
|
-
target: tsconfig.compilerOptions.target ?? 'es2019',
|
|
86
78
|
typeRoots,
|
|
87
|
-
...(tsconfig.compilerOptions.moduleResolution
|
|
88
|
-
? { moduleResolution: tsconfig.compilerOptions.moduleResolution }
|
|
89
|
-
: {}),
|
|
90
|
-
...(tsconfig.compilerOptions.jsx ? { jsx: tsconfig.compilerOptions.jsx } : {}),
|
|
91
79
|
},
|
|
80
|
+
...tsconfig['ts-node'],
|
|
92
81
|
cwd: root,
|
|
93
82
|
esm: tsconfig['ts-node']?.esm ?? true,
|
|
94
83
|
experimentalSpecifierResolution: tsconfig['ts-node']?.experimentalSpecifierResolution ?? 'explicit',
|
|
@@ -99,7 +88,8 @@ function registerTSNode(root) {
|
|
|
99
88
|
};
|
|
100
89
|
tsNode.register(conf);
|
|
101
90
|
REGISTERED.add(root);
|
|
102
|
-
debug('%O', tsconfig);
|
|
91
|
+
debug('tsconfig: %O', tsconfig);
|
|
92
|
+
debug('ts-node options: %O', conf);
|
|
103
93
|
return tsconfig;
|
|
104
94
|
}
|
|
105
95
|
/**
|
|
@@ -136,8 +126,8 @@ function cannotUseTsNode(root, plugin, isProduction) {
|
|
|
136
126
|
/**
|
|
137
127
|
* Determine the path to the source file from the compiled ./lib files
|
|
138
128
|
*/
|
|
139
|
-
function determinePath(root, orig) {
|
|
140
|
-
const tsconfig = registerTSNode(root);
|
|
129
|
+
async function determinePath(root, orig) {
|
|
130
|
+
const tsconfig = await registerTSNode(root);
|
|
141
131
|
if (!tsconfig)
|
|
142
132
|
return orig;
|
|
143
133
|
debug(`determining path for ${orig}`);
|
|
@@ -174,7 +164,7 @@ function determinePath(root, orig) {
|
|
|
174
164
|
(0, errors_1.memoizedWarn)(`Could not find source for ${orig} based on tsconfig. Defaulting to compiled source.`);
|
|
175
165
|
return orig;
|
|
176
166
|
}
|
|
177
|
-
function tsPath(root, orig, plugin) {
|
|
167
|
+
async function tsPath(root, orig, plugin) {
|
|
178
168
|
const rootPlugin = plugin?.options.isRoot ? plugin : cache_1.default.getInstance().get('rootPlugin');
|
|
179
169
|
if (!orig)
|
|
180
170
|
return orig;
|
|
@@ -204,7 +194,7 @@ function tsPath(root, orig, plugin) {
|
|
|
204
194
|
return orig;
|
|
205
195
|
}
|
|
206
196
|
try {
|
|
207
|
-
return determinePath(root, orig);
|
|
197
|
+
return await determinePath(root, orig);
|
|
208
198
|
}
|
|
209
199
|
catch (error) {
|
|
210
200
|
debug(error);
|
package/lib/errors/index.js
CHANGED
|
@@ -22,8 +22,12 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
25
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
29
|
exports.Logger = exports.memoizedWarn = exports.warn = exports.error = exports.exit = exports.handle = exports.ModuleLoadError = exports.ExitError = exports.CLIError = exports.config = void 0;
|
|
30
|
+
const write_1 = __importDefault(require("../cli-ux/write"));
|
|
27
31
|
const config_1 = require("./config");
|
|
28
32
|
const cli_1 = require("./errors/cli");
|
|
29
33
|
const exit_1 = require("./errors/exit");
|
|
@@ -56,7 +60,8 @@ function error(input, options = {}) {
|
|
|
56
60
|
err = (0, pretty_print_1.applyPrettyPrintOptions)(err, options);
|
|
57
61
|
if (options.exit === false) {
|
|
58
62
|
const message = (0, pretty_print_1.default)(err);
|
|
59
|
-
|
|
63
|
+
if (message)
|
|
64
|
+
write_1.default.stderr(message + '\n');
|
|
60
65
|
if (config_1.config.errorLogger)
|
|
61
66
|
config_1.config.errorLogger.log(err?.stack ?? '');
|
|
62
67
|
}
|
|
@@ -76,7 +81,8 @@ function warn(input) {
|
|
|
76
81
|
throw new TypeError('first argument must be a string or instance of Error');
|
|
77
82
|
}
|
|
78
83
|
const message = (0, pretty_print_1.default)(err);
|
|
79
|
-
|
|
84
|
+
if (message)
|
|
85
|
+
write_1.default.stderr(message + '\n');
|
|
80
86
|
if (config_1.config.errorLogger)
|
|
81
87
|
config_1.config.errorLogger.log(err?.stack ?? '');
|
|
82
88
|
}
|
package/lib/module-loader.js
CHANGED
|
@@ -35,7 +35,7 @@ async function load(config, modulePath) {
|
|
|
35
35
|
let isESM;
|
|
36
36
|
try {
|
|
37
37
|
;
|
|
38
|
-
({ filePath, isESM } = resolvePath(config, modulePath));
|
|
38
|
+
({ filePath, isESM } = await resolvePath(config, modulePath));
|
|
39
39
|
return (isESM ? await import((0, node_url_1.pathToFileURL)(filePath).href) : require(filePath));
|
|
40
40
|
}
|
|
41
41
|
catch (error) {
|
|
@@ -68,7 +68,7 @@ async function loadWithData(config, modulePath) {
|
|
|
68
68
|
let isESM;
|
|
69
69
|
try {
|
|
70
70
|
;
|
|
71
|
-
({ filePath, isESM } = resolvePath(config, modulePath));
|
|
71
|
+
({ filePath, isESM } = await resolvePath(config, modulePath));
|
|
72
72
|
const module = isESM ? await import((0, node_url_1.pathToFileURL)(filePath).href) : require(filePath);
|
|
73
73
|
return { filePath, isESM, module };
|
|
74
74
|
}
|
|
@@ -155,7 +155,7 @@ exports.isPathModule = isPathModule;
|
|
|
155
155
|
*
|
|
156
156
|
* @returns {{isESM: boolean, filePath: string}} An object including file path and whether the module is ESM.
|
|
157
157
|
*/
|
|
158
|
-
function resolvePath(config, modulePath) {
|
|
158
|
+
async function resolvePath(config, modulePath) {
|
|
159
159
|
let isESM;
|
|
160
160
|
let filePath;
|
|
161
161
|
try {
|
|
@@ -164,7 +164,8 @@ function resolvePath(config, modulePath) {
|
|
|
164
164
|
}
|
|
165
165
|
catch {
|
|
166
166
|
filePath =
|
|
167
|
-
(isPlugin(config) ? (0, ts_node_1.tsPath)(config.root, modulePath, config) : (0, ts_node_1.tsPath)(config.root, modulePath)) ??
|
|
167
|
+
(isPlugin(config) ? await (0, ts_node_1.tsPath)(config.root, modulePath, config) : await (0, ts_node_1.tsPath)(config.root, modulePath)) ??
|
|
168
|
+
modulePath;
|
|
168
169
|
let fileExists = false;
|
|
169
170
|
let isDirectory = false;
|
|
170
171
|
if ((0, fs_1.existsSync)(filePath)) {
|
package/lib/util/find-root.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.findRoot = void 0;
|
|
7
|
+
const debug_1 = __importDefault(require("debug"));
|
|
4
8
|
const node_path_1 = require("node:path");
|
|
5
9
|
const fs_1 = require("./fs");
|
|
10
|
+
const debug = (0, debug_1.default)('find-root');
|
|
6
11
|
// essentially just "cd .."
|
|
7
12
|
function* up(from) {
|
|
8
13
|
while ((0, node_path_1.dirname)(from) !== from) {
|
|
@@ -21,7 +26,9 @@ async function findPluginRoot(root, name) {
|
|
|
21
26
|
// If we know the plugin name then we just need to traverse the file
|
|
22
27
|
// system until we find the directory that matches the plugin name.
|
|
23
28
|
if (name) {
|
|
29
|
+
debug.extend(name)(`Finding root starting at ${root}`);
|
|
24
30
|
for (const next of up(root)) {
|
|
31
|
+
debug.extend(name)(`Checking ${next}`);
|
|
25
32
|
if (next.endsWith((0, node_path_1.basename)(name)))
|
|
26
33
|
return next;
|
|
27
34
|
}
|
|
@@ -36,6 +43,7 @@ async function findPluginRoot(root, name) {
|
|
|
36
43
|
}
|
|
37
44
|
try {
|
|
38
45
|
const cur = (0, node_path_1.join)(next, 'package.json');
|
|
46
|
+
debug.extend('root-plugin')(`Checking ${cur}`);
|
|
39
47
|
if (await (0, fs_1.safeReadJson)(cur))
|
|
40
48
|
return (0, node_path_1.dirname)(cur);
|
|
41
49
|
}
|
|
@@ -49,6 +57,7 @@ async function findPluginRoot(root, name) {
|
|
|
49
57
|
* See https://github.com/oclif/config/pull/289#issuecomment-983904051
|
|
50
58
|
*/
|
|
51
59
|
async function findRootLegacy(name, root) {
|
|
60
|
+
debug.extend(name ?? 'root-plugin')('Finding root using legacy method');
|
|
52
61
|
for (const next of up(root)) {
|
|
53
62
|
let cur;
|
|
54
63
|
if (name) {
|
|
@@ -94,6 +103,7 @@ function findPnpRoot(name, root) {
|
|
|
94
103
|
maybeRequirePnpApi(root);
|
|
95
104
|
if (!pnp)
|
|
96
105
|
return;
|
|
106
|
+
debug.extend(name)('Finding root for using pnp method');
|
|
97
107
|
const seen = new Set();
|
|
98
108
|
const traverseDependencyTree = (locator, parentPkg) => {
|
|
99
109
|
// Prevent infinite recursion when A depends on B which depends on A
|
|
@@ -145,15 +155,29 @@ function findPnpRoot(name, root) {
|
|
|
145
155
|
*/
|
|
146
156
|
async function findRoot(name, root) {
|
|
147
157
|
if (name) {
|
|
158
|
+
debug.extend(name)(`Finding root using ${root}`);
|
|
148
159
|
let pkgPath;
|
|
149
160
|
try {
|
|
150
161
|
pkgPath = require.resolve(name, { paths: [root] });
|
|
162
|
+
debug.extend(name)(`Found starting point with require.resolve`);
|
|
151
163
|
}
|
|
152
|
-
catch {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
164
|
+
catch {
|
|
165
|
+
debug.extend(name)(`require.resolve could not find plugin starting point`);
|
|
166
|
+
}
|
|
167
|
+
if (pkgPath) {
|
|
168
|
+
const found = await findPluginRoot((0, node_path_1.dirname)(pkgPath), name);
|
|
169
|
+
if (found) {
|
|
170
|
+
debug.extend(name)(`Found root at ${found}`);
|
|
171
|
+
return found;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const found = process.versions.pnp ? findPnpRoot(name, root) : await findRootLegacy(name, root);
|
|
175
|
+
debug.extend(name)(found ? `Found root at ${found}` : 'No root found!');
|
|
176
|
+
return found;
|
|
156
177
|
}
|
|
157
|
-
|
|
178
|
+
debug.extend('root-plugin')(`Finding root plugin using ${root}`);
|
|
179
|
+
const found = await findPluginRoot(root);
|
|
180
|
+
debug.extend('root-plugin')(found ? `Found root at ${found}` : 'No root found!');
|
|
181
|
+
return found;
|
|
158
182
|
}
|
|
159
183
|
exports.findRoot = findRoot;
|
package/lib/util/fs.d.ts
CHANGED
|
@@ -18,3 +18,4 @@ export declare function readJsonSync(path: string, parse: false): string;
|
|
|
18
18
|
export declare function readJsonSync<T = unknown>(path: string, parse?: true): T;
|
|
19
19
|
export declare function safeReadJson<T>(path: string): Promise<T | undefined>;
|
|
20
20
|
export declare function existsSync(path: string): boolean;
|
|
21
|
+
export declare function readTSConfig(path: string): Promise<any>;
|
package/lib/util/fs.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
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 = exports.requireJson = void 0;
|
|
3
|
+
exports.readTSConfig = 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
6
|
const node_path_1 = require("node:path");
|
|
7
|
-
const debug = require('debug');
|
|
8
7
|
function requireJson(...pathParts) {
|
|
9
8
|
return JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(...pathParts), 'utf8'));
|
|
10
9
|
}
|
|
@@ -50,7 +49,6 @@ const fileExists = async (input) => {
|
|
|
50
49
|
};
|
|
51
50
|
exports.fileExists = fileExists;
|
|
52
51
|
async function readJson(path) {
|
|
53
|
-
debug('config')('readJson %s', path);
|
|
54
52
|
const contents = await (0, promises_1.readFile)(path, 'utf8');
|
|
55
53
|
return JSON.parse(contents);
|
|
56
54
|
}
|
|
@@ -71,3 +69,10 @@ function existsSync(path) {
|
|
|
71
69
|
return (0, node_fs_1.existsSync)(path);
|
|
72
70
|
}
|
|
73
71
|
exports.existsSync = existsSync;
|
|
72
|
+
async function readTSConfig(path) {
|
|
73
|
+
const { parse } = await import('tsconfck');
|
|
74
|
+
const result = await parse(path);
|
|
75
|
+
const tsNodeOpts = Object.fromEntries((result.extended ?? []).flatMap((e) => Object.entries(e.tsconfig['ts-node'] ?? {})).reverse());
|
|
76
|
+
return { ...result.tsconfig, 'ts-node': tsNodeOpts };
|
|
77
|
+
}
|
|
78
|
+
exports.readTSConfig = readTSConfig;
|
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.
|
|
4
|
+
"version": "3.10.1",
|
|
5
5
|
"author": "Salesforce",
|
|
6
6
|
"bugs": "https://github.com/oclif/core/issues",
|
|
7
7
|
"dependencies": {
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"strip-ansi": "^6.0.1",
|
|
28
28
|
"supports-color": "^8.1.1",
|
|
29
29
|
"supports-hyperlinks": "^2.2.0",
|
|
30
|
+
"tsconfck": "^3.0.0",
|
|
30
31
|
"widest-line": "^3.1.0",
|
|
31
32
|
"wordwrap": "^1.0.0",
|
|
32
33
|
"wrap-ansi": "^7.0.0"
|
|
@@ -43,6 +44,7 @@
|
|
|
43
44
|
"@types/chai-as-promised": "^7.1.5",
|
|
44
45
|
"@types/clean-stack": "^2.1.1",
|
|
45
46
|
"@types/cli-progress": "^3.11.0",
|
|
47
|
+
"@types/debug": "^4.1.10",
|
|
46
48
|
"@types/ejs": "^3.1.3",
|
|
47
49
|
"@types/indent-string": "^4.0.1",
|
|
48
50
|
"@types/js-yaml": "^3.12.7",
|