@pnpm/deps.inspection.commands 1000.0.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/LICENSE +22 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +3 -0
- package/lib/listing/common.d.ts +26 -0
- package/lib/listing/common.js +79 -0
- package/lib/listing/index.d.ts +4 -0
- package/lib/listing/index.js +5 -0
- package/lib/listing/list.d.ts +41 -0
- package/lib/listing/list.js +115 -0
- package/lib/listing/ll.d.ts +6 -0
- package/lib/listing/ll.js +12 -0
- package/lib/listing/recursive.d.ts +11 -0
- package/lib/listing/recursive.js +36 -0
- package/lib/listing/why.d.ts +7 -0
- package/lib/listing/why.js +70 -0
- package/lib/outdated/index.d.ts +2 -0
- package/lib/outdated/index.js +3 -0
- package/lib/outdated/outdated.d.ts +36 -0
- package/lib/outdated/outdated.js +321 -0
- package/lib/outdated/recursive.d.ts +17 -0
- package/lib/outdated/recursive.js +156 -0
- package/lib/outdated/utils.d.ts +13 -0
- package/lib/outdated/utils.js +22 -0
- package/package.json +79 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2015-2016 Rico Sta. Cruz and other contributors
|
|
4
|
+
Copyright (c) 2016-2026 Zoltan Kochan and other contributors
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/lib/index.d.ts
ADDED
package/lib/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Finder, IncludedDependencies } from '@pnpm/types';
|
|
2
|
+
export type ReportAs = 'parseable' | 'json' | 'tree';
|
|
3
|
+
export declare function computeInclude(opts: {
|
|
4
|
+
production?: boolean;
|
|
5
|
+
dev?: boolean;
|
|
6
|
+
optional?: boolean;
|
|
7
|
+
}): IncludedDependencies;
|
|
8
|
+
export declare function resolveFinders(opts: {
|
|
9
|
+
findBy?: string[];
|
|
10
|
+
finders?: Record<string, Finder>;
|
|
11
|
+
}): Finder[];
|
|
12
|
+
export declare function determineReportAs(opts: {
|
|
13
|
+
parseable?: boolean;
|
|
14
|
+
json?: boolean;
|
|
15
|
+
}): ReportAs;
|
|
16
|
+
export declare const shorthands: Record<string, string>;
|
|
17
|
+
export declare const BASE_RC_OPTION_KEYS: readonly ["dev", "global-dir", "global", "json", "long", "only", "optional", "parseable", "production"];
|
|
18
|
+
export declare const SHARED_CLI_HELP_OPTIONS: ({
|
|
19
|
+
description: string;
|
|
20
|
+
name: string;
|
|
21
|
+
shortAlias: string;
|
|
22
|
+
} | {
|
|
23
|
+
shortAlias?: undefined;
|
|
24
|
+
description: string;
|
|
25
|
+
name: string;
|
|
26
|
+
})[];
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { PnpmError } from '@pnpm/error';
|
|
2
|
+
export function computeInclude(opts) {
|
|
3
|
+
return {
|
|
4
|
+
dependencies: opts.production !== false,
|
|
5
|
+
devDependencies: opts.dev !== false,
|
|
6
|
+
optionalDependencies: opts.optional !== false,
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export function resolveFinders(opts) {
|
|
10
|
+
const finders = [];
|
|
11
|
+
if (opts.findBy) {
|
|
12
|
+
for (const finderName of opts.findBy) {
|
|
13
|
+
if (opts.finders?.[finderName] == null) {
|
|
14
|
+
throw new PnpmError('FINDER_NOT_FOUND', `No finder with name ${finderName} is found`);
|
|
15
|
+
}
|
|
16
|
+
finders.push(opts.finders[finderName]);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return finders;
|
|
20
|
+
}
|
|
21
|
+
export function determineReportAs(opts) {
|
|
22
|
+
return opts.parseable ? 'parseable' : (opts.json ? 'json' : 'tree');
|
|
23
|
+
}
|
|
24
|
+
export const shorthands = {
|
|
25
|
+
D: '--dev',
|
|
26
|
+
P: '--production',
|
|
27
|
+
};
|
|
28
|
+
export const BASE_RC_OPTION_KEYS = [
|
|
29
|
+
'dev',
|
|
30
|
+
'global-dir',
|
|
31
|
+
'global',
|
|
32
|
+
'json',
|
|
33
|
+
'long',
|
|
34
|
+
'only',
|
|
35
|
+
'optional',
|
|
36
|
+
'parseable',
|
|
37
|
+
'production',
|
|
38
|
+
];
|
|
39
|
+
export const SHARED_CLI_HELP_OPTIONS = [
|
|
40
|
+
{
|
|
41
|
+
description: 'Perform command on every package in subdirectories \
|
|
42
|
+
or on every workspace package, when executed inside a workspace. \
|
|
43
|
+
For options that may be used with `-r`, see "pnpm help recursive"',
|
|
44
|
+
name: '--recursive',
|
|
45
|
+
shortAlias: '-r',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
description: 'Show extended information',
|
|
49
|
+
name: '--long',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
description: 'Show parseable output instead of tree view',
|
|
53
|
+
name: '--parseable',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
description: 'Show information in JSON format',
|
|
57
|
+
name: '--json',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
description: 'List packages in the global install prefix instead of in the current project',
|
|
61
|
+
name: '--global',
|
|
62
|
+
shortAlias: '-g',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
description: 'Display only the dependency graph for packages in `dependencies` and `optionalDependencies`',
|
|
66
|
+
name: '--prod',
|
|
67
|
+
shortAlias: '-P',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
description: 'Display only the dependency graph for packages in `devDependencies`',
|
|
71
|
+
name: '--dev',
|
|
72
|
+
shortAlias: '-D',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
description: "Don't display packages from `optionalDependencies`",
|
|
76
|
+
name: '--no-optional',
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
//# sourceMappingURL=common.js.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type Config } from '@pnpm/config.reader';
|
|
2
|
+
import type { Finder, IncludedDependencies } from '@pnpm/types';
|
|
3
|
+
export declare const EXCLUDE_PEERS_HELP: {
|
|
4
|
+
description: string;
|
|
5
|
+
name: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function rcOptionsTypes(): Record<string, unknown>;
|
|
8
|
+
export declare const cliOptionsTypes: () => Record<string, unknown>;
|
|
9
|
+
export { shorthands } from './common.js';
|
|
10
|
+
export declare const commandNames: string[];
|
|
11
|
+
export declare function help(): string;
|
|
12
|
+
export type ListCommandOptions = Pick<Config, 'allProjects' | 'dev' | 'dir' | 'finders' | 'optional' | 'production' | 'selectedProjectsGraph' | 'modulesDir' | 'virtualStoreDirMaxLength'> & Partial<Pick<Config, 'cliOptions'>> & {
|
|
13
|
+
alwaysPrintRootPackage?: boolean;
|
|
14
|
+
depth?: number;
|
|
15
|
+
excludePeers?: boolean;
|
|
16
|
+
json?: boolean;
|
|
17
|
+
lockfileDir?: string;
|
|
18
|
+
lockfileOnly?: boolean;
|
|
19
|
+
long?: boolean;
|
|
20
|
+
parseable?: boolean;
|
|
21
|
+
onlyProjects?: boolean;
|
|
22
|
+
recursive?: boolean;
|
|
23
|
+
findBy?: string[];
|
|
24
|
+
} & Partial<Pick<Config, 'global' | 'globalPkgDir'>>;
|
|
25
|
+
export declare function handler(opts: ListCommandOptions, params: string[]): Promise<string>;
|
|
26
|
+
export declare function render(prefixes: string[], params: string[], opts: {
|
|
27
|
+
alwaysPrintRootPackage?: boolean;
|
|
28
|
+
depth?: number;
|
|
29
|
+
excludePeers?: boolean;
|
|
30
|
+
include: IncludedDependencies;
|
|
31
|
+
lockfileDir: string;
|
|
32
|
+
checkWantedLockfileOnly?: boolean;
|
|
33
|
+
long?: boolean;
|
|
34
|
+
json?: boolean;
|
|
35
|
+
onlyProjects?: boolean;
|
|
36
|
+
parseable?: boolean;
|
|
37
|
+
modulesDir?: string;
|
|
38
|
+
virtualStoreDirMaxLength: number;
|
|
39
|
+
finders?: Record<string, Finder>;
|
|
40
|
+
findBy?: string[];
|
|
41
|
+
}): Promise<string>;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { FILTERING, OPTIONS, UNIVERSAL_OPTIONS } from '@pnpm/cli.common-cli-options-help';
|
|
2
|
+
import { docsUrl } from '@pnpm/cli.utils';
|
|
3
|
+
import { types as allTypes } from '@pnpm/config.reader';
|
|
4
|
+
import { list, listForPackages } from '@pnpm/deps.inspection.list';
|
|
5
|
+
import { listGlobalPackages } from '@pnpm/global.commands';
|
|
6
|
+
import { pick } from 'ramda';
|
|
7
|
+
import { renderHelp } from 'render-help';
|
|
8
|
+
import { BASE_RC_OPTION_KEYS, computeInclude, determineReportAs, resolveFinders, SHARED_CLI_HELP_OPTIONS } from './common.js';
|
|
9
|
+
import { listRecursive } from './recursive.js';
|
|
10
|
+
export const EXCLUDE_PEERS_HELP = {
|
|
11
|
+
description: 'Exclude peer dependencies',
|
|
12
|
+
name: '--exclude-peers',
|
|
13
|
+
};
|
|
14
|
+
export function rcOptionsTypes() {
|
|
15
|
+
return pick([
|
|
16
|
+
...BASE_RC_OPTION_KEYS,
|
|
17
|
+
'depth',
|
|
18
|
+
'lockfile-only',
|
|
19
|
+
], allTypes);
|
|
20
|
+
}
|
|
21
|
+
export const cliOptionsTypes = () => ({
|
|
22
|
+
...rcOptionsTypes(),
|
|
23
|
+
'exclude-peers': Boolean,
|
|
24
|
+
'only-projects': Boolean,
|
|
25
|
+
recursive: Boolean,
|
|
26
|
+
'find-by': [String, Array],
|
|
27
|
+
});
|
|
28
|
+
export { shorthands } from './common.js';
|
|
29
|
+
export const commandNames = ['list', 'ls'];
|
|
30
|
+
export function help() {
|
|
31
|
+
return renderHelp({
|
|
32
|
+
aliases: ['list', 'ls', 'la', 'll'],
|
|
33
|
+
description: 'When run as ll or la, it shows extended information by default. \
|
|
34
|
+
All dependencies are printed by default. Search by patterns is supported. \
|
|
35
|
+
For example: pnpm ls babel-* eslint-*',
|
|
36
|
+
descriptionLists: [
|
|
37
|
+
{
|
|
38
|
+
title: 'Options',
|
|
39
|
+
list: [
|
|
40
|
+
...SHARED_CLI_HELP_OPTIONS,
|
|
41
|
+
{
|
|
42
|
+
description: 'Max display depth of the dependency tree',
|
|
43
|
+
name: '--depth <number>',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
description: 'Display only direct dependencies',
|
|
47
|
+
name: '--depth 0',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
description: 'Display only projects. Useful in a monorepo. `pnpm ls -r --depth -1` lists all projects in a monorepo',
|
|
51
|
+
name: '--depth -1',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
description: 'Display only dependencies that are also projects within the workspace',
|
|
55
|
+
name: '--only-projects',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
description: 'List packages from the lockfile only, without checking node_modules.',
|
|
59
|
+
name: '--lockfile-only',
|
|
60
|
+
},
|
|
61
|
+
EXCLUDE_PEERS_HELP,
|
|
62
|
+
OPTIONS.globalDir,
|
|
63
|
+
...UNIVERSAL_OPTIONS,
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
FILTERING,
|
|
67
|
+
],
|
|
68
|
+
url: docsUrl('list'),
|
|
69
|
+
usages: [
|
|
70
|
+
'pnpm ls [<pkg> ...]',
|
|
71
|
+
],
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
export async function handler(opts, params) {
|
|
75
|
+
if (opts.global && opts.globalPkgDir) {
|
|
76
|
+
return listGlobalPackages(opts.globalPkgDir, params);
|
|
77
|
+
}
|
|
78
|
+
const include = computeInclude(opts);
|
|
79
|
+
const depth = opts.cliOptions?.['depth'] ?? 0;
|
|
80
|
+
if (opts.recursive && (opts.selectedProjectsGraph != null)) {
|
|
81
|
+
const pkgs = Object.values(opts.selectedProjectsGraph).map((wsPkg) => wsPkg.package);
|
|
82
|
+
return listRecursive(pkgs, params, { ...opts, depth, include, checkWantedLockfileOnly: opts.lockfileOnly, onlyProjects: opts.cliOptions?.['only-projects'] ?? opts.onlyProjects });
|
|
83
|
+
}
|
|
84
|
+
return render([opts.dir], params, {
|
|
85
|
+
...opts,
|
|
86
|
+
depth,
|
|
87
|
+
include,
|
|
88
|
+
lockfileDir: opts.lockfileDir ?? opts.dir,
|
|
89
|
+
checkWantedLockfileOnly: opts.lockfileOnly,
|
|
90
|
+
onlyProjects: opts.cliOptions?.['only-projects'] ?? opts.onlyProjects,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
export async function render(prefixes, params, opts) {
|
|
94
|
+
const finders = resolveFinders(opts);
|
|
95
|
+
const listOpts = {
|
|
96
|
+
alwaysPrintRootPackage: opts.alwaysPrintRootPackage,
|
|
97
|
+
depth: opts.depth ?? 0,
|
|
98
|
+
excludePeerDependencies: opts.excludePeers,
|
|
99
|
+
include: opts.include,
|
|
100
|
+
lockfileDir: opts.lockfileDir,
|
|
101
|
+
checkWantedLockfileOnly: opts.checkWantedLockfileOnly,
|
|
102
|
+
long: opts.long,
|
|
103
|
+
onlyProjects: opts.onlyProjects,
|
|
104
|
+
reportAs: determineReportAs(opts),
|
|
105
|
+
showExtraneous: false,
|
|
106
|
+
showSummary: true,
|
|
107
|
+
modulesDir: opts.modulesDir,
|
|
108
|
+
virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength,
|
|
109
|
+
finders,
|
|
110
|
+
};
|
|
111
|
+
return (params.length > 0) || listOpts.finders.length > 0
|
|
112
|
+
? listForPackages(params, prefixes, listOpts)
|
|
113
|
+
: list(prefixes, listOpts);
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as list from './list.js';
|
|
2
|
+
export declare const commandNames: string[];
|
|
3
|
+
export declare const rcOptionsTypes: typeof list.rcOptionsTypes;
|
|
4
|
+
export declare function cliOptionsTypes(): Record<string, unknown>;
|
|
5
|
+
export declare const help: typeof list.help;
|
|
6
|
+
export declare function handler(opts: list.ListCommandOptions, params: string[]): Promise<string>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { omit } from 'ramda';
|
|
2
|
+
import * as list from './list.js';
|
|
3
|
+
export const commandNames = ['ll', 'la'];
|
|
4
|
+
export const rcOptionsTypes = list.rcOptionsTypes;
|
|
5
|
+
export function cliOptionsTypes() {
|
|
6
|
+
return omit(['long'], list.cliOptionsTypes());
|
|
7
|
+
}
|
|
8
|
+
export const help = list.help;
|
|
9
|
+
export async function handler(opts, params) {
|
|
10
|
+
return list.handler({ ...opts, long: true }, params);
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=ll.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Config } from '@pnpm/config.reader';
|
|
2
|
+
import type { IncludedDependencies, Project } from '@pnpm/types';
|
|
3
|
+
export declare function listRecursive(pkgs: Project[], params: string[], opts: Pick<Config, 'lockfileDir' | 'virtualStoreDirMaxLength'> & {
|
|
4
|
+
depth?: number;
|
|
5
|
+
include: IncludedDependencies;
|
|
6
|
+
long?: boolean;
|
|
7
|
+
parseable?: boolean;
|
|
8
|
+
lockfileDir?: string;
|
|
9
|
+
checkWantedLockfileOnly?: boolean;
|
|
10
|
+
onlyProjects?: boolean;
|
|
11
|
+
}): Promise<string>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import util from 'node:util';
|
|
3
|
+
import { logger } from '@pnpm/logger';
|
|
4
|
+
import { render } from './list.js';
|
|
5
|
+
export async function listRecursive(pkgs, params, opts) {
|
|
6
|
+
const depth = opts.depth ?? 0;
|
|
7
|
+
if (opts.lockfileDir) {
|
|
8
|
+
return render(pkgs.map((pkg) => pkg.rootDir), params, {
|
|
9
|
+
...opts,
|
|
10
|
+
alwaysPrintRootPackage: depth === -1,
|
|
11
|
+
lockfileDir: opts.lockfileDir,
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
const outputs = (await Promise.all(pkgs.map(async ({ rootDir }) => {
|
|
15
|
+
try {
|
|
16
|
+
return await render([rootDir], params, {
|
|
17
|
+
...opts,
|
|
18
|
+
alwaysPrintRootPackage: depth === -1,
|
|
19
|
+
lockfileDir: opts.lockfileDir ?? rootDir,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
assert(util.types.isNativeError(err));
|
|
24
|
+
const errWithPrefix = Object.assign(err, {
|
|
25
|
+
prefix: rootDir,
|
|
26
|
+
});
|
|
27
|
+
logger.info(errWithPrefix);
|
|
28
|
+
throw errWithPrefix;
|
|
29
|
+
}
|
|
30
|
+
}))).filter(Boolean);
|
|
31
|
+
if (outputs.length === 0)
|
|
32
|
+
return '';
|
|
33
|
+
const joiner = typeof depth === 'number' && depth > -1 ? '\n\n' : '\n';
|
|
34
|
+
return outputs.join(joiner);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=recursive.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type ListCommandOptions } from './list.js';
|
|
2
|
+
export declare function rcOptionsTypes(): Record<string, unknown>;
|
|
3
|
+
export declare const cliOptionsTypes: () => Record<string, unknown>;
|
|
4
|
+
export { shorthands } from './common.js';
|
|
5
|
+
export declare const commandNames: string[];
|
|
6
|
+
export declare function help(): string;
|
|
7
|
+
export declare function handler(opts: ListCommandOptions, params: string[]): Promise<string>;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { FILTERING, OPTIONS, UNIVERSAL_OPTIONS } from '@pnpm/cli.common-cli-options-help';
|
|
2
|
+
import { docsUrl } from '@pnpm/cli.utils';
|
|
3
|
+
import { types as allTypes } from '@pnpm/config.reader';
|
|
4
|
+
import { whyForPackages } from '@pnpm/deps.inspection.list';
|
|
5
|
+
import { PnpmError } from '@pnpm/error';
|
|
6
|
+
import { pick } from 'ramda';
|
|
7
|
+
import { renderHelp } from 'render-help';
|
|
8
|
+
import { BASE_RC_OPTION_KEYS, computeInclude, determineReportAs, resolveFinders, SHARED_CLI_HELP_OPTIONS } from './common.js';
|
|
9
|
+
import { EXCLUDE_PEERS_HELP } from './list.js';
|
|
10
|
+
export function rcOptionsTypes() {
|
|
11
|
+
return pick([...BASE_RC_OPTION_KEYS, 'depth'], allTypes);
|
|
12
|
+
}
|
|
13
|
+
export const cliOptionsTypes = () => ({
|
|
14
|
+
...rcOptionsTypes(),
|
|
15
|
+
'exclude-peers': Boolean,
|
|
16
|
+
recursive: Boolean,
|
|
17
|
+
'find-by': [String, Array],
|
|
18
|
+
});
|
|
19
|
+
export { shorthands } from './common.js';
|
|
20
|
+
export const commandNames = ['why'];
|
|
21
|
+
export function help() {
|
|
22
|
+
return renderHelp({
|
|
23
|
+
description: `Shows the packages that depend on <pkg>
|
|
24
|
+
For example: pnpm why babel-* eslint-*`,
|
|
25
|
+
descriptionLists: [
|
|
26
|
+
{
|
|
27
|
+
title: 'Options',
|
|
28
|
+
list: [
|
|
29
|
+
...SHARED_CLI_HELP_OPTIONS,
|
|
30
|
+
{
|
|
31
|
+
description: 'Max display depth of the reverse dependency tree',
|
|
32
|
+
name: '--depth <number>',
|
|
33
|
+
},
|
|
34
|
+
EXCLUDE_PEERS_HELP,
|
|
35
|
+
OPTIONS.globalDir,
|
|
36
|
+
...UNIVERSAL_OPTIONS,
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
FILTERING,
|
|
40
|
+
],
|
|
41
|
+
url: docsUrl('why'),
|
|
42
|
+
usages: [
|
|
43
|
+
'pnpm why <pkg> ...',
|
|
44
|
+
],
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
export async function handler(opts, params) {
|
|
48
|
+
if (params.length === 0 && opts.findBy == null) {
|
|
49
|
+
throw new PnpmError('MISSING_PACKAGE_NAME', '`pnpm why` requires the package name or --find-by=<finder-name>');
|
|
50
|
+
}
|
|
51
|
+
const include = computeInclude(opts);
|
|
52
|
+
const finders = resolveFinders(opts);
|
|
53
|
+
const lockfileDir = opts.lockfileDir ?? opts.dir;
|
|
54
|
+
const reportAs = determineReportAs(opts);
|
|
55
|
+
const depth = opts.cliOptions?.['depth'];
|
|
56
|
+
const projectPaths = opts.recursive && opts.selectedProjectsGraph
|
|
57
|
+
? Object.keys(opts.selectedProjectsGraph)
|
|
58
|
+
: [opts.dir];
|
|
59
|
+
return whyForPackages(params, projectPaths, {
|
|
60
|
+
depth,
|
|
61
|
+
include,
|
|
62
|
+
long: opts.long,
|
|
63
|
+
lockfileDir,
|
|
64
|
+
reportAs,
|
|
65
|
+
modulesDir: opts.modulesDir,
|
|
66
|
+
checkWantedLockfileOnly: opts.lockfileOnly,
|
|
67
|
+
finders,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=why.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { CompletionFunc } from '@pnpm/cli.command';
|
|
2
|
+
import { type Config } from '@pnpm/config.reader';
|
|
3
|
+
import { type OutdatedPackage } from '@pnpm/deps.inspection.outdated';
|
|
4
|
+
import type { DependenciesField, PackageManifest } from '@pnpm/types';
|
|
5
|
+
import { type OutdatedWithVersionDiff } from './utils.js';
|
|
6
|
+
export declare function rcOptionsTypes(): Record<string, unknown>;
|
|
7
|
+
export declare const cliOptionsTypes: () => Record<string, unknown>;
|
|
8
|
+
export declare const shorthands: Record<string, string>;
|
|
9
|
+
export declare const commandNames: string[];
|
|
10
|
+
export declare function help(): string;
|
|
11
|
+
export declare const completion: CompletionFunc;
|
|
12
|
+
export type OutdatedCommandOptions = {
|
|
13
|
+
compatible?: boolean;
|
|
14
|
+
long?: boolean;
|
|
15
|
+
recursive?: boolean;
|
|
16
|
+
format?: 'table' | 'list' | 'json';
|
|
17
|
+
sortBy?: 'name';
|
|
18
|
+
} & Pick<Config, 'allProjects' | 'ca' | 'cacheDir' | 'catalogs' | 'cert' | 'dev' | 'dir' | 'engineStrict' | 'fetchRetries' | 'fetchRetryFactor' | 'fetchRetryMaxtimeout' | 'fetchRetryMintimeout' | 'fetchTimeout' | 'global' | 'httpProxy' | 'httpsProxy' | 'key' | 'localAddress' | 'lockfileDir' | 'minimumReleaseAge' | 'minimumReleaseAgeExclude' | 'networkConcurrency' | 'noProxy' | 'offline' | 'optional' | 'production' | 'rawConfig' | 'registries' | 'selectedProjectsGraph' | 'strictSsl' | 'tag' | 'userAgent' | 'updateConfig'> & Partial<Pick<Config, 'globalPkgDir' | 'userConfig'>>;
|
|
19
|
+
export declare function handler(opts: OutdatedCommandOptions, params?: string[]): Promise<{
|
|
20
|
+
output: string;
|
|
21
|
+
exitCode: number;
|
|
22
|
+
}>;
|
|
23
|
+
export interface OutdatedPackageJSONOutput {
|
|
24
|
+
current?: string;
|
|
25
|
+
latest?: string;
|
|
26
|
+
wanted: string;
|
|
27
|
+
isDeprecated: boolean;
|
|
28
|
+
dependencyType: DependenciesField;
|
|
29
|
+
latestManifest?: PackageManifest;
|
|
30
|
+
}
|
|
31
|
+
export declare function getCellWidth(data: string[][], columnNumber: number, maxWidth: number): number;
|
|
32
|
+
export declare function toOutdatedWithVersionDiff<Pkg extends OutdatedPackage>(outdated: Pkg): Pkg & OutdatedWithVersionDiff;
|
|
33
|
+
export declare function renderPackageName({ belongsTo, packageName }: OutdatedPackage): string;
|
|
34
|
+
export declare function renderCurrent({ current, wanted }: OutdatedPackage): string;
|
|
35
|
+
export declare function renderLatest(outdatedPkg: OutdatedWithVersionDiff): string;
|
|
36
|
+
export declare function renderDetails({ latestManifest }: OutdatedPackage): string;
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import { stripVTControlCharacters as stripAnsi } from 'node:util';
|
|
2
|
+
import { FILTERING, OPTIONS, UNIVERSAL_OPTIONS } from '@pnpm/cli.common-cli-options-help';
|
|
3
|
+
import { docsUrl, readDepNameCompletions, readProjectManifestOnly, TABLE_OPTIONS, } from '@pnpm/cli.utils';
|
|
4
|
+
import colorizeSemverDiff from '@pnpm/colorize-semver-diff';
|
|
5
|
+
import { types as allTypes } from '@pnpm/config.reader';
|
|
6
|
+
import { outdatedDepsOfProjects, } from '@pnpm/deps.inspection.outdated';
|
|
7
|
+
import { PnpmError } from '@pnpm/error';
|
|
8
|
+
import { scanGlobalPackages } from '@pnpm/global.packages';
|
|
9
|
+
import semverDiff from '@pnpm/semver-diff';
|
|
10
|
+
import { table } from '@zkochan/table';
|
|
11
|
+
import chalk from 'chalk';
|
|
12
|
+
import { pick, sortWith } from 'ramda';
|
|
13
|
+
import { renderHelp } from 'render-help';
|
|
14
|
+
import { outdatedRecursive } from './recursive.js';
|
|
15
|
+
import { DEFAULT_COMPARATORS, NAME_COMPARATOR, } from './utils.js';
|
|
16
|
+
export function rcOptionsTypes() {
|
|
17
|
+
return {
|
|
18
|
+
...pick([
|
|
19
|
+
'depth',
|
|
20
|
+
'dev',
|
|
21
|
+
'global-dir',
|
|
22
|
+
'global',
|
|
23
|
+
'long',
|
|
24
|
+
'optional',
|
|
25
|
+
'production',
|
|
26
|
+
], allTypes),
|
|
27
|
+
compatible: Boolean,
|
|
28
|
+
format: ['table', 'list', 'json'],
|
|
29
|
+
'sort-by': 'name',
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export const cliOptionsTypes = () => ({
|
|
33
|
+
...rcOptionsTypes(),
|
|
34
|
+
recursive: Boolean,
|
|
35
|
+
});
|
|
36
|
+
export const shorthands = {
|
|
37
|
+
D: '--dev',
|
|
38
|
+
P: '--production',
|
|
39
|
+
table: '--format=table',
|
|
40
|
+
'no-table': '--format=list',
|
|
41
|
+
json: '--format=json',
|
|
42
|
+
};
|
|
43
|
+
export const commandNames = ['outdated'];
|
|
44
|
+
export function help() {
|
|
45
|
+
return renderHelp({
|
|
46
|
+
description: `Check for outdated packages. The check can be limited to a subset of the installed packages by providing arguments (patterns are supported).
|
|
47
|
+
|
|
48
|
+
Examples:
|
|
49
|
+
pnpm outdated
|
|
50
|
+
pnpm outdated --long
|
|
51
|
+
pnpm outdated gulp-* @babel/core`,
|
|
52
|
+
descriptionLists: [
|
|
53
|
+
{
|
|
54
|
+
title: 'Options',
|
|
55
|
+
list: [
|
|
56
|
+
{
|
|
57
|
+
description: 'Print only versions that satisfy specs in package.json',
|
|
58
|
+
name: '--compatible',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
description: 'By default, details about the outdated packages (such as a link to the repo) are not displayed. \
|
|
62
|
+
To display the details, pass this option.',
|
|
63
|
+
name: '--long',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
description: 'Check for outdated dependencies in every package found in subdirectories \
|
|
67
|
+
or in every workspace package, when executed inside a workspace. \
|
|
68
|
+
For options that may be used with `-r`, see "pnpm help recursive"',
|
|
69
|
+
name: '--recursive',
|
|
70
|
+
shortAlias: '-r',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
description: 'Prints the outdated packages in a list. Good for small consoles',
|
|
74
|
+
name: '--no-table',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
description: 'Check only "dependencies" and "optionalDependencies"',
|
|
78
|
+
name: '--prod',
|
|
79
|
+
shortAlias: '-P',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
description: 'Check only "devDependencies"',
|
|
83
|
+
name: '--dev',
|
|
84
|
+
shortAlias: '-D',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
description: 'Don\'t check "optionalDependencies"',
|
|
88
|
+
name: '--no-optional',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
description: 'Prints the outdated dependencies in the given format. Default is "table". Supported options: "table, list, json"',
|
|
92
|
+
name: '--format <format>',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
description: 'Specify the sorting method. Currently only `name` is supported.',
|
|
96
|
+
name: '--sort-by',
|
|
97
|
+
},
|
|
98
|
+
OPTIONS.globalDir,
|
|
99
|
+
...UNIVERSAL_OPTIONS,
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
FILTERING,
|
|
103
|
+
],
|
|
104
|
+
url: docsUrl('outdated'),
|
|
105
|
+
usages: ['pnpm outdated [<pkg> ...]'],
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
export const completion = async (cliOpts) => {
|
|
109
|
+
return readDepNameCompletions(cliOpts.dir);
|
|
110
|
+
};
|
|
111
|
+
export async function handler(opts, params = []) {
|
|
112
|
+
const include = {
|
|
113
|
+
dependencies: opts.production !== false,
|
|
114
|
+
devDependencies: opts.dev !== false,
|
|
115
|
+
optionalDependencies: opts.optional !== false,
|
|
116
|
+
};
|
|
117
|
+
if (opts.recursive && (opts.selectedProjectsGraph != null)) {
|
|
118
|
+
const pkgs = Object.values(opts.selectedProjectsGraph).map((wsPkg) => wsPkg.package);
|
|
119
|
+
return outdatedRecursive(pkgs, params, { ...opts, include });
|
|
120
|
+
}
|
|
121
|
+
let packages;
|
|
122
|
+
if (opts.global && opts.globalPkgDir) {
|
|
123
|
+
const globalPackages = scanGlobalPackages(opts.globalPkgDir);
|
|
124
|
+
packages = await Promise.all(globalPackages.map(async (pkg) => ({
|
|
125
|
+
rootDir: pkg.installDir,
|
|
126
|
+
manifest: await readProjectManifestOnly(pkg.installDir, opts),
|
|
127
|
+
})));
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
const manifest = await readProjectManifestOnly(opts.dir, opts);
|
|
131
|
+
packages = [
|
|
132
|
+
{
|
|
133
|
+
rootDir: opts.dir,
|
|
134
|
+
manifest,
|
|
135
|
+
},
|
|
136
|
+
];
|
|
137
|
+
}
|
|
138
|
+
const outdatedPerProject = await outdatedDepsOfProjects(packages, params, {
|
|
139
|
+
...opts,
|
|
140
|
+
fullMetadata: opts.long,
|
|
141
|
+
ignoreDependencies: opts.updateConfig?.ignoreDependencies,
|
|
142
|
+
include,
|
|
143
|
+
minimumReleaseAge: opts.minimumReleaseAge,
|
|
144
|
+
minimumReleaseAgeExclude: opts.minimumReleaseAgeExclude,
|
|
145
|
+
retry: {
|
|
146
|
+
factor: opts.fetchRetryFactor,
|
|
147
|
+
maxTimeout: opts.fetchRetryMaxtimeout,
|
|
148
|
+
minTimeout: opts.fetchRetryMintimeout,
|
|
149
|
+
retries: opts.fetchRetries,
|
|
150
|
+
},
|
|
151
|
+
timeout: opts.fetchTimeout,
|
|
152
|
+
});
|
|
153
|
+
const outdatedPackages = outdatedPerProject.flat();
|
|
154
|
+
let output;
|
|
155
|
+
switch (opts.format ?? 'table') {
|
|
156
|
+
case 'table': {
|
|
157
|
+
output = renderOutdatedTable(outdatedPackages, opts);
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
case 'list': {
|
|
161
|
+
output = renderOutdatedList(outdatedPackages, opts);
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
case 'json': {
|
|
165
|
+
output = renderOutdatedJSON(outdatedPackages, opts);
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
default: {
|
|
169
|
+
throw new PnpmError('BAD_OUTDATED_FORMAT', `Unsupported format: ${opts.format?.toString() ?? 'undefined'}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
output,
|
|
174
|
+
exitCode: outdatedPackages.length === 0 ? 0 : 1,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function renderOutdatedTable(outdatedPackages, opts) {
|
|
178
|
+
if (outdatedPackages.length === 0)
|
|
179
|
+
return '';
|
|
180
|
+
const columnNames = [
|
|
181
|
+
'Package',
|
|
182
|
+
'Current',
|
|
183
|
+
'Latest',
|
|
184
|
+
];
|
|
185
|
+
const columnFns = [
|
|
186
|
+
renderPackageName,
|
|
187
|
+
renderCurrent,
|
|
188
|
+
renderLatest,
|
|
189
|
+
];
|
|
190
|
+
if (opts.long) {
|
|
191
|
+
columnNames.push('Details');
|
|
192
|
+
columnFns.push(renderDetails);
|
|
193
|
+
}
|
|
194
|
+
// Avoid the overhead of allocating a new array caused by calling `array.map()`
|
|
195
|
+
for (let i = 0; i < columnNames.length; i++)
|
|
196
|
+
columnNames[i] = chalk.blueBright(columnNames[i]);
|
|
197
|
+
const data = [
|
|
198
|
+
columnNames,
|
|
199
|
+
...sortOutdatedPackages(outdatedPackages, { sortBy: opts.sortBy })
|
|
200
|
+
.map((outdatedPkg) => columnFns.map((fn) => fn(outdatedPkg))),
|
|
201
|
+
];
|
|
202
|
+
const tableOptions = {
|
|
203
|
+
...TABLE_OPTIONS,
|
|
204
|
+
};
|
|
205
|
+
if (opts.long) {
|
|
206
|
+
const detailsColumnMaxWidth = outdatedPackages.filter(pkg => pkg.latestManifest && !pkg.latestManifest.deprecated).reduce((maxWidth, pkg) => {
|
|
207
|
+
const cellWidth = pkg.latestManifest?.homepage?.length ?? 0;
|
|
208
|
+
return Math.max(maxWidth, cellWidth);
|
|
209
|
+
}, 40);
|
|
210
|
+
tableOptions.columns = {
|
|
211
|
+
// Detail column:
|
|
212
|
+
3: {
|
|
213
|
+
width: detailsColumnMaxWidth,
|
|
214
|
+
wrapWord: true,
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
return table(data, tableOptions);
|
|
219
|
+
}
|
|
220
|
+
function renderOutdatedList(outdatedPackages, opts) {
|
|
221
|
+
if (outdatedPackages.length === 0)
|
|
222
|
+
return '';
|
|
223
|
+
return sortOutdatedPackages(outdatedPackages, { sortBy: opts.sortBy })
|
|
224
|
+
.map((outdatedPkg) => {
|
|
225
|
+
let info = `${chalk.bold(renderPackageName(outdatedPkg))}
|
|
226
|
+
${renderCurrent(outdatedPkg)} ${chalk.grey('=>')} ${renderLatest(outdatedPkg)}`;
|
|
227
|
+
if (opts.long) {
|
|
228
|
+
const details = renderDetails(outdatedPkg);
|
|
229
|
+
if (details) {
|
|
230
|
+
info += `\n${details}`;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return info;
|
|
234
|
+
})
|
|
235
|
+
.join('\n\n') + '\n';
|
|
236
|
+
}
|
|
237
|
+
function renderOutdatedJSON(outdatedPackages, opts) {
|
|
238
|
+
const outdatedPackagesJSON = sortOutdatedPackages(outdatedPackages, { sortBy: opts.sortBy })
|
|
239
|
+
.reduce((acc, outdatedPkg) => {
|
|
240
|
+
acc[outdatedPkg.packageName] = {
|
|
241
|
+
current: outdatedPkg.current,
|
|
242
|
+
latest: outdatedPkg.latestManifest?.version,
|
|
243
|
+
wanted: outdatedPkg.wanted,
|
|
244
|
+
isDeprecated: Boolean(outdatedPkg.latestManifest?.deprecated),
|
|
245
|
+
dependencyType: outdatedPkg.belongsTo,
|
|
246
|
+
};
|
|
247
|
+
if (opts.long) {
|
|
248
|
+
acc[outdatedPkg.packageName].latestManifest = outdatedPkg.latestManifest;
|
|
249
|
+
}
|
|
250
|
+
return acc;
|
|
251
|
+
}, {});
|
|
252
|
+
return JSON.stringify(outdatedPackagesJSON, null, 2);
|
|
253
|
+
}
|
|
254
|
+
function sortOutdatedPackages(outdatedPackages, opts) {
|
|
255
|
+
const sortBy = opts?.sortBy;
|
|
256
|
+
const comparators = (sortBy === 'name') ? [NAME_COMPARATOR] : DEFAULT_COMPARATORS;
|
|
257
|
+
return sortWith(comparators, outdatedPackages.map(toOutdatedWithVersionDiff));
|
|
258
|
+
}
|
|
259
|
+
export function getCellWidth(data, columnNumber, maxWidth) {
|
|
260
|
+
const maxCellWidth = data.reduce((cellWidth, row) => {
|
|
261
|
+
const cellLines = stripAnsi(row[columnNumber]).split('\n');
|
|
262
|
+
const currentCellWidth = cellLines.reduce((lineWidth, line) => {
|
|
263
|
+
return Math.max(lineWidth, line.length);
|
|
264
|
+
}, 0);
|
|
265
|
+
return Math.max(cellWidth, currentCellWidth);
|
|
266
|
+
}, 0);
|
|
267
|
+
return Math.min(maxWidth, maxCellWidth);
|
|
268
|
+
}
|
|
269
|
+
export function toOutdatedWithVersionDiff(outdated) {
|
|
270
|
+
if (outdated.latestManifest != null) {
|
|
271
|
+
return {
|
|
272
|
+
...outdated,
|
|
273
|
+
...semverDiff.default(outdated.wanted, outdated.latestManifest.version),
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
return {
|
|
277
|
+
...outdated,
|
|
278
|
+
change: 'unknown',
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
export function renderPackageName({ belongsTo, packageName }) {
|
|
282
|
+
switch (belongsTo) {
|
|
283
|
+
case 'devDependencies': return `${packageName} ${chalk.dim('(dev)')}`;
|
|
284
|
+
case 'optionalDependencies': return `${packageName} ${chalk.dim('(optional)')}`;
|
|
285
|
+
default: return packageName;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
export function renderCurrent({ current, wanted }) {
|
|
289
|
+
const output = current ?? 'missing';
|
|
290
|
+
if (current === wanted)
|
|
291
|
+
return output;
|
|
292
|
+
return `${output} (wanted ${wanted})`;
|
|
293
|
+
}
|
|
294
|
+
export function renderLatest(outdatedPkg) {
|
|
295
|
+
const { latestManifest, change, diff } = outdatedPkg;
|
|
296
|
+
if (latestManifest == null)
|
|
297
|
+
return '';
|
|
298
|
+
if (change === null || (diff == null)) {
|
|
299
|
+
return latestManifest.deprecated
|
|
300
|
+
? chalk.redBright.bold('Deprecated')
|
|
301
|
+
: latestManifest.version;
|
|
302
|
+
}
|
|
303
|
+
const versionText = colorizeSemverDiff.default({ change, diff });
|
|
304
|
+
if (latestManifest.deprecated) {
|
|
305
|
+
return `${versionText} ${chalk.redBright('(deprecated)')}`;
|
|
306
|
+
}
|
|
307
|
+
return versionText;
|
|
308
|
+
}
|
|
309
|
+
export function renderDetails({ latestManifest }) {
|
|
310
|
+
if (latestManifest == null)
|
|
311
|
+
return '';
|
|
312
|
+
const outputs = [];
|
|
313
|
+
if (latestManifest.deprecated) {
|
|
314
|
+
outputs.push(chalk.redBright(latestManifest.deprecated));
|
|
315
|
+
}
|
|
316
|
+
if (latestManifest.homepage) {
|
|
317
|
+
outputs.push(chalk.underline(latestManifest.homepage));
|
|
318
|
+
}
|
|
319
|
+
return outputs.join('\n');
|
|
320
|
+
}
|
|
321
|
+
//# sourceMappingURL=outdated.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IncludedDependencies, ProjectManifest, ProjectRootDir } from '@pnpm/types';
|
|
2
|
+
import { type OutdatedCommandOptions, type OutdatedPackageJSONOutput } from './outdated.js';
|
|
3
|
+
export declare function outdatedRecursive(pkgs: Array<{
|
|
4
|
+
rootDir: ProjectRootDir;
|
|
5
|
+
manifest: ProjectManifest;
|
|
6
|
+
}>, params: string[], opts: OutdatedCommandOptions & {
|
|
7
|
+
include: IncludedDependencies;
|
|
8
|
+
}): Promise<{
|
|
9
|
+
output: string;
|
|
10
|
+
exitCode: number;
|
|
11
|
+
}>;
|
|
12
|
+
export interface OutdatedPackageInWorkspaceJSONOutput extends OutdatedPackageJSONOutput {
|
|
13
|
+
dependentPackages: Array<{
|
|
14
|
+
name: string;
|
|
15
|
+
location: string;
|
|
16
|
+
}>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { TABLE_OPTIONS } from '@pnpm/cli.utils';
|
|
2
|
+
import { outdatedDepsOfProjects, } from '@pnpm/deps.inspection.outdated';
|
|
3
|
+
import { PnpmError } from '@pnpm/error';
|
|
4
|
+
import { table } from '@zkochan/table';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { isEmpty, sortWith } from 'ramda';
|
|
7
|
+
import { getCellWidth, renderCurrent, renderDetails, renderLatest, renderPackageName, toOutdatedWithVersionDiff, } from './outdated.js';
|
|
8
|
+
import { DEFAULT_COMPARATORS } from './utils.js';
|
|
9
|
+
const DEP_PRIORITY = {
|
|
10
|
+
dependencies: 1,
|
|
11
|
+
devDependencies: 2,
|
|
12
|
+
optionalDependencies: 0,
|
|
13
|
+
};
|
|
14
|
+
const COMPARATORS = [
|
|
15
|
+
...DEFAULT_COMPARATORS,
|
|
16
|
+
(o1, o2) => DEP_PRIORITY[o1.belongsTo] - DEP_PRIORITY[o2.belongsTo],
|
|
17
|
+
];
|
|
18
|
+
export async function outdatedRecursive(pkgs, params, opts) {
|
|
19
|
+
const outdatedMap = {};
|
|
20
|
+
const outdatedPackagesByProject = await outdatedDepsOfProjects(pkgs, params, {
|
|
21
|
+
...opts,
|
|
22
|
+
fullMetadata: opts.long,
|
|
23
|
+
ignoreDependencies: opts.updateConfig?.ignoreDependencies,
|
|
24
|
+
minimumReleaseAge: opts.minimumReleaseAge,
|
|
25
|
+
minimumReleaseAgeExclude: opts.minimumReleaseAgeExclude,
|
|
26
|
+
retry: {
|
|
27
|
+
factor: opts.fetchRetryFactor,
|
|
28
|
+
maxTimeout: opts.fetchRetryMaxtimeout,
|
|
29
|
+
minTimeout: opts.fetchRetryMintimeout,
|
|
30
|
+
retries: opts.fetchRetries,
|
|
31
|
+
},
|
|
32
|
+
timeout: opts.fetchTimeout,
|
|
33
|
+
});
|
|
34
|
+
for (let i = 0; i < outdatedPackagesByProject.length; i++) {
|
|
35
|
+
const { rootDir, manifest } = pkgs[i];
|
|
36
|
+
for (const outdatedPkg of outdatedPackagesByProject[i]) {
|
|
37
|
+
const key = JSON.stringify([outdatedPkg.packageName, outdatedPkg.current, outdatedPkg.belongsTo]);
|
|
38
|
+
if (!outdatedMap[key]) {
|
|
39
|
+
outdatedMap[key] = { ...outdatedPkg, dependentPkgs: [] };
|
|
40
|
+
}
|
|
41
|
+
outdatedMap[key].dependentPkgs.push({ location: rootDir, manifest });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
let output;
|
|
45
|
+
switch (opts.format ?? 'table') {
|
|
46
|
+
case 'table': {
|
|
47
|
+
output = renderOutdatedTable(outdatedMap, opts);
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
case 'list': {
|
|
51
|
+
output = renderOutdatedList(outdatedMap, opts);
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case 'json': {
|
|
55
|
+
output = renderOutdatedJSON(outdatedMap, opts);
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
default: {
|
|
59
|
+
throw new PnpmError('BAD_OUTDATED_FORMAT', `Unsupported format: ${opts.format?.toString() ?? 'undefined'}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
output,
|
|
64
|
+
exitCode: isEmpty(outdatedMap) ? 0 : 1,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function renderOutdatedTable(outdatedMap, opts) {
|
|
68
|
+
if (isEmpty(outdatedMap))
|
|
69
|
+
return '';
|
|
70
|
+
const columnNames = [
|
|
71
|
+
'Package',
|
|
72
|
+
'Current',
|
|
73
|
+
'Latest',
|
|
74
|
+
'Dependents',
|
|
75
|
+
];
|
|
76
|
+
const columnFns = [
|
|
77
|
+
renderPackageName,
|
|
78
|
+
renderCurrent,
|
|
79
|
+
renderLatest,
|
|
80
|
+
dependentPackages,
|
|
81
|
+
];
|
|
82
|
+
if (opts.long) {
|
|
83
|
+
columnNames.push('Details');
|
|
84
|
+
columnFns.push(renderDetails);
|
|
85
|
+
}
|
|
86
|
+
// Avoid the overhead of allocating a new array caused by calling `array.map()`
|
|
87
|
+
for (let i = 0; i < columnNames.length; i++)
|
|
88
|
+
columnNames[i] = chalk.blueBright(columnNames[i]);
|
|
89
|
+
const data = [
|
|
90
|
+
columnNames,
|
|
91
|
+
...sortOutdatedPackages(Object.values(outdatedMap))
|
|
92
|
+
.map((outdatedPkg) => columnFns.map((fn) => fn(outdatedPkg))),
|
|
93
|
+
];
|
|
94
|
+
return table(data, {
|
|
95
|
+
...TABLE_OPTIONS,
|
|
96
|
+
columns: {
|
|
97
|
+
...TABLE_OPTIONS.columns,
|
|
98
|
+
// Dependents column:
|
|
99
|
+
3: {
|
|
100
|
+
width: getCellWidth(data, 3, 30),
|
|
101
|
+
wrapWord: true,
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
function renderOutdatedList(outdatedMap, opts) {
|
|
107
|
+
if (isEmpty(outdatedMap))
|
|
108
|
+
return '';
|
|
109
|
+
return sortOutdatedPackages(Object.values(outdatedMap))
|
|
110
|
+
.map((outdatedPkg) => {
|
|
111
|
+
let info = `${chalk.bold(renderPackageName(outdatedPkg))}
|
|
112
|
+
${renderCurrent(outdatedPkg)} ${chalk.grey('=>')} ${renderLatest(outdatedPkg)}`;
|
|
113
|
+
const dependents = dependentPackages(outdatedPkg);
|
|
114
|
+
if (dependents) {
|
|
115
|
+
info += `\n${chalk.bold(outdatedPkg.dependentPkgs.length > 1
|
|
116
|
+
? 'Dependents:'
|
|
117
|
+
: 'Dependent:')} ${dependents}`;
|
|
118
|
+
}
|
|
119
|
+
if (opts.long) {
|
|
120
|
+
const details = renderDetails(outdatedPkg);
|
|
121
|
+
if (details) {
|
|
122
|
+
info += `\n${details}`;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return info;
|
|
126
|
+
})
|
|
127
|
+
.join('\n\n') + '\n';
|
|
128
|
+
}
|
|
129
|
+
function renderOutdatedJSON(outdatedMap, opts) {
|
|
130
|
+
const outdatedPackagesJSON = sortOutdatedPackages(Object.values(outdatedMap))
|
|
131
|
+
.reduce((acc, outdatedPkg) => {
|
|
132
|
+
acc[outdatedPkg.packageName] = {
|
|
133
|
+
current: outdatedPkg.current,
|
|
134
|
+
latest: outdatedPkg.latestManifest?.version,
|
|
135
|
+
wanted: outdatedPkg.wanted,
|
|
136
|
+
isDeprecated: Boolean(outdatedPkg.latestManifest?.deprecated),
|
|
137
|
+
dependencyType: outdatedPkg.belongsTo,
|
|
138
|
+
dependentPackages: outdatedPkg.dependentPkgs.map(({ manifest, location }) => ({ name: manifest.name, location })),
|
|
139
|
+
};
|
|
140
|
+
if (opts.long) {
|
|
141
|
+
acc[outdatedPkg.packageName].latestManifest = outdatedPkg.latestManifest;
|
|
142
|
+
}
|
|
143
|
+
return acc;
|
|
144
|
+
}, {});
|
|
145
|
+
return JSON.stringify(outdatedPackagesJSON, null, 2);
|
|
146
|
+
}
|
|
147
|
+
function dependentPackages({ dependentPkgs }) {
|
|
148
|
+
return dependentPkgs
|
|
149
|
+
.map(({ manifest, location }) => manifest.name ?? location)
|
|
150
|
+
.sort()
|
|
151
|
+
.join(', ');
|
|
152
|
+
}
|
|
153
|
+
function sortOutdatedPackages(outdatedPackages) {
|
|
154
|
+
return sortWith(COMPARATORS, outdatedPackages.map(toOutdatedWithVersionDiff));
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=recursive.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { OutdatedPackage } from '@pnpm/deps.inspection.outdated';
|
|
2
|
+
import type { SEMVER_CHANGE } from '@pnpm/semver-diff';
|
|
3
|
+
export interface OutdatedWithVersionDiff extends OutdatedPackage {
|
|
4
|
+
change: SEMVER_CHANGE | null;
|
|
5
|
+
diff?: [string[], string[]];
|
|
6
|
+
}
|
|
7
|
+
export type Comparator = (o1: OutdatedWithVersionDiff, o2: OutdatedWithVersionDiff) => number;
|
|
8
|
+
export declare const NAME_COMPARATOR: Comparator;
|
|
9
|
+
/**
|
|
10
|
+
* Default comparators used as the argument to `ramda.sortWith()`.
|
|
11
|
+
*/
|
|
12
|
+
export declare const DEFAULT_COMPARATORS: Comparator[];
|
|
13
|
+
export declare function sortBySemverChange(outdated1: OutdatedWithVersionDiff, outdated2: OutdatedWithVersionDiff): number;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const NAME_COMPARATOR = (o1, o2) => o1.packageName.localeCompare(o2.packageName);
|
|
2
|
+
/**
|
|
3
|
+
* Default comparators used as the argument to `ramda.sortWith()`.
|
|
4
|
+
*/
|
|
5
|
+
export const DEFAULT_COMPARATORS = [
|
|
6
|
+
sortBySemverChange,
|
|
7
|
+
NAME_COMPARATOR,
|
|
8
|
+
(o1, o2) => (o1.current && o2.current) ? o1.current.localeCompare(o2.current) : 0, // eslint-disable-line @typescript-eslint/explicit-module-boundary-types
|
|
9
|
+
];
|
|
10
|
+
export function sortBySemverChange(outdated1, outdated2) {
|
|
11
|
+
return pkgPriority(outdated1) - pkgPriority(outdated2);
|
|
12
|
+
}
|
|
13
|
+
function pkgPriority(pkg) {
|
|
14
|
+
switch (pkg.change) {
|
|
15
|
+
case null: return 0;
|
|
16
|
+
case 'fix': return 1;
|
|
17
|
+
case 'feature': return 2;
|
|
18
|
+
case 'breaking': return 3;
|
|
19
|
+
default: return 4;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=utils.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pnpm/deps.inspection.commands",
|
|
3
|
+
"version": "1000.0.0",
|
|
4
|
+
"description": "The list, ll, why, and outdated commands of pnpm",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"pnpm",
|
|
7
|
+
"pnpm11"
|
|
8
|
+
],
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"funding": "https://opencollective.com/pnpm",
|
|
11
|
+
"repository": "https://github.com/pnpm/pnpm/tree/main/deps/inspection/commands",
|
|
12
|
+
"homepage": "https://github.com/pnpm/pnpm/tree/main/deps/inspection/commands#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/pnpm/pnpm/issues"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "lib/index.js",
|
|
18
|
+
"types": "lib/index.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": "./lib/index.js"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"lib",
|
|
24
|
+
"!*.map"
|
|
25
|
+
],
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@pnpm/colorize-semver-diff": "^1.0.1",
|
|
28
|
+
"@pnpm/semver-diff": "^1.1.0",
|
|
29
|
+
"@zkochan/table": "^2.0.1",
|
|
30
|
+
"chalk": "^5.6.0",
|
|
31
|
+
"ramda": "npm:@pnpm/ramda@0.28.1",
|
|
32
|
+
"render-help": "^2.0.0",
|
|
33
|
+
"@pnpm/cli.common-cli-options-help": "1000.0.1",
|
|
34
|
+
"@pnpm/cli.command": "1000.0.0",
|
|
35
|
+
"@pnpm/cli.utils": "1001.2.8",
|
|
36
|
+
"@pnpm/config.reader": "1004.4.2",
|
|
37
|
+
"@pnpm/deps.inspection.outdated": "1001.1.1",
|
|
38
|
+
"@pnpm/deps.inspection.list": "1000.1.3",
|
|
39
|
+
"@pnpm/error": "1000.0.5",
|
|
40
|
+
"@pnpm/config.matcher": "1000.1.0",
|
|
41
|
+
"@pnpm/global.commands": "1000.0.0-0",
|
|
42
|
+
"@pnpm/global.packages": "1000.0.0-0",
|
|
43
|
+
"@pnpm/installing.modules-yaml": "1000.3.6",
|
|
44
|
+
"@pnpm/resolving.default-resolver": "1002.2.12",
|
|
45
|
+
"@pnpm/store.path": "1000.0.5",
|
|
46
|
+
"@pnpm/types": "1000.9.0",
|
|
47
|
+
"@pnpm/lockfile.fs": "1001.1.21"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"@pnpm/logger": ">=1001.0.0 <1002.0.0"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@jest/globals": "30.0.5",
|
|
54
|
+
"@pnpm/registry-mock": "5.2.4",
|
|
55
|
+
"@types/ramda": "0.29.12",
|
|
56
|
+
"@types/zkochan__table": "npm:@types/table@6.0.0",
|
|
57
|
+
"execa": "npm:safe-execa@0.3.0",
|
|
58
|
+
"symlink-dir": "^7.0.0",
|
|
59
|
+
"write-yaml-file": "^6.0.0",
|
|
60
|
+
"@pnpm/constants": "1001.3.1",
|
|
61
|
+
"@pnpm/prepare": "1000.0.4",
|
|
62
|
+
"@pnpm/installing.commands": "1004.6.10",
|
|
63
|
+
"@pnpm/test-fixtures": "1000.0.0",
|
|
64
|
+
"@pnpm/deps.inspection.commands": "1000.0.0",
|
|
65
|
+
"@pnpm/workspace.projects-filter": "1000.0.43"
|
|
66
|
+
},
|
|
67
|
+
"engines": {
|
|
68
|
+
"node": ">=22.13"
|
|
69
|
+
},
|
|
70
|
+
"jest": {
|
|
71
|
+
"preset": "@pnpm/jest-config/with-registry"
|
|
72
|
+
},
|
|
73
|
+
"scripts": {
|
|
74
|
+
"lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
75
|
+
"_test": "cross-env NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules --disable-warning=ExperimentalWarning --disable-warning=DEP0169\" jest",
|
|
76
|
+
"test": "pnpm run compile && pnpm run _test",
|
|
77
|
+
"compile": "tsgo --build && pnpm run lint --fix"
|
|
78
|
+
}
|
|
79
|
+
}
|