@pnpm/installing.deps-installer 1102.2.1 → 1102.3.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.
@@ -259,5 +259,11 @@ export type InstallOptions = Partial<StrictInstallOptions> & Pick<StrictInstallO
259
259
  export interface ProcessedInstallOptions extends StrictInstallOptions {
260
260
  readPackageHook?: ReadPackageHook;
261
261
  parsedOverrides: VersionOverride[];
262
+ /**
263
+ * Present when the overrides contain convergence entries (`"pkg@"`). The
264
+ * versions overrider fills it with every declared semver range it sees for
265
+ * those packages; the staleness check reads it after a full resolution.
266
+ */
267
+ convergeDeclaredRanges?: Map<string, Set<string>>;
262
268
  }
263
269
  export declare function extendOptions(opts: InstallOptions): ProcessedInstallOptions;
@@ -124,10 +124,14 @@ export function extendOptions(opts) {
124
124
  storeDir: defaultOpts.storeDir,
125
125
  parsedOverrides: parseOverrides(opts.overrides ?? {}, opts.catalogs ?? {}),
126
126
  };
127
+ if (extendedOpts.parsedOverrides.some(({ converge }) => converge)) {
128
+ extendedOpts.convergeDeclaredRanges = new Map();
129
+ }
127
130
  extendedOpts.readPackageHook = createReadPackageHook({
128
131
  ignoreCompatibilityDb: extendedOpts.ignoreCompatibilityDb,
129
132
  readPackageHook: extendedOpts.hooks?.readPackage,
130
133
  overrides: extendedOpts.parsedOverrides,
134
+ convergeDeclaredRanges: extendedOpts.convergeDeclaredRanges,
131
135
  lockfileDir: extendedOpts.lockfileDir,
132
136
  packageExtensions: extendedOpts.packageExtensions,
133
137
  ignoredOptionalDependencies: extendedOpts.ignoredOptionalDependencies,
@@ -41,6 +41,7 @@ import { linkPackages } from './link.js';
41
41
  import { reportPeerDependencyIssues } from './reportPeerDependencyIssues.js';
42
42
  import { validateModules } from './validateModules.js';
43
43
  import { verifyLockfileResolutions } from './verifyLockfileResolutions.js';
44
+ import { warnOnStaleConvergenceOverrides } from './warnOnStaleConvergenceOverrides.js';
44
45
  import { writeLockfilesAndRecordVerified } from './writeLockfilesAndRecordVerified.js';
45
46
  import { writeWantedLockfileAndRecordVerified } from './writeWantedLockfileAndRecordVerified.js';
46
47
  class LockfileConfigMismatchError extends PnpmError {
@@ -1167,6 +1168,20 @@ const _installInContext = async (projects, ctx, opts) => {
1167
1168
  allProjectIds: Object.values(ctx.projects).map((p) => p.id),
1168
1169
  handleResolutionPolicyViolations: opts.handleResolutionPolicyViolations,
1169
1170
  });
1171
+ // Only a full resolution walks every manifest through the versions
1172
+ // overrider, making the collected declared ranges complete enough for the
1173
+ // staleness verdict; partial resolutions must stay silent to avoid false
1174
+ // positives from unseen ranges.
1175
+ if (opts.convergeDeclaredRanges != null && (forceFullResolution || opts.dedupe)) {
1176
+ await warnOnStaleConvergenceOverrides({
1177
+ convergeDeclaredRanges: opts.convergeDeclaredRanges,
1178
+ parsedOverrides: opts.parsedOverrides,
1179
+ requestPackage: opts.storeController.requestPackage,
1180
+ lockfileDir: opts.lockfileDir,
1181
+ minimumReleaseAge: opts.minimumReleaseAge,
1182
+ minimumReleaseAgeExclude: opts.minimumReleaseAgeExclude,
1183
+ });
1184
+ }
1170
1185
  if (!opts.include.optionalDependencies || !opts.include.devDependencies || !opts.include.dependencies) {
1171
1186
  linkedDependenciesByProjectId = mapValues((linkedDeps) => linkedDeps.filter((linkedDep) => !(linkedDep.dev && !opts.include.devDependencies ||
1172
1187
  linkedDep.optional && !opts.include.optionalDependencies ||
@@ -0,0 +1,31 @@
1
+ import type { VersionOverride } from '@pnpm/config.parse-overrides';
2
+ import type { RequestPackageFunction } from '@pnpm/store.controller-types';
3
+ export interface WarnOnStaleConvergenceOverridesOptions {
4
+ convergeDeclaredRanges: Map<string, Set<string>>;
5
+ parsedOverrides: VersionOverride[];
6
+ requestPackage: RequestPackageFunction;
7
+ lockfileDir: string;
8
+ minimumReleaseAge?: number;
9
+ minimumReleaseAgeExclude?: string[];
10
+ }
11
+ /**
12
+ * A convergence override's value is derived state — the best version that
13
+ * converges the currently declared ranges. It goes stale when dependents
14
+ * start declaring ranges that admit newer versions: the override then keeps
15
+ * the edges it governs on the old version while newer edges resolve past it,
16
+ * producing the duplication the entry was written to prevent.
17
+ *
18
+ * Must only run after a full resolution: only then has every manifest
19
+ * streamed through the versions overrider, so `convergeDeclaredRanges` holds
20
+ * the complete set of declared ranges. For each convergence override this
21
+ * resolves every declared range to the best version it admits (metadata is
22
+ * already cached from the resolution that just ran, and the release-age
23
+ * policy applies, so the recommendation is a version the resolver would
24
+ * actually pick) and warns when a version newer than the override's value
25
+ * satisfies every declared range — a strictly better convergence.
26
+ *
27
+ * A range that fails to resolve contributes no candidate but still
28
+ * participates in the satisfies-every-range check, so failures can only
29
+ * suppress the warning, never fabricate one.
30
+ */
31
+ export declare function warnOnStaleConvergenceOverrides(opts: WarnOnStaleConvergenceOverridesOptions): Promise<void>;
@@ -0,0 +1,62 @@
1
+ import { getPublishedByPolicy } from '@pnpm/config.version-policy';
2
+ import { globalWarn } from '@pnpm/logger';
3
+ import semver from 'semver';
4
+ /**
5
+ * A convergence override's value is derived state — the best version that
6
+ * converges the currently declared ranges. It goes stale when dependents
7
+ * start declaring ranges that admit newer versions: the override then keeps
8
+ * the edges it governs on the old version while newer edges resolve past it,
9
+ * producing the duplication the entry was written to prevent.
10
+ *
11
+ * Must only run after a full resolution: only then has every manifest
12
+ * streamed through the versions overrider, so `convergeDeclaredRanges` holds
13
+ * the complete set of declared ranges. For each convergence override this
14
+ * resolves every declared range to the best version it admits (metadata is
15
+ * already cached from the resolution that just ran, and the release-age
16
+ * policy applies, so the recommendation is a version the resolver would
17
+ * actually pick) and warns when a version newer than the override's value
18
+ * satisfies every declared range — a strictly better convergence.
19
+ *
20
+ * A range that fails to resolve contributes no candidate but still
21
+ * participates in the satisfies-every-range check, so failures can only
22
+ * suppress the warning, never fabricate one.
23
+ */
24
+ export async function warnOnStaleConvergenceOverrides(opts) {
25
+ const convergeOverrides = opts.parsedOverrides.filter(({ converge }) => converge);
26
+ if (convergeOverrides.length === 0)
27
+ return;
28
+ const { publishedBy, publishedByExclude } = getPublishedByPolicy(opts);
29
+ await Promise.all(convergeOverrides.map(async (override) => {
30
+ const name = override.targetPkg.name;
31
+ const ranges = opts.convergeDeclaredRanges.get(name);
32
+ if (ranges == null || ranges.size === 0)
33
+ return;
34
+ const candidates = await Promise.all([...ranges].map(async (range) => {
35
+ try {
36
+ const response = await opts.requestPackage({ alias: name, bareSpecifier: range }, {
37
+ downloadPriority: 0,
38
+ lockfileDir: opts.lockfileDir,
39
+ projectDir: opts.lockfileDir,
40
+ preferredVersions: {},
41
+ skipFetch: true,
42
+ publishedBy,
43
+ publishedByExclude,
44
+ });
45
+ if (response.body.policyViolation != null)
46
+ return undefined;
47
+ return response.body.manifest?.version;
48
+ }
49
+ catch {
50
+ return undefined;
51
+ }
52
+ }));
53
+ const best = candidates
54
+ .filter((version) => version != null && semver.gt(version, override.newBareSpecifier))
55
+ .sort(semver.rcompare)
56
+ .find((version) => [...ranges].every((range) => semver.satisfies(version, range, true)));
57
+ if (best == null)
58
+ return;
59
+ globalWarn(`The convergence override "${name}@": "${override.newBareSpecifier}" is stale: every declared range of ${name} also admits ${best}. Change the override's value to ${best} in pnpm-workspace.yaml, or remove the override and run "pnpm dedupe".`);
60
+ }));
61
+ }
62
+ //# sourceMappingURL=warnOnStaleConvergenceOverrides.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pnpm/installing.deps-installer",
3
- "version": "1102.2.1",
3
+ "version": "1102.3.0",
4
4
  "description": "Fast, disk space efficient installation engine",
5
5
  "keywords": [
6
6
  "pnpm",
@@ -51,8 +51,61 @@
51
51
  },
52
52
  "dependencies": {
53
53
  "@inquirer/prompts": "^8.4.3",
54
+ "@pnpm/bins.linker": "1100.0.17",
55
+ "@pnpm/bins.remover": "1100.0.13",
56
+ "@pnpm/building.after-install": "1102.0.6",
57
+ "@pnpm/building.during-install": "1102.0.6",
58
+ "@pnpm/building.policy": "1100.0.13",
59
+ "@pnpm/catalogs.config": "1100.0.2",
60
+ "@pnpm/catalogs.protocol-parser": "1100.0.0",
61
+ "@pnpm/catalogs.resolver": "1100.0.0",
62
+ "@pnpm/catalogs.types": "1100.0.0",
63
+ "@pnpm/config.matcher": "1100.0.1",
64
+ "@pnpm/config.normalize-registries": "1100.0.9",
65
+ "@pnpm/config.parse-overrides": "1100.1.0",
66
+ "@pnpm/config.version-policy": "1100.1.7",
67
+ "@pnpm/constants": "1100.0.0",
68
+ "@pnpm/core-loggers": "1100.2.2",
69
+ "@pnpm/crypto.hash": "1100.0.1",
70
+ "@pnpm/crypto.object-hasher": "1100.0.0",
71
+ "@pnpm/deps.graph-hasher": "1100.2.10",
72
+ "@pnpm/deps.graph-sequencer": "1100.0.0",
73
+ "@pnpm/deps.path": "1100.0.9",
74
+ "@pnpm/error": "1100.0.1",
75
+ "@pnpm/exec.lifecycle": "1100.1.3",
76
+ "@pnpm/fs.read-modules-dir": "1100.0.1",
77
+ "@pnpm/fs.symlink-dependency": "1100.0.11",
78
+ "@pnpm/hooks.read-package-hook": "1100.1.0",
79
+ "@pnpm/hooks.types": "1100.2.1",
80
+ "@pnpm/installing.context": "1100.0.24",
81
+ "@pnpm/installing.deps-resolver": "1100.2.9",
82
+ "@pnpm/installing.deps-restorer": "1102.1.5",
83
+ "@pnpm/installing.linking.direct-dep-linker": "1100.0.11",
84
+ "@pnpm/installing.linking.hoist": "1100.0.17",
85
+ "@pnpm/installing.linking.modules-cleaner": "1100.1.12",
86
+ "@pnpm/installing.modules-yaml": "1100.0.10",
87
+ "@pnpm/installing.package-requester": "1102.1.3",
88
+ "@pnpm/lockfile.filtering": "1100.1.11",
89
+ "@pnpm/lockfile.fs": "1100.1.11",
90
+ "@pnpm/lockfile.preferred-versions": "1100.0.20",
91
+ "@pnpm/lockfile.pruner": "1100.0.14",
92
+ "@pnpm/lockfile.settings-checker": "1100.1.3",
93
+ "@pnpm/lockfile.to-pnp": "1100.1.5",
94
+ "@pnpm/lockfile.utils": "1100.1.3",
95
+ "@pnpm/lockfile.verification": "1100.0.24",
96
+ "@pnpm/lockfile.walker": "1100.0.14",
97
+ "@pnpm/network.auth-header": "1101.1.4",
54
98
  "@pnpm/npm-package-arg": "^2.0.0",
99
+ "@pnpm/patching.config": "1100.0.10",
100
+ "@pnpm/pkg-manifest.utils": "1100.2.7",
101
+ "@pnpm/pnpr.client": "1.3.3",
102
+ "@pnpm/resolving.parse-wanted-dependency": "1100.0.1",
103
+ "@pnpm/resolving.resolver-base": "1100.5.2",
104
+ "@pnpm/store.controller-types": "1100.1.8",
105
+ "@pnpm/store.index": "1100.2.1",
106
+ "@pnpm/types": "1101.4.0",
55
107
  "@pnpm/util.lex-comparator": "^4.0.1",
108
+ "@pnpm/workspace.project-manifest-reader": "1100.0.15",
56
109
  "@zkochan/rimraf": "^4.0.0",
57
110
  "is-inner-link": "^5.0.0",
58
111
  "is-subdir": "^2.0.0",
@@ -64,66 +117,30 @@
64
117
  "path-exists": "^5.0.0",
65
118
  "ramda": "npm:@pnpm/ramda@0.28.1",
66
119
  "run-groups": "^5.0.0",
67
- "semver": "^7.8.4",
68
- "@pnpm/bins.remover": "1100.0.12",
69
- "@pnpm/bins.linker": "1100.0.16",
70
- "@pnpm/building.during-install": "1102.0.4",
71
- "@pnpm/building.after-install": "1102.0.4",
72
- "@pnpm/building.policy": "1100.0.12",
73
- "@pnpm/catalogs.config": "1100.0.2",
74
- "@pnpm/catalogs.protocol-parser": "1100.0.0",
75
- "@pnpm/catalogs.resolver": "1100.0.0",
76
- "@pnpm/catalogs.types": "1100.0.0",
77
- "@pnpm/config.matcher": "1100.0.1",
78
- "@pnpm/config.normalize-registries": "1100.0.8",
79
- "@pnpm/core-loggers": "1100.2.1",
80
- "@pnpm/constants": "1100.0.0",
81
- "@pnpm/deps.graph-hasher": "1100.2.8",
82
- "@pnpm/crypto.object-hasher": "1100.0.0",
83
- "@pnpm/deps.path": "1100.0.8",
84
- "@pnpm/crypto.hash": "1100.0.1",
85
- "@pnpm/deps.graph-sequencer": "1100.0.0",
86
- "@pnpm/error": "1100.0.1",
87
- "@pnpm/fs.read-modules-dir": "1100.0.1",
88
- "@pnpm/hooks.types": "1100.1.1",
89
- "@pnpm/fs.symlink-dependency": "1100.0.10",
90
- "@pnpm/installing.context": "1100.0.22",
91
- "@pnpm/exec.lifecycle": "1100.1.2",
92
- "@pnpm/installing.deps-resolver": "1100.2.7",
93
- "@pnpm/config.parse-overrides": "1100.0.2",
94
- "@pnpm/hooks.read-package-hook": "1100.0.9",
95
- "@pnpm/installing.linking.hoist": "1100.0.16",
96
- "@pnpm/installing.linking.direct-dep-linker": "1100.0.10",
97
- "@pnpm/installing.deps-restorer": "1102.1.3",
98
- "@pnpm/installing.modules-yaml": "1100.0.9",
99
- "@pnpm/lockfile.filtering": "1100.1.9",
100
- "@pnpm/installing.linking.modules-cleaner": "1100.1.10",
101
- "@pnpm/lockfile.preferred-versions": "1100.0.18",
102
- "@pnpm/lockfile.pruner": "1100.0.13",
103
- "@pnpm/lockfile.fs": "1100.1.9",
104
- "@pnpm/lockfile.to-pnp": "1100.1.3",
105
- "@pnpm/lockfile.verification": "1100.0.22",
106
- "@pnpm/lockfile.utils": "1100.1.1",
107
- "@pnpm/lockfile.settings-checker": "1100.1.1",
108
- "@pnpm/lockfile.walker": "1100.0.13",
109
- "@pnpm/network.auth-header": "1101.1.3",
110
- "@pnpm/patching.config": "1100.0.9",
111
- "@pnpm/pkg-manifest.utils": "1100.2.6",
112
- "@pnpm/resolving.parse-wanted-dependency": "1100.0.1",
113
- "@pnpm/resolving.resolver-base": "1100.5.1",
114
- "@pnpm/store.controller-types": "1100.1.7",
115
- "@pnpm/installing.package-requester": "1102.1.1",
116
- "@pnpm/store.index": "1100.2.1",
117
- "@pnpm/pnpr.client": "1.3.1",
118
- "@pnpm/types": "1101.3.2",
119
- "@pnpm/workspace.project-manifest-reader": "1100.0.14"
120
+ "semver": "^7.8.4"
120
121
  },
121
122
  "peerDependencies": {
122
123
  "@pnpm/logger": "^1100.0.0",
123
- "@pnpm/worker": "^1100.2.3"
124
+ "@pnpm/worker": "^1100.2.4"
124
125
  },
125
126
  "devDependencies": {
126
127
  "@jest/globals": "30.4.1",
128
+ "@pnpm/assert-project": "1100.0.19",
129
+ "@pnpm/assert-store": "1100.0.19",
130
+ "@pnpm/installing.deps-installer": "1102.3.0",
131
+ "@pnpm/lockfile.types": "1100.0.14",
132
+ "@pnpm/logger": "1100.0.0",
133
+ "@pnpm/network.git-utils": "1100.0.2",
134
+ "@pnpm/pkg-manifest.reader": "1100.0.10",
135
+ "@pnpm/prepare": "1100.0.19",
136
+ "@pnpm/resolving.registry.types": "1100.1.4",
137
+ "@pnpm/store.cafs": "1100.1.13",
138
+ "@pnpm/store.path": "1100.0.2",
139
+ "@pnpm/test-fixtures": "1100.0.0",
140
+ "@pnpm/test-ipc-server": "1100.0.0",
141
+ "@pnpm/testing.mock-agent": "1101.0.5",
142
+ "@pnpm/testing.registry-mock": "1100.0.9",
143
+ "@pnpm/testing.temp-store": "1100.1.15",
127
144
  "@types/fs-extra": "^11.0.4",
128
145
  "@types/is-windows": "^1.0.2",
129
146
  "@types/normalize-path": "^3.0.2",
@@ -140,23 +157,7 @@
140
157
  "resolve-link-target": "^3.0.0",
141
158
  "symlink-dir": "^10.0.1",
142
159
  "write-json-file": "^7.0.0",
143
- "write-yaml-file": "^6.0.0",
144
- "@pnpm/assert-store": "1100.0.18",
145
- "@pnpm/logger": "1100.0.0",
146
- "@pnpm/installing.deps-installer": "1102.2.1",
147
- "@pnpm/network.git-utils": "1100.0.2",
148
- "@pnpm/lockfile.types": "1100.0.13",
149
- "@pnpm/prepare": "1100.0.18",
150
- "@pnpm/pkg-manifest.reader": "1100.0.9",
151
- "@pnpm/resolving.registry.types": "1100.1.3",
152
- "@pnpm/assert-project": "1100.0.18",
153
- "@pnpm/store.cafs": "1100.1.12",
154
- "@pnpm/store.path": "1100.0.2",
155
- "@pnpm/test-fixtures": "1100.0.0",
156
- "@pnpm/test-ipc-server": "1100.0.0",
157
- "@pnpm/testing.registry-mock": "1100.0.8",
158
- "@pnpm/testing.mock-agent": "1101.0.4",
159
- "@pnpm/testing.temp-store": "1100.1.13"
160
+ "write-yaml-file": "^6.0.0"
160
161
  },
161
162
  "engines": {
162
163
  "node": ">=22.13"