@pnpm/deps.inspection.outdated 1100.0.16 → 1100.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/outdated.d.ts +5 -4
- package/lib/outdated.js +59 -30
- package/lib/outdatedDepsOfProjects.d.ts +14 -6
- package/lib/outdatedDepsOfProjects.js +10 -7
- package/package.json +13 -14
package/lib/outdated.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Catalogs } from '@pnpm/catalogs.types';
|
|
2
|
+
import type { ResolveLatestDispatcher } from '@pnpm/installing.client';
|
|
2
3
|
import { type LockfileObject } from '@pnpm/lockfile.fs';
|
|
3
|
-
import { type DependenciesField, type IncludedDependencies, type PackageManifest, type
|
|
4
|
+
import { type DependenciesField, type IncludedDependencies, type PackageManifest, type PackageVersionPolicy, type ProjectManifest } from '@pnpm/types';
|
|
4
5
|
export * from './createManifestGetter.js';
|
|
5
|
-
export type GetLatestManifestFunction = (packageName: string, rangeOrTag: string) => Promise<PackageManifest | null>;
|
|
6
6
|
export interface OutdatedPackage {
|
|
7
7
|
alias: string;
|
|
8
8
|
belongsTo: DependenciesField;
|
|
@@ -16,7 +16,7 @@ export declare function outdated(opts: {
|
|
|
16
16
|
catalogs?: Catalogs;
|
|
17
17
|
compatible?: boolean;
|
|
18
18
|
currentLockfile: LockfileObject | null;
|
|
19
|
-
|
|
19
|
+
resolveLatest: ResolveLatestDispatcher;
|
|
20
20
|
ignoreDependencies?: string[];
|
|
21
21
|
include?: IncludedDependencies;
|
|
22
22
|
lockfileDir: string;
|
|
@@ -25,6 +25,7 @@ export declare function outdated(opts: {
|
|
|
25
25
|
minimumReleaseAge?: number;
|
|
26
26
|
minimumReleaseAgeExclude?: string[];
|
|
27
27
|
prefix: string;
|
|
28
|
-
|
|
28
|
+
publishedBy?: Date;
|
|
29
|
+
publishedByExclude?: PackageVersionPolicy;
|
|
29
30
|
wantedLockfile: LockfileObject | null;
|
|
30
31
|
}): Promise<OutdatedPackage[]>;
|
package/lib/outdated.js
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { matchCatalogResolveResult, resolveFromCatalog, } from '@pnpm/catalogs.resolver';
|
|
2
2
|
import { createMatcher } from '@pnpm/config.matcher';
|
|
3
3
|
import { parseOverrides } from '@pnpm/config.parse-overrides';
|
|
4
|
-
import {
|
|
5
|
-
import { LOCKFILE_VERSION, WANTED_LOCKFILE } from '@pnpm/constants';
|
|
4
|
+
import { LOCKFILE_VERSION } from '@pnpm/constants';
|
|
6
5
|
import * as dp from '@pnpm/deps.path';
|
|
7
6
|
import { PnpmError } from '@pnpm/error';
|
|
8
7
|
import { createReadPackageHook } from '@pnpm/hooks.read-package-hook';
|
|
9
8
|
import { getLockfileImporterId, } from '@pnpm/lockfile.fs';
|
|
10
|
-
import { nameVerFromPkgSnapshot } from '@pnpm/lockfile.utils';
|
|
11
9
|
import { getAllDependenciesFromManifest } from '@pnpm/pkg-manifest.utils';
|
|
12
|
-
import { parseBareSpecifier } from '@pnpm/resolving.npm-resolver';
|
|
13
10
|
import { DEPENDENCIES_FIELDS, } from '@pnpm/types';
|
|
14
11
|
import semver from 'semver';
|
|
15
12
|
export * from './createManifestGetter.js';
|
|
@@ -37,6 +34,13 @@ export async function outdated(opts) {
|
|
|
37
34
|
const currentLockfile = opts.currentLockfile ?? { lockfileVersion: LOCKFILE_VERSION, importers: { [importerId]: { specifiers: {} } } };
|
|
38
35
|
const outdated = [];
|
|
39
36
|
const ignoreDependenciesMatcher = opts.ignoreDependencies?.length ? createMatcher(opts.ignoreDependencies) : undefined;
|
|
37
|
+
const resolveOpts = {
|
|
38
|
+
lockfileDir: opts.lockfileDir,
|
|
39
|
+
preferredVersions: {},
|
|
40
|
+
projectDir: opts.prefix,
|
|
41
|
+
publishedBy: opts.publishedBy,
|
|
42
|
+
publishedByExclude: opts.publishedByExclude,
|
|
43
|
+
};
|
|
40
44
|
await Promise.all(DEPENDENCIES_FIELDS.map(async (depType) => {
|
|
41
45
|
if (opts.include?.[depType] === false ||
|
|
42
46
|
(opts.wantedLockfile.importers[importerId][depType] == null))
|
|
@@ -49,31 +53,31 @@ export async function outdated(opts) {
|
|
|
49
53
|
await Promise.all(pkgs.map(async (alias) => {
|
|
50
54
|
if (!allDeps[alias])
|
|
51
55
|
return;
|
|
52
|
-
const
|
|
53
|
-
if (
|
|
54
|
-
ignoreDependenciesMatcher?.(alias)) {
|
|
56
|
+
const wantedRef = opts.wantedLockfile.importers[importerId][depType][alias];
|
|
57
|
+
if (ignoreDependenciesMatcher?.(alias))
|
|
55
58
|
return;
|
|
56
|
-
}
|
|
57
|
-
const relativeDepPath = dp.refToRelative(ref, alias);
|
|
58
|
-
// ignoring linked packages
|
|
59
|
-
if (relativeDepPath === null)
|
|
60
|
-
return;
|
|
61
|
-
const pkgSnapshot = opts.wantedLockfile.packages?.[relativeDepPath];
|
|
62
|
-
if (pkgSnapshot == null) {
|
|
63
|
-
throw new Error(`Invalid ${WANTED_LOCKFILE} file. ${relativeDepPath} not found in packages field`);
|
|
64
|
-
}
|
|
65
59
|
const currentRef = currentLockfile.importers[importerId]?.[depType]?.[alias];
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
const
|
|
69
|
-
const
|
|
70
|
-
|
|
60
|
+
const wantedRelative = dp.refToRelative(wantedRef, alias);
|
|
61
|
+
const currentRelative = currentRef ? dp.refToRelative(currentRef, alias) : null;
|
|
62
|
+
const wantedSnapshot = wantedRelative != null ? opts.wantedLockfile.packages?.[wantedRelative] : undefined;
|
|
63
|
+
const currentSnapshot = currentRelative != null ? currentLockfile.packages?.[currentRelative] : undefined;
|
|
64
|
+
// Aliased npm deps lock under their real name (e.g. `positive: is-positive@3.1.0`);
|
|
65
|
+
// pull the name off the depPath so the report shows the real package.
|
|
66
|
+
const packageName = (wantedRelative != null ? dp.parse(wantedRelative).name : undefined) ?? alias;
|
|
71
67
|
const bareSpecifier = _replaceCatalogProtocolIfNecessary({ alias, bareSpecifier: allDeps[alias] });
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
68
|
+
const info = await opts.resolveLatest({ wantedDependency: { alias, bareSpecifier }, compatible: opts.compatible }, resolveOpts);
|
|
69
|
+
if (info == null)
|
|
70
|
+
return; // resolver doesn't claim this dep — skip silently
|
|
71
|
+
const wanted = displayVersion(wantedRef, wantedRelative, wantedSnapshot?.version);
|
|
72
|
+
const current = currentRef ? displayVersion(currentRef, currentRelative, currentSnapshot?.version) : undefined;
|
|
73
|
+
const { latestManifest } = info;
|
|
74
|
+
// Compare the parsed `wanted` / `current` rather than raw refs.
|
|
75
|
+
// For npm-style deps that means peer-graph-only changes (same
|
|
76
|
+
// semver, different `(peer-hash)`) don't surface as fake
|
|
77
|
+
// "outdated" entries; for URL/git refs the display values *are*
|
|
78
|
+
// the refs, so a commit/path change still fires correctly.
|
|
79
|
+
if (latestManifest == null) {
|
|
80
|
+
if (wanted !== current) {
|
|
77
81
|
outdated.push({
|
|
78
82
|
alias,
|
|
79
83
|
belongsTo: depType,
|
|
@@ -86,9 +90,6 @@ export async function outdated(opts) {
|
|
|
86
90
|
}
|
|
87
91
|
return;
|
|
88
92
|
}
|
|
89
|
-
const latestManifest = await opts.getLatestManifest(name, opts.compatible ? (bareSpecifier ?? 'latest') : 'latest');
|
|
90
|
-
if (latestManifest == null)
|
|
91
|
-
return;
|
|
92
93
|
if (!current) {
|
|
93
94
|
outdated.push({
|
|
94
95
|
alias,
|
|
@@ -100,7 +101,7 @@ export async function outdated(opts) {
|
|
|
100
101
|
});
|
|
101
102
|
return;
|
|
102
103
|
}
|
|
103
|
-
if (
|
|
104
|
+
if (wanted !== current || isLowerVersion(wanted, latestManifest.version) || latestManifest.deprecated) {
|
|
104
105
|
outdated.push({
|
|
105
106
|
alias,
|
|
106
107
|
belongsTo: depType,
|
|
@@ -123,6 +124,34 @@ function packageHasNoDeps(manifest) {
|
|
|
123
124
|
function isEmpty(obj) {
|
|
124
125
|
return Object.keys(obj).length === 0;
|
|
125
126
|
}
|
|
127
|
+
// Pick a clean display string for a lockfile ref.
|
|
128
|
+
//
|
|
129
|
+
// - If the dep-path parses to a semver, that's the value (handles
|
|
130
|
+
// `pkg@1.0.0(peer-hash)` and aliased `positive: is-positive@3.1.0`).
|
|
131
|
+
// - If the dep-path's non-semver version contains a `/`, it's a
|
|
132
|
+
// URL/git-shape (`https://`, `git+ssh://`, scheme-less `github.com/…/sha`,
|
|
133
|
+
// `link:../foo`, etc.) — return the raw ref so a commit/path change is
|
|
134
|
+
// visible to the user.
|
|
135
|
+
// - Otherwise prefer `snapshot.version` (clean semver for `runtime:`-style
|
|
136
|
+
// refs); fall back to the raw ref when the snapshot didn't record one.
|
|
137
|
+
function displayVersion(ref, relativeDepPath, snapshotVersion) {
|
|
138
|
+
if (relativeDepPath != null) {
|
|
139
|
+
const parsed = dp.parse(relativeDepPath);
|
|
140
|
+
if (parsed.version != null)
|
|
141
|
+
return parsed.version;
|
|
142
|
+
if (parsed.nonSemverVersion?.includes('/'))
|
|
143
|
+
return ref;
|
|
144
|
+
}
|
|
145
|
+
return snapshotVersion ?? ref;
|
|
146
|
+
}
|
|
147
|
+
// semver.lt throws on non-semver strings (e.g. URL refs from git/tarball).
|
|
148
|
+
// Treat those as "not lower" so a ref change still gets surfaced via the
|
|
149
|
+
// `wantedRef !== currentRef` check above.
|
|
150
|
+
function isLowerVersion(current, latest) {
|
|
151
|
+
if (!semver.valid(current) || !semver.valid(latest))
|
|
152
|
+
return false;
|
|
153
|
+
return semver.lt(current, latest);
|
|
154
|
+
}
|
|
126
155
|
function replaceCatalogProtocolIfNecessary(catalogs, wantedDependency) {
|
|
127
156
|
return matchCatalogResolveResult(resolveFromCatalog(catalogs, wantedDependency), {
|
|
128
157
|
unused: () => wantedDependency.bareSpecifier,
|
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import type { Catalogs } from '@pnpm/catalogs.types';
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import { type ClientOptions } from '@pnpm/installing.client';
|
|
3
|
+
import type { IncludedDependencies, ProjectManifest, ProjectRootDir, RegistryConfig } from '@pnpm/types';
|
|
4
4
|
import { type OutdatedPackage } from './outdated.js';
|
|
5
|
+
export type OutdatedDepsOfProjectsOptions = Omit<ClientOptions, 'configByUri' | 'minimumReleaseAgeExclude' | 'storeIndex'> & {
|
|
6
|
+
dir: string;
|
|
7
|
+
lockfileDir?: string;
|
|
8
|
+
configByUri: Record<string, RegistryConfig>;
|
|
9
|
+
fullMetadata?: boolean;
|
|
10
|
+
minimumReleaseAge?: number;
|
|
11
|
+
minimumReleaseAgeExclude?: string[];
|
|
12
|
+
minimumReleaseAgeIgnoreMissingTime?: boolean;
|
|
13
|
+
minimumReleaseAgeStrict?: boolean;
|
|
14
|
+
};
|
|
5
15
|
export declare function outdatedDepsOfProjects(pkgs: Array<{
|
|
6
16
|
rootDir: ProjectRootDir;
|
|
7
17
|
manifest: ProjectManifest;
|
|
8
|
-
}>, args: string[], opts:
|
|
18
|
+
}>, args: string[], opts: OutdatedDepsOfProjectsOptions & {
|
|
9
19
|
catalogs?: Catalogs;
|
|
10
20
|
compatible?: boolean;
|
|
11
21
|
ignoreDependencies?: string[];
|
|
12
22
|
include: IncludedDependencies;
|
|
13
|
-
|
|
14
|
-
minimumReleaseAgeExclude?: string[];
|
|
15
|
-
} & Partial<Pick<ManifestGetterOptions, 'fullMetadata' | 'lockfileDir'>>): Promise<OutdatedPackage[][]>;
|
|
23
|
+
}): Promise<OutdatedPackage[][]>;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { createMatcher } from '@pnpm/config.matcher';
|
|
3
|
+
import { getPublishedByPolicy } from '@pnpm/config.version-policy';
|
|
4
|
+
import { createResolver } from '@pnpm/installing.client';
|
|
3
5
|
import { readCurrentLockfile, readWantedLockfile, } from '@pnpm/lockfile.fs';
|
|
4
6
|
import { unnest } from 'ramda';
|
|
5
|
-
import { createManifestGetter } from './createManifestGetter.js';
|
|
6
7
|
import { outdated } from './outdated.js';
|
|
7
8
|
export async function outdatedDepsOfProjects(pkgs, args, opts) {
|
|
8
9
|
if (!opts.lockfileDir) {
|
|
@@ -12,12 +13,13 @@ export async function outdatedDepsOfProjects(pkgs, args, opts) {
|
|
|
12
13
|
const internalPnpmDir = path.join(path.join(lockfileDir, 'node_modules/.pnpm'));
|
|
13
14
|
const currentLockfile = await readCurrentLockfile(internalPnpmDir, { ignoreIncompatible: false });
|
|
14
15
|
const wantedLockfile = await readWantedLockfile(lockfileDir, { ignoreIncompatible: false }) ?? currentLockfile;
|
|
15
|
-
const
|
|
16
|
+
const { publishedBy, publishedByExclude } = getPublishedByPolicy(opts);
|
|
17
|
+
const { resolveLatest } = createResolver({
|
|
16
18
|
...opts,
|
|
19
|
+
configByUri: opts.configByUri,
|
|
20
|
+
filterMetadata: false,
|
|
17
21
|
fullMetadata: opts.fullMetadata === true || Boolean(opts.minimumReleaseAge),
|
|
18
|
-
|
|
19
|
-
minimumReleaseAge: opts.minimumReleaseAge,
|
|
20
|
-
minimumReleaseAgeExclude: opts.minimumReleaseAgeExclude,
|
|
22
|
+
ignoreMissingTimeField: opts.minimumReleaseAgeIgnoreMissingTime,
|
|
21
23
|
});
|
|
22
24
|
return Promise.all(pkgs.map(async ({ rootDir, manifest }) => {
|
|
23
25
|
const match = (args.length > 0) && createMatcher(args) || undefined;
|
|
@@ -25,7 +27,7 @@ export async function outdatedDepsOfProjects(pkgs, args, opts) {
|
|
|
25
27
|
catalogs: opts.catalogs,
|
|
26
28
|
compatible: opts.compatible,
|
|
27
29
|
currentLockfile,
|
|
28
|
-
|
|
30
|
+
resolveLatest,
|
|
29
31
|
ignoreDependencies: opts.ignoreDependencies,
|
|
30
32
|
include: opts.include,
|
|
31
33
|
lockfileDir,
|
|
@@ -34,7 +36,8 @@ export async function outdatedDepsOfProjects(pkgs, args, opts) {
|
|
|
34
36
|
minimumReleaseAge: opts.minimumReleaseAge,
|
|
35
37
|
minimumReleaseAgeExclude: opts.minimumReleaseAgeExclude,
|
|
36
38
|
prefix: rootDir,
|
|
37
|
-
|
|
39
|
+
publishedBy,
|
|
40
|
+
publishedByExclude,
|
|
38
41
|
wantedLockfile,
|
|
39
42
|
});
|
|
40
43
|
}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/deps.inspection.outdated",
|
|
3
|
-
"version": "1100.
|
|
3
|
+
"version": "1100.1.1",
|
|
4
4
|
"description": "Check for outdated packages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -27,22 +27,21 @@
|
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"ramda": "npm:@pnpm/ramda@0.28.1",
|
|
29
29
|
"semver": "^7.7.2",
|
|
30
|
+
"@pnpm/catalogs.resolver": "1100.0.0",
|
|
30
31
|
"@pnpm/catalogs.types": "1100.0.0",
|
|
31
32
|
"@pnpm/config.matcher": "1100.0.1",
|
|
32
33
|
"@pnpm/config.parse-overrides": "1100.0.1",
|
|
33
|
-
"@pnpm/config.version-policy": "1100.1.
|
|
34
|
+
"@pnpm/config.version-policy": "1100.1.1",
|
|
35
|
+
"@pnpm/deps.path": "1100.0.4",
|
|
34
36
|
"@pnpm/constants": "1100.0.0",
|
|
35
|
-
"@pnpm/
|
|
37
|
+
"@pnpm/hooks.read-package-hook": "1100.0.4",
|
|
38
|
+
"@pnpm/lockfile.fs": "1100.1.1",
|
|
39
|
+
"@pnpm/installing.client": "1100.2.1",
|
|
40
|
+
"@pnpm/lockfile.utils": "1100.0.9",
|
|
41
|
+
"@pnpm/pkg-manifest.utils": "1100.2.0",
|
|
42
|
+
"@pnpm/resolving.npm-resolver": "1101.3.1",
|
|
36
43
|
"@pnpm/error": "1100.0.0",
|
|
37
|
-
"@pnpm/
|
|
38
|
-
"@pnpm/installing.client": "1100.1.0",
|
|
39
|
-
"@pnpm/lockfile.fs": "1100.1.0",
|
|
40
|
-
"@pnpm/resolving.npm-resolver": "1101.2.0",
|
|
41
|
-
"@pnpm/catalogs.resolver": "1100.0.0",
|
|
42
|
-
"@pnpm/types": "1101.1.0",
|
|
43
|
-
"@pnpm/pkg-manifest.utils": "1100.1.4",
|
|
44
|
-
"@pnpm/config.pick-registry-for-package": "1100.0.3",
|
|
45
|
-
"@pnpm/lockfile.utils": "1100.0.8"
|
|
44
|
+
"@pnpm/types": "1101.1.1"
|
|
46
45
|
},
|
|
47
46
|
"peerDependencies": {
|
|
48
47
|
"@pnpm/logger": ">=1001.0.0 <1002.0.0"
|
|
@@ -51,9 +50,9 @@
|
|
|
51
50
|
"@jest/globals": "30.3.0",
|
|
52
51
|
"@types/ramda": "0.31.1",
|
|
53
52
|
"@types/semver": "7.7.1",
|
|
54
|
-
"@pnpm/deps.inspection.outdated": "1100.0.16",
|
|
55
53
|
"@pnpm/logger": "1100.0.0",
|
|
56
|
-
"@pnpm/
|
|
54
|
+
"@pnpm/deps.inspection.outdated": "1100.1.1",
|
|
55
|
+
"@pnpm/resolving.resolver-base": "1100.3.0"
|
|
57
56
|
},
|
|
58
57
|
"engines": {
|
|
59
58
|
"node": ">=22.13"
|