pnpm 11.28.1 → 11.28.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # pnpm
2
2
 
3
+ ## 11.28.2
4
+
5
+ pnpm 11.28.2 fixes `pnpm install` skipping every workspace project whose common ancestor is the filesystem root, and stops `pnpm run` from reinstalling or installing when nothing needs it.
6
+
7
+ ### Patch Changes
8
+
9
+ - `pnpm install` reported success without installing anything when the workspace projects' common ancestor was the filesystem root, such as `/` or a drive root like `C:\`. It now installs these projects [#16328](https://github.com/pnpm/pnpm/issues/16328).
10
+
11
+ - `verifyDepsBeforeRun` no longer reports dependencies as outdated after a filtered install just because `pnpm-lock.yaml` has a newer modification time. It checks the lockfile against the packages that install put in place. Before, `pnpm run` reinstalled the whole workspace with lifecycle scripts on, for example after a Docker `COPY` brought in a lockfile with a newer mtime [#16322](https://github.com/pnpm/pnpm/issues/16322).
12
+
13
+ After a filtered install, `verifyDepsBeforeRun` now also checks that the install put the selected projects' dependencies in place. A `node_modules` directory alone no longer counts as proof.
14
+
15
+ - `pnpm run` and `pnpm exec` no longer install a project that has never been installed and has nothing to install. Such a project declares no dependencies, no peer dependencies that `autoInstallPeers` would fetch, and no install lifecycle scripts. The command now runs without writing `node_modules` or `pnpm-lock.yaml` [#16313](https://github.com/pnpm/pnpm/issues/16313).
16
+
3
17
  ## 11.28.1
4
18
 
5
19
  pnpm 11.28.1 makes `pnpm install` work in StackBlitz WebContainers, repairs lockfiles whose patch hashes disagree with `patchedDependencies`, and fixes many bugs in Windows command shims, injected workspace dependencies, and `pnpm deploy`.
package/dist/pnpm.mjs CHANGED
@@ -223,7 +223,7 @@ var init_lib = __esm({
223
223
  init_selfEntry();
224
224
  defaultManifest = {
225
225
  name: true ? "pnpm" : "pnpm",
226
- version: true ? "11.28.1" : "0.0.0"
226
+ version: true ? "11.28.2" : "0.0.0"
227
227
  };
228
228
  pkgJson = defaultManifest;
229
229
  packageManager = {
@@ -7157,20 +7157,24 @@ var init_better_path_resolve = __esm({
7157
7157
  }
7158
7158
  });
7159
7159
 
7160
- // ../../../../../setup-pnpm/store/v11/links/@/is-subdir/2.0.0/86b3cd44735afb9f459dad7b43ddfc23f1a21495323a3fb38b9ab590c29f23ce/node_modules/is-subdir/index.js
7160
+ // ../../../../../setup-pnpm/store/v11/links/@/is-subdir/2.0.1/930a5285b376d962304fd10a15f6382f59e4b31eb7c98b5f184535f0320114ee/node_modules/is-subdir/index.js
7161
7161
  import path8 from "node:path";
7162
7162
  function isSubdir(parentDir, subdir) {
7163
- const rParent = `${betterPathResolve(parentDir)}${path8.sep}`;
7164
- const rDir = `${betterPathResolve(subdir)}${path8.sep}`;
7163
+ const rParent = resolveWithTrailingSep(parentDir);
7164
+ const rDir = resolveWithTrailingSep(subdir);
7165
7165
  return rDir.startsWith(rParent);
7166
7166
  }
7167
7167
  function strict(parentDir, subdir) {
7168
- const rParent = `${betterPathResolve(parentDir)}${path8.sep}`;
7169
- const rDir = `${betterPathResolve(subdir)}${path8.sep}`;
7168
+ const rParent = resolveWithTrailingSep(parentDir);
7169
+ const rDir = resolveWithTrailingSep(subdir);
7170
7170
  return rDir !== rParent && rDir.startsWith(rParent);
7171
7171
  }
7172
+ function resolveWithTrailingSep(dir) {
7173
+ const resolved = betterPathResolve(dir);
7174
+ return resolved.endsWith(path8.sep) ? resolved : `${resolved}${path8.sep}`;
7175
+ }
7172
7176
  var init_is_subdir = __esm({
7173
- "../../../../../setup-pnpm/store/v11/links/@/is-subdir/2.0.0/86b3cd44735afb9f459dad7b43ddfc23f1a21495323a3fb38b9ab590c29f23ce/node_modules/is-subdir/index.js"() {
7177
+ "../../../../../setup-pnpm/store/v11/links/@/is-subdir/2.0.1/930a5285b376d962304fd10a15f6382f59e4b31eb7c98b5f184535f0320114ee/node_modules/is-subdir/index.js"() {
7174
7178
  init_better_path_resolve();
7175
7179
  }
7176
7180
  });
@@ -219768,7 +219772,7 @@ var init_resolvePeers = __esm({
219768
219772
  }
219769
219773
  });
219770
219774
 
219771
- // ../../../../../setup-pnpm/store/v11/links/@/is-inner-link/5.0.0/72b7eb44d56e1666d7ca026d99a5fb2fb1b7840dde1a66e0e9ee7e333683e310/node_modules/is-inner-link/index.js
219775
+ // ../../../../../setup-pnpm/store/v11/links/@/is-inner-link/5.0.0/cce13b91443927cfbdb861aaaa9ef4ad3c89350d4dca46d5b1dafb56bb24e74a/node_modules/is-inner-link/index.js
219772
219776
  import path150 from "node:path";
219773
219777
  async function isInnerLink(parent, relativePathToLink) {
219774
219778
  const linkPath = path150.resolve(parent, relativePathToLink);
@@ -219779,7 +219783,7 @@ async function isInnerLink(parent, relativePathToLink) {
219779
219783
  };
219780
219784
  }
219781
219785
  var init_is_inner_link = __esm({
219782
- "../../../../../setup-pnpm/store/v11/links/@/is-inner-link/5.0.0/72b7eb44d56e1666d7ca026d99a5fb2fb1b7840dde1a66e0e9ee7e333683e310/node_modules/is-inner-link/index.js"() {
219786
+ "../../../../../setup-pnpm/store/v11/links/@/is-inner-link/5.0.0/cce13b91443927cfbdb861aaaa9ef4ad3c89350d4dca46d5b1dafb56bb24e74a/node_modules/is-inner-link/index.js"() {
219783
219787
  init_is_subdir();
219784
219788
  init_resolve_link_target();
219785
219789
  }
@@ -230477,7 +230481,7 @@ var init_lib147 = __esm({
230477
230481
  });
230478
230482
 
230479
230483
  // ../deps/status/lib/assertLockfilesEqual.js
230480
- function assertLockfilesEqual(currentLockfile, wantedLockfile, wantedLockfileDir) {
230484
+ function assertLockfilesEqual(currentLockfile, wantedLockfile, opts3) {
230481
230485
  if (!currentLockfile) {
230482
230486
  for (const [name, snapshot] of Object.entries(wantedLockfile.importers)) {
230483
230487
  if (!equals_default(snapshot.specifiers, {})) {
@@ -230486,12 +230490,17 @@ function assertLockfilesEqual(currentLockfile, wantedLockfile, wantedLockfileDir
230486
230490
  });
230487
230491
  }
230488
230492
  }
230489
- } else if (!equals_default(currentLockfile, wantedLockfile)) {
230490
- throw new PnpmError("RUN_CHECK_DEPS_OUTDATED_DEPS", `The installed dependencies in the modules directory is not up-to-date with the lockfile in ${wantedLockfileDir}.`, {
230493
+ } else if (!equals_default(currentLockfile, wantedLockfile) && !(opts3.filteredInstall === true && recordsSubsetOfPackages(currentLockfile, wantedLockfile))) {
230494
+ throw new PnpmError("RUN_CHECK_DEPS_OUTDATED_DEPS", `The installed dependencies in the modules directory is not up-to-date with the lockfile in ${opts3.wantedLockfileDir}.`, {
230491
230495
  hint: "Run `pnpm install` to update dependencies."
230492
230496
  });
230493
230497
  }
230494
230498
  }
230499
+ function recordsSubsetOfPackages(currentLockfile, wantedLockfile) {
230500
+ const { packages: currentPackages, ...currentRest } = currentLockfile;
230501
+ const { packages: wantedPackages, ...wantedRest } = wantedLockfile;
230502
+ return equals_default(currentRest, wantedRest) && Object.entries(currentPackages ?? {}).every(([depPath, pkg]) => equals_default(pkg, wantedPackages?.[depPath]));
230503
+ }
230495
230504
  var init_assertLockfilesEqual = __esm({
230496
230505
  "../deps/status/lib/assertLockfilesEqual.js"() {
230497
230506
  "use strict";
@@ -230860,6 +230869,16 @@ async function _checkDepsStatus(opts3, workspaceState) {
230860
230869
  workspaceState
230861
230870
  };
230862
230871
  }
230872
+ if (selectedProjectDirs != null) {
230873
+ const notInstalled = await findProjectMissingFromCurrentLockfile(allProjects.filter((project) => selectedProjectDirs.has(path184.resolve(project.rootDir)) && declaresDependencies(project)), createCurrentLockfileLocator({ ...opts3, workspaceDir }));
230874
+ if (notInstalled != null) {
230875
+ return {
230876
+ upToDate: false,
230877
+ issue: `Workspace package ${notInstalled.manifest.name ?? notInstalled.rootDir} has dependencies but was not installed`,
230878
+ workspaceState
230879
+ };
230880
+ }
230881
+ }
230863
230882
  }
230864
230883
  const issue = await patchesOrHooksAreModified({
230865
230884
  patchedDependencies,
@@ -230914,7 +230933,10 @@ async function _checkDepsStatus(opts3, workspaceState) {
230914
230933
  if (modifiedAtOrAfter(wantedLockfileStats, workspaceState.lastValidatedTimestamp)) {
230915
230934
  const currentLockfile = await readCurrentLockfile(path184.join(workspaceDir, "node_modules/.pnpm"), { ignoreIncompatible: false });
230916
230935
  const wantedLockfile = await wantedLockfilePromise ?? throwLockfileNotFound(workspaceDir);
230917
- assertLockfilesEqual(currentLockfile, wantedLockfile, workspaceDir);
230936
+ assertLockfilesEqual(currentLockfile, wantedLockfile, {
230937
+ wantedLockfileDir: workspaceDir,
230938
+ filteredInstall: workspaceState.filteredInstall
230939
+ });
230918
230940
  }
230919
230941
  readWantedLockfileAndDir = async () => ({
230920
230942
  wantedLockfile: await wantedLockfilePromise ?? throwLockfileNotFound(workspaceDir),
@@ -230934,7 +230956,10 @@ async function _checkDepsStatus(opts3, workspaceState) {
230934
230956
  if (modifiedAtOrAfter(wantedLockfileStats, workspaceState.lastValidatedTimestamp)) {
230935
230957
  const currentLockfile = await readCurrentLockfile(path184.join(wantedLockfileDir, "node_modules/.pnpm"), { ignoreIncompatible: false });
230936
230958
  const wantedLockfile = await wantedLockfilePromise ?? throwLockfileNotFound(wantedLockfileDir);
230937
- assertLockfilesEqual(currentLockfile, wantedLockfile, wantedLockfileDir);
230959
+ assertLockfilesEqual(currentLockfile, wantedLockfile, {
230960
+ wantedLockfileDir,
230961
+ filteredInstall: workspaceState.filteredInstall
230962
+ });
230938
230963
  }
230939
230964
  return {
230940
230965
  wantedLockfile: await wantedLockfilePromise ?? throwLockfileNotFound(wantedLockfileDir),
@@ -231042,7 +231067,7 @@ async function _checkDepsStatus(opts3, workspaceState) {
231042
231067
  if (!wantedLockfileIsMissing && currentLockfileStats && modifiedAtOrAfter(wantedLockfileStats, currentLockfileStats.mtime.valueOf())) {
231043
231068
  const currentLockfile = await currentLockfilePromise;
231044
231069
  const wantedLockfile = await wantedLockfilePromise ?? throwLockfileNotFound(rootProjectManifestDir);
231045
- assertLockfilesEqual(currentLockfile, wantedLockfile, rootProjectManifestDir);
231070
+ assertLockfilesEqual(currentLockfile, wantedLockfile, { wantedLockfileDir: rootProjectManifestDir });
231046
231071
  }
231047
231072
  if (!manifestStats) {
231048
231073
  throw new Error(`Cannot find one of ${MANIFEST_BASE_NAMES.join(", ")} in ${rootProjectManifestDir}`);
@@ -231357,6 +231382,42 @@ function missingModulesDirIssue(project) {
231357
231382
  const id2 = project.manifest.name ?? project.rootDir;
231358
231383
  return `Workspace package ${id2} has dependencies but does not have a modules directory`;
231359
231384
  }
231385
+ function declaresDependencies(project) {
231386
+ return DEPENDENCIES_FIELDS.some((field) => !isEmpty_default(project.manifest[field] ?? {}));
231387
+ }
231388
+ function createCurrentLockfileLocator(opts3) {
231389
+ if (opts3.sharedWorkspaceLockfile) {
231390
+ const lockfileDir = opts3.lockfileDir ?? opts3.workspaceDir;
231391
+ const virtualStoreDir = path184.join(path184.resolve(lockfileDir, opts3.modulesDir ?? "node_modules"), ".pnpm");
231392
+ return (project) => ({ virtualStoreDir, importerId: getLockfileImporterId(lockfileDir, project.rootDir) });
231393
+ }
231394
+ const modulesDirOf2 = createProjectModulesDirResolver(opts3);
231395
+ return (project) => ({
231396
+ virtualStoreDir: path184.join(path184.resolve(project.rootDir, modulesDirOf2(project.manifest.name) ?? "node_modules"), ".pnpm"),
231397
+ importerId: "."
231398
+ });
231399
+ }
231400
+ async function findProjectMissingFromCurrentLockfile(projects, locateCurrentLockfile) {
231401
+ const currentLockfiles = /* @__PURE__ */ new Map();
231402
+ for (const project of projects) {
231403
+ const { virtualStoreDir, importerId } = locateCurrentLockfile(project);
231404
+ if (!currentLockfiles.has(virtualStoreDir)) {
231405
+ currentLockfiles.set(virtualStoreDir, readCurrentLockfile(virtualStoreDir, { ignoreIncompatible: false }));
231406
+ }
231407
+ const currentLockfile = await currentLockfiles.get(virtualStoreDir);
231408
+ const importer = currentLockfile?.importers[importerId];
231409
+ if (importer == null || !directDependenciesRecorded(importer, currentLockfile?.packages ?? {})) {
231410
+ return project;
231411
+ }
231412
+ }
231413
+ return void 0;
231414
+ }
231415
+ function directDependenciesRecorded(importer, packages) {
231416
+ return DEPENDENCIES_FIELDS.every((field) => Object.entries(importer[field] ?? {}).every(([alias, ref]) => {
231417
+ const depPath = refToRelative(ref, alias);
231418
+ return depPath == null || packages[depPath] != null;
231419
+ }));
231420
+ }
231360
231421
  function selectProjectDirs(opts3) {
231361
231422
  if (opts3.selectedProjectsGraph != null) {
231362
231423
  return new Set(Object.keys(opts3.selectedProjectsGraph).map((dir) => path184.resolve(dir)));
@@ -231376,6 +231437,7 @@ var init_checkDepsStatus = __esm({
231376
231437
  init_lib85();
231377
231438
  init_lib2();
231378
231439
  init_lib90();
231440
+ init_lib43();
231379
231441
  init_lib3();
231380
231442
  init_lib138();
231381
231443
  init_lib114();
@@ -305837,6 +305899,7 @@ var init_hiddenScripts = __esm({
305837
305899
  });
305838
305900
 
305839
305901
  // ../exec/commands/lib/runDepsStatusCheck.js
305902
+ import { existsSync as existsSync6 } from "node:fs";
305840
305903
  import fs139 from "node:fs/promises";
305841
305904
  import os22 from "node:os";
305842
305905
  import path230 from "node:path";
@@ -305844,7 +305907,7 @@ async function runDepsStatusCheck(opts3) {
305844
305907
  const ignoredWorkspaceStateSettings = ["dev", "optional", "production"];
305845
305908
  opts3.ignoredWorkspaceStateSettings = ignoredWorkspaceStateSettings;
305846
305909
  const { upToDate, issue, workspaceState } = await checkDepsStatus(opts3);
305847
- if (!needsInstall(upToDate, opts3))
305910
+ if (await installNotRequired(opts3, upToDate, workspaceState))
305848
305911
  return;
305849
305912
  const command = ["install", ...createInstallArgs(workspaceState?.settings), ...createFilterArgs(opts3)];
305850
305913
  const install2 = lockedInstall.bind(null, opts3, command);
@@ -305903,6 +305966,55 @@ function needsInstall(upToDate, opts3) {
305903
305966
  return false;
305904
305967
  return upToDate === false || opts3.allProjects != null || opts3.rootProjectManifest != null;
305905
305968
  }
305969
+ async function installNotRequired(opts3, upToDate, workspaceState) {
305970
+ if (!needsInstall(upToDate, opts3))
305971
+ return true;
305972
+ if (workspaceState != null)
305973
+ return false;
305974
+ return projectsHaveNothingToInstall(opts3);
305975
+ }
305976
+ async function projectsHaveNothingToInstall(opts3) {
305977
+ if (opts3.pnpmfile.length > 0 || lockfileDirIsPinned(opts3))
305978
+ return false;
305979
+ try {
305980
+ return await coveredProjectsHaveNothingToInstall(opts3);
305981
+ } catch {
305982
+ return false;
305983
+ }
305984
+ }
305985
+ function lockfileDirIsPinned(opts3) {
305986
+ if (opts3.lockfileDir == null)
305987
+ return false;
305988
+ const defaultLockfileDir = opts3.sharedWorkspaceLockfile === false ? opts3.dir : opts3.workspaceDir ?? opts3.dir;
305989
+ return path230.resolve(opts3.lockfileDir) !== path230.resolve(defaultLockfileDir);
305990
+ }
305991
+ async function coveredProjectsHaveNothingToInstall(opts3) {
305992
+ if (opts3.sharedWorkspaceLockfile === false && opts3.workspaceDir != null && opts3.allProjects == null) {
305993
+ const manifest = await safeReadProjectManifestOnly(opts3.dir);
305994
+ return manifest == null || !(projectHasInstallWork(opts3.dir, manifest, opts3) || path230.resolve(opts3.dir) === path230.resolve(opts3.workspaceDir) && runsScript(manifest, "pnpm:devPreinstall", opts3));
305995
+ }
305996
+ const root = opts3.rootProjectManifest;
305997
+ if (root != null && opts3.rootProjectManifestDir != null && (projectHasInstallWork(opts3.rootProjectManifestDir, root, opts3) || runsScript(root, "pnpm:devPreinstall", opts3)))
305998
+ return false;
305999
+ const projects = opts3.allProjects ?? (opts3.workspaceDir == null ? [] : await findWorkspaceProjectsNoCheck(opts3.workspaceDir, {
306000
+ patterns: opts3.workspacePackagePatterns ?? ["."],
306001
+ modulesDir: opts3.modulesDir,
306002
+ modulesDirsByProjectName: opts3.modulesDirsByProjectName
306003
+ }));
306004
+ return projects.every(({ rootDir, manifest }) => !projectHasInstallWork(rootDir, manifest, opts3));
306005
+ }
306006
+ function projectHasInstallWork(rootDir, manifest, opts3) {
306007
+ return [manifest.dependencies, manifest.devDependencies, manifest.optionalDependencies].some((group) => group != null && Object.keys(group).length > 0) || opts3.autoInstallPeers === true && hasRequiredPeers(manifest) || PROJECT_LIFECYCLE_STAGES.some((stage) => runsScript(manifest, stage, opts3)) || !opts3.ignoreScripts && hasImplicitGypBuild(rootDir, manifest);
306008
+ }
306009
+ function hasRequiredPeers(manifest) {
306010
+ return Object.keys(manifest.peerDependencies ?? {}).some((name) => manifest.peerDependenciesMeta?.[name]?.optional !== true);
306011
+ }
306012
+ function runsScript(manifest, stage, opts3) {
306013
+ return !opts3.ignoreScripts && manifest.scripts?.[stage] != null;
306014
+ }
306015
+ function hasImplicitGypBuild(rootDir, manifest) {
306016
+ return manifest.gypfile !== false && existsSync6(path230.join(rootDir, "binding.gyp"));
306017
+ }
305906
306018
  async function lockedInstall(opts3, command) {
305907
306019
  refuseInstallDroppingIgnoredSettings(opts3);
305908
306020
  const root = opts3.workspaceDir ?? opts3.dir;
@@ -305922,7 +306034,7 @@ async function lockedInstall(opts3, command) {
305922
306034
  try {
305923
306035
  if (waited) {
305924
306036
  const { upToDate, workspaceState } = await checkDepsStatus(opts3);
305925
- if (!needsInstall(upToDate, opts3))
306037
+ if (await installNotRequired(opts3, upToDate, workspaceState))
305926
306038
  return;
305927
306039
  command = ["install", ...createInstallArgs(workspaceState?.settings), ...createFilterArgs(opts3)];
305928
306040
  }
@@ -305975,9 +306087,12 @@ var init_runDepsStatusCheck = __esm({
305975
306087
  init_lib42();
305976
306088
  init_lib148();
305977
306089
  init_lib3();
306090
+ init_lib27();
305978
306091
  init_lib178();
305979
306092
  init_lib115();
305980
306093
  init_lib4();
306094
+ init_lib18();
306095
+ init_lib61();
305981
306096
  init_realpath_missing();
305982
306097
  INSTALL_LOCK_NAMESPACE = "pnpm-verify-deps-install-locks";
305983
306098
  INSTALL_LOCK_WAIT_MS = 5 * 6e4;
package/dist/worker.js CHANGED
@@ -11538,13 +11538,17 @@ import crypto4 from "node:crypto";
11538
11538
  import fs8, {} from "node:fs";
11539
11539
  import path8 from "node:path";
11540
11540
 
11541
- // ../../../../../setup-pnpm/store/v11/links/@/is-subdir/2.0.0/86b3cd44735afb9f459dad7b43ddfc23f1a21495323a3fb38b9ab590c29f23ce/node_modules/is-subdir/index.js
11541
+ // ../../../../../setup-pnpm/store/v11/links/@/is-subdir/2.0.1/930a5285b376d962304fd10a15f6382f59e4b31eb7c98b5f184535f0320114ee/node_modules/is-subdir/index.js
11542
11542
  import path6 from "node:path";
11543
11543
  function isSubdir(parentDir, subdir) {
11544
- const rParent = `${betterPathResolve(parentDir)}${path6.sep}`;
11545
- const rDir = `${betterPathResolve(subdir)}${path6.sep}`;
11544
+ const rParent = resolveWithTrailingSep(parentDir);
11545
+ const rDir = resolveWithTrailingSep(subdir);
11546
11546
  return rDir.startsWith(rParent);
11547
11547
  }
11548
+ function resolveWithTrailingSep(dir) {
11549
+ const resolved = betterPathResolve(dir);
11550
+ return resolved.endsWith(path6.sep) ? resolved : `${resolved}${path6.sep}`;
11551
+ }
11548
11552
 
11549
11553
  // ../../../../../setup-pnpm/store/v11/links/@/strip-bom/5.0.0/c5abc9f591760d7581de2026bc6da7f255db82a0b75d02fcc6cebf460005b3e6/node_modules/strip-bom/index.js
11550
11554
  function stripBom(string) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pnpm",
3
- "version": "11.28.1",
3
+ "version": "11.28.2",
4
4
  "description": "Fast, disk space efficient package manager",
5
5
  "keywords": [
6
6
  "pnpm",