@pnpm/cli.default-reporter 1002.0.11
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/LICENSE +22 -0
- package/README.md +41 -0
- package/lib/constants.d.ts +1 -0
- package/lib/constants.js +4 -0
- package/lib/index.d.ts +54 -0
- package/lib/index.js +230 -0
- package/lib/mergeOutputs.d.ts +4 -0
- package/lib/mergeOutputs.js +69 -0
- package/lib/reportError.d.ts +3 -0
- package/lib/reportError.js +425 -0
- package/lib/reporterForClient/index.d.ts +52 -0
- package/lib/reporterForClient/index.js +94 -0
- package/lib/reporterForClient/outputConstants.d.ts +4 -0
- package/lib/reporterForClient/outputConstants.js +6 -0
- package/lib/reporterForClient/pkgsDiff.d.ts +36 -0
- package/lib/reporterForClient/pkgsDiff.js +113 -0
- package/lib/reporterForClient/reportBigTarballsProgress.d.ts +8 -0
- package/lib/reporterForClient/reportBigTarballsProgress.js +26 -0
- package/lib/reporterForClient/reportContext.d.ts +10 -0
- package/lib/reporterForClient/reportContext.js +34 -0
- package/lib/reporterForClient/reportDeprecations.d.ts +11 -0
- package/lib/reporterForClient/reportDeprecations.js +27 -0
- package/lib/reporterForClient/reportExecutionTime.d.ts +6 -0
- package/lib/reporterForClient/reportExecutionTime.js +13 -0
- package/lib/reporterForClient/reportHooks.d.ts +8 -0
- package/lib/reporterForClient/reportHooks.js +12 -0
- package/lib/reporterForClient/reportIgnoredBuilds.d.ts +11 -0
- package/lib/reporterForClient/reportIgnoredBuilds.js +21 -0
- package/lib/reporterForClient/reportInstallChecks.d.ts +7 -0
- package/lib/reporterForClient/reportInstallChecks.js +19 -0
- package/lib/reporterForClient/reportInstallingConfigDeps.d.ts +5 -0
- package/lib/reporterForClient/reportInstallingConfigDeps.js +18 -0
- package/lib/reporterForClient/reportLifecycleScripts.d.ts +13 -0
- package/lib/reporterForClient/reportLifecycleScripts.js +193 -0
- package/lib/reporterForClient/reportMisc.d.ts +17 -0
- package/lib/reporterForClient/reportMisc.js +69 -0
- package/lib/reporterForClient/reportPeerDependencyIssues.d.ts +7 -0
- package/lib/reporterForClient/reportPeerDependencyIssues.js +16 -0
- package/lib/reporterForClient/reportProgress.d.ts +16 -0
- package/lib/reporterForClient/reportProgress.js +123 -0
- package/lib/reporterForClient/reportRequestRetry.d.ts +5 -0
- package/lib/reporterForClient/reportRequestRetry.js +15 -0
- package/lib/reporterForClient/reportScope.d.ts +8 -0
- package/lib/reporterForClient/reportScope.js +41 -0
- package/lib/reporterForClient/reportSkippedOptionalDependencies.d.ts +7 -0
- package/lib/reporterForClient/reportSkippedOptionalDependencies.js +8 -0
- package/lib/reporterForClient/reportStats.d.ts +13 -0
- package/lib/reporterForClient/reportStats.js +143 -0
- package/lib/reporterForClient/reportSummary.d.ts +19 -0
- package/lib/reporterForClient/reportSummary.js +79 -0
- package/lib/reporterForClient/reportUpdateCheck.d.ts +8 -0
- package/lib/reporterForClient/reportUpdateCheck.js +42 -0
- package/lib/reporterForClient/utils/formatPrefix.d.ts +2 -0
- package/lib/reporterForClient/utils/formatPrefix.js +19 -0
- package/lib/reporterForClient/utils/formatWarn.d.ts +1 -0
- package/lib/reporterForClient/utils/formatWarn.js +8 -0
- package/lib/reporterForClient/utils/zooming.d.ts +4 -0
- package/lib/reporterForClient/utils/zooming.js +13 -0
- package/package.json +76 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { difference, mergeRight } from 'ramda';
|
|
2
|
+
import * as Rx from 'rxjs';
|
|
3
|
+
import { filter, map, mapTo, reduce, scan, startWith, take } from 'rxjs/operators';
|
|
4
|
+
export const propertyByDependencyType = {
|
|
5
|
+
dev: 'devDependencies',
|
|
6
|
+
nodeModulesOnly: 'node_modules',
|
|
7
|
+
optional: 'optionalDependencies',
|
|
8
|
+
peer: 'peerDependencies',
|
|
9
|
+
prod: 'dependencies',
|
|
10
|
+
};
|
|
11
|
+
export function getPkgsDiff(log$, opts) {
|
|
12
|
+
const deprecationSet$ = log$.deprecation
|
|
13
|
+
.pipe(filter((log) => !opts.prefix || log.prefix === opts.prefix), scan((acc, log) => {
|
|
14
|
+
acc.add(log.pkgId);
|
|
15
|
+
return acc;
|
|
16
|
+
}, new Set()), startWith(new Set()));
|
|
17
|
+
const filterPrefix = opts.prefix
|
|
18
|
+
? filter((log) => log.prefix === opts.prefix)
|
|
19
|
+
: (x) => x;
|
|
20
|
+
const pkgsDiff$ = Rx.combineLatest(log$.root.pipe(filterPrefix), deprecationSet$).pipe(scan((pkgsDiff, args) => {
|
|
21
|
+
const rootLog = args[0];
|
|
22
|
+
const deprecationSet = args[1];
|
|
23
|
+
let action;
|
|
24
|
+
let log; // eslint-disable-line
|
|
25
|
+
if ('added' in rootLog) {
|
|
26
|
+
action = '+';
|
|
27
|
+
log = rootLog['added'];
|
|
28
|
+
}
|
|
29
|
+
else if ('removed' in rootLog) {
|
|
30
|
+
action = '-';
|
|
31
|
+
log = rootLog['removed'];
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
return pkgsDiff;
|
|
35
|
+
}
|
|
36
|
+
const depType = (log.dependencyType || 'nodeModulesOnly');
|
|
37
|
+
const oppositeKey = `${action === '-' ? '+' : '-'}${log.name}`;
|
|
38
|
+
const previous = pkgsDiff[depType][oppositeKey];
|
|
39
|
+
if (previous && previous.version === log.version) {
|
|
40
|
+
delete pkgsDiff[depType][oppositeKey];
|
|
41
|
+
return pkgsDiff;
|
|
42
|
+
}
|
|
43
|
+
pkgsDiff[depType][`${action}${log.name}`] = {
|
|
44
|
+
added: action === '+',
|
|
45
|
+
deprecated: deprecationSet.has(log.id),
|
|
46
|
+
from: log.linkedFrom,
|
|
47
|
+
latest: log.latest,
|
|
48
|
+
name: log.name,
|
|
49
|
+
realName: log.realName,
|
|
50
|
+
version: log.version ?? log.id,
|
|
51
|
+
};
|
|
52
|
+
return pkgsDiff;
|
|
53
|
+
}, {
|
|
54
|
+
dev: {},
|
|
55
|
+
nodeModulesOnly: {},
|
|
56
|
+
optional: {},
|
|
57
|
+
peer: {},
|
|
58
|
+
prod: {},
|
|
59
|
+
}), startWith({
|
|
60
|
+
dev: {},
|
|
61
|
+
nodeModulesOnly: {},
|
|
62
|
+
optional: {},
|
|
63
|
+
peer: {},
|
|
64
|
+
prod: {},
|
|
65
|
+
}));
|
|
66
|
+
const packageManifest$ = Rx.merge(log$.packageManifest.pipe(filterPrefix), log$.summary.pipe(filterPrefix, mapTo({})))
|
|
67
|
+
.pipe(take(2), reduce(mergeRight, {}) // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
68
|
+
);
|
|
69
|
+
return Rx.combineLatest(pkgsDiff$, packageManifest$)
|
|
70
|
+
.pipe(map(([pkgsDiff, packageManifests]) => {
|
|
71
|
+
if ((packageManifests['initial'] == null) || (packageManifests['updated'] == null))
|
|
72
|
+
return pkgsDiff;
|
|
73
|
+
const initialPackageManifest = removeOptionalFromProdDeps(packageManifests['initial']);
|
|
74
|
+
const updatedPackageManifest = removeOptionalFromProdDeps(packageManifests['updated']);
|
|
75
|
+
for (const depType of ['peer', 'prod', 'optional', 'dev']) {
|
|
76
|
+
const prop = propertyByDependencyType[depType];
|
|
77
|
+
const initialDeps = Object.keys(initialPackageManifest[prop] ?? {});
|
|
78
|
+
const updatedDeps = Object.keys(updatedPackageManifest[prop] ?? {});
|
|
79
|
+
const removedDeps = difference(initialDeps, updatedDeps);
|
|
80
|
+
for (const removedDep of removedDeps) {
|
|
81
|
+
if (!pkgsDiff[depType][`-${removedDep}`]) {
|
|
82
|
+
pkgsDiff[depType][`-${removedDep}`] = {
|
|
83
|
+
added: false,
|
|
84
|
+
name: removedDep,
|
|
85
|
+
version: initialPackageManifest[prop]?.[removedDep],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const addedDeps = difference(updatedDeps, initialDeps);
|
|
90
|
+
for (const addedDep of addedDeps) {
|
|
91
|
+
if (!pkgsDiff[depType][`+${addedDep}`]) {
|
|
92
|
+
pkgsDiff[depType][`+${addedDep}`] = {
|
|
93
|
+
added: true,
|
|
94
|
+
name: addedDep,
|
|
95
|
+
version: updatedPackageManifest[prop]?.[addedDep],
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return pkgsDiff;
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
103
|
+
function removeOptionalFromProdDeps(pkg) {
|
|
104
|
+
if ((pkg.dependencies == null) || (pkg.optionalDependencies == null))
|
|
105
|
+
return pkg;
|
|
106
|
+
for (const depName of Object.keys(pkg.dependencies)) {
|
|
107
|
+
if (pkg.optionalDependencies[depName]) {
|
|
108
|
+
delete pkg.dependencies[depName];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return pkg;
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=pkgsDiff.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FetchingProgressLog } from '@pnpm/core-loggers';
|
|
2
|
+
import type * as Rx from 'rxjs';
|
|
3
|
+
export declare function reportBigTarballProgress(log$: {
|
|
4
|
+
fetchingProgress: Rx.Observable<FetchingProgressLog>;
|
|
5
|
+
}): Rx.Observable<Rx.Observable<{
|
|
6
|
+
fixed: boolean;
|
|
7
|
+
msg: string;
|
|
8
|
+
}>>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import prettyBytes from 'pretty-bytes';
|
|
2
|
+
import { filter, map, startWith } from 'rxjs/operators';
|
|
3
|
+
import { hlValue, } from './outputConstants.js';
|
|
4
|
+
const BIG_TARBALL_SIZE = 1024 * 1024 * 5; // 5 MB
|
|
5
|
+
const PRETTY_OPTS = {
|
|
6
|
+
minimumFractionDigits: 2,
|
|
7
|
+
maximumFractionDigits: 2,
|
|
8
|
+
};
|
|
9
|
+
export function reportBigTarballProgress(log$) {
|
|
10
|
+
return log$.fetchingProgress.pipe(filter((log) => log.status === 'started' &&
|
|
11
|
+
typeof log.size === 'number' && log.size >= BIG_TARBALL_SIZE &&
|
|
12
|
+
// When retrying the download, keep the existing progress line.
|
|
13
|
+
// Fixing issue: https://github.com/pnpm/pnpm/issues/1013
|
|
14
|
+
log.attempt === 1), map((startedLog) => {
|
|
15
|
+
const size = prettyBytes(startedLog.size ?? 0, PRETTY_OPTS);
|
|
16
|
+
return log$.fetchingProgress.pipe(filter((log) => log.status === 'in_progress' && log.packageId === startedLog['packageId']), map((log) => log.downloaded ?? 0), startWith(0), map((downloadedRaw) => {
|
|
17
|
+
const done = startedLog.size === downloadedRaw;
|
|
18
|
+
const downloaded = prettyBytes(downloadedRaw, PRETTY_OPTS);
|
|
19
|
+
return {
|
|
20
|
+
fixed: !done,
|
|
21
|
+
msg: `Downloading ${startedLog['packageId']}: ${hlValue(downloaded)}/${hlValue(size)}${done ? ', done' : ''}`,
|
|
22
|
+
};
|
|
23
|
+
}));
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=reportBigTarballsProgress.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ContextLog, PackageImportMethodLog } from '@pnpm/core-loggers';
|
|
2
|
+
import * as Rx from 'rxjs';
|
|
3
|
+
export declare function reportContext(log$: {
|
|
4
|
+
context: Rx.Observable<ContextLog>;
|
|
5
|
+
packageImportMethod: Rx.Observable<PackageImportMethodLog>;
|
|
6
|
+
}, opts: {
|
|
7
|
+
cwd: string;
|
|
8
|
+
}): Rx.Observable<Rx.Observable<{
|
|
9
|
+
msg: string;
|
|
10
|
+
}>>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import normalize from 'normalize-path';
|
|
3
|
+
import * as Rx from 'rxjs';
|
|
4
|
+
import { map, take } from 'rxjs/operators';
|
|
5
|
+
export function reportContext(log$, opts) {
|
|
6
|
+
return Rx.combineLatest(log$.context.pipe(take(1)), log$.packageImportMethod.pipe(take(1)))
|
|
7
|
+
.pipe(map(([context, packageImportMethod]) => {
|
|
8
|
+
if (context.currentLockfileExists) {
|
|
9
|
+
return Rx.NEVER;
|
|
10
|
+
}
|
|
11
|
+
let method;
|
|
12
|
+
switch (packageImportMethod.method) {
|
|
13
|
+
case 'copy':
|
|
14
|
+
method = 'copied';
|
|
15
|
+
break;
|
|
16
|
+
case 'clone':
|
|
17
|
+
method = 'cloned';
|
|
18
|
+
break;
|
|
19
|
+
case 'hardlink':
|
|
20
|
+
method = 'hard linked';
|
|
21
|
+
break;
|
|
22
|
+
default:
|
|
23
|
+
method = packageImportMethod.method;
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
return Rx.of({
|
|
27
|
+
msg: `\
|
|
28
|
+
Packages are ${method} from the content-addressable store to the virtual store.
|
|
29
|
+
Content-addressable store is at: ${context.storeDir}
|
|
30
|
+
Virtual store is at: ${normalize(path.relative(opts.cwd, context.virtualStoreDir))}`,
|
|
31
|
+
});
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=reportContext.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { DeprecationLog, StageLog } from '@pnpm/core-loggers';
|
|
2
|
+
import * as Rx from 'rxjs';
|
|
3
|
+
export declare function reportDeprecations(log$: {
|
|
4
|
+
deprecation: Rx.Observable<DeprecationLog>;
|
|
5
|
+
stage: Rx.Observable<StageLog>;
|
|
6
|
+
}, opts: {
|
|
7
|
+
cwd: string;
|
|
8
|
+
isRecursive: boolean;
|
|
9
|
+
}): Rx.Observable<Rx.Observable<{
|
|
10
|
+
msg: string;
|
|
11
|
+
}>>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import * as Rx from 'rxjs';
|
|
3
|
+
import { buffer, filter, map, switchMap } from 'rxjs/operators';
|
|
4
|
+
import { formatWarn } from './utils/formatWarn.js';
|
|
5
|
+
import { zoomOut } from './utils/zooming.js';
|
|
6
|
+
export function reportDeprecations(log$, opts) {
|
|
7
|
+
const [deprecatedDirectDeps$, deprecatedSubdeps$] = Rx.partition(log$.deprecation, (log) => log.depth === 0);
|
|
8
|
+
const resolutionDone$ = log$.stage.pipe(filter((log) => log.stage === 'resolution_done'));
|
|
9
|
+
return Rx.merge(deprecatedDirectDeps$.pipe(map((log) => {
|
|
10
|
+
if (!opts.isRecursive && log.prefix === opts.cwd) {
|
|
11
|
+
return Rx.of({
|
|
12
|
+
msg: formatWarn(`${chalk.red('deprecated')} ${log.pkgName}@${log.pkgVersion}: ${log.deprecated}`),
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
return Rx.of({
|
|
16
|
+
msg: zoomOut(opts.cwd, log.prefix, formatWarn(`${chalk.red('deprecated')} ${log.pkgName}@${log.pkgVersion}`)),
|
|
17
|
+
});
|
|
18
|
+
})), deprecatedSubdeps$.pipe(buffer(resolutionDone$), switchMap(deprecatedSubdeps => {
|
|
19
|
+
if (deprecatedSubdeps.length > 0) {
|
|
20
|
+
return Rx.of(Rx.of({
|
|
21
|
+
msg: formatWarn(`${chalk.red(`${deprecatedSubdeps.length} deprecated subdependencies found:`)} ${deprecatedSubdeps.map(log => `${log.pkgName}@${log.pkgVersion}`).sort().join(', ')}`),
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
return Rx.EMPTY;
|
|
25
|
+
})));
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=reportDeprecations.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { packageManager } from '@pnpm/cli.meta';
|
|
2
|
+
import prettyMs from 'pretty-ms';
|
|
3
|
+
import * as Rx from 'rxjs';
|
|
4
|
+
import { map, take } from 'rxjs/operators';
|
|
5
|
+
export function reportExecutionTime(executionTime$) {
|
|
6
|
+
return executionTime$.pipe(take(1), map((log) => {
|
|
7
|
+
return Rx.of({
|
|
8
|
+
fixed: true, // Without this, for some reason sometimes the progress bar is printed after the execution time
|
|
9
|
+
msg: `Done in ${prettyMs(log.endedAt - log.startedAt)} using ${packageManager.name} v${packageManager.version}`,
|
|
10
|
+
});
|
|
11
|
+
}));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=reportExecutionTime.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import * as Rx from 'rxjs';
|
|
3
|
+
import { map } from 'rxjs/operators';
|
|
4
|
+
import { autozoom } from './utils/zooming.js';
|
|
5
|
+
export function reportHooks(hook$, opts) {
|
|
6
|
+
return hook$.pipe(map((log) => Rx.of({
|
|
7
|
+
msg: autozoom(opts.cwd, log.prefix, `${chalk.magentaBright(log.hook)}: ${log.message}`, {
|
|
8
|
+
zoomOutCurrent: opts.isRecursive,
|
|
9
|
+
}),
|
|
10
|
+
})));
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=reportHooks.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Config } from '@pnpm/config.reader';
|
|
2
|
+
import type { IgnoredScriptsLog } from '@pnpm/core-loggers';
|
|
3
|
+
import * as Rx from 'rxjs';
|
|
4
|
+
export declare function reportIgnoredBuilds(log$: {
|
|
5
|
+
ignoredScripts: Rx.Observable<IgnoredScriptsLog>;
|
|
6
|
+
}, opts: {
|
|
7
|
+
pnpmConfig?: Config;
|
|
8
|
+
approveBuildsInstructionText?: string;
|
|
9
|
+
}): Rx.Observable<Rx.Observable<{
|
|
10
|
+
msg: string;
|
|
11
|
+
}>>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { lexCompare } from '@pnpm/util.lex-comparator';
|
|
2
|
+
import boxen from 'boxen';
|
|
3
|
+
import * as Rx from 'rxjs';
|
|
4
|
+
import { map } from 'rxjs/operators';
|
|
5
|
+
export function reportIgnoredBuilds(log$, opts) {
|
|
6
|
+
return log$.ignoredScripts.pipe(map((ignoredScripts) => {
|
|
7
|
+
if (ignoredScripts.packageNames && ignoredScripts.packageNames.length > 0 && !opts.pnpmConfig?.strictDepBuilds) {
|
|
8
|
+
const msg = boxen(`Ignored build scripts: ${Array.from(ignoredScripts.packageNames).sort(lexCompare).join(', ')}.
|
|
9
|
+
${opts.approveBuildsInstructionText ?? `Run "pnpm approve-builds${opts.pnpmConfig?.cliOptions?.global ? ' -g' : ''}" to pick which dependencies should be allowed to run scripts.`}`, {
|
|
10
|
+
title: 'Warning',
|
|
11
|
+
padding: 1,
|
|
12
|
+
margin: 0,
|
|
13
|
+
borderStyle: 'round',
|
|
14
|
+
borderColor: 'yellow',
|
|
15
|
+
});
|
|
16
|
+
return Rx.of({ msg });
|
|
17
|
+
}
|
|
18
|
+
return Rx.NEVER;
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=reportIgnoredBuilds.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as Rx from 'rxjs';
|
|
2
|
+
import { filter, map } from 'rxjs/operators';
|
|
3
|
+
import { formatWarn } from './utils/formatWarn.js';
|
|
4
|
+
import { autozoom } from './utils/zooming.js';
|
|
5
|
+
export function reportInstallChecks(installCheck$, opts) {
|
|
6
|
+
return installCheck$.pipe(map((log) => formatInstallCheck(opts.cwd, log)), filter(Boolean), map((msg) => Rx.of({ msg })));
|
|
7
|
+
}
|
|
8
|
+
function formatInstallCheck(currentPrefix, logObj, opts) {
|
|
9
|
+
const zoomOutCurrent = opts?.zoomOutCurrent ?? false;
|
|
10
|
+
switch (logObj.code) {
|
|
11
|
+
case 'EBADPLATFORM':
|
|
12
|
+
return autozoom(currentPrefix, logObj.prefix, formatWarn(`Unsupported system. Skipping dependency ${logObj.pkgId}`), { zoomOutCurrent });
|
|
13
|
+
case 'ENOTSUP':
|
|
14
|
+
return autozoom(currentPrefix, logObj.prefix, logObj.toString(), { zoomOutCurrent });
|
|
15
|
+
default:
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=reportInstallChecks.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as Rx from 'rxjs';
|
|
2
|
+
import { map } from 'rxjs/operators';
|
|
3
|
+
export function reportInstallingConfigDeps(installingConfigDeps$) {
|
|
4
|
+
return Rx.of(installingConfigDeps$.pipe(map((log) => {
|
|
5
|
+
switch (log.status) {
|
|
6
|
+
case 'started': {
|
|
7
|
+
return {
|
|
8
|
+
msg: 'Installing config dependencies...',
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
case 'done':
|
|
12
|
+
return {
|
|
13
|
+
msg: `Installed config dependencies: ${log.deps.map(({ name, version }) => `${name}@${version}`).join(', ')}`,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
})));
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=reportInstallingConfigDeps.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { LifecycleLog } from '@pnpm/core-loggers';
|
|
2
|
+
import * as Rx from 'rxjs';
|
|
3
|
+
export declare function reportLifecycleScripts(log$: {
|
|
4
|
+
lifecycle: Rx.Observable<LifecycleLog>;
|
|
5
|
+
}, opts: {
|
|
6
|
+
appendOnly?: boolean;
|
|
7
|
+
aggregateOutput?: boolean;
|
|
8
|
+
hideLifecyclePrefix?: boolean;
|
|
9
|
+
cwd: string;
|
|
10
|
+
width: number;
|
|
11
|
+
}): Rx.Observable<Rx.Observable<{
|
|
12
|
+
msg: string;
|
|
13
|
+
}>>;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import cliTruncate from 'cli-truncate';
|
|
4
|
+
import prettyTime from 'pretty-ms';
|
|
5
|
+
import * as Rx from 'rxjs';
|
|
6
|
+
import { buffer, filter, groupBy, map, mergeAll, mergeMap } from 'rxjs/operators';
|
|
7
|
+
import { EOL } from '../constants.js';
|
|
8
|
+
import { hlValue } from './outputConstants.js';
|
|
9
|
+
import { formatPrefix, formatPrefixNoTrim } from './utils/formatPrefix.js';
|
|
10
|
+
const NODE_MODULES = `${path.sep}node_modules${path.sep}`;
|
|
11
|
+
const TMP_DIR_IN_STORE = `tmp${path.sep}_tmp_`; // git-hosted dependencies are built in these temporary directories
|
|
12
|
+
// When streaming processes are spawned, use this color for prefix
|
|
13
|
+
const colorWheel = ['cyan', 'magenta', 'blue', 'yellow', 'green', 'red'];
|
|
14
|
+
const NUM_COLORS = colorWheel.length;
|
|
15
|
+
// Ever-increasing index ensures colors are always sequential
|
|
16
|
+
let currentColor = 0;
|
|
17
|
+
export function reportLifecycleScripts(log$, opts) {
|
|
18
|
+
// When the reporter is not append-only, the length of output is limited
|
|
19
|
+
// in order to reduce flickering
|
|
20
|
+
if (opts.appendOnly) {
|
|
21
|
+
let lifecycle$ = log$.lifecycle;
|
|
22
|
+
if (opts.aggregateOutput) {
|
|
23
|
+
lifecycle$ = lifecycle$.pipe(aggregateOutput);
|
|
24
|
+
}
|
|
25
|
+
const streamLifecycleOutput = createStreamLifecycleOutput(opts.cwd, !!opts.hideLifecyclePrefix);
|
|
26
|
+
return lifecycle$.pipe(map((log) => Rx.of({
|
|
27
|
+
msg: streamLifecycleOutput(log),
|
|
28
|
+
})));
|
|
29
|
+
}
|
|
30
|
+
const lifecycleMessages = {};
|
|
31
|
+
const lifecycleStreamByDepPath = {};
|
|
32
|
+
const lifecyclePushStream = new Rx.Subject();
|
|
33
|
+
// TODO: handle promise of .forEach?!
|
|
34
|
+
log$.lifecycle
|
|
35
|
+
.forEach((log) => {
|
|
36
|
+
const key = `${log.stage}:${log.depPath}`;
|
|
37
|
+
lifecycleMessages[key] = lifecycleMessages[key] || {
|
|
38
|
+
collapsed: log.wd.includes(NODE_MODULES) || log.wd.includes(TMP_DIR_IN_STORE),
|
|
39
|
+
output: [],
|
|
40
|
+
startTime: process.hrtime(),
|
|
41
|
+
status: formatIndentedStatus(chalk.magentaBright('Running...')),
|
|
42
|
+
};
|
|
43
|
+
const exit = typeof log['exitCode'] === 'number';
|
|
44
|
+
let msg;
|
|
45
|
+
if (lifecycleMessages[key].collapsed) {
|
|
46
|
+
msg = renderCollapsedScriptOutput(log, lifecycleMessages[key], { cwd: opts.cwd, exit, maxWidth: opts.width });
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
msg = renderScriptOutput(log, lifecycleMessages[key], { cwd: opts.cwd, exit, maxWidth: opts.width });
|
|
50
|
+
}
|
|
51
|
+
if (exit) {
|
|
52
|
+
delete lifecycleMessages[key];
|
|
53
|
+
}
|
|
54
|
+
if (!lifecycleStreamByDepPath[key]) {
|
|
55
|
+
lifecycleStreamByDepPath[key] = new Rx.Subject();
|
|
56
|
+
lifecyclePushStream.next(Rx.from(lifecycleStreamByDepPath[key]));
|
|
57
|
+
}
|
|
58
|
+
lifecycleStreamByDepPath[key].next({ msg });
|
|
59
|
+
if (exit) {
|
|
60
|
+
lifecycleStreamByDepPath[key].complete();
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
return Rx.from(lifecyclePushStream);
|
|
64
|
+
}
|
|
65
|
+
function toNano(time) {
|
|
66
|
+
return (time[0] + (time[1] / 1e9)) * 1e3;
|
|
67
|
+
}
|
|
68
|
+
function renderCollapsedScriptOutput(log, messageCache, opts) {
|
|
69
|
+
if (!messageCache.label) {
|
|
70
|
+
messageCache.label = highlightLastFolder(formatPrefixNoTrim(opts.cwd, log.wd));
|
|
71
|
+
if (log.wd.includes(TMP_DIR_IN_STORE)) {
|
|
72
|
+
messageCache.label += ` [${log.depPath}]`;
|
|
73
|
+
}
|
|
74
|
+
messageCache.label += `: Running ${log.stage} script`;
|
|
75
|
+
}
|
|
76
|
+
if (!opts.exit) {
|
|
77
|
+
updateMessageCache(log, messageCache, opts);
|
|
78
|
+
return `${messageCache.label}...`;
|
|
79
|
+
}
|
|
80
|
+
const time = prettyTime(toNano(process.hrtime(messageCache.startTime)));
|
|
81
|
+
if (log.exitCode === 0) {
|
|
82
|
+
return `${messageCache.label}, done in ${time}`;
|
|
83
|
+
}
|
|
84
|
+
if (log.optional === true) {
|
|
85
|
+
return `${messageCache.label}, failed in ${time} (skipped as optional)`;
|
|
86
|
+
}
|
|
87
|
+
return `${messageCache.label}, failed in ${time}${EOL}${renderScriptOutput(log, messageCache, opts)}`;
|
|
88
|
+
}
|
|
89
|
+
function renderScriptOutput(log, messageCache, opts) {
|
|
90
|
+
updateMessageCache(log, messageCache, opts);
|
|
91
|
+
if (opts.exit && log['exitCode'] !== 0) {
|
|
92
|
+
return [
|
|
93
|
+
messageCache.script,
|
|
94
|
+
...messageCache.output,
|
|
95
|
+
messageCache.status,
|
|
96
|
+
].join(EOL);
|
|
97
|
+
}
|
|
98
|
+
if (messageCache.output.length > 10) {
|
|
99
|
+
return [
|
|
100
|
+
messageCache.script,
|
|
101
|
+
`[${messageCache.output.length - 10} lines collapsed]`,
|
|
102
|
+
...messageCache.output.slice(messageCache.output.length - 10),
|
|
103
|
+
messageCache.status,
|
|
104
|
+
].join(EOL);
|
|
105
|
+
}
|
|
106
|
+
return [
|
|
107
|
+
messageCache.script,
|
|
108
|
+
...messageCache.output,
|
|
109
|
+
messageCache.status,
|
|
110
|
+
].join(EOL);
|
|
111
|
+
}
|
|
112
|
+
function updateMessageCache(log, messageCache, opts) {
|
|
113
|
+
if (log.script) {
|
|
114
|
+
const prefix = `${formatPrefix(opts.cwd, log.wd)} ${hlValue(log.stage)}`;
|
|
115
|
+
const maxLineWidth = opts.maxWidth - prefix.length - 2 + ANSI_ESCAPES_LENGTH_OF_PREFIX;
|
|
116
|
+
messageCache.script = `${prefix}$ ${cutLine(log.script, maxLineWidth)}`;
|
|
117
|
+
}
|
|
118
|
+
else if (opts.exit) {
|
|
119
|
+
const time = prettyTime(toNano(process.hrtime(messageCache.startTime)));
|
|
120
|
+
if (log.exitCode === 0) {
|
|
121
|
+
messageCache.status = formatIndentedStatus(chalk.magentaBright(`Done in ${time}`));
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
messageCache.status = formatIndentedStatus(chalk.red(`Failed in ${time} at ${log.wd}`));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
messageCache.output.push(formatIndentedOutput(opts.maxWidth, log));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function formatIndentedStatus(status) {
|
|
132
|
+
return `${chalk.magentaBright('└─')} ${status}`;
|
|
133
|
+
}
|
|
134
|
+
function highlightLastFolder(p) {
|
|
135
|
+
const lastSlash = p.lastIndexOf('/') + 1;
|
|
136
|
+
return `${chalk.gray(p.slice(0, lastSlash))}${p.slice(lastSlash)}`;
|
|
137
|
+
}
|
|
138
|
+
const ANSI_ESCAPES_LENGTH_OF_PREFIX = hlValue(' ').length - 1;
|
|
139
|
+
function createStreamLifecycleOutput(cwd, hideLifecyclePrefix) {
|
|
140
|
+
currentColor = 0;
|
|
141
|
+
const colorByPrefix = new Map();
|
|
142
|
+
return streamLifecycleOutput.bind(null, colorByPrefix, cwd, hideLifecyclePrefix);
|
|
143
|
+
}
|
|
144
|
+
function streamLifecycleOutput(colorByPkg, cwd, hideLifecyclePrefix, logObj) {
|
|
145
|
+
const prefix = formatLifecycleScriptPrefix(colorByPkg, cwd, logObj.wd, logObj.stage);
|
|
146
|
+
if (typeof logObj.exitCode === 'number') {
|
|
147
|
+
if (logObj.exitCode === 0) {
|
|
148
|
+
return `${prefix}: Done`;
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
return `${prefix}: Failed`;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (logObj['script']) {
|
|
155
|
+
return `${prefix}$ ${logObj['script']}`;
|
|
156
|
+
}
|
|
157
|
+
const line = formatLine(Infinity, logObj);
|
|
158
|
+
return hideLifecyclePrefix ? line : `${prefix}: ${line}`;
|
|
159
|
+
}
|
|
160
|
+
function formatIndentedOutput(maxWidth, logObj) {
|
|
161
|
+
return `${chalk.magentaBright('│')} ${formatLine(maxWidth - 2, logObj)}`;
|
|
162
|
+
}
|
|
163
|
+
function formatLifecycleScriptPrefix(colorByPkg, cwd, wd, stage) {
|
|
164
|
+
if (!colorByPkg.has(wd)) {
|
|
165
|
+
const colorName = colorWheel[currentColor % NUM_COLORS];
|
|
166
|
+
colorByPkg.set(wd, chalk[colorName]);
|
|
167
|
+
currentColor += 1;
|
|
168
|
+
}
|
|
169
|
+
const color = colorByPkg.get(wd);
|
|
170
|
+
return `${color(formatPrefix(cwd, wd))} ${hlValue(stage)}`;
|
|
171
|
+
}
|
|
172
|
+
function formatLine(maxWidth, logObj) {
|
|
173
|
+
const line = cutLine(logObj.line, maxWidth);
|
|
174
|
+
// TODO: strip only the non-color/style ansi escape codes
|
|
175
|
+
if (logObj.stdio === 'stderr') {
|
|
176
|
+
return chalk.gray(line);
|
|
177
|
+
}
|
|
178
|
+
return line;
|
|
179
|
+
}
|
|
180
|
+
function cutLine(line, maxLength) {
|
|
181
|
+
if (!line)
|
|
182
|
+
return '';
|
|
183
|
+
return cliTruncate(line, maxLength);
|
|
184
|
+
}
|
|
185
|
+
function aggregateOutput(source) {
|
|
186
|
+
return source.pipe(
|
|
187
|
+
// The '\0' is a null character which delimits these strings. This works since JS doesn't use
|
|
188
|
+
// null-terminated strings.
|
|
189
|
+
groupBy((data) => `${data.depPath}\0${data.stage}`), mergeMap(group => {
|
|
190
|
+
return group.pipe(buffer(group.pipe(filter(msg => 'exitCode' in msg))));
|
|
191
|
+
}), map(ar => Rx.from(ar)), mergeAll());
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=reportLifecycleScripts.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Config } from '@pnpm/config.reader';
|
|
2
|
+
import type { Log, RegistryLog } from '@pnpm/core-loggers';
|
|
3
|
+
import type { LogLevel } from '@pnpm/logger';
|
|
4
|
+
import * as Rx from 'rxjs';
|
|
5
|
+
export declare const LOG_LEVEL_NUMBER: Record<LogLevel, number>;
|
|
6
|
+
export declare function reportMisc(log$: {
|
|
7
|
+
registry: Rx.Observable<RegistryLog>;
|
|
8
|
+
other: Rx.Observable<Log>;
|
|
9
|
+
}, opts: {
|
|
10
|
+
appendOnly: boolean;
|
|
11
|
+
cwd: string;
|
|
12
|
+
logLevel?: LogLevel;
|
|
13
|
+
config?: Config;
|
|
14
|
+
zoomOutCurrent: boolean;
|
|
15
|
+
}): Rx.Observable<Rx.Observable<{
|
|
16
|
+
msg: string;
|
|
17
|
+
}>>;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import * as Rx from 'rxjs';
|
|
3
|
+
import { filter, map } from 'rxjs/operators';
|
|
4
|
+
import { reportError } from '../reportError.js';
|
|
5
|
+
import { formatWarn } from './utils/formatWarn.js';
|
|
6
|
+
import { autozoom } from './utils/zooming.js';
|
|
7
|
+
// eslint-disable:object-literal-sort-keys
|
|
8
|
+
export const LOG_LEVEL_NUMBER = {
|
|
9
|
+
error: 0,
|
|
10
|
+
warn: 1,
|
|
11
|
+
info: 2,
|
|
12
|
+
debug: 3,
|
|
13
|
+
};
|
|
14
|
+
// eslint-enable:object-literal-sort-keys
|
|
15
|
+
const MAX_SHOWN_WARNINGS = 5;
|
|
16
|
+
export function reportMisc(log$, opts) {
|
|
17
|
+
const maxLogLevel = LOG_LEVEL_NUMBER[opts.logLevel ?? 'info'] ?? LOG_LEVEL_NUMBER['info'];
|
|
18
|
+
const reportWarning = makeWarningReporter(opts);
|
|
19
|
+
return Rx.merge(log$.registry, log$.other).pipe(filter((obj) => LOG_LEVEL_NUMBER[obj.level] <= maxLogLevel &&
|
|
20
|
+
(obj.level !== 'info' || !obj['prefix'] || obj['prefix'] === opts.cwd)), map((obj) => {
|
|
21
|
+
switch (obj.level) {
|
|
22
|
+
case 'warn': {
|
|
23
|
+
return reportWarning(obj);
|
|
24
|
+
}
|
|
25
|
+
case 'error': {
|
|
26
|
+
const errorOutput = reportError(obj, opts.config);
|
|
27
|
+
if (!errorOutput)
|
|
28
|
+
return Rx.NEVER;
|
|
29
|
+
if (obj['prefix'] && obj['prefix'] !== opts.cwd) {
|
|
30
|
+
return Rx.of({
|
|
31
|
+
msg: `${obj['prefix']}:` + os.EOL + errorOutput,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return Rx.of({ msg: errorOutput });
|
|
35
|
+
}
|
|
36
|
+
default:
|
|
37
|
+
return Rx.of({ msg: obj.message });
|
|
38
|
+
}
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
// Sometimes, when installing new dependencies that rely on many peer dependencies,
|
|
42
|
+
// or when running installation on a huge monorepo, there will be hundreds or thousands of warnings.
|
|
43
|
+
// Printing many messages to the terminal is expensive and reduces speed,
|
|
44
|
+
// so pnpm will only print a few warnings and report the total number of the unprinted warnings.
|
|
45
|
+
function makeWarningReporter(opts) {
|
|
46
|
+
let warningsCounter = 0;
|
|
47
|
+
let collapsedWarnings;
|
|
48
|
+
return (obj) => {
|
|
49
|
+
warningsCounter++;
|
|
50
|
+
if (opts.appendOnly || warningsCounter <= MAX_SHOWN_WARNINGS) {
|
|
51
|
+
return Rx.of({ msg: autozoom(opts.cwd, obj.prefix, formatWarn(obj.message), opts) });
|
|
52
|
+
}
|
|
53
|
+
const warningMsg = formatWarn(`${warningsCounter - MAX_SHOWN_WARNINGS} other warnings`);
|
|
54
|
+
if (!collapsedWarnings) {
|
|
55
|
+
collapsedWarnings = new Rx.Subject();
|
|
56
|
+
// For some reason, without using setTimeout, the warning summary is printed above the rest of the warnings
|
|
57
|
+
// Even though the summary event happens last. Probably a bug in "most".
|
|
58
|
+
setTimeout(() => {
|
|
59
|
+
collapsedWarnings.next({ msg: warningMsg });
|
|
60
|
+
}, 0);
|
|
61
|
+
return Rx.from(collapsedWarnings);
|
|
62
|
+
}
|
|
63
|
+
setTimeout(() => {
|
|
64
|
+
collapsedWarnings.next({ msg: warningMsg });
|
|
65
|
+
}, 0);
|
|
66
|
+
return Rx.NEVER;
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=reportMisc.js.map
|