@pnpm/cli.default-reporter 1100.3.17 → 1100.3.19
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/CHANGELOG.md +21 -0
- package/lib/index.js +115 -6
- package/lib/reporterForClient/reportUpdateCheck.js +10 -10
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @pnpm/default-reporter
|
|
2
2
|
|
|
3
|
+
## 1100.3.19
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies:
|
|
8
|
+
- @pnpm/error@1100.1.4
|
|
9
|
+
|
|
10
|
+
## 1100.3.18
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- The progress output no longer overwrites the lines above it once it grows taller than the terminal window [#14270](https://github.com/pnpm/pnpm/issues/14270).
|
|
15
|
+
|
|
16
|
+
- The update notification now suggests `pnpm self-update` when `PNPM_HOME` manages the pnpm in use, and the [standalone install script](https://pnpm.io/installation) otherwise — under Corepack, or when another package manager installed pnpm. `pnpm self-update` under Corepack names the standalone install script too.
|
|
17
|
+
|
|
18
|
+
- Updated dependencies:
|
|
19
|
+
- @pnpm/cli.meta@1100.1.0
|
|
20
|
+
- @pnpm/core-loggers@1100.3.4
|
|
21
|
+
- @pnpm/deps.inspection.peers-issues-renderer@1100.0.14
|
|
22
|
+
- @pnpm/types@1102.1.0
|
|
23
|
+
|
|
3
24
|
## 1100.3.17
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import createDiffer from 'ansi-diff';
|
|
2
2
|
import * as Rx from 'rxjs';
|
|
3
3
|
import { filter, map, mergeAll } from 'rxjs/operators';
|
|
4
|
+
import stringLength from 'string-length';
|
|
4
5
|
import { EOL } from './constants.js';
|
|
5
6
|
import { mergeOutputs } from './mergeOutputs.js';
|
|
6
7
|
import { reporterForClient } from './reporterForClient/index.js';
|
|
@@ -12,7 +13,10 @@ export { formatWarn };
|
|
|
12
13
|
const ERASE_TO_END_OF_DISPLAY = '\x1b[0J';
|
|
13
14
|
export function initDefaultReporter(opts) {
|
|
14
15
|
const proc = opts.context.process ?? process;
|
|
15
|
-
|
|
16
|
+
// At least one column: `columns - 2` is zero on a two-column terminal, and a
|
|
17
|
+
// caller may pass zero outright. A zero width would make every wrap
|
|
18
|
+
// calculation — the differ's and `renderedRows`' — meaningless.
|
|
19
|
+
const outputMaxWidth = Math.max(1, opts.reportingOptions?.outputMaxWidth ?? (proc.stdout.columns && proc.stdout.columns - 2) ?? 80);
|
|
16
20
|
const output$ = toOutput$({
|
|
17
21
|
...opts,
|
|
18
22
|
reportingOptions: {
|
|
@@ -38,11 +42,20 @@ export function initDefaultReporter(opts) {
|
|
|
38
42
|
}
|
|
39
43
|
const stream = opts.useStderr ? proc.stderr : proc.stdout;
|
|
40
44
|
const write = stream.write.bind(stream);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
// The width the live differ wraps its frame at, so a resize can be noticed.
|
|
46
|
+
let differWidth = 0;
|
|
47
|
+
const newDiffer = () => {
|
|
48
|
+
differWidth = Math.max(1, stream.columns ?? outputMaxWidth);
|
|
49
|
+
return createDiffer({ height: stream.rows, width: differWidth });
|
|
50
|
+
};
|
|
45
51
|
let diff = newDiffer();
|
|
52
|
+
// How many leading lines of the view have scrolled out of the differ's frame
|
|
53
|
+
// and been committed to the scrollback, how many rows the frame the differ is
|
|
54
|
+
// holding takes up, and whether it already outgrew the terminal it was drawn
|
|
55
|
+
// on. See `commitOverflow`.
|
|
56
|
+
let committedLines = 0;
|
|
57
|
+
let renderedFrameRows = 0;
|
|
58
|
+
let renderedFrameOutgrewTerminal = false;
|
|
46
59
|
// Hold redraws while an interactive prompt owns the terminal (see PromptMessage).
|
|
47
60
|
let promptActive = false;
|
|
48
61
|
const onLog = (log) => {
|
|
@@ -74,6 +87,11 @@ export function initDefaultReporter(opts) {
|
|
|
74
87
|
// An example of such prompt may be seen by running: pnpm update --interactive
|
|
75
88
|
if (!view.endsWith(EOL))
|
|
76
89
|
view += EOL;
|
|
90
|
+
const lines = view.slice(0, -EOL.length).split(EOL);
|
|
91
|
+
const committed = commitOverflow(lines);
|
|
92
|
+
// The lines from `committedLines` on are already laid out contiguously in
|
|
93
|
+
// the view, so the visible frame is a slice of it rather than a second copy.
|
|
94
|
+
const frame = view.slice(viewOffsetOfLine(view, lines, committedLines));
|
|
77
95
|
// `\r` resets the column to 0 in case an external process (e.g. an SSH
|
|
78
96
|
// passphrase prompt) left the cursor mid-line. `ansi-diff` then writes
|
|
79
97
|
// only the differential — the characters that actually changed between
|
|
@@ -82,13 +100,104 @@ export function initDefaultReporter(opts) {
|
|
|
82
100
|
// tick. `\x1b[K` erases trailing characters on the current line;
|
|
83
101
|
// `\x1b[0J` erases anything an external process wrote below the
|
|
84
102
|
// rendered frame.
|
|
85
|
-
write(`\r${diff.update(
|
|
103
|
+
write(`\r${committed}${diff.update(frame)}\x1b[K${ERASE_TO_END_OF_DISPLAY}`);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Hands the lines that no longer fit on screen over to the scrollback and
|
|
107
|
+
* restarts the differ below them, returning the differential that performs
|
|
108
|
+
* the handover.
|
|
109
|
+
*
|
|
110
|
+
* `ansi-diff` redraws by moving the cursor up from the end of its frame, so
|
|
111
|
+
* it can only reach lines that are still on screen. A frame taller than the
|
|
112
|
+
* terminal has scrolled its top away, and every later redraw then lands that
|
|
113
|
+
* many rows too low — overwriting output above the frame instead of updating
|
|
114
|
+
* it (pnpm/pnpm#14270). Committing the overflow keeps the frame within the
|
|
115
|
+
* terminal, at the cost of no longer being able to revise what was committed.
|
|
116
|
+
*/
|
|
117
|
+
function commitOverflow(lines) {
|
|
118
|
+
if (Math.max(1, stream.columns ?? outputMaxWidth) !== differWidth) {
|
|
119
|
+
// The terminal was resized. The frame on screen has reflowed at the new
|
|
120
|
+
// width, so every position the differ tracked against the old one is
|
|
121
|
+
// wrong: start over below what is already there.
|
|
122
|
+
diff = newDiffer();
|
|
123
|
+
}
|
|
124
|
+
if (lines.length <= committedLines) {
|
|
125
|
+
// The view no longer reaches past what was committed — an error frame
|
|
126
|
+
// replaces it rather than extending it. Render it whole, below.
|
|
127
|
+
committedLines = 0;
|
|
128
|
+
diff = newDiffer();
|
|
129
|
+
return '';
|
|
130
|
+
}
|
|
131
|
+
const rows = stream.rows;
|
|
132
|
+
if (!rows)
|
|
133
|
+
return '';
|
|
134
|
+
const width = differWidth;
|
|
135
|
+
// One row is left over for the cursor line that the trailing EOL puts
|
|
136
|
+
// below the frame.
|
|
137
|
+
const maxRows = Math.max(rows - 1, 1);
|
|
138
|
+
let uncommittedRows = 0;
|
|
139
|
+
for (let i = committedLines; i < lines.length; i++) {
|
|
140
|
+
uncommittedRows += renderedRows(lines[i], width);
|
|
141
|
+
}
|
|
142
|
+
// The last line always stays in the frame — there would be nothing left to
|
|
143
|
+
// redraw otherwise — so the walk upwards starts one line above it.
|
|
144
|
+
let firstVisible = lines.length - 1;
|
|
145
|
+
let frameRows = renderedRows(lines[firstVisible], width);
|
|
146
|
+
for (let i = firstVisible - 1; i >= committedLines; i--) {
|
|
147
|
+
const lineRows = renderedRows(lines[i], width);
|
|
148
|
+
if (frameRows + lineRows > maxRows)
|
|
149
|
+
break;
|
|
150
|
+
frameRows += lineRows;
|
|
151
|
+
firstVisible = i;
|
|
152
|
+
}
|
|
153
|
+
// A frame taller than the terminal has scrolled its own top away — whether
|
|
154
|
+
// because a line outgrew the screen or because the window shrank under it —
|
|
155
|
+
// so no cursor move reaches back into it, and growing the window again does
|
|
156
|
+
// not bring it back. Start afresh below instead, reprinting rather than
|
|
157
|
+
// revising, and leave the commit for the next frame, whose layout is one
|
|
158
|
+
// this differ laid out itself.
|
|
159
|
+
const cannotRevise = renderedFrameOutgrewTerminal || renderedFrameRows > maxRows;
|
|
160
|
+
if (cannotRevise || firstVisible === committedLines) {
|
|
161
|
+
renderedFrameRows = uncommittedRows;
|
|
162
|
+
renderedFrameOutgrewTerminal = uncommittedRows > maxRows;
|
|
163
|
+
if (cannotRevise || renderedFrameOutgrewTerminal)
|
|
164
|
+
diff = newDiffer();
|
|
165
|
+
return '';
|
|
166
|
+
}
|
|
167
|
+
renderedFrameRows = frameRows;
|
|
168
|
+
renderedFrameOutgrewTerminal = false;
|
|
169
|
+
// Shrinking the frame to just the overflow leaves those lines untouched
|
|
170
|
+
// where they already are, erases the rest of the frame below them, and
|
|
171
|
+
// parks the cursor on the next line — where the fresh differ starts.
|
|
172
|
+
const handover = diff.update(`${lines.slice(committedLines, firstVisible).join(EOL)}${EOL}`).toString();
|
|
173
|
+
diff = newDiffer();
|
|
174
|
+
committedLines = firstVisible;
|
|
175
|
+
return handover;
|
|
86
176
|
}
|
|
87
177
|
return () => {
|
|
88
178
|
subscription.unsubscribe();
|
|
89
179
|
opts.streamParser.removeListener('data', onLog);
|
|
90
180
|
};
|
|
91
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* Where the `index`-th of `lines` starts in the `view` they were split from.
|
|
184
|
+
* Measured from the end, so a long committed prefix costs nothing.
|
|
185
|
+
*/
|
|
186
|
+
function viewOffsetOfLine(view, lines, index) {
|
|
187
|
+
let trailing = 0;
|
|
188
|
+
for (let i = lines.length - 1; i >= index; i--) {
|
|
189
|
+
trailing += lines[i].length + EOL.length;
|
|
190
|
+
}
|
|
191
|
+
return view.length - trailing;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* How many terminal rows `line` occupies once wrapped at `width`, counting the
|
|
195
|
+
* escape sequences in it as zero-width. Never zero: an empty line still takes a
|
|
196
|
+
* row. `width` is the terminal's own column count, clamped to at least one.
|
|
197
|
+
*/
|
|
198
|
+
function renderedRows(line, width) {
|
|
199
|
+
return Math.max(1, Math.ceil(stringLength(line) / width));
|
|
200
|
+
}
|
|
92
201
|
export function toOutput$(opts) {
|
|
93
202
|
opts = opts || {};
|
|
94
203
|
const contextPushStream = new Rx.Subject();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isExecutedByCorepack, standaloneInstallCommand } from '@pnpm/cli.meta';
|
|
2
2
|
import boxen from 'boxen';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import * as Rx from 'rxjs';
|
|
@@ -7,9 +7,8 @@ import semver from 'semver';
|
|
|
7
7
|
export function reportUpdateCheck(log$, opts) {
|
|
8
8
|
return log$.pipe(take(1), filter((log) => semver.gt(log.latestVersion, log.currentVersion)), map((log) => {
|
|
9
9
|
const updateMessage = renderUpdateMessage({
|
|
10
|
-
currentPkgIsExecutable: detectIfCurrentPkgIsExecutable(opts.process),
|
|
11
|
-
latestVersion: log.latestVersion,
|
|
12
10
|
env: opts.env,
|
|
11
|
+
platform: opts.process.platform,
|
|
13
12
|
});
|
|
14
13
|
return Rx.of({
|
|
15
14
|
msg: boxen(`\
|
|
@@ -30,13 +29,14 @@ function renderUpdateMessage(opts) {
|
|
|
30
29
|
return `To update, run: ${chalk.magenta(updateCommand)}`;
|
|
31
30
|
}
|
|
32
31
|
function renderUpdateCommand(opts) {
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
// `pnpm self-update` replaces the pnpm that PNPM_HOME manages. Corepack
|
|
33
|
+
// refuses it outright, and an install another package manager owns is
|
|
34
|
+
// resolved from that manager's bin directory rather than pnpm's home, so a
|
|
35
|
+
// self-update would land beside the executable in use instead of replacing
|
|
36
|
+
// it. The installer is the command that updates either one.
|
|
37
|
+
if (isExecutedByCorepack(opts.env) || !opts.env.PNPM_HOME) {
|
|
38
|
+
return standaloneInstallCommand(opts.platform);
|
|
35
39
|
}
|
|
36
|
-
|
|
37
|
-
return 'pnpm self-update';
|
|
38
|
-
}
|
|
39
|
-
const pkgName = opts.currentPkgIsExecutable ? '@pnpm/exe' : 'pnpm';
|
|
40
|
-
return `pnpm add -g ${pkgName}`;
|
|
40
|
+
return 'pnpm self-update';
|
|
41
41
|
}
|
|
42
42
|
//# sourceMappingURL=reportUpdateCheck.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/cli.default-reporter",
|
|
3
|
-
"version": "1100.3.
|
|
3
|
+
"version": "1100.3.19",
|
|
4
4
|
"description": "The default reporter of pnpm",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -32,21 +32,21 @@
|
|
|
32
32
|
"pnpm-render": "bin/pnpm-render.mjs"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@pnpm/cli.meta": "1100.0
|
|
36
|
-
"@pnpm/core-loggers": "1100.3.
|
|
37
|
-
"@pnpm/deps.inspection.peers-issues-renderer": "1100.0.
|
|
38
|
-
"@pnpm/error": "1100.1.
|
|
35
|
+
"@pnpm/cli.meta": "1100.1.0",
|
|
36
|
+
"@pnpm/core-loggers": "1100.3.4",
|
|
37
|
+
"@pnpm/deps.inspection.peers-issues-renderer": "1100.0.14",
|
|
38
|
+
"@pnpm/error": "1100.1.4",
|
|
39
39
|
"@pnpm/installing.dedupe.issues-renderer": "1100.0.3",
|
|
40
40
|
"@pnpm/installing.dedupe.types": "1100.0.2",
|
|
41
41
|
"@pnpm/text.ordinal-comparator": "1100.0.0",
|
|
42
|
-
"@pnpm/types": "1102.
|
|
42
|
+
"@pnpm/types": "1102.1.0",
|
|
43
43
|
"ansi-diff": "^1.2.0",
|
|
44
44
|
"boxen": "npm:@zkochan/boxen@5.1.2",
|
|
45
45
|
"chalk": "^6.0.0",
|
|
46
46
|
"cli-truncate": "^6.1.1",
|
|
47
47
|
"normalize-path": "^3.0.0",
|
|
48
|
-
"pretty-bytes": "^7.1.
|
|
49
|
-
"pretty-ms": "^9.3.
|
|
48
|
+
"pretty-bytes": "^7.1.3",
|
|
49
|
+
"pretty-ms": "^9.3.1",
|
|
50
50
|
"ramda": "npm:@pnpm/ramda@0.28.1",
|
|
51
51
|
"rxjs": "^7.8.2",
|
|
52
52
|
"semver": "^7.8.5",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@jest/globals": "30.4.1",
|
|
61
|
-
"@pnpm/cli.default-reporter": "1100.3.
|
|
61
|
+
"@pnpm/cli.default-reporter": "1100.3.19",
|
|
62
62
|
"@pnpm/logger": "1100.0.0",
|
|
63
63
|
"@types/normalize-path": "^3.0.2",
|
|
64
64
|
"@types/ramda": "0.32.0",
|