@pnpm/installing.deps-installer 1102.0.0 → 1102.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/install/extendInstallOptions.d.ts +9 -0
- package/lib/install/extendInstallOptions.js +2 -0
- package/lib/install/index.d.ts +18 -0
- package/lib/install/index.js +97 -16
- package/lib/install/link.d.ts +1 -1
- package/lib/install/link.js +109 -24
- package/lib/install/verifyLockfileResolutions.js +34 -11
- package/package.json +60 -59
|
@@ -46,6 +46,13 @@ export interface StrictInstallOptions {
|
|
|
46
46
|
preferFrozenLockfile: boolean;
|
|
47
47
|
saveWorkspaceProtocol: boolean | 'rolling';
|
|
48
48
|
lockfileCheck?: (prev: LockfileObject, next: LockfileObject) => void;
|
|
49
|
+
/**
|
|
50
|
+
* When true, resolve fully but write nothing to disk (no lockfile, no
|
|
51
|
+
* `node_modules`). The before/after wanted lockfiles are returned in the
|
|
52
|
+
* install result's `dryRunResult` so the caller can report what an install
|
|
53
|
+
* would change. Powers `pnpm install --dry-run`.
|
|
54
|
+
*/
|
|
55
|
+
dryRun?: boolean;
|
|
49
56
|
lockfileIncludeTarballUrl?: boolean;
|
|
50
57
|
preferWorkspacePackages: boolean;
|
|
51
58
|
preserveWorkspaceProtocol: boolean;
|
|
@@ -65,6 +72,8 @@ export interface StrictInstallOptions {
|
|
|
65
72
|
engineStrict: boolean;
|
|
66
73
|
allowBuilds?: Record<string, boolean | string>;
|
|
67
74
|
nodeLinker: 'isolated' | 'hoisted' | 'pnp';
|
|
75
|
+
nodeExperimentalPackageMap: boolean;
|
|
76
|
+
nodePackageMapType: 'standard' | 'loose';
|
|
68
77
|
nodeVersion?: string;
|
|
69
78
|
packageExtensions: Record<string, PackageExtension>;
|
|
70
79
|
ignoredOptionalDependencies: string[];
|
|
@@ -48,6 +48,8 @@ const defaults = (opts) => {
|
|
|
48
48
|
updateChecksums: false,
|
|
49
49
|
nodeVersion: opts.nodeVersion,
|
|
50
50
|
nodeLinker: 'isolated',
|
|
51
|
+
nodeExperimentalPackageMap: false,
|
|
52
|
+
nodePackageMapType: 'standard',
|
|
51
53
|
overrides: {},
|
|
52
54
|
ownLifecycleHooksStdio: 'inherit',
|
|
53
55
|
ignoreCompatibilityDb: false,
|
package/lib/install/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { Catalogs } from '@pnpm/catalogs.types';
|
|
|
2
2
|
import { PnpmError } from '@pnpm/error';
|
|
3
3
|
import { type PinnedVersion, type UpdateMatchingFunction, type WantedDependency } from '@pnpm/installing.deps-resolver';
|
|
4
4
|
import { type InstallationResultStats } from '@pnpm/installing.deps-restorer';
|
|
5
|
+
import { type LockfileObject } from '@pnpm/lockfile.fs';
|
|
5
6
|
import type { PreferredVersions, ResolutionPolicyViolation } from '@pnpm/resolving.resolver-base';
|
|
6
7
|
import type { DependenciesField, DepPath, IgnoredBuilds, PeerDependencyIssues, ProjectId, ProjectManifest, ProjectRootDir, ReadPackageHook } from '@pnpm/types';
|
|
7
8
|
import { type InstallOptions } from './extendInstallOptions.js';
|
|
@@ -47,6 +48,8 @@ export interface InstallResult {
|
|
|
47
48
|
ignoredBuilds: IgnoredBuilds | undefined;
|
|
48
49
|
/** Forwarded from {@link MutateModulesResult.resolutionPolicyViolations}. */
|
|
49
50
|
resolutionPolicyViolations: ResolutionPolicyViolation[];
|
|
51
|
+
/** Forwarded from {@link MutateModulesResult.dryRunResult}. */
|
|
52
|
+
dryRunResult?: DryRunInstallResult;
|
|
50
53
|
}
|
|
51
54
|
export declare function install(manifest: ProjectManifest, opts: Opts): Promise<InstallResult>;
|
|
52
55
|
export type MutatedProject = DependenciesMutation & {
|
|
@@ -64,6 +67,8 @@ export interface MutateModulesInSingleProjectResult {
|
|
|
64
67
|
ignoredBuilds: IgnoredBuilds | undefined;
|
|
65
68
|
/** Forwarded from {@link MutateModulesResult.resolutionPolicyViolations}. */
|
|
66
69
|
resolutionPolicyViolations: ResolutionPolicyViolation[];
|
|
70
|
+
/** Forwarded from {@link MutateModulesResult.dryRunResult}. */
|
|
71
|
+
dryRunResult?: DryRunInstallResult;
|
|
67
72
|
}
|
|
68
73
|
export declare function mutateModulesInSingleProject(project: MutatedProject & {
|
|
69
74
|
binsDir?: string;
|
|
@@ -86,6 +91,11 @@ export interface MutateModulesResult {
|
|
|
86
91
|
* verifier reported a violation or no policy was active.
|
|
87
92
|
*/
|
|
88
93
|
resolutionPolicyViolations: ResolutionPolicyViolation[];
|
|
94
|
+
/**
|
|
95
|
+
* Present only for a `dryRun` install: the before/after wanted lockfiles
|
|
96
|
+
* the resolve produced without writing, for the caller to diff.
|
|
97
|
+
*/
|
|
98
|
+
dryRunResult?: DryRunInstallResult;
|
|
89
99
|
}
|
|
90
100
|
export declare function mutateModules(projects: MutatedProject[], maybeOpts: MutateModulesOptions): Promise<MutateModulesResult>;
|
|
91
101
|
export declare function addDependenciesToPackage(manifest: ProjectManifest, dependencySelectors: string[], opts: Omit<InstallOptions, 'allProjects'> & {
|
|
@@ -117,6 +127,14 @@ export interface UpdatedProject {
|
|
|
117
127
|
peerDependencyIssues?: PeerDependencyIssues;
|
|
118
128
|
rootDir: ProjectRootDir;
|
|
119
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* The before/after wanted lockfiles a `dryRun` install resolved without
|
|
132
|
+
* writing. The caller diffs them to report what a real install would change.
|
|
133
|
+
*/
|
|
134
|
+
export interface DryRunInstallResult {
|
|
135
|
+
originalLockfile: LockfileObject;
|
|
136
|
+
wantedLockfile: LockfileObject;
|
|
137
|
+
}
|
|
120
138
|
export declare class IgnoredBuildsError extends PnpmError {
|
|
121
139
|
constructor(ignoredBuilds: IgnoredBuilds);
|
|
122
140
|
}
|
package/lib/install/index.js
CHANGED
|
@@ -3,22 +3,24 @@ import { linkBins, linkBinsOfPackages } from '@pnpm/bins.linker';
|
|
|
3
3
|
import { buildSelectedPkgs } from '@pnpm/building.after-install';
|
|
4
4
|
import { buildModules, linkBinsOfDependencies } from '@pnpm/building.during-install';
|
|
5
5
|
import { createAllowBuildFunction, isBuildExplicitlyDisallowed } from '@pnpm/building.policy';
|
|
6
|
+
import { mergeCatalogs } from '@pnpm/catalogs.config';
|
|
6
7
|
import { parseCatalogProtocol } from '@pnpm/catalogs.protocol-parser';
|
|
7
8
|
import { matchCatalogResolveResult, resolveFromCatalog } from '@pnpm/catalogs.resolver';
|
|
9
|
+
import { parseOverrides } from '@pnpm/config.parse-overrides';
|
|
8
10
|
import { LAYOUT_VERSION, LOCKFILE_MAJOR_VERSION, LOCKFILE_VERSION, WANTED_LOCKFILE, } from '@pnpm/constants';
|
|
9
11
|
import { ignoredScriptsLogger, stageLogger, summaryLogger, } from '@pnpm/core-loggers';
|
|
10
12
|
import { hashObjectNullableWithPrefix } from '@pnpm/crypto.object-hasher';
|
|
11
13
|
import * as dp from '@pnpm/deps.path';
|
|
12
14
|
import { PnpmError } from '@pnpm/error';
|
|
13
|
-
import { makeNodeRequireOption, runLifecycleHook, runLifecycleHooksConcurrently, } from '@pnpm/exec.lifecycle';
|
|
15
|
+
import { makeNodePackageMapOption, makeNodeRequireOption, runLifecycleHook, runLifecycleHooksConcurrently, } from '@pnpm/exec.lifecycle';
|
|
14
16
|
import { getContext } from '@pnpm/installing.context';
|
|
15
17
|
import { getWantedDependencies, resolveDependencies, } from '@pnpm/installing.deps-resolver';
|
|
16
18
|
import { extendProjectsWithTargetDirs, headlessInstall } from '@pnpm/installing.deps-restorer';
|
|
17
|
-
import { writeModulesManifest } from '@pnpm/installing.modules-yaml';
|
|
19
|
+
import { readModulesManifest, writeModulesManifest } from '@pnpm/installing.modules-yaml';
|
|
18
20
|
import { cleanGitBranchLockfiles, getWantedLockfileName, isEmptyLockfile, readEnvLockfile, readWantedLockfile, readWantedLockfileFile, writeCurrentLockfile, writeEnvLockfile, writeLockfiles, writeWantedLockfile, } from '@pnpm/lockfile.fs';
|
|
19
21
|
import { getPreferredVersionsFromLockfileAndManifests } from '@pnpm/lockfile.preferred-versions';
|
|
20
22
|
import { calcPatchHashes, createOverridesMapFromParsed, getOutdatedLockfileSetting, } from '@pnpm/lockfile.settings-checker';
|
|
21
|
-
import { writePnpFile } from '@pnpm/lockfile.to-pnp';
|
|
23
|
+
import { PACKAGE_MAP_FILENAME, writePackageMap, writePnpFile } from '@pnpm/lockfile.to-pnp';
|
|
22
24
|
import { allProjectsAreUpToDate, satisfiesPackageManifest } from '@pnpm/lockfile.verification';
|
|
23
25
|
import { globalInfo, logger, streamParser } from '@pnpm/logger';
|
|
24
26
|
import { groupPatchedDependencies } from '@pnpm/patching.config';
|
|
@@ -60,7 +62,7 @@ export async function install(manifest, opts) {
|
|
|
60
62
|
if (opts.pnprServer) {
|
|
61
63
|
return installViaPnprServer(manifest, rootDir, opts);
|
|
62
64
|
}
|
|
63
|
-
const { updatedCatalogs, updatedProjects: projects, ignoredBuilds, resolutionPolicyViolations } = await mutateModules([
|
|
65
|
+
const { updatedCatalogs, updatedProjects: projects, ignoredBuilds, resolutionPolicyViolations, dryRunResult } = await mutateModules([
|
|
64
66
|
{
|
|
65
67
|
mutation: 'install',
|
|
66
68
|
pruneDirectDependencies: opts.pruneDirectDependencies,
|
|
@@ -79,7 +81,7 @@ export async function install(manifest, opts) {
|
|
|
79
81
|
binsDir: opts.binsDir,
|
|
80
82
|
}],
|
|
81
83
|
});
|
|
82
|
-
return { updatedCatalogs, updatedManifest: projects[0].manifest, ignoredBuilds, resolutionPolicyViolations };
|
|
84
|
+
return { updatedCatalogs, updatedManifest: projects[0].manifest, ignoredBuilds, resolutionPolicyViolations, dryRunResult };
|
|
83
85
|
}
|
|
84
86
|
export async function mutateModulesInSingleProject(project, maybeOpts) {
|
|
85
87
|
const result = await mutateModules([
|
|
@@ -102,6 +104,7 @@ export async function mutateModulesInSingleProject(project, maybeOpts) {
|
|
|
102
104
|
updatedProject: result.updatedProjects[0],
|
|
103
105
|
ignoredBuilds: result.ignoredBuilds,
|
|
104
106
|
resolutionPolicyViolations: result.resolutionPolicyViolations,
|
|
107
|
+
dryRunResult: result.dryRunResult,
|
|
105
108
|
};
|
|
106
109
|
}
|
|
107
110
|
const pickCatalogSpecifier = {
|
|
@@ -198,7 +201,7 @@ export async function mutateModules(projects, maybeOpts) {
|
|
|
198
201
|
opts.useLockfile &&
|
|
199
202
|
!opts.useGitBranchLockfile &&
|
|
200
203
|
!opts.mergeGitBranchLockfiles &&
|
|
201
|
-
opts
|
|
204
|
+
!isCheckOnlyInstall(opts) &&
|
|
202
205
|
opts.enableModulesDir &&
|
|
203
206
|
installsOnly &&
|
|
204
207
|
!opts.lockfileOnly &&
|
|
@@ -288,6 +291,7 @@ export async function mutateModules(projects, maybeOpts) {
|
|
|
288
291
|
if (!opts.ignoreScripts && ignoredBuilds?.size) {
|
|
289
292
|
ignoredBuilds = await runUnignoredDependencyBuilds(opts, ignoredBuilds, ctx.wantedLockfile, allowBuild);
|
|
290
293
|
}
|
|
294
|
+
let revokedBuilds = false;
|
|
291
295
|
// Detect packages whose build approval was revoked between the previous
|
|
292
296
|
// and current install. A package is considered revoked when it was
|
|
293
297
|
// previously allowed (true) but is now undecided (undefined). Packages
|
|
@@ -310,10 +314,28 @@ export async function mutateModules(projects, maybeOpts) {
|
|
|
310
314
|
if (allowBuild?.(depPath) === undefined) {
|
|
311
315
|
ignoredBuilds ??= new Set();
|
|
312
316
|
ignoredBuilds.add(depPath);
|
|
317
|
+
revokedBuilds = true;
|
|
313
318
|
}
|
|
314
319
|
}
|
|
315
320
|
}
|
|
316
321
|
}
|
|
322
|
+
if (revokedBuilds && !opts.lockfileOnly && opts.enableModulesDir) {
|
|
323
|
+
// The install path already wrote .modules.yaml with the current
|
|
324
|
+
// install's state, but it captured ignoredBuilds before the revocation
|
|
325
|
+
// scan above added to it. Re-read the manifest from disk so we only
|
|
326
|
+
// update ignoredBuilds and don't clobber fields (hoistedDependencies,
|
|
327
|
+
// pendingBuilds, etc.) the install just wrote. The current computed
|
|
328
|
+
// set is authoritative — runUnignoredDependencyBuilds may have removed
|
|
329
|
+
// entries (for packages it successfully rebuilt) that the on-disk
|
|
330
|
+
// manifest still records, and those must not be re-introduced.
|
|
331
|
+
const writtenManifest = await readModulesManifest(ctx.rootModulesDir);
|
|
332
|
+
if (writtenManifest) {
|
|
333
|
+
// writeModulesManifest converts ignoredBuilds to an array before
|
|
334
|
+
// serializing, so a Set is fine here.
|
|
335
|
+
writtenManifest.ignoredBuilds = ignoredBuilds;
|
|
336
|
+
await writeModulesManifest(ctx.rootModulesDir, writtenManifest);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
317
339
|
ignoredScriptsLogger.debug({
|
|
318
340
|
packageNames: ignoredBuilds ? dedupePackageNamesFromIgnoredBuilds(ignoredBuilds) : [],
|
|
319
341
|
});
|
|
@@ -325,6 +347,7 @@ export async function mutateModules(projects, maybeOpts) {
|
|
|
325
347
|
depsRequiringBuild: result.depsRequiringBuild,
|
|
326
348
|
ignoredBuilds,
|
|
327
349
|
resolutionPolicyViolations: result.resolutionPolicyViolations ?? [],
|
|
350
|
+
dryRunResult: result.dryRunResult,
|
|
328
351
|
};
|
|
329
352
|
// Reconcile the install with the lockfile verification that runs alongside
|
|
330
353
|
// it. The verification verdict is awaited first so it takes precedence and
|
|
@@ -647,6 +670,7 @@ export async function mutateModules(projects, maybeOpts) {
|
|
|
647
670
|
depsRequiringBuild: result.depsRequiringBuild,
|
|
648
671
|
ignoredBuilds: result.ignoredBuilds,
|
|
649
672
|
resolutionPolicyViolations: result.resolutionPolicyViolations,
|
|
673
|
+
dryRunResult: result.dryRunResult,
|
|
650
674
|
};
|
|
651
675
|
}
|
|
652
676
|
/**
|
|
@@ -680,6 +704,11 @@ export async function mutateModules(projects, maybeOpts) {
|
|
|
680
704
|
!ctx.lockfileHadConflicts &&
|
|
681
705
|
!opts.fixLockfile &&
|
|
682
706
|
!opts.dedupe &&
|
|
707
|
+
// A check-only install (`lockfileCheck`, used by `--dry-run` and
|
|
708
|
+
// `dedupe --check`) must always run a full resolution so the wanted
|
|
709
|
+
// lockfile can be compared, and must never materialize anything. The
|
|
710
|
+
// frozen path would skip resolution and/or perform a real install.
|
|
711
|
+
!isCheckOnlyInstall(opts) &&
|
|
683
712
|
installsOnly &&
|
|
684
713
|
(
|
|
685
714
|
// If the user explicitly requested a frozen lockfile install, attempt
|
|
@@ -767,7 +796,7 @@ Note that in CI environments, this setting is enabled by default.`,
|
|
|
767
796
|
else {
|
|
768
797
|
logger.info({ message: 'Lockfile is up to date, resolution step is skipped', prefix: opts.lockfileDir });
|
|
769
798
|
}
|
|
770
|
-
if (opts.runPacquet != null && opts.useLockfile && !opts.useGitBranchLockfile && !opts.mergeGitBranchLockfiles && opts
|
|
799
|
+
if (opts.runPacquet != null && opts.useLockfile && !opts.useGitBranchLockfile && !opts.mergeGitBranchLockfiles && !isCheckOnlyInstall(opts) && opts.enableModulesDir) {
|
|
771
800
|
try {
|
|
772
801
|
await opts.runPacquet.run();
|
|
773
802
|
}
|
|
@@ -989,18 +1018,29 @@ export async function addDependenciesToPackage(manifest, dependencySelectors, op
|
|
|
989
1018
|
});
|
|
990
1019
|
return { updatedCatalogs, updatedManifest: projects[0].manifest, ignoredBuilds, resolutionPolicyViolations };
|
|
991
1020
|
}
|
|
1021
|
+
/**
|
|
1022
|
+
* A "check-only" install resolves fully but writes nothing: `dryRun`
|
|
1023
|
+
* (`pnpm install --dry-run`) and `lockfileCheck` (`pnpm dedupe --check`)
|
|
1024
|
+
* both take this path. The shared flag suppresses every write and forces a
|
|
1025
|
+
* full resolution (the frozen/headless fast paths are skipped) so the wanted
|
|
1026
|
+
* lockfile can always be compared.
|
|
1027
|
+
*/
|
|
1028
|
+
function isCheckOnlyInstall(opts) {
|
|
1029
|
+
return opts.lockfileCheck != null || opts.dryRun === true;
|
|
1030
|
+
}
|
|
992
1031
|
const _installInContext = async (projects, ctx, opts) => {
|
|
1032
|
+
// Aliasing for clarity in boolean expressions below. True for both
|
|
1033
|
+
// `--dry-run` and `dedupe --check`: resolve fully, write nothing.
|
|
1034
|
+
const isInstallationOnlyForLockfileCheck = isCheckOnlyInstall(opts);
|
|
993
1035
|
// The wanted lockfile is mutated during installation. To compare changes, a
|
|
994
1036
|
// deep copy before installation is needed. This copy should represent the
|
|
995
1037
|
// original wanted lockfile on disk as close as possible.
|
|
996
1038
|
//
|
|
997
1039
|
// This object can be quite large. Intentionally avoiding an expensive copy
|
|
998
|
-
//
|
|
999
|
-
const originalLockfileForCheck =
|
|
1040
|
+
// unless this is a check-only install that needs the comparison.
|
|
1041
|
+
const originalLockfileForCheck = isInstallationOnlyForLockfileCheck
|
|
1000
1042
|
? clone(ctx.wantedLockfile)
|
|
1001
1043
|
: null;
|
|
1002
|
-
// Aliasing for clarity in boolean expressions below.
|
|
1003
|
-
const isInstallationOnlyForLockfileCheck = opts.lockfileCheck != null;
|
|
1004
1044
|
ctx.wantedLockfile.importers = ctx.wantedLockfile.importers || {};
|
|
1005
1045
|
for (const { id } of projects) {
|
|
1006
1046
|
if (!ctx.wantedLockfile.importers[id]) {
|
|
@@ -1159,6 +1199,17 @@ const _installInContext = async (projects, ctx, opts) => {
|
|
|
1159
1199
|
prefix: ctx.lockfileDir,
|
|
1160
1200
|
stage: 'resolution_done',
|
|
1161
1201
|
});
|
|
1202
|
+
// `pnpm update` may bump catalog entries during resolution. Overrides that
|
|
1203
|
+
// reference a catalog (e.g. `overrides: { foo: 'catalog:' }`) were resolved
|
|
1204
|
+
// against the pre-update catalog when the install options were extended, so
|
|
1205
|
+
// re-resolve them against the updated catalog. Done before `afterAllResolved`
|
|
1206
|
+
// so that hook still sees (and can amend) the final overrides. Otherwise
|
|
1207
|
+
// lockfile `overrides` keeps pointing at the old version while `catalogs`
|
|
1208
|
+
// advances, and a later `--frozen-lockfile` install fails with
|
|
1209
|
+
// ERR_PNPM_LOCKFILE_CONFIG_MISMATCH.
|
|
1210
|
+
if (updatedCatalogs != null && opts.overrides != null && Object.keys(opts.overrides).length > 0) {
|
|
1211
|
+
newLockfile.overrides = createOverridesMapFromParsed(parseOverrides(opts.overrides, mergeCatalogs(opts.catalogs, updatedCatalogs)));
|
|
1212
|
+
}
|
|
1162
1213
|
newLockfile = ((opts.hooks?.afterAllResolved) != null)
|
|
1163
1214
|
? await pipeWith(async (f, res) => f(await res), opts.hooks.afterAllResolved)(newLockfile) // eslint-disable-line
|
|
1164
1215
|
: newLockfile;
|
|
@@ -1172,6 +1223,7 @@ const _installInContext = async (projects, ctx, opts) => {
|
|
|
1172
1223
|
};
|
|
1173
1224
|
let stats;
|
|
1174
1225
|
let ignoredBuilds;
|
|
1226
|
+
const shouldWritePackageMap = opts.enableModulesDir !== false && opts.nodeLinker === 'isolated' && !opts.virtualStoreOnly;
|
|
1175
1227
|
if (!opts.lockfileOnly && !isInstallationOnlyForLockfileCheck && opts.enableModulesDir) {
|
|
1176
1228
|
const result = await linkPackages(projects, dependenciesGraph, {
|
|
1177
1229
|
allowBuild: opts.allowBuild,
|
|
@@ -1211,6 +1263,20 @@ const _installInContext = async (projects, ctx, opts) => {
|
|
|
1211
1263
|
supportedArchitectures: opts.supportedArchitectures,
|
|
1212
1264
|
});
|
|
1213
1265
|
stats = result.stats;
|
|
1266
|
+
if (shouldWritePackageMap) {
|
|
1267
|
+
// Omit the importer self-mapping when a project has no name (see the
|
|
1268
|
+
// deps-restorer write): a non-package-name key like `.` would be invalid.
|
|
1269
|
+
const importerNames = Object.fromEntries(projects.map(({ manifest, id }) => [id, manifest.name]));
|
|
1270
|
+
await writePackageMap(result.currentLockfile, {
|
|
1271
|
+
importerNames,
|
|
1272
|
+
lockfileDir: ctx.lockfileDir,
|
|
1273
|
+
locationByDepPath: Object.fromEntries(Object.values(dependenciesGraph).map((node) => [node.depPath, node.dir])),
|
|
1274
|
+
packageMapType: opts.nodePackageMapType,
|
|
1275
|
+
rootModulesDir: ctx.rootModulesDir,
|
|
1276
|
+
virtualStoreDir: ctx.virtualStoreDir,
|
|
1277
|
+
virtualStoreDirMaxLength: ctx.virtualStoreDirMaxLength,
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1214
1280
|
if (opts.enablePnp) {
|
|
1215
1281
|
const importerNames = Object.fromEntries(projects.map(({ manifest, id }) => [id, manifest.name ?? id]));
|
|
1216
1282
|
await writePnpFile(result.currentLockfile, {
|
|
@@ -1237,7 +1303,13 @@ const _installInContext = async (projects, ctx, opts) => {
|
|
|
1237
1303
|
if (opts.enablePnp) {
|
|
1238
1304
|
extraEnv = {
|
|
1239
1305
|
...extraEnv,
|
|
1240
|
-
...makeNodeRequireOption(path.join(opts.lockfileDir, '.pnp.cjs')),
|
|
1306
|
+
...makeNodeRequireOption(path.join(opts.lockfileDir, '.pnp.cjs'), extraEnv),
|
|
1307
|
+
};
|
|
1308
|
+
}
|
|
1309
|
+
if (opts.nodeExperimentalPackageMap && shouldWritePackageMap) {
|
|
1310
|
+
extraEnv = {
|
|
1311
|
+
...extraEnv,
|
|
1312
|
+
...makeNodePackageMapOption(path.join(ctx.rootModulesDir, PACKAGE_MAP_FILENAME), extraEnv),
|
|
1241
1313
|
};
|
|
1242
1314
|
}
|
|
1243
1315
|
// Dependency lifecycle scripts must not run on an unverified lockfile.
|
|
@@ -1382,7 +1454,13 @@ const _installInContext = async (projects, ctx, opts) => {
|
|
|
1382
1454
|
if (opts.enablePnp) {
|
|
1383
1455
|
opts.scriptsOpts.extraEnv = {
|
|
1384
1456
|
...opts.scriptsOpts.extraEnv,
|
|
1385
|
-
...makeNodeRequireOption(path.join(opts.lockfileDir, '.pnp.cjs')),
|
|
1457
|
+
...makeNodeRequireOption(path.join(opts.lockfileDir, '.pnp.cjs'), opts.scriptsOpts.extraEnv),
|
|
1458
|
+
};
|
|
1459
|
+
}
|
|
1460
|
+
if (opts.nodeExperimentalPackageMap && shouldWritePackageMap) {
|
|
1461
|
+
opts.scriptsOpts.extraEnv = {
|
|
1462
|
+
...opts.scriptsOpts.extraEnv,
|
|
1463
|
+
...makeNodePackageMapOption(path.join(ctx.rootModulesDir, PACKAGE_MAP_FILENAME), opts.scriptsOpts.extraEnv),
|
|
1386
1464
|
};
|
|
1387
1465
|
}
|
|
1388
1466
|
const projectsToBeBuilt = projectsWithTargetDirs.filter(({ mutation }) => mutation === 'install');
|
|
@@ -1466,6 +1544,9 @@ const _installInContext = async (projects, ctx, opts) => {
|
|
|
1466
1544
|
depsRequiringBuild,
|
|
1467
1545
|
ignoredBuilds,
|
|
1468
1546
|
resolutionPolicyViolations,
|
|
1547
|
+
dryRunResult: (opts.dryRun && originalLockfileForCheck != null)
|
|
1548
|
+
? { originalLockfile: originalLockfileForCheck, wantedLockfile: newLockfile }
|
|
1549
|
+
: undefined,
|
|
1469
1550
|
};
|
|
1470
1551
|
};
|
|
1471
1552
|
function allMutationsAreInstalls(projects) {
|
|
@@ -1530,7 +1611,7 @@ const installInContext = async (projects, ctx, opts) => {
|
|
|
1530
1611
|
if (!opts.frozenLockfile && opts.useLockfile) {
|
|
1531
1612
|
const allProjectsLocatedInsideWorkspace = Object.values(ctx.projects)
|
|
1532
1613
|
.filter((project) => isPathInsideWorkspace(project.rootDirRealPath ?? project.rootDir));
|
|
1533
|
-
if (allProjectsLocatedInsideWorkspace.length > projects.length && opts
|
|
1614
|
+
if (allProjectsLocatedInsideWorkspace.length > projects.length && !isCheckOnlyInstall(opts) && opts.enableModulesDir) {
|
|
1534
1615
|
const newProjects = [...projects];
|
|
1535
1616
|
const getWantedDepsOpts = {
|
|
1536
1617
|
autoInstallPeers: opts.autoInstallPeers,
|
|
@@ -1582,7 +1663,7 @@ const installInContext = async (projects, ctx, opts) => {
|
|
|
1582
1663
|
};
|
|
1583
1664
|
}
|
|
1584
1665
|
}
|
|
1585
|
-
if (opts.nodeLinker === 'hoisted' && !opts.lockfileOnly && opts
|
|
1666
|
+
if (opts.nodeLinker === 'hoisted' && !opts.lockfileOnly && !isCheckOnlyInstall(opts) && opts.enableModulesDir) {
|
|
1586
1667
|
const result = await _installInContext(projects, ctx, {
|
|
1587
1668
|
...opts,
|
|
1588
1669
|
lockfileOnly: true,
|
|
@@ -1611,7 +1692,7 @@ const installInContext = async (projects, ctx, opts) => {
|
|
|
1611
1692
|
// Isolated `nodeLinker` (the default) with a non-frozen install.
|
|
1612
1693
|
// The frozen branch is handled earlier in `tryFrozenInstall`; the
|
|
1613
1694
|
// hoisted branch above runs a resolve-then-materialize sequence.
|
|
1614
|
-
if (opts.runPacquet != null && opts.useLockfile && opts.saveLockfile && !opts.useGitBranchLockfile && !opts.mergeGitBranchLockfiles && !opts.lockfileOnly && opts
|
|
1695
|
+
if (opts.runPacquet != null && opts.useLockfile && opts.saveLockfile && !opts.useGitBranchLockfile && !opts.mergeGitBranchLockfiles && !opts.lockfileOnly && !isCheckOnlyInstall(opts) && opts.enableModulesDir) {
|
|
1615
1696
|
// pacquet >= 0.11.7 resolves itself: hand it the whole install
|
|
1616
1697
|
// (resolve + fetch + import + link + build, writing the lockfile)
|
|
1617
1698
|
// in a single non-frozen pass. Only for plain installs — `add` /
|
package/lib/install/link.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type DepsStateCache } from '@pnpm/deps.graph-hasher';
|
|
2
|
-
import type
|
|
2
|
+
import { type DependenciesGraph, type LinkedDependency } from '@pnpm/installing.deps-resolver';
|
|
3
3
|
import type { InstallationResultStats } from '@pnpm/installing.deps-restorer';
|
|
4
4
|
import type { IncludedDependencies } from '@pnpm/installing.modules-yaml';
|
|
5
5
|
import type { LockfileObject } from '@pnpm/lockfile.fs';
|
package/lib/install/link.js
CHANGED
|
@@ -2,13 +2,16 @@ import { promises as fs } from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { progressLogger, stageLogger, statsLogger, } from '@pnpm/core-loggers';
|
|
4
4
|
import { calcDepState, findRuntimeNodeVersion } from '@pnpm/deps.graph-hasher';
|
|
5
|
+
import { readModulesDir } from '@pnpm/fs.read-modules-dir';
|
|
5
6
|
import { symlinkDependency } from '@pnpm/fs.symlink-dependency';
|
|
7
|
+
import { isValidDependencyAlias, } from '@pnpm/installing.deps-resolver';
|
|
6
8
|
import { linkDirectDeps } from '@pnpm/installing.linking.direct-dep-linker';
|
|
7
9
|
import { hoist } from '@pnpm/installing.linking.hoist';
|
|
8
10
|
import { prune } from '@pnpm/installing.linking.modules-cleaner';
|
|
9
11
|
import { filterLockfileByImporters, } from '@pnpm/lockfile.filtering';
|
|
10
12
|
import { logger } from '@pnpm/logger';
|
|
11
13
|
import { symlinkAllModules } from '@pnpm/worker';
|
|
14
|
+
import { rimraf } from '@zkochan/rimraf';
|
|
12
15
|
import pLimit from 'p-limit';
|
|
13
16
|
import { pathExists } from 'path-exists';
|
|
14
17
|
import { difference, equals, isEmpty, pick, pickBy, props } from 'ramda';
|
|
@@ -250,20 +253,47 @@ async function linkNewPackages(currentLockfile, wantedLockfile, depGraph, opts)
|
|
|
250
253
|
});
|
|
251
254
|
const existingWithUpdatedDeps = [];
|
|
252
255
|
if (!opts.force && (currentLockfile.packages != null) && (wantedLockfile.packages != null)) {
|
|
256
|
+
const currentPackages = currentLockfile.packages;
|
|
257
|
+
const wantedPackages = wantedLockfile.packages;
|
|
253
258
|
// add subdependencies that have been updated
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
!isEmpty(
|
|
259
|
-
!isEmpty(wantedLockfile.packages[depPath].optionalDependencies ?? {}))) {
|
|
259
|
+
await Promise.all(wantedRelDepPaths.map((depPath) => limitModulesDirReads(async () => {
|
|
260
|
+
if (currentPackages[depPath] &&
|
|
261
|
+
(!equals(currentPackages[depPath].dependencies, wantedPackages[depPath].dependencies) ||
|
|
262
|
+
!isEmpty(currentPackages[depPath].optionalDependencies ?? {}) ||
|
|
263
|
+
!isEmpty(wantedPackages[depPath].optionalDependencies ?? {}))) {
|
|
260
264
|
// TODO: come up with a test that triggers the usecase of depGraph[depPath] undefined
|
|
261
265
|
// see related issue: https://github.com/pnpm/pnpm/issues/870
|
|
262
266
|
if (depGraph[depPath] && !newDepPathsSet.has(depPath)) {
|
|
263
|
-
|
|
267
|
+
const { actualChildrenChanged, removedAliases: actualRemovedAliases } = await getActualChildrenDiff(depGraph[depPath], depGraph, opts.lockfileDir, opts.optional);
|
|
268
|
+
if (actualChildrenChanged) {
|
|
269
|
+
existingWithUpdatedDeps.push({
|
|
270
|
+
children: depGraph[depPath].children,
|
|
271
|
+
modules: depGraph[depPath].modules,
|
|
272
|
+
name: depGraph[depPath].name,
|
|
273
|
+
optionalDependencies: depGraph[depPath].optionalDependencies,
|
|
274
|
+
removedAliases: actualRemovedAliases,
|
|
275
|
+
});
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const { changedChildren, removedAliases } = getChangedChildren({
|
|
279
|
+
currentDependencies: currentPackages[depPath].dependencies,
|
|
280
|
+
currentOptionalDependencies: currentPackages[depPath].optionalDependencies,
|
|
281
|
+
wantedDependencies: wantedPackages[depPath].dependencies,
|
|
282
|
+
wantedOptionalDependencies: wantedPackages[depPath].optionalDependencies,
|
|
283
|
+
allChildren: depGraph[depPath].children,
|
|
284
|
+
});
|
|
285
|
+
if (!isEmpty(changedChildren) || removedAliases.length > 0) {
|
|
286
|
+
existingWithUpdatedDeps.push({
|
|
287
|
+
children: changedChildren,
|
|
288
|
+
modules: depGraph[depPath].modules,
|
|
289
|
+
name: depGraph[depPath].name,
|
|
290
|
+
optionalDependencies: depGraph[depPath].optionalDependencies,
|
|
291
|
+
removedAliases,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
264
294
|
}
|
|
265
295
|
}
|
|
266
|
-
}
|
|
296
|
+
})));
|
|
267
297
|
}
|
|
268
298
|
if (!newDepPathsSet.size && (existingWithUpdatedDeps.length === 0))
|
|
269
299
|
return { newDepPaths: [], added };
|
|
@@ -317,6 +347,7 @@ async function selectNewFromWantedDeps(wantedRelDepPaths, currentLockfile, depGr
|
|
|
317
347
|
return newDeps;
|
|
318
348
|
}
|
|
319
349
|
const limitLinking = pLimit(16);
|
|
350
|
+
const limitModulesDirReads = pLimit(16);
|
|
320
351
|
async function linkAllPkgs(storeController, depNodes, opts) {
|
|
321
352
|
// Resolved `engines.runtime` Node version (when present) so the
|
|
322
353
|
// side-effects-cache key prefix tracks the script-runner Node
|
|
@@ -365,29 +396,83 @@ async function linkAllPkgs(storeController, depNodes, opts) {
|
|
|
365
396
|
}));
|
|
366
397
|
}
|
|
367
398
|
async function linkAllModules(depNodes, depGraph, opts) {
|
|
399
|
+
await Promise.all(depNodes.flatMap((depNode) => (depNode.removedAliases ?? []).map(async (alias) => limitModulesDirReads(async () => removeObsoleteChild(depNode.modules, alias)))));
|
|
368
400
|
await symlinkAllModules({
|
|
369
401
|
deps: depNodes.map((depNode) => {
|
|
370
|
-
const children = opts.optional
|
|
371
|
-
? depNode.children
|
|
372
|
-
: pickBy((_, childAlias) => !depNode.optionalDependencies.has(childAlias), depNode.children);
|
|
373
|
-
const childrenPaths = {};
|
|
374
|
-
for (const [alias, childDepPath] of Object.entries(children ?? {})) {
|
|
375
|
-
if (childDepPath.startsWith('link:')) {
|
|
376
|
-
childrenPaths[alias] = path.resolve(opts.lockfileDir, childDepPath.slice(5));
|
|
377
|
-
}
|
|
378
|
-
else {
|
|
379
|
-
const pkg = depGraph[childDepPath];
|
|
380
|
-
if (!pkg || !pkg.installable && pkg.optional || alias === depNode.name)
|
|
381
|
-
continue;
|
|
382
|
-
childrenPaths[alias] = pkg.dir;
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
402
|
return {
|
|
386
|
-
children:
|
|
403
|
+
children: getChildrenPaths(depNode, depGraph, opts.lockfileDir, opts.optional),
|
|
387
404
|
modules: depNode.modules,
|
|
388
405
|
name: depNode.name,
|
|
389
406
|
};
|
|
390
407
|
}),
|
|
391
408
|
});
|
|
392
409
|
}
|
|
410
|
+
function getChangedChildren(opts) {
|
|
411
|
+
const { currentOptionalDependencies, wantedOptionalDependencies, allChildren } = opts;
|
|
412
|
+
// Use null-prototype maps so a child literally named `constructor`,
|
|
413
|
+
// `toString`, `__proto__`, etc. is treated as a normal alias instead
|
|
414
|
+
// of colliding with an inherited `Object.prototype` key during the
|
|
415
|
+
// `in`/index lookups below.
|
|
416
|
+
const currentChildren = Object.assign(Object.create(null), opts.currentDependencies, currentOptionalDependencies);
|
|
417
|
+
const wantedChildren = Object.assign(Object.create(null), opts.wantedDependencies, wantedOptionalDependencies);
|
|
418
|
+
const changedChildren = {};
|
|
419
|
+
const removedAliases = [];
|
|
420
|
+
for (const [alias, wantedChildDepPath] of Object.entries(wantedChildren)) {
|
|
421
|
+
const optionalityChanged = hasOwn(wantedOptionalDependencies, alias) !== hasOwn(currentOptionalDependencies, alias);
|
|
422
|
+
if (currentChildren[alias] !== wantedChildDepPath || optionalityChanged) {
|
|
423
|
+
const resolvedChildDepPath = hasOwn(allChildren, alias) ? allChildren[alias] : undefined;
|
|
424
|
+
if (resolvedChildDepPath != null) {
|
|
425
|
+
changedChildren[alias] = resolvedChildDepPath;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
for (const alias of Object.keys(currentChildren)) {
|
|
430
|
+
if (!hasOwn(wantedChildren, alias)) {
|
|
431
|
+
removedAliases.push(alias);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return { changedChildren, removedAliases };
|
|
435
|
+
}
|
|
436
|
+
function hasOwn(obj, key) {
|
|
437
|
+
return obj != null && Object.hasOwn(obj, key);
|
|
438
|
+
}
|
|
439
|
+
async function getActualChildrenDiff(depNode, depGraph, lockfileDir, optional) {
|
|
440
|
+
if (depNode.optionalDependencies.size === 0) {
|
|
441
|
+
return { actualChildrenChanged: false, removedAliases: [] };
|
|
442
|
+
}
|
|
443
|
+
const currentAliases = new Set((await readModulesDir(depNode.modules) ?? []).filter((alias) => alias !== depNode.name));
|
|
444
|
+
const nextAliases = new Set(Object.keys(getChildrenPaths(depNode, depGraph, lockfileDir, optional)));
|
|
445
|
+
const removedAliases = Array.from(currentAliases).filter((alias) => !nextAliases.has(alias));
|
|
446
|
+
const actualChildrenChanged = removedAliases.length > 0 ||
|
|
447
|
+
Array.from(nextAliases).some((alias) => !currentAliases.has(alias));
|
|
448
|
+
return { actualChildrenChanged, removedAliases };
|
|
449
|
+
}
|
|
450
|
+
async function removeObsoleteChild(modulesDir, alias) {
|
|
451
|
+
// Guard against an alias that would escape the modules directory (e.g. `../../x`).
|
|
452
|
+
if (!isValidDependencyAlias(alias))
|
|
453
|
+
return;
|
|
454
|
+
await rimraf(path.join(modulesDir, alias));
|
|
455
|
+
if (alias[0] === '@') {
|
|
456
|
+
await fs.rmdir(path.join(modulesDir, alias.split('/')[0])).catch(() => { });
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
function getChildrenPaths(depNode, depGraph, lockfileDir, optional) {
|
|
460
|
+
const children = optional
|
|
461
|
+
? depNode.children
|
|
462
|
+
: pickBy((_, childAlias) => !depNode.optionalDependencies.has(childAlias), depNode.children);
|
|
463
|
+
const childrenPaths = {};
|
|
464
|
+
for (const [alias, childDepPath] of Object.entries(children ?? {})) {
|
|
465
|
+
if (alias === depNode.name)
|
|
466
|
+
continue;
|
|
467
|
+
if (childDepPath.startsWith('link:')) {
|
|
468
|
+
childrenPaths[alias] = path.resolve(lockfileDir, childDepPath.slice(5));
|
|
469
|
+
continue;
|
|
470
|
+
}
|
|
471
|
+
const pkg = depGraph[childDepPath];
|
|
472
|
+
if (!pkg || !pkg.installable && pkg.optional)
|
|
473
|
+
continue;
|
|
474
|
+
childrenPaths[alias] = pkg.dir;
|
|
475
|
+
}
|
|
476
|
+
return childrenPaths;
|
|
477
|
+
}
|
|
393
478
|
//# sourceMappingURL=link.js.map
|
|
@@ -205,6 +205,10 @@ function buildVerificationError(violations) {
|
|
|
205
205
|
const details = omitted > 0
|
|
206
206
|
? `${breakdown}\n …and ${omitted} more`
|
|
207
207
|
: breakdown;
|
|
208
|
+
// Registry fetch failures (auth/network/5xx) don't reach this batch — the
|
|
209
|
+
// verifier throws the registry's own error and the gate aborts with it. So
|
|
210
|
+
// every violation here is a genuine policy rejection, and the hint points at
|
|
211
|
+
// the lockfile rather than at connectivity.
|
|
208
212
|
return new PnpmError(errorCode, `${violations.length} lockfile entries failed verification:\n${details}`, {
|
|
209
213
|
hint: 'The lockfile contains entries that the active policies reject. ' +
|
|
210
214
|
'This can mean the lockfile is stale, or that someone committed a ' +
|
|
@@ -346,22 +350,41 @@ function pushInvalidAliases(deps, invalid) {
|
|
|
346
350
|
}
|
|
347
351
|
async function iterateLockfileViolations(candidates, verifiers, concurrency) {
|
|
348
352
|
const violations = [];
|
|
353
|
+
// A verifier may throw rather than return a violation when it can't reach the
|
|
354
|
+
// registry to verify an entry (auth/network/5xx) — that's not a per-entry
|
|
355
|
+
// policy pick, it's an incomplete verification, so the registry's own error
|
|
356
|
+
// should abort the install. Capture the first such error and rethrow it after
|
|
357
|
+
// the fan-out settles: rethrowing straight into Promise.all would leave the
|
|
358
|
+
// sibling tasks (all failing against the same dead registry) as unhandled
|
|
359
|
+
// rejections once Promise.all rejects on the first.
|
|
360
|
+
let fetchError;
|
|
349
361
|
const limit = pLimit(concurrency ?? DEFAULT_CONCURRENCY);
|
|
350
362
|
await Promise.all(Array.from(candidates.values(), ({ name, version, nonSemverVersion, resolution }) => limit(async () => {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
363
|
+
try {
|
|
364
|
+
// Fan out across every active verifier; each handles its own
|
|
365
|
+
// protocol short-circuit (e.g. the npm verifier returns ok:true for
|
|
366
|
+
// git resolutions). We stop at the first failure per entry so a
|
|
367
|
+
// multi-verifier setup doesn't produce duplicate violations for the
|
|
368
|
+
// same (name, version).
|
|
369
|
+
for (const verifier of verifiers) {
|
|
370
|
+
// eslint-disable-next-line no-await-in-loop
|
|
371
|
+
const result = await verifier.verify(resolution, { name, version, nonSemverVersion });
|
|
372
|
+
if (!result.ok) {
|
|
373
|
+
violations.push({ name, version, resolution, code: result.code, reason: result.reason });
|
|
374
|
+
break;
|
|
375
|
+
}
|
|
362
376
|
}
|
|
363
377
|
}
|
|
378
|
+
catch (err) {
|
|
379
|
+
fetchError ??= err;
|
|
380
|
+
}
|
|
364
381
|
})));
|
|
382
|
+
// A registry that couldn't be reached takes precedence over collected
|
|
383
|
+
// violations: the run never finished verifying, so the batch is incomplete
|
|
384
|
+
// and the actionable failure is the transport error. Once it's resolved the
|
|
385
|
+
// re-run surfaces any remaining violations.
|
|
386
|
+
if (fetchError != null)
|
|
387
|
+
throw fetchError;
|
|
365
388
|
return violations;
|
|
366
389
|
}
|
|
367
390
|
//# sourceMappingURL=verifyLockfileResolutions.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/installing.deps-installer",
|
|
3
|
-
"version": "1102.
|
|
3
|
+
"version": "1102.1.1",
|
|
4
4
|
"description": "Fast, disk space efficient installation engine",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
"funding": "https://opencollective.com/pnpm",
|
|
31
31
|
"repository": {
|
|
32
32
|
"type": "git",
|
|
33
|
-
"url": "https://github.com/pnpm/pnpm/tree/main/installing/deps-installer"
|
|
33
|
+
"url": "https://github.com/pnpm/pnpm/tree/main/pnpm11/installing/deps-installer"
|
|
34
34
|
},
|
|
35
|
-
"homepage": "https://github.com/pnpm/pnpm/tree/main/installing/deps-installer#readme",
|
|
35
|
+
"homepage": "https://github.com/pnpm/pnpm/tree/main/pnpm11/installing/deps-installer#readme",
|
|
36
36
|
"bugs": {
|
|
37
37
|
"url": "https://github.com/pnpm/pnpm/issues"
|
|
38
38
|
},
|
|
@@ -65,61 +65,62 @@
|
|
|
65
65
|
"ramda": "npm:@pnpm/ramda@0.28.1",
|
|
66
66
|
"run-groups": "^5.0.0",
|
|
67
67
|
"semver": "^7.8.4",
|
|
68
|
-
"@pnpm/
|
|
69
|
-
"@pnpm/building.during-install": "1102.0.
|
|
70
|
-
"@pnpm/
|
|
71
|
-
"@pnpm/
|
|
68
|
+
"@pnpm/bins.remover": "1100.0.11",
|
|
69
|
+
"@pnpm/building.during-install": "1102.0.2",
|
|
70
|
+
"@pnpm/bins.linker": "1100.0.16",
|
|
71
|
+
"@pnpm/catalogs.config": "1100.0.2",
|
|
72
|
+
"@pnpm/building.policy": "1100.0.11",
|
|
73
|
+
"@pnpm/building.after-install": "1102.0.2",
|
|
74
|
+
"@pnpm/catalogs.types": "1100.0.0",
|
|
72
75
|
"@pnpm/catalogs.resolver": "1100.0.0",
|
|
76
|
+
"@pnpm/catalogs.protocol-parser": "1100.0.0",
|
|
77
|
+
"@pnpm/config.parse-overrides": "1100.0.2",
|
|
73
78
|
"@pnpm/config.normalize-registries": "1100.0.8",
|
|
74
|
-
"@pnpm/config.
|
|
75
|
-
"@pnpm/catalogs.types": "1100.0.0",
|
|
79
|
+
"@pnpm/config.matcher": "1100.0.1",
|
|
76
80
|
"@pnpm/core-loggers": "1100.2.1",
|
|
77
81
|
"@pnpm/constants": "1100.0.0",
|
|
78
|
-
"@pnpm/
|
|
79
|
-
"@pnpm/deps.graph-hasher": "1100.2.
|
|
80
|
-
"@pnpm/deps.path": "1100.0.8",
|
|
82
|
+
"@pnpm/crypto.hash": "1100.0.1",
|
|
83
|
+
"@pnpm/deps.graph-hasher": "1100.2.6",
|
|
81
84
|
"@pnpm/deps.graph-sequencer": "1100.0.0",
|
|
82
|
-
"@pnpm/building.policy": "1100.0.10",
|
|
83
|
-
"@pnpm/bins.linker": "1100.0.14",
|
|
84
85
|
"@pnpm/crypto.object-hasher": "1100.0.0",
|
|
85
|
-
"@pnpm/
|
|
86
|
-
"@pnpm/
|
|
86
|
+
"@pnpm/error": "1100.0.1",
|
|
87
|
+
"@pnpm/fs.read-modules-dir": "1100.0.1",
|
|
88
|
+
"@pnpm/deps.path": "1100.0.8",
|
|
89
|
+
"@pnpm/exec.lifecycle": "1100.1.1",
|
|
87
90
|
"@pnpm/fs.symlink-dependency": "1100.0.10",
|
|
88
|
-
"@pnpm/hooks.types": "1100.0
|
|
89
|
-
"@pnpm/
|
|
90
|
-
"@pnpm/installing.
|
|
91
|
+
"@pnpm/hooks.types": "1100.1.0",
|
|
92
|
+
"@pnpm/installing.context": "1100.0.20",
|
|
93
|
+
"@pnpm/installing.deps-resolver": "1100.2.5",
|
|
94
|
+
"@pnpm/installing.deps-restorer": "1102.1.1",
|
|
95
|
+
"@pnpm/hooks.read-package-hook": "1100.0.9",
|
|
91
96
|
"@pnpm/installing.linking.direct-dep-linker": "1100.0.10",
|
|
92
|
-
"@pnpm/installing.
|
|
93
|
-
"@pnpm/crypto.hash": "1100.0.1",
|
|
94
|
-
"@pnpm/fs.read-modules-dir": "1100.0.1",
|
|
95
|
-
"@pnpm/installing.linking.hoist": "1100.0.14",
|
|
96
|
-
"@pnpm/installing.package-requester": "1102.0.0",
|
|
97
|
-
"@pnpm/installing.deps-restorer": "1102.0.0",
|
|
98
|
-
"@pnpm/lockfile.fs": "1100.1.5",
|
|
99
|
-
"@pnpm/lockfile.pruner": "1100.0.11",
|
|
100
|
-
"@pnpm/installing.linking.modules-cleaner": "1100.1.8",
|
|
101
|
-
"@pnpm/lockfile.preferred-versions": "1100.0.16",
|
|
97
|
+
"@pnpm/installing.linking.hoist": "1100.0.16",
|
|
102
98
|
"@pnpm/installing.modules-yaml": "1100.0.9",
|
|
103
|
-
"@pnpm/
|
|
104
|
-
"@pnpm/
|
|
105
|
-
"@pnpm/lockfile.
|
|
106
|
-
"@pnpm/
|
|
107
|
-
"@pnpm/lockfile.
|
|
108
|
-
"@pnpm/
|
|
99
|
+
"@pnpm/installing.linking.modules-cleaner": "1100.1.9",
|
|
100
|
+
"@pnpm/installing.package-requester": "1102.1.0",
|
|
101
|
+
"@pnpm/lockfile.fs": "1100.1.7",
|
|
102
|
+
"@pnpm/lockfile.preferred-versions": "1100.0.17",
|
|
103
|
+
"@pnpm/lockfile.filtering": "1100.1.8",
|
|
104
|
+
"@pnpm/lockfile.pruner": "1100.0.12",
|
|
105
|
+
"@pnpm/lockfile.settings-checker": "1100.0.20",
|
|
106
|
+
"@pnpm/lockfile.verification": "1100.0.20",
|
|
107
|
+
"@pnpm/lockfile.to-pnp": "1100.1.1",
|
|
108
|
+
"@pnpm/patching.config": "1100.0.9",
|
|
109
|
+
"@pnpm/lockfile.utils": "1100.1.0",
|
|
110
|
+
"@pnpm/lockfile.walker": "1100.0.12",
|
|
111
|
+
"@pnpm/network.auth-header": "1101.1.3",
|
|
112
|
+
"@pnpm/pkg-manifest.utils": "1100.2.6",
|
|
109
113
|
"@pnpm/resolving.parse-wanted-dependency": "1100.0.1",
|
|
110
|
-
"@pnpm/
|
|
111
|
-
"@pnpm/
|
|
112
|
-
"@pnpm/
|
|
113
|
-
"@pnpm/
|
|
114
|
-
"@pnpm/
|
|
115
|
-
"@pnpm/
|
|
116
|
-
"@pnpm/store.controller-types": "1100.1.5",
|
|
117
|
-
"@pnpm/lockfile.verification": "1100.0.18",
|
|
118
|
-
"@pnpm/store.index": "1100.2.0"
|
|
114
|
+
"@pnpm/pnpr.client": "1.2.3",
|
|
115
|
+
"@pnpm/store.index": "1100.2.1",
|
|
116
|
+
"@pnpm/resolving.resolver-base": "1100.5.0",
|
|
117
|
+
"@pnpm/workspace.project-manifest-reader": "1100.0.14",
|
|
118
|
+
"@pnpm/store.controller-types": "1100.1.6",
|
|
119
|
+
"@pnpm/types": "1101.3.2"
|
|
119
120
|
},
|
|
120
121
|
"peerDependencies": {
|
|
121
122
|
"@pnpm/logger": "^1100.0.0",
|
|
122
|
-
"@pnpm/worker": "^1100.2.
|
|
123
|
+
"@pnpm/worker": "^1100.2.2"
|
|
123
124
|
},
|
|
124
125
|
"devDependencies": {
|
|
125
126
|
"@jest/globals": "30.4.1",
|
|
@@ -140,22 +141,22 @@
|
|
|
140
141
|
"symlink-dir": "^10.0.1",
|
|
141
142
|
"write-json-file": "^7.0.0",
|
|
142
143
|
"write-yaml-file": "^6.0.0",
|
|
143
|
-
"@pnpm/assert-project": "1100.0.
|
|
144
|
-
"@pnpm/
|
|
145
|
-
"@pnpm/
|
|
144
|
+
"@pnpm/assert-project": "1100.0.17",
|
|
145
|
+
"@pnpm/assert-store": "1100.0.17",
|
|
146
|
+
"@pnpm/installing.deps-installer": "1102.1.1",
|
|
147
|
+
"@pnpm/lockfile.types": "1100.0.12",
|
|
146
148
|
"@pnpm/logger": "1100.0.0",
|
|
147
|
-
"@pnpm/
|
|
148
|
-
"@pnpm/pkg-manifest.reader": "1100.0.8",
|
|
149
|
-
"@pnpm/store.cafs": "1100.1.10",
|
|
150
|
-
"@pnpm/prepare": "1100.0.16",
|
|
151
|
-
"@pnpm/store.path": "1100.0.1",
|
|
152
|
-
"@pnpm/test-ipc-server": "1100.0.0",
|
|
153
|
-
"@pnpm/testing.registry-mock": "1100.0.6",
|
|
154
|
-
"@pnpm/testing.mock-agent": "1101.0.3",
|
|
155
|
-
"@pnpm/test-fixtures": "1100.0.0",
|
|
156
|
-
"@pnpm/testing.temp-store": "1100.1.9",
|
|
149
|
+
"@pnpm/prepare": "1100.0.17",
|
|
157
150
|
"@pnpm/resolving.registry.types": "1100.1.3",
|
|
158
|
-
"@pnpm/
|
|
151
|
+
"@pnpm/store.cafs": "1100.1.11",
|
|
152
|
+
"@pnpm/pkg-manifest.reader": "1100.0.9",
|
|
153
|
+
"@pnpm/store.path": "1100.0.2",
|
|
154
|
+
"@pnpm/test-fixtures": "1100.0.0",
|
|
155
|
+
"@pnpm/test-ipc-server": "1100.0.0",
|
|
156
|
+
"@pnpm/testing.mock-agent": "1101.0.4",
|
|
157
|
+
"@pnpm/testing.temp-store": "1100.1.11",
|
|
158
|
+
"@pnpm/network.git-utils": "1100.0.2",
|
|
159
|
+
"@pnpm/testing.registry-mock": "1100.0.7"
|
|
159
160
|
},
|
|
160
161
|
"engines": {
|
|
161
162
|
"node": ">=22.13"
|