@oclif/core 3.5.0 → 3.6.0
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.js +2 -75
- package/lib/config/ts-node.js +1 -1
- package/lib/config/util.d.ts +0 -3
- package/lib/config/util.js +1 -5
- package/lib/util/find-root.d.ts +15 -0
- package/lib/util/find-root.js +159 -0
- package/package.json +2 -1
package/lib/config/plugin.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Plugin = void 0;
|
|
4
|
-
/* eslint-disable no-await-in-loop */
|
|
5
4
|
const globby_1 = require("globby");
|
|
6
5
|
const node_path_1 = require("node:path");
|
|
7
6
|
const node_util_1 = require("node:util");
|
|
@@ -9,6 +8,7 @@ const errors_1 = require("../errors");
|
|
|
9
8
|
const module_loader_1 = require("../module-loader");
|
|
10
9
|
const performance_1 = require("../performance");
|
|
11
10
|
const cache_command_1 = require("../util/cache-command");
|
|
11
|
+
const find_root_1 = require("../util/find-root");
|
|
12
12
|
const fs_1 = require("../util/fs");
|
|
13
13
|
const util_1 = require("../util/util");
|
|
14
14
|
const ts_node_1 = require("./ts-node");
|
|
@@ -26,79 +26,6 @@ function topicsToArray(input, base) {
|
|
|
26
26
|
return [{ ...input[k], name: `${base}${k}` }, ...topicsToArray(input[k].subtopics, `${base}${input[k].name}`)];
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
|
-
// essentially just "cd .."
|
|
30
|
-
function* up(from) {
|
|
31
|
-
while ((0, node_path_1.dirname)(from) !== from) {
|
|
32
|
-
yield from;
|
|
33
|
-
from = (0, node_path_1.dirname)(from);
|
|
34
|
-
}
|
|
35
|
-
yield from;
|
|
36
|
-
}
|
|
37
|
-
async function findSourcesRoot(root, name) {
|
|
38
|
-
// If we know the plugin name then we just need to traverse the file
|
|
39
|
-
// system until we find the directory that matches the plugin name.
|
|
40
|
-
if (name) {
|
|
41
|
-
for (const next of up(root)) {
|
|
42
|
-
if (next.endsWith((0, node_path_1.basename)(name)))
|
|
43
|
-
return next;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
// If there's no plugin name (typically just the root plugin), then we need
|
|
47
|
-
// to traverse the file system until we find a directory with a package.json
|
|
48
|
-
for (const next of up(root)) {
|
|
49
|
-
// Skip the bin directory
|
|
50
|
-
if ((0, node_path_1.basename)((0, node_path_1.dirname)(next)) === 'bin' &&
|
|
51
|
-
['dev', 'dev.cmd', 'dev.js', 'run', 'run.cmd', 'run.js'].includes((0, node_path_1.basename)(next))) {
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
try {
|
|
55
|
-
const cur = (0, node_path_1.join)(next, 'package.json');
|
|
56
|
-
if (await (0, fs_1.safeReadJson)(cur))
|
|
57
|
-
return (0, node_path_1.dirname)(cur);
|
|
58
|
-
}
|
|
59
|
-
catch { }
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Find package root for packages installed into node_modules. This will go up directories
|
|
64
|
-
* until it finds a node_modules directory with the plugin installed into it
|
|
65
|
-
*
|
|
66
|
-
* This is needed because some oclif plugins do not declare the `main` field in their package.json
|
|
67
|
-
* https://github.com/oclif/config/pull/289#issuecomment-983904051
|
|
68
|
-
*
|
|
69
|
-
* @returns string
|
|
70
|
-
* @param name string
|
|
71
|
-
* @param root string
|
|
72
|
-
*/
|
|
73
|
-
async function findRootLegacy(name, root) {
|
|
74
|
-
for (const next of up(root)) {
|
|
75
|
-
let cur;
|
|
76
|
-
if (name) {
|
|
77
|
-
cur = (0, node_path_1.join)(next, 'node_modules', name, 'package.json');
|
|
78
|
-
if (await (0, fs_1.safeReadJson)(cur))
|
|
79
|
-
return (0, node_path_1.dirname)(cur);
|
|
80
|
-
const pkg = await (0, fs_1.safeReadJson)((0, node_path_1.join)(next, 'package.json'));
|
|
81
|
-
if (pkg?.name === name)
|
|
82
|
-
return next;
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
cur = (0, node_path_1.join)(next, 'package.json');
|
|
86
|
-
if (await (0, fs_1.safeReadJson)(cur))
|
|
87
|
-
return (0, node_path_1.dirname)(cur);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
async function findRoot(name, root) {
|
|
92
|
-
if (name) {
|
|
93
|
-
let pkgPath;
|
|
94
|
-
try {
|
|
95
|
-
pkgPath = (0, util_2.resolvePackage)(name, { paths: [root] });
|
|
96
|
-
}
|
|
97
|
-
catch { }
|
|
98
|
-
return pkgPath ? findSourcesRoot((0, node_path_1.dirname)(pkgPath), name) : findRootLegacy(name, root);
|
|
99
|
-
}
|
|
100
|
-
return findSourcesRoot(root);
|
|
101
|
-
}
|
|
102
29
|
const cachedCommandCanBeUsed = (manifest, id) => Boolean(manifest?.commands[id] && 'isESM' in manifest.commands[id] && 'relativePath' in manifest.commands[id]);
|
|
103
30
|
const search = (cmd) => {
|
|
104
31
|
if (typeof cmd.run === 'function')
|
|
@@ -212,7 +139,7 @@ class Plugin {
|
|
|
212
139
|
// Linked plugins already have a root so there's no need to search for it.
|
|
213
140
|
// However there could be child plugins nested inside the linked plugin, in which
|
|
214
141
|
// case we still need to search for the child plugin's root.
|
|
215
|
-
const root = this.type === 'link' && !this.parent ? this.options.root : await findRoot(this.options.name, this.options.root);
|
|
142
|
+
const root = this.type === 'link' && !this.parent ? this.options.root : await (0, find_root_1.findRoot)(this.options.name, this.options.root);
|
|
216
143
|
if (!root)
|
|
217
144
|
throw new errors_1.CLIError(`could not find package.json with ${(0, node_util_1.inspect)(this.options)}`);
|
|
218
145
|
this.root = root;
|
package/lib/config/ts-node.js
CHANGED
|
@@ -25,7 +25,7 @@ function loadTSConfig(root) {
|
|
|
25
25
|
}
|
|
26
26
|
catch {
|
|
27
27
|
try {
|
|
28
|
-
typescript = require((
|
|
28
|
+
typescript = require(require.resolve('typescript', { paths: [root, __dirname] }));
|
|
29
29
|
}
|
|
30
30
|
catch {
|
|
31
31
|
debug(`Could not find typescript dependency. Skipping ts-node registration for ${root}.`);
|
package/lib/config/util.d.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
export declare function resolvePackage(id: string, paths: {
|
|
2
|
-
paths: string[];
|
|
3
|
-
}): string;
|
|
4
1
|
export declare function Debug(...scope: string[]): (..._: any) => void;
|
|
5
2
|
export declare function getPermutations(arr: string[]): Array<string[]>;
|
|
6
3
|
export declare function getCommandIdPermutations(commandId: string): string[];
|
package/lib/config/util.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.collectUsableIds = exports.getCommandIdPermutations = exports.getPermutations = exports.Debug =
|
|
3
|
+
exports.collectUsableIds = exports.getCommandIdPermutations = exports.getPermutations = exports.Debug = void 0;
|
|
4
4
|
const debug = require('debug');
|
|
5
|
-
function resolvePackage(id, paths) {
|
|
6
|
-
return require.resolve(id, paths);
|
|
7
|
-
}
|
|
8
|
-
exports.resolvePackage = resolvePackage;
|
|
9
5
|
function displayWarnings() {
|
|
10
6
|
if (process.listenerCount('warning') > 1)
|
|
11
7
|
return;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the root directory of the plugin.
|
|
3
|
+
*
|
|
4
|
+
* It first attempts to use require.resolve to find the plugin root.
|
|
5
|
+
* If that returns a path, it will `cd` up the file system until if finds the package.json for the plugin
|
|
6
|
+
* Example: node_modules/@oclif/plugin-version/dist/index.js -> node_modules/@oclif/plugin-version
|
|
7
|
+
*
|
|
8
|
+
* If require.resolve throws an error, it will attempt to find the plugin root by traversing the file system.
|
|
9
|
+
* If we're in a PnP environment (determined by process.versions.pnp), it will use the pnpapi module to
|
|
10
|
+
* traverse the dependency tree. Otherwise, it will traverse the node_modules until it finds a package.json
|
|
11
|
+
* with a matching name.
|
|
12
|
+
*
|
|
13
|
+
* If no path is found, undefined is returned which will eventually result in a thrown Error from Plugin.
|
|
14
|
+
*/
|
|
15
|
+
export declare function findRoot(name: string | undefined, root: string): Promise<string | undefined>;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findRoot = void 0;
|
|
4
|
+
const node_path_1 = require("node:path");
|
|
5
|
+
const fs_1 = require("./fs");
|
|
6
|
+
// essentially just "cd .."
|
|
7
|
+
function* up(from) {
|
|
8
|
+
while ((0, node_path_1.dirname)(from) !== from) {
|
|
9
|
+
yield from;
|
|
10
|
+
from = (0, node_path_1.dirname)(from);
|
|
11
|
+
}
|
|
12
|
+
yield from;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Return the plugin root directory from a given file. This will `cd` up the file system until it finds
|
|
16
|
+
* a package.json and then return the dirname of that path.
|
|
17
|
+
*
|
|
18
|
+
* Example: node_modules/@oclif/plugin-version/dist/index.js -> node_modules/@oclif/plugin-version
|
|
19
|
+
*/
|
|
20
|
+
async function findPluginRoot(root, name) {
|
|
21
|
+
// If we know the plugin name then we just need to traverse the file
|
|
22
|
+
// system until we find the directory that matches the plugin name.
|
|
23
|
+
if (name) {
|
|
24
|
+
for (const next of up(root)) {
|
|
25
|
+
if (next.endsWith((0, node_path_1.basename)(name)))
|
|
26
|
+
return next;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// If there's no plugin name (typically just the root plugin), then we need
|
|
30
|
+
// to traverse the file system until we find a directory with a package.json
|
|
31
|
+
for (const next of up(root)) {
|
|
32
|
+
// Skip the bin directory
|
|
33
|
+
if ((0, node_path_1.basename)((0, node_path_1.dirname)(next)) === 'bin' &&
|
|
34
|
+
['dev', 'dev.cmd', 'dev.js', 'run', 'run.cmd', 'run.js'].includes((0, node_path_1.basename)(next))) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const cur = (0, node_path_1.join)(next, 'package.json');
|
|
39
|
+
if (await (0, fs_1.safeReadJson)(cur))
|
|
40
|
+
return (0, node_path_1.dirname)(cur);
|
|
41
|
+
}
|
|
42
|
+
catch { }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Find plugin root directory for plugins installed into node_modules that don't have a `main` or `export`.
|
|
47
|
+
* This will go up directories until it finds a directory with the plugin installed into it.
|
|
48
|
+
*
|
|
49
|
+
* See https://github.com/oclif/config/pull/289#issuecomment-983904051
|
|
50
|
+
*/
|
|
51
|
+
async function findRootLegacy(name, root) {
|
|
52
|
+
for (const next of up(root)) {
|
|
53
|
+
let cur;
|
|
54
|
+
if (name) {
|
|
55
|
+
cur = (0, node_path_1.join)(next, 'node_modules', name, 'package.json');
|
|
56
|
+
if (await (0, fs_1.safeReadJson)(cur))
|
|
57
|
+
return (0, node_path_1.dirname)(cur);
|
|
58
|
+
const pkg = await (0, fs_1.safeReadJson)((0, node_path_1.join)(next, 'package.json'));
|
|
59
|
+
if (pkg?.name === name)
|
|
60
|
+
return next;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
cur = (0, node_path_1.join)(next, 'package.json');
|
|
64
|
+
if (await (0, fs_1.safeReadJson)(cur))
|
|
65
|
+
return (0, node_path_1.dirname)(cur);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
let pnp;
|
|
70
|
+
/**
|
|
71
|
+
* The pnpapi module is only available if running in a pnp environment. Because of that
|
|
72
|
+
* we have to require it from the plugin.
|
|
73
|
+
*
|
|
74
|
+
* Solution taken from here: https://github.com/yarnpkg/berry/issues/1467#issuecomment-642869600
|
|
75
|
+
*/
|
|
76
|
+
function maybeRequirePnpApi(root) {
|
|
77
|
+
if (pnp)
|
|
78
|
+
return pnp;
|
|
79
|
+
try {
|
|
80
|
+
// eslint-disable-next-line node/no-missing-require
|
|
81
|
+
pnp = require(require.resolve('pnpapi', { paths: [root] }));
|
|
82
|
+
return pnp;
|
|
83
|
+
}
|
|
84
|
+
catch { }
|
|
85
|
+
}
|
|
86
|
+
const getKey = (locator) => JSON.stringify(locator);
|
|
87
|
+
const isPeerDependency = (pkg, parentPkg, name) => getKey(pkg?.packageDependencies.get(name)) === getKey(parentPkg?.packageDependencies.get(name));
|
|
88
|
+
/**
|
|
89
|
+
* Traverse PnP dependency tree to find plugin root directory.
|
|
90
|
+
*
|
|
91
|
+
* Implementation adapted from https://yarnpkg.com/advanced/pnpapi#traversing-the-dependency-tree
|
|
92
|
+
*/
|
|
93
|
+
function findPnpRoot(name, root) {
|
|
94
|
+
maybeRequirePnpApi(root);
|
|
95
|
+
if (!pnp)
|
|
96
|
+
return;
|
|
97
|
+
const seen = new Set();
|
|
98
|
+
const traverseDependencyTree = (locator, parentPkg) => {
|
|
99
|
+
// Prevent infinite recursion when A depends on B which depends on A
|
|
100
|
+
const key = getKey(locator);
|
|
101
|
+
if (seen.has(key))
|
|
102
|
+
return;
|
|
103
|
+
const pkg = pnp.getPackageInformation(locator);
|
|
104
|
+
if (locator.name === name) {
|
|
105
|
+
return pkg.packageLocation;
|
|
106
|
+
}
|
|
107
|
+
seen.add(key);
|
|
108
|
+
for (const [name, referencish] of pkg.packageDependencies) {
|
|
109
|
+
// Unmet peer dependencies
|
|
110
|
+
if (referencish === null)
|
|
111
|
+
continue;
|
|
112
|
+
// Avoid iterating on peer dependencies - very expensive
|
|
113
|
+
if (parentPkg !== null && isPeerDependency(pkg, parentPkg, name))
|
|
114
|
+
continue;
|
|
115
|
+
const childLocator = pnp.getLocator(name, referencish);
|
|
116
|
+
const foundSomething = traverseDependencyTree(childLocator, pkg);
|
|
117
|
+
if (foundSomething)
|
|
118
|
+
return foundSomething;
|
|
119
|
+
}
|
|
120
|
+
// Important: This `delete` here causes the traversal to go over nodes even
|
|
121
|
+
// if they have already been traversed in another branch. If you don't need
|
|
122
|
+
// that, remove this line for a hefty speed increase.
|
|
123
|
+
seen.delete(key);
|
|
124
|
+
};
|
|
125
|
+
// Iterate on each workspace
|
|
126
|
+
for (const locator of pnp.getDependencyTreeRoots()) {
|
|
127
|
+
const foundSomething = traverseDependencyTree(locator);
|
|
128
|
+
if (foundSomething)
|
|
129
|
+
return foundSomething;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Returns the root directory of the plugin.
|
|
134
|
+
*
|
|
135
|
+
* It first attempts to use require.resolve to find the plugin root.
|
|
136
|
+
* If that returns a path, it will `cd` up the file system until if finds the package.json for the plugin
|
|
137
|
+
* Example: node_modules/@oclif/plugin-version/dist/index.js -> node_modules/@oclif/plugin-version
|
|
138
|
+
*
|
|
139
|
+
* If require.resolve throws an error, it will attempt to find the plugin root by traversing the file system.
|
|
140
|
+
* If we're in a PnP environment (determined by process.versions.pnp), it will use the pnpapi module to
|
|
141
|
+
* traverse the dependency tree. Otherwise, it will traverse the node_modules until it finds a package.json
|
|
142
|
+
* with a matching name.
|
|
143
|
+
*
|
|
144
|
+
* If no path is found, undefined is returned which will eventually result in a thrown Error from Plugin.
|
|
145
|
+
*/
|
|
146
|
+
async function findRoot(name, root) {
|
|
147
|
+
if (name) {
|
|
148
|
+
let pkgPath;
|
|
149
|
+
try {
|
|
150
|
+
pkgPath = require.resolve(name, { paths: [root] });
|
|
151
|
+
}
|
|
152
|
+
catch { }
|
|
153
|
+
if (pkgPath)
|
|
154
|
+
return findPluginRoot((0, node_path_1.dirname)(pkgPath), name);
|
|
155
|
+
return process.versions.pnp ? findPnpRoot(name, root) : findRootLegacy(name, root);
|
|
156
|
+
}
|
|
157
|
+
return findPluginRoot(root);
|
|
158
|
+
}
|
|
159
|
+
exports.findRoot = findRoot;
|
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.6.0",
|
|
5
5
|
"author": "Salesforce",
|
|
6
6
|
"bugs": "https://github.com/oclif/core/issues",
|
|
7
7
|
"dependencies": {
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
"@types/mocha": "^10.0.2",
|
|
50
50
|
"@types/node": "^18",
|
|
51
51
|
"@types/node-notifier": "^8.0.2",
|
|
52
|
+
"@types/pnpapi": "^0.0.4",
|
|
52
53
|
"@types/slice-ansi": "^4.0.0",
|
|
53
54
|
"@types/strip-ansi": "^5.2.1",
|
|
54
55
|
"@types/supports-color": "^8.1.1",
|