@oclif/core 3.3.3 → 3.4.1-dev.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/cli-ux/action/base.js +10 -11
- package/lib/cli-ux/flush.js +2 -3
- package/lib/cli-ux/index.d.ts +5 -4
- package/lib/cli-ux/index.js +13 -7
- package/lib/cli-ux/prompt.js +3 -4
- package/lib/cli-ux/stream.d.ts +6 -0
- package/lib/cli-ux/stream.js +6 -0
- package/lib/cli-ux/stub.d.ts +32 -0
- package/lib/cli-ux/stub.js +39 -0
- package/lib/cli-ux/styled/table.js +4 -4
- package/lib/cli-ux/write.d.ts +5 -0
- package/lib/cli-ux/write.js +12 -0
- package/lib/command.d.ts +2 -1
- package/lib/command.js +3 -4
- package/lib/config/config.js +2 -3
- package/lib/config/plugin.js +2 -75
- package/lib/config/ts-node.js +3 -4
- package/lib/config/util.d.ts +0 -3
- package/lib/config/util.js +1 -5
- package/lib/errors/index.d.ts +1 -1
- package/lib/errors/index.js +3 -1
- package/lib/help/index.js +2 -2
- package/lib/index.js +9 -5
- package/lib/interfaces/pjson.d.ts +1 -0
- package/lib/interfaces/plugin.d.ts +1 -0
- package/lib/main.js +2 -7
- package/lib/module-loader.js +3 -2
- package/lib/screen.js +2 -3
- package/lib/util/find-root.d.ts +15 -0
- package/lib/util/find-root.js +154 -0
- package/lib/util/fs.d.ts +1 -0
- package/lib/util/fs.js +5 -1
- package/package.json +3 -2
|
@@ -3,14 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ActionBase = void 0;
|
|
4
4
|
const node_util_1 = require("node:util");
|
|
5
5
|
const util_1 = require("../../util/util");
|
|
6
|
-
const stream_1 = require("../stream");
|
|
7
6
|
class ActionBase {
|
|
8
7
|
std = 'stderr';
|
|
9
8
|
stdmocks;
|
|
10
9
|
type;
|
|
11
10
|
stdmockOrigs = {
|
|
12
|
-
stderr:
|
|
13
|
-
stdout:
|
|
11
|
+
stderr: process.stderr.write,
|
|
12
|
+
stdout: process.stdout.write,
|
|
14
13
|
};
|
|
15
14
|
get output() {
|
|
16
15
|
return this.globals.output;
|
|
@@ -125,15 +124,15 @@ class ActionBase {
|
|
|
125
124
|
if (this.stdmocks)
|
|
126
125
|
return;
|
|
127
126
|
this.stdmockOrigs = {
|
|
128
|
-
stderr:
|
|
129
|
-
stdout:
|
|
127
|
+
stderr: process.stderr.write,
|
|
128
|
+
stdout: process.stdout.write,
|
|
130
129
|
};
|
|
131
130
|
this.stdmocks = [];
|
|
132
|
-
|
|
131
|
+
process.stdout.write = (...args) => {
|
|
133
132
|
this.stdmocks.push(['stdout', args]);
|
|
134
133
|
return true;
|
|
135
134
|
};
|
|
136
|
-
|
|
135
|
+
process.stderr.write = (...args) => {
|
|
137
136
|
this.stdmocks.push(['stderr', args]);
|
|
138
137
|
return true;
|
|
139
138
|
};
|
|
@@ -143,8 +142,8 @@ class ActionBase {
|
|
|
143
142
|
return;
|
|
144
143
|
// this._write('stderr', '\nresetstdmock\n\n\n')
|
|
145
144
|
delete this.stdmocks;
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
process.stdout.write = this.stdmockOrigs.stdout;
|
|
146
|
+
process.stderr.write = this.stdmockOrigs.stderr;
|
|
148
147
|
}
|
|
149
148
|
}
|
|
150
149
|
catch (error) {
|
|
@@ -161,11 +160,11 @@ class ActionBase {
|
|
|
161
160
|
_write(std, s) {
|
|
162
161
|
switch (std) {
|
|
163
162
|
case 'stdout': {
|
|
164
|
-
this.stdmockOrigs.stdout.apply(
|
|
163
|
+
this.stdmockOrigs.stdout.apply(process.stdout, (0, util_1.castArray)(s));
|
|
165
164
|
break;
|
|
166
165
|
}
|
|
167
166
|
case 'stderr': {
|
|
168
|
-
this.stdmockOrigs.stderr.apply(
|
|
167
|
+
this.stdmockOrigs.stderr.apply(process.stderr, (0, util_1.castArray)(s));
|
|
169
168
|
break;
|
|
170
169
|
}
|
|
171
170
|
default: {
|
package/lib/cli-ux/flush.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.flush = void 0;
|
|
4
4
|
const errors_1 = require("../errors");
|
|
5
|
-
const stream_1 = require("./stream");
|
|
6
5
|
function timeout(p, ms) {
|
|
7
6
|
function wait(ms, unref = false) {
|
|
8
7
|
return new Promise((resolve) => {
|
|
@@ -15,9 +14,9 @@ function timeout(p, ms) {
|
|
|
15
14
|
}
|
|
16
15
|
async function _flush() {
|
|
17
16
|
const p = new Promise((resolve) => {
|
|
18
|
-
|
|
17
|
+
process.stdout.once('drain', () => resolve(null));
|
|
19
18
|
});
|
|
20
|
-
const flushed =
|
|
19
|
+
const flushed = process.stdout.write('');
|
|
21
20
|
if (flushed)
|
|
22
21
|
return;
|
|
23
22
|
return p;
|
package/lib/cli-ux/index.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import * as Errors from '../errors';
|
|
2
2
|
import { ActionBase } from './action/base';
|
|
3
|
-
import { Config } from './config';
|
|
4
3
|
import * as uxPrompt from './prompt';
|
|
5
4
|
import * as styled from './styled';
|
|
6
5
|
import uxWait from './wait';
|
|
7
6
|
export declare class ux {
|
|
8
|
-
static config: Config;
|
|
7
|
+
static config: import("./config").Config;
|
|
9
8
|
static get action(): ActionBase;
|
|
10
9
|
static annotation(text: string, annotation: string): void;
|
|
11
10
|
/**
|
|
@@ -18,6 +17,7 @@ export declare class ux {
|
|
|
18
17
|
static flush(ms?: number): Promise<void>;
|
|
19
18
|
static info(format: string, ...args: string[]): void;
|
|
20
19
|
static log(format?: string, ...args: string[]): void;
|
|
20
|
+
static logToStderr(format?: string, ...args: string[]): void;
|
|
21
21
|
static get progress(): typeof styled.progress;
|
|
22
22
|
static get prompt(): typeof uxPrompt.prompt;
|
|
23
23
|
static styledHeader(header: string): void;
|
|
@@ -29,11 +29,12 @@ export declare class ux {
|
|
|
29
29
|
static url(text: string, uri: string, params?: {}): void;
|
|
30
30
|
static get wait(): typeof uxWait;
|
|
31
31
|
}
|
|
32
|
-
declare const action: ActionBase, annotation: typeof ux.annotation, anykey: typeof uxPrompt.anykey, confirm: typeof uxPrompt.confirm, debug: typeof ux.debug, done: typeof ux.done, flush: typeof ux.flush, info: typeof ux.info, log: typeof ux.log, progress: typeof styled.progress, prompt: typeof uxPrompt.prompt, styledHeader: typeof ux.styledHeader, styledJSON: typeof ux.styledJSON, styledObject: typeof ux.styledObject, table: typeof styled.Table.table, trace: typeof ux.trace, tree: typeof styled.tree, url: typeof ux.url, wait: (ms?: number) => Promise<void>;
|
|
32
|
+
declare const action: ActionBase, annotation: typeof ux.annotation, anykey: typeof uxPrompt.anykey, confirm: typeof uxPrompt.confirm, debug: typeof ux.debug, done: typeof ux.done, flush: typeof ux.flush, info: typeof ux.info, log: typeof ux.log, logToStderr: typeof ux.logToStderr, progress: typeof styled.progress, prompt: typeof uxPrompt.prompt, styledHeader: typeof ux.styledHeader, styledJSON: typeof ux.styledJSON, styledObject: typeof ux.styledObject, table: typeof styled.Table.table, trace: typeof ux.trace, tree: typeof styled.tree, url: typeof ux.url, wait: (ms?: number) => Promise<void>;
|
|
33
33
|
declare const error: typeof Errors.error, exit: typeof Errors.exit, warn: typeof Errors.warn;
|
|
34
|
-
export { action, annotation, anykey, confirm, debug, done, error, exit, flush, info, log, progress, prompt, styledHeader, styledJSON, styledObject, table, trace, tree, url, wait, warn, };
|
|
34
|
+
export { action, annotation, anykey, confirm, debug, done, error, exit, flush, info, log, logToStderr, progress, prompt, styledHeader, styledJSON, styledObject, table, trace, tree, url, wait, warn, };
|
|
35
35
|
export { ActionBase } from './action/base';
|
|
36
36
|
export { Config, config } from './config';
|
|
37
37
|
export { ExitError } from './exit';
|
|
38
38
|
export { IPromptOptions } from './prompt';
|
|
39
|
+
export { makeStubs } from './stub';
|
|
39
40
|
export { Table } from './styled';
|
package/lib/cli-ux/index.js
CHANGED
|
@@ -26,16 +26,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.Table = exports.ExitError = exports.config = exports.Config = exports.ActionBase = exports.warn = exports.wait = exports.url = exports.tree = exports.trace = exports.table = exports.styledObject = exports.styledJSON = exports.styledHeader = exports.prompt = exports.progress = exports.log = exports.info = exports.flush = exports.exit = exports.error = exports.done = exports.debug = exports.confirm = exports.anykey = exports.annotation = exports.action = exports.ux = void 0;
|
|
29
|
+
exports.Table = exports.makeStubs = exports.ExitError = exports.config = exports.Config = exports.ActionBase = exports.warn = exports.wait = exports.url = exports.tree = exports.trace = exports.table = exports.styledObject = exports.styledJSON = exports.styledHeader = exports.prompt = exports.progress = exports.logToStderr = exports.log = exports.info = exports.flush = exports.exit = exports.error = exports.done = exports.debug = exports.confirm = exports.anykey = exports.annotation = exports.action = exports.ux = void 0;
|
|
30
30
|
const chalk_1 = __importDefault(require("chalk"));
|
|
31
31
|
const node_util_1 = require("node:util");
|
|
32
32
|
const Errors = __importStar(require("../errors"));
|
|
33
33
|
const config_1 = require("./config");
|
|
34
34
|
const flush_1 = require("./flush");
|
|
35
35
|
const uxPrompt = __importStar(require("./prompt"));
|
|
36
|
-
const stream_1 = require("./stream");
|
|
37
36
|
const styled = __importStar(require("./styled"));
|
|
38
37
|
const wait_1 = __importDefault(require("./wait"));
|
|
38
|
+
const write_1 = __importDefault(require("./write"));
|
|
39
39
|
const hyperlinker = require('hyperlinker');
|
|
40
40
|
class ux {
|
|
41
41
|
static config = config_1.config;
|
|
@@ -63,7 +63,7 @@ class ux {
|
|
|
63
63
|
}
|
|
64
64
|
static debug(format, ...args) {
|
|
65
65
|
if (['debug', 'trace'].includes(this.config.outputLevel)) {
|
|
66
|
-
|
|
66
|
+
this.info((0, node_util_1.format)(format, ...args) + '\n');
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
static async done() {
|
|
@@ -73,11 +73,14 @@ class ux {
|
|
|
73
73
|
await (0, flush_1.flush)(ms);
|
|
74
74
|
}
|
|
75
75
|
static info(format, ...args) {
|
|
76
|
-
|
|
76
|
+
write_1.default.stdout((0, node_util_1.format)(format, ...args) + '\n');
|
|
77
77
|
}
|
|
78
78
|
static log(format, ...args) {
|
|
79
79
|
this.info(format || '', ...args);
|
|
80
80
|
}
|
|
81
|
+
static logToStderr(format, ...args) {
|
|
82
|
+
write_1.default.stderr((0, node_util_1.format)(format, ...args) + '\n');
|
|
83
|
+
}
|
|
81
84
|
static get progress() {
|
|
82
85
|
return styled.progress;
|
|
83
86
|
}
|
|
@@ -90,7 +93,7 @@ class ux {
|
|
|
90
93
|
static styledJSON(obj) {
|
|
91
94
|
const json = JSON.stringify(obj, null, 2);
|
|
92
95
|
if (!chalk_1.default.level) {
|
|
93
|
-
info(json);
|
|
96
|
+
this.info(json);
|
|
94
97
|
return;
|
|
95
98
|
}
|
|
96
99
|
const cardinal = require('cardinal');
|
|
@@ -105,7 +108,7 @@ class ux {
|
|
|
105
108
|
}
|
|
106
109
|
static trace(format, ...args) {
|
|
107
110
|
if (this.config.outputLevel === 'trace') {
|
|
108
|
-
|
|
111
|
+
this.info((0, node_util_1.format)(format, ...args) + '\n');
|
|
109
112
|
}
|
|
110
113
|
}
|
|
111
114
|
static get tree() {
|
|
@@ -125,7 +128,7 @@ class ux {
|
|
|
125
128
|
}
|
|
126
129
|
}
|
|
127
130
|
exports.ux = ux;
|
|
128
|
-
const { action, annotation, anykey, confirm, debug, done, flush, info, log, progress, prompt, styledHeader, styledJSON, styledObject, table, trace, tree, url, wait, } = ux;
|
|
131
|
+
const { action, annotation, anykey, confirm, debug, done, flush, info, log, logToStderr, progress, prompt, styledHeader, styledJSON, styledObject, table, trace, tree, url, wait, } = ux;
|
|
129
132
|
exports.action = action;
|
|
130
133
|
exports.annotation = annotation;
|
|
131
134
|
exports.anykey = anykey;
|
|
@@ -135,6 +138,7 @@ exports.done = done;
|
|
|
135
138
|
exports.flush = flush;
|
|
136
139
|
exports.info = info;
|
|
137
140
|
exports.log = log;
|
|
141
|
+
exports.logToStderr = logToStderr;
|
|
138
142
|
exports.progress = progress;
|
|
139
143
|
exports.prompt = prompt;
|
|
140
144
|
exports.styledHeader = styledHeader;
|
|
@@ -171,5 +175,7 @@ Object.defineProperty(exports, "Config", { enumerable: true, get: function () {
|
|
|
171
175
|
Object.defineProperty(exports, "config", { enumerable: true, get: function () { return config_2.config; } });
|
|
172
176
|
var exit_1 = require("./exit");
|
|
173
177
|
Object.defineProperty(exports, "ExitError", { enumerable: true, get: function () { return exit_1.ExitError; } });
|
|
178
|
+
var stub_1 = require("./stub");
|
|
179
|
+
Object.defineProperty(exports, "makeStubs", { enumerable: true, get: function () { return stub_1.makeStubs; } });
|
|
174
180
|
var styled_1 = require("./styled");
|
|
175
181
|
Object.defineProperty(exports, "Table", { enumerable: true, get: function () { return styled_1.Table; } });
|
package/lib/cli-ux/prompt.js
CHANGED
|
@@ -30,7 +30,6 @@ exports.anykey = exports.confirm = exports.prompt = void 0;
|
|
|
30
30
|
const chalk_1 = __importDefault(require("chalk"));
|
|
31
31
|
const Errors = __importStar(require("../errors"));
|
|
32
32
|
const config_1 = require("./config");
|
|
33
|
-
const stream_1 = require("./stream");
|
|
34
33
|
function normal(options, retries = 100) {
|
|
35
34
|
if (retries < 0)
|
|
36
35
|
throw new Error('no input');
|
|
@@ -44,7 +43,7 @@ function normal(options, retries = 100) {
|
|
|
44
43
|
timer.unref();
|
|
45
44
|
}
|
|
46
45
|
process.stdin.setEncoding('utf8');
|
|
47
|
-
|
|
46
|
+
process.stderr.write(options.prompt);
|
|
48
47
|
process.stdin.resume();
|
|
49
48
|
process.stdin.once('data', (b) => {
|
|
50
49
|
if (timer)
|
|
@@ -83,7 +82,7 @@ async function single(options) {
|
|
|
83
82
|
}
|
|
84
83
|
function replacePrompt(prompt) {
|
|
85
84
|
const ansiEscapes = require('ansi-escapes');
|
|
86
|
-
|
|
85
|
+
process.stderr.write(ansiEscapes.cursorHide +
|
|
87
86
|
ansiEscapes.cursorUp(1) +
|
|
88
87
|
ansiEscapes.cursorLeft +
|
|
89
88
|
prompt +
|
|
@@ -176,7 +175,7 @@ async function anykey(message) {
|
|
|
176
175
|
}
|
|
177
176
|
const char = await prompt(message, { required: false, type: 'single' });
|
|
178
177
|
if (tty)
|
|
179
|
-
|
|
178
|
+
process.stderr.write('\n');
|
|
180
179
|
if (char === 'q')
|
|
181
180
|
Errors.error('quit');
|
|
182
181
|
if (char === '\u0003')
|
package/lib/cli-ux/stream.d.ts
CHANGED
|
@@ -12,6 +12,12 @@ declare class Stream {
|
|
|
12
12
|
read(): boolean;
|
|
13
13
|
write(data: string): boolean;
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* @deprecated Use process.stdout directly. This will be removed in the next major version
|
|
17
|
+
*/
|
|
15
18
|
export declare const stdout: Stream;
|
|
19
|
+
/**
|
|
20
|
+
* @deprecated Use process.stderr directly. This will be removed in the next major version
|
|
21
|
+
*/
|
|
16
22
|
export declare const stderr: Stream;
|
|
17
23
|
export {};
|
package/lib/cli-ux/stream.js
CHANGED
|
@@ -33,5 +33,11 @@ class Stream {
|
|
|
33
33
|
return process[this.channel].write(data);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* @deprecated Use process.stdout directly. This will be removed in the next major version
|
|
38
|
+
*/
|
|
36
39
|
exports.stdout = new Stream('stdout');
|
|
40
|
+
/**
|
|
41
|
+
* @deprecated Use process.stderr directly. This will be removed in the next major version
|
|
42
|
+
*/
|
|
37
43
|
exports.stderr = new Stream('stderr');
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { SinonSandbox, SinonStub } from 'sinon';
|
|
2
|
+
type Stubs = {
|
|
3
|
+
stderr: SinonStub;
|
|
4
|
+
stdout: SinonStub;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Create sinon stubs for writing to stdout and stderr.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* import {ux} from '@oclif/core'
|
|
11
|
+
*
|
|
12
|
+
* describe('example', () => {
|
|
13
|
+
* let sandbox: SinonSandbox
|
|
14
|
+
* let stubs: ReturnType<typeof ux.makeStubs>
|
|
15
|
+
*
|
|
16
|
+
* beforeEach(() => {
|
|
17
|
+
* sandbox = createSandbox()
|
|
18
|
+
* stubs = ux.makeStubs(sandbox)
|
|
19
|
+
* })
|
|
20
|
+
*
|
|
21
|
+
* afterEach(() => {
|
|
22
|
+
* sandbox.restore()
|
|
23
|
+
* })
|
|
24
|
+
*
|
|
25
|
+
* it('should log text to the console', () => {
|
|
26
|
+
* ux.log('Hello, world!')
|
|
27
|
+
* expect(stubs.stdout.firstCall.firstArg).to.equal('Hello, world!\n')
|
|
28
|
+
* })
|
|
29
|
+
* })
|
|
30
|
+
*/
|
|
31
|
+
export declare function makeStubs(sandbox: SinonSandbox): Stubs;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.makeStubs = void 0;
|
|
7
|
+
const write_1 = __importDefault(require("./write"));
|
|
8
|
+
/**
|
|
9
|
+
* Create sinon stubs for writing to stdout and stderr.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* import {ux} from '@oclif/core'
|
|
13
|
+
*
|
|
14
|
+
* describe('example', () => {
|
|
15
|
+
* let sandbox: SinonSandbox
|
|
16
|
+
* let stubs: ReturnType<typeof ux.makeStubs>
|
|
17
|
+
*
|
|
18
|
+
* beforeEach(() => {
|
|
19
|
+
* sandbox = createSandbox()
|
|
20
|
+
* stubs = ux.makeStubs(sandbox)
|
|
21
|
+
* })
|
|
22
|
+
*
|
|
23
|
+
* afterEach(() => {
|
|
24
|
+
* sandbox.restore()
|
|
25
|
+
* })
|
|
26
|
+
*
|
|
27
|
+
* it('should log text to the console', () => {
|
|
28
|
+
* ux.log('Hello, world!')
|
|
29
|
+
* expect(stubs.stdout.firstCall.firstArg).to.equal('Hello, world!\n')
|
|
30
|
+
* })
|
|
31
|
+
* })
|
|
32
|
+
*/
|
|
33
|
+
function makeStubs(sandbox) {
|
|
34
|
+
return {
|
|
35
|
+
stderr: sandbox.stub(write_1.default, 'stderr'),
|
|
36
|
+
stdout: sandbox.stub(write_1.default, 'stdout'),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
exports.makeStubs = makeStubs;
|
|
@@ -36,7 +36,7 @@ const string_width_1 = __importDefault(require("string-width"));
|
|
|
36
36
|
const F = __importStar(require("../../flags"));
|
|
37
37
|
const screen_1 = require("../../screen");
|
|
38
38
|
const util_1 = require("../../util/util");
|
|
39
|
-
const
|
|
39
|
+
const write_1 = __importDefault(require("../write"));
|
|
40
40
|
class Table {
|
|
41
41
|
data;
|
|
42
42
|
columns;
|
|
@@ -68,7 +68,7 @@ class Table {
|
|
|
68
68
|
'no-header': options['no-header'] ?? false,
|
|
69
69
|
'no-truncate': options['no-truncate'] ?? false,
|
|
70
70
|
output: csv ? 'csv' : output,
|
|
71
|
-
printLine: printLine ?? ((s) =>
|
|
71
|
+
printLine: printLine ?? ((s) => write_1.default.stdout(s + '\n')),
|
|
72
72
|
rowStart: ' ',
|
|
73
73
|
sort,
|
|
74
74
|
title,
|
|
@@ -116,7 +116,7 @@ class Table {
|
|
|
116
116
|
this.columns = this.filterColumnsFromHeaders(filters);
|
|
117
117
|
}
|
|
118
118
|
else if (!this.options.extended) {
|
|
119
|
-
// show
|
|
119
|
+
// show extended columns/properties
|
|
120
120
|
this.columns = this.columns.filter((c) => !c.extended);
|
|
121
121
|
}
|
|
122
122
|
this.data = rows;
|
|
@@ -188,7 +188,7 @@ class Table {
|
|
|
188
188
|
// truncation logic
|
|
189
189
|
const shouldShorten = () => {
|
|
190
190
|
// don't shorten if full mode
|
|
191
|
-
if (options['no-truncate'] || (!
|
|
191
|
+
if (options['no-truncate'] || (!process.stdout.isTTY && !process.env.CLI_UX_SKIP_TTY_CHECK))
|
|
192
192
|
return;
|
|
193
193
|
// don't shorten if there is enough screen width
|
|
194
194
|
const dataMaxWidth = (0, util_1.sumBy)(columns, (c) => c.width);
|
package/lib/command.d.ts
CHANGED
|
@@ -97,7 +97,8 @@ export declare abstract class Command {
|
|
|
97
97
|
code?: string;
|
|
98
98
|
exit?: number;
|
|
99
99
|
} & PrettyPrintableError): never;
|
|
100
|
-
exit(code
|
|
100
|
+
exit(code: number): never;
|
|
101
|
+
exit(code: 0): void;
|
|
101
102
|
protected finally(_: Error | undefined): Promise<any>;
|
|
102
103
|
protected init(): Promise<any>;
|
|
103
104
|
/**
|
package/lib/command.js
CHANGED
|
@@ -31,7 +31,6 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
31
31
|
const node_url_1 = require("node:url");
|
|
32
32
|
const node_util_1 = require("node:util");
|
|
33
33
|
const cli_ux_1 = require("./cli-ux");
|
|
34
|
-
const stream_1 = require("./cli-ux/stream");
|
|
35
34
|
const config_1 = require("./config");
|
|
36
35
|
const Errors = __importStar(require("./errors"));
|
|
37
36
|
const util_1 = require("./help/util");
|
|
@@ -44,7 +43,7 @@ const pjson = (0, fs_1.requireJson)(__dirname, '..', 'package.json');
|
|
|
44
43
|
* swallows stdout epipe errors
|
|
45
44
|
* this occurs when stdout closes such as when piping to head
|
|
46
45
|
*/
|
|
47
|
-
|
|
46
|
+
process.stdout.on('error', (err) => {
|
|
48
47
|
if (err && err.code === 'EPIPE')
|
|
49
48
|
return;
|
|
50
49
|
throw err;
|
|
@@ -223,7 +222,7 @@ class Command {
|
|
|
223
222
|
log(message = '', ...args) {
|
|
224
223
|
if (!this.jsonEnabled()) {
|
|
225
224
|
message = typeof message === 'string' ? message : (0, node_util_1.inspect)(message);
|
|
226
|
-
|
|
225
|
+
cli_ux_1.ux.info(message, ...args);
|
|
227
226
|
}
|
|
228
227
|
}
|
|
229
228
|
logJson(json) {
|
|
@@ -232,7 +231,7 @@ class Command {
|
|
|
232
231
|
logToStderr(message = '', ...args) {
|
|
233
232
|
if (!this.jsonEnabled()) {
|
|
234
233
|
message = typeof message === 'string' ? message : (0, node_util_1.inspect)(message);
|
|
235
|
-
|
|
234
|
+
cli_ux_1.ux.logToStderr(message, ...args);
|
|
236
235
|
}
|
|
237
236
|
}
|
|
238
237
|
async parse(options, argv = this.argv) {
|
package/lib/config/config.js
CHANGED
|
@@ -32,8 +32,7 @@ const is_wsl_1 = __importDefault(require("is-wsl"));
|
|
|
32
32
|
const node_os_1 = require("node:os");
|
|
33
33
|
const node_path_1 = require("node:path");
|
|
34
34
|
const node_url_1 = require("node:url");
|
|
35
|
-
const
|
|
36
|
-
const stream_1 = require("../cli-ux/stream");
|
|
35
|
+
const cli_ux_1 = require("../cli-ux");
|
|
37
36
|
const errors_1 = require("../errors");
|
|
38
37
|
const util_1 = require("../help/util");
|
|
39
38
|
const module_loader_1 = require("../module-loader");
|
|
@@ -448,7 +447,7 @@ class Config {
|
|
|
448
447
|
(0, errors_1.exit)(code);
|
|
449
448
|
},
|
|
450
449
|
log(message, ...args) {
|
|
451
|
-
|
|
450
|
+
cli_ux_1.ux.info(message, ...args);
|
|
452
451
|
},
|
|
453
452
|
warn(message) {
|
|
454
453
|
(0, errors_1.warn)(message);
|
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
|
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.tsPath = exports.TS_CONFIGS = void 0;
|
|
7
|
-
const node_fs_1 = require("node:fs");
|
|
8
7
|
const node_path_1 = require("node:path");
|
|
9
8
|
const errors_1 = require("../errors");
|
|
10
9
|
const settings_1 = require("../settings");
|
|
@@ -26,7 +25,7 @@ function loadTSConfig(root) {
|
|
|
26
25
|
}
|
|
27
26
|
catch {
|
|
28
27
|
try {
|
|
29
|
-
typescript = require((
|
|
28
|
+
typescript = require(require.resolve('typescript', { paths: [root, __dirname] }));
|
|
30
29
|
}
|
|
31
30
|
catch {
|
|
32
31
|
debug(`Could not find typescript dependency. Skipping ts-node registration for ${root}.`);
|
|
@@ -34,7 +33,7 @@ function loadTSConfig(root) {
|
|
|
34
33
|
return;
|
|
35
34
|
}
|
|
36
35
|
}
|
|
37
|
-
if ((0,
|
|
36
|
+
if ((0, fs_1.existsSync)(tsconfigPath) && typescript) {
|
|
38
37
|
const tsconfig = typescript.parseConfigFileTextToJson(tsconfigPath, (0, fs_1.readJsonSync)(tsconfigPath, false)).config;
|
|
39
38
|
if (!tsconfig || !tsconfig.compilerOptions) {
|
|
40
39
|
throw new Error(`Could not read and parse tsconfig.json at ${tsconfigPath}, or it ` +
|
|
@@ -166,7 +165,7 @@ function determinePath(root, orig) {
|
|
|
166
165
|
debug(`lib dir: ${lib}`);
|
|
167
166
|
debug(`src dir: ${src}`);
|
|
168
167
|
debug(`src commands dir: ${out}`);
|
|
169
|
-
if ((0,
|
|
168
|
+
if ((0, fs_1.existsSync)(out) || (0, fs_1.existsSync)(out + '.ts')) {
|
|
170
169
|
debug(`Found source file for ${orig} at ${out}`);
|
|
171
170
|
return out;
|
|
172
171
|
}
|
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;
|
package/lib/errors/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { CLIError } from './errors/cli';
|
|
|
5
5
|
export { ExitError } from './errors/exit';
|
|
6
6
|
export { ModuleLoadError } from './errors/module-load';
|
|
7
7
|
export { handle } from './handle';
|
|
8
|
-
export declare function exit(code?: number):
|
|
8
|
+
export declare function exit(code?: number): void;
|
|
9
9
|
export declare function error(input: Error | string, options: {
|
|
10
10
|
exit: false;
|
|
11
11
|
} & PrettyPrintableError): void;
|
package/lib/errors/index.js
CHANGED
|
@@ -39,7 +39,9 @@ Object.defineProperty(exports, "ModuleLoadError", { enumerable: true, get: funct
|
|
|
39
39
|
var handle_1 = require("./handle");
|
|
40
40
|
Object.defineProperty(exports, "handle", { enumerable: true, get: function () { return handle_1.handle; } });
|
|
41
41
|
function exit(code = 0) {
|
|
42
|
-
|
|
42
|
+
if (code !== 0) {
|
|
43
|
+
throw new exit_1.ExitError(code);
|
|
44
|
+
}
|
|
43
45
|
}
|
|
44
46
|
exports.exit = exit;
|
|
45
47
|
function error(input, options = {}) {
|
package/lib/help/index.js
CHANGED
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.loadHelpClass = exports.Help = exports.HelpBase = exports.standardizeIDFromArgv = exports.normalizeArgv = exports.getHelpFlagAdditions = exports.CommandHelp = void 0;
|
|
7
7
|
const node_util_1 = require("node:util");
|
|
8
8
|
const strip_ansi_1 = __importDefault(require("strip-ansi"));
|
|
9
|
-
const
|
|
9
|
+
const write_1 = __importDefault(require("../cli-ux/write"));
|
|
10
10
|
const errors_1 = require("../errors");
|
|
11
11
|
const module_loader_1 = require("../module-loader");
|
|
12
12
|
const cache_default_value_1 = require("../util/cache-default-value");
|
|
@@ -133,7 +133,7 @@ class Help extends HelpBase {
|
|
|
133
133
|
return new this.CommandHelpClass(command, this.config, this.opts);
|
|
134
134
|
}
|
|
135
135
|
log(...args) {
|
|
136
|
-
|
|
136
|
+
write_1.default.stdout(node_util_1.format.apply(this, args) + '\n');
|
|
137
137
|
}
|
|
138
138
|
async showCommandHelp(command) {
|
|
139
139
|
const name = command.id;
|
package/lib/index.js
CHANGED
|
@@ -22,16 +22,19 @@ 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.settings = exports.Performance = exports.Parser = exports.run = exports.Interfaces = exports.toStandardizedId = exports.toConfiguredId = exports.loadHelpClass = exports.HelpBase = exports.Help = exports.CommandHelp = exports.Flags = exports.execute = exports.handle = exports.Errors = exports.Plugin = exports.Config = exports.Command = exports.stdout = exports.stderr = exports.flush = exports.ux = exports.Args = void 0;
|
|
27
|
-
const
|
|
30
|
+
const write_1 = __importDefault(require("./cli-ux/write"));
|
|
28
31
|
function checkCWD() {
|
|
29
32
|
try {
|
|
30
33
|
process.cwd();
|
|
31
34
|
}
|
|
32
35
|
catch (error) {
|
|
33
36
|
if (error.code === 'ENOENT') {
|
|
34
|
-
|
|
37
|
+
write_1.default.stderr('WARNING: current directory does not exist\n');
|
|
35
38
|
}
|
|
36
39
|
}
|
|
37
40
|
}
|
|
@@ -40,9 +43,10 @@ exports.Args = __importStar(require("./args"));
|
|
|
40
43
|
exports.ux = __importStar(require("./cli-ux"));
|
|
41
44
|
var flush_1 = require("./cli-ux/flush");
|
|
42
45
|
Object.defineProperty(exports, "flush", { enumerable: true, get: function () { return flush_1.flush; } });
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
Object.defineProperty(exports, "
|
|
46
|
+
// Remove these in the next major version
|
|
47
|
+
var stream_1 = require("./cli-ux/stream");
|
|
48
|
+
Object.defineProperty(exports, "stderr", { enumerable: true, get: function () { return stream_1.stderr; } });
|
|
49
|
+
Object.defineProperty(exports, "stdout", { enumerable: true, get: function () { return stream_1.stdout; } });
|
|
46
50
|
var command_1 = require("./command");
|
|
47
51
|
Object.defineProperty(exports, "Command", { enumerable: true, get: function () { return command_1.Command; } });
|
|
48
52
|
var config_1 = require("./config");
|
package/lib/main.js
CHANGED
|
@@ -2,16 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.run = exports.versionAddition = exports.helpAddition = void 0;
|
|
4
4
|
const node_url_1 = require("node:url");
|
|
5
|
-
const
|
|
6
|
-
const stream_1 = require("./cli-ux/stream");
|
|
5
|
+
const cli_ux_1 = require("./cli-ux");
|
|
7
6
|
const config_1 = require("./config");
|
|
8
7
|
const help_1 = require("./help");
|
|
9
8
|
const performance_1 = require("./performance");
|
|
10
9
|
const debug = require('debug')('oclif:main');
|
|
11
|
-
const log = (message = '', ...args) => {
|
|
12
|
-
message = typeof message === 'string' ? message : (0, node_util_1.inspect)(message);
|
|
13
|
-
stream_1.stdout.write((0, node_util_1.format)(message, ...args) + '\n');
|
|
14
|
-
};
|
|
15
10
|
const helpAddition = (argv, config) => {
|
|
16
11
|
if (argv.length === 0 && !config.pjson.oclif.default)
|
|
17
12
|
return true;
|
|
@@ -57,7 +52,7 @@ async function run(argv, options) {
|
|
|
57
52
|
await config.runHook('init', { argv: argvSlice, id });
|
|
58
53
|
// display version if applicable
|
|
59
54
|
if ((0, exports.versionAddition)(argv, config)) {
|
|
60
|
-
log(config.userAgent);
|
|
55
|
+
cli_ux_1.ux.log(config.userAgent);
|
|
61
56
|
await collectPerf();
|
|
62
57
|
return;
|
|
63
58
|
}
|
package/lib/module-loader.js
CHANGED
|
@@ -6,6 +6,7 @@ const node_path_1 = require("node:path");
|
|
|
6
6
|
const node_url_1 = require("node:url");
|
|
7
7
|
const ts_node_1 = require("./config/ts-node");
|
|
8
8
|
const errors_1 = require("./errors");
|
|
9
|
+
const fs_1 = require("./util/fs");
|
|
9
10
|
const getPackageType = require('get-package-type');
|
|
10
11
|
/**
|
|
11
12
|
* Defines file extension resolution when source files do not have an extension.
|
|
@@ -166,7 +167,7 @@ function resolvePath(config, modulePath) {
|
|
|
166
167
|
(isPlugin(config) ? (0, ts_node_1.tsPath)(config.root, modulePath, config) : (0, ts_node_1.tsPath)(config.root, modulePath)) ?? modulePath;
|
|
167
168
|
let fileExists = false;
|
|
168
169
|
let isDirectory = false;
|
|
169
|
-
if ((0,
|
|
170
|
+
if ((0, fs_1.existsSync)(filePath)) {
|
|
170
171
|
fileExists = true;
|
|
171
172
|
try {
|
|
172
173
|
if ((0, node_fs_1.lstatSync)(filePath)?.isDirectory?.()) {
|
|
@@ -202,7 +203,7 @@ function findFile(filePath) {
|
|
|
202
203
|
// eslint-disable-next-line camelcase
|
|
203
204
|
for (const extension of s_EXTENSIONS) {
|
|
204
205
|
const testPath = `${filePath}${extension}`;
|
|
205
|
-
if ((0,
|
|
206
|
+
if ((0, fs_1.existsSync)(testPath)) {
|
|
206
207
|
return testPath;
|
|
207
208
|
}
|
|
208
209
|
}
|
package/lib/screen.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.errtermwidth = exports.stdtermwidth = void 0;
|
|
4
|
-
const stream_1 = require("./cli-ux/stream");
|
|
5
4
|
const settings_1 = require("./settings");
|
|
6
5
|
function termwidth(stream) {
|
|
7
6
|
if (!stream.isTTY) {
|
|
@@ -17,5 +16,5 @@ function termwidth(stream) {
|
|
|
17
16
|
return width;
|
|
18
17
|
}
|
|
19
18
|
const columns = Number.parseInt(process.env.OCLIF_COLUMNS, 10) || settings_1.settings.columns;
|
|
20
|
-
exports.stdtermwidth = columns || termwidth(
|
|
21
|
-
exports.errtermwidth = columns || termwidth(
|
|
19
|
+
exports.stdtermwidth = columns || termwidth(process.stdout);
|
|
20
|
+
exports.errtermwidth = columns || termwidth(process.stderr);
|
|
@@ -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,154 @@
|
|
|
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
|
+
// eslint-disable-next-line node/no-missing-require
|
|
80
|
+
pnp = require(require.resolve('pnpapi', { paths: [root] }));
|
|
81
|
+
return pnp;
|
|
82
|
+
}
|
|
83
|
+
const getKey = (locator) => JSON.stringify(locator);
|
|
84
|
+
const isPeerDependency = (pkg, parentPkg, name) => getKey(pkg?.packageDependencies.get(name)) === getKey(parentPkg?.packageDependencies.get(name));
|
|
85
|
+
/**
|
|
86
|
+
* Traverse PnP dependency tree to find plugin root directory.
|
|
87
|
+
*
|
|
88
|
+
* Implementation adapted from https://yarnpkg.com/advanced/pnpapi#traversing-the-dependency-tree
|
|
89
|
+
*/
|
|
90
|
+
function findPnpRoot(name, root) {
|
|
91
|
+
maybeRequirePnpApi(root);
|
|
92
|
+
const seen = new Set();
|
|
93
|
+
const traverseDependencyTree = (locator, parentPkg) => {
|
|
94
|
+
// Prevent infinite recursion when A depends on B which depends on A
|
|
95
|
+
const key = getKey(locator);
|
|
96
|
+
if (seen.has(key))
|
|
97
|
+
return;
|
|
98
|
+
const pkg = pnp.getPackageInformation(locator);
|
|
99
|
+
if (locator.name === name) {
|
|
100
|
+
return pkg.packageLocation;
|
|
101
|
+
}
|
|
102
|
+
seen.add(key);
|
|
103
|
+
for (const [name, referencish] of pkg.packageDependencies) {
|
|
104
|
+
// Unmet peer dependencies
|
|
105
|
+
if (referencish === null)
|
|
106
|
+
continue;
|
|
107
|
+
// Avoid iterating on peer dependencies - very expensive
|
|
108
|
+
if (parentPkg !== null && isPeerDependency(pkg, parentPkg, name))
|
|
109
|
+
continue;
|
|
110
|
+
const childLocator = pnp.getLocator(name, referencish);
|
|
111
|
+
const foundSomething = traverseDependencyTree(childLocator, pkg);
|
|
112
|
+
if (foundSomething)
|
|
113
|
+
return foundSomething;
|
|
114
|
+
}
|
|
115
|
+
// Important: This `delete` here causes the traversal to go over nodes even
|
|
116
|
+
// if they have already been traversed in another branch. If you don't need
|
|
117
|
+
// that, remove this line for a hefty speed increase.
|
|
118
|
+
seen.delete(key);
|
|
119
|
+
};
|
|
120
|
+
// Iterate on each workspace
|
|
121
|
+
for (const locator of pnp.getDependencyTreeRoots()) {
|
|
122
|
+
const foundSomething = traverseDependencyTree(locator);
|
|
123
|
+
if (foundSomething)
|
|
124
|
+
return foundSomething;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Returns the root directory of the plugin.
|
|
129
|
+
*
|
|
130
|
+
* It first attempts to use require.resolve to find the plugin root.
|
|
131
|
+
* If that returns a path, it will `cd` up the file system until if finds the package.json for the plugin
|
|
132
|
+
* Example: node_modules/@oclif/plugin-version/dist/index.js -> node_modules/@oclif/plugin-version
|
|
133
|
+
*
|
|
134
|
+
* If require.resolve throws an error, it will attempt to find the plugin root by traversing the file system.
|
|
135
|
+
* If we're in a PnP environment (determined by process.versions.pnp), it will use the pnpapi module to
|
|
136
|
+
* traverse the dependency tree. Otherwise, it will traverse the node_modules until it finds a package.json
|
|
137
|
+
* with a matching name.
|
|
138
|
+
*
|
|
139
|
+
* If no path is found, undefined is returned which will eventually result in a thrown Error from Plugin.
|
|
140
|
+
*/
|
|
141
|
+
async function findRoot(name, root) {
|
|
142
|
+
if (name) {
|
|
143
|
+
let pkgPath;
|
|
144
|
+
try {
|
|
145
|
+
pkgPath = require.resolve(name, { paths: [root] });
|
|
146
|
+
}
|
|
147
|
+
catch { }
|
|
148
|
+
if (pkgPath)
|
|
149
|
+
return findPluginRoot((0, node_path_1.dirname)(pkgPath), name);
|
|
150
|
+
return process.versions.pnp ? findPnpRoot(name, root) : findRootLegacy(name, root);
|
|
151
|
+
}
|
|
152
|
+
return findPluginRoot(root);
|
|
153
|
+
}
|
|
154
|
+
exports.findRoot = findRoot;
|
package/lib/util/fs.d.ts
CHANGED
|
@@ -17,3 +17,4 @@ export declare function readJson<T = unknown>(path: string): Promise<T>;
|
|
|
17
17
|
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
|
+
export declare function existsSync(path: string): boolean;
|
package/lib/util/fs.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.safeReadJson = exports.readJsonSync = exports.readJson = exports.fileExists = exports.dirExists = exports.requireJson = void 0;
|
|
3
|
+
exports.existsSync = exports.safeReadJson = exports.readJsonSync = exports.readJson = exports.fileExists = exports.dirExists = exports.requireJson = void 0;
|
|
4
4
|
const node_fs_1 = require("node:fs");
|
|
5
5
|
const promises_1 = require("node:fs/promises");
|
|
6
6
|
const node_path_1 = require("node:path");
|
|
@@ -67,3 +67,7 @@ async function safeReadJson(path) {
|
|
|
67
67
|
catch { }
|
|
68
68
|
}
|
|
69
69
|
exports.safeReadJson = safeReadJson;
|
|
70
|
+
function existsSync(path) {
|
|
71
|
+
return (0, node_fs_1.existsSync)(path);
|
|
72
|
+
}
|
|
73
|
+
exports.existsSync = existsSync;
|
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.4.1-dev.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",
|
|
@@ -72,7 +73,7 @@
|
|
|
72
73
|
"nyc": "^15.1.0",
|
|
73
74
|
"prettier": "^3.0.3",
|
|
74
75
|
"shx": "^0.3.4",
|
|
75
|
-
"sinon": "^
|
|
76
|
+
"sinon": "^16.1.0",
|
|
76
77
|
"ts-node": "^10.9.1",
|
|
77
78
|
"tsd": "^0.29.0",
|
|
78
79
|
"typescript": "^5"
|