@pnpm/workspace.root-finder 1100.0.8 → 1100.0.9

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,11 @@
1
1
  # @pnpm/workspace.root-finder
2
2
 
3
+ ## 1100.0.9
4
+
5
+ ### Patch Changes
6
+
7
+ - A command run in a project that the workspace does not include now acts on that project alone. A project is outside the workspace when it has a manifest of its own and no pattern in the `packages` setting selects it, or when a `!` pattern excludes it. A directory with no manifest of its own, such as a package's source directory, still belongs to the workspace. `pnpm install` in an excluded project used to install every project in the workspace [#3561](https://github.com/pnpm/pnpm/issues/3561).
8
+
3
9
  ## 1100.0.8
4
10
 
5
11
  ### Patch Changes
package/lib/index.js CHANGED
@@ -1,7 +1,12 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
+ import util from 'node:util';
4
+ import { MANIFEST_BASE_NAMES } from '@pnpm/constants';
3
5
  import { PnpmError } from '@pnpm/error';
6
+ import { isWorkspaceProjectDir } from '@pnpm/workspace.package-patterns';
7
+ import { readWorkspaceManifest } from '@pnpm/workspace.workspace-manifest-reader';
4
8
  import * as find from 'empathic/find';
9
+ const MANIFEST_BASE_NAMES_SET = new Set(MANIFEST_BASE_NAMES);
5
10
  const WORKSPACE_DIR_ENV_VAR = 'NPM_CONFIG_WORKSPACE_DIR';
6
11
  const WORKSPACE_MANIFEST_FILENAME = 'pnpm-workspace.yaml';
7
12
  const INVALID_WORKSPACE_MANIFEST_FILENAME = [
@@ -15,13 +20,47 @@ const INVALID_WORKSPACE_MANIFEST_FILENAME = [
15
20
  ];
16
21
  export async function findWorkspaceDir(cwd) {
17
22
  const workspaceManifestDirEnvVar = process.env[WORKSPACE_DIR_ENV_VAR] ?? process.env[WORKSPACE_DIR_ENV_VAR.toLowerCase()];
18
- const workspaceManifestLocation = workspaceManifestDirEnvVar
19
- ? path.join(workspaceManifestDirEnvVar, WORKSPACE_MANIFEST_FILENAME)
20
- : find.any([WORKSPACE_MANIFEST_FILENAME, ...INVALID_WORKSPACE_MANIFEST_FILENAME], { cwd: await getRealPath(cwd) });
21
- if (workspaceManifestLocation && path.basename(workspaceManifestLocation) !== WORKSPACE_MANIFEST_FILENAME) {
23
+ if (workspaceManifestDirEnvVar) {
24
+ return path.dirname(path.join(workspaceManifestDirEnvVar, WORKSPACE_MANIFEST_FILENAME));
25
+ }
26
+ const realCwd = await getRealPath(cwd);
27
+ const workspaceManifestLocation = find.any([WORKSPACE_MANIFEST_FILENAME, ...INVALID_WORKSPACE_MANIFEST_FILENAME], { cwd: realCwd });
28
+ if (!workspaceManifestLocation)
29
+ return undefined;
30
+ if (path.basename(workspaceManifestLocation) !== WORKSPACE_MANIFEST_FILENAME) {
22
31
  throw new PnpmError('BAD_WORKSPACE_MANIFEST_NAME', `The workspace manifest file should be named "pnpm-workspace.yaml". File found: ${workspaceManifestLocation}`);
23
32
  }
24
- return workspaceManifestLocation && path.dirname(workspaceManifestLocation);
33
+ const workspaceDir = path.dirname(workspaceManifestLocation);
34
+ return await belongsToWorkspace(workspaceDir, realCwd) ? workspaceDir : undefined;
35
+ }
36
+ /**
37
+ * A project that the workspace does not include stands on its own, so pnpm
38
+ * runs it as a standalone project instead of acting on the whole workspace
39
+ * (https://github.com/pnpm/pnpm/issues/3561).
40
+ *
41
+ * A directory without a manifest of its own is not such a project. It is some
42
+ * place inside the workspace, like a package's source directory, and a command
43
+ * run from there still acts on the workspace.
44
+ */
45
+ async function belongsToWorkspace(workspaceDir, dir) {
46
+ if (path.relative(workspaceDir, dir) === '' || !await hasProjectManifest(dir))
47
+ return true;
48
+ const workspaceManifest = await readWorkspaceManifest(workspaceDir);
49
+ return isWorkspaceProjectDir({ workspaceDir, dir, patterns: workspaceManifest?.packages ?? ['.'] });
50
+ }
51
+ async function hasProjectManifest(dir) {
52
+ let entries;
53
+ try {
54
+ entries = await fs.promises.readdir(dir);
55
+ }
56
+ catch (err) {
57
+ // The directory pnpm was pointed at may not exist. Reporting that is the
58
+ // job of the command that needs it, not of the workspace lookup.
59
+ if (util.types.isNativeError(err) && 'code' in err && (err.code === 'ENOENT' || err.code === 'ENOTDIR'))
60
+ return false;
61
+ throw err;
62
+ }
63
+ return entries.some((entry) => MANIFEST_BASE_NAMES_SET.has(entry));
25
64
  }
26
65
  async function getRealPath(path) {
27
66
  return new Promise((resolve) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pnpm/workspace.root-finder",
3
- "version": "1100.0.8",
3
+ "version": "1100.0.9",
4
4
  "description": "Finds the root of a pnpm workspace",
5
5
  "keywords": [
6
6
  "pnpm",
@@ -27,12 +27,16 @@
27
27
  "!*.map"
28
28
  ],
29
29
  "dependencies": {
30
+ "@pnpm/constants": "1102.0.0",
30
31
  "@pnpm/error": "1100.1.4",
31
- "empathic": "^2.0.1"
32
+ "@pnpm/workspace.package-patterns": "1100.0.0",
33
+ "@pnpm/workspace.workspace-manifest-reader": "1100.1.9",
34
+ "empathic": "^2.1.0"
32
35
  },
33
36
  "devDependencies": {
34
37
  "@jest/globals": "30.4.1",
35
- "@pnpm/workspace.root-finder": "1100.0.8"
38
+ "@pnpm/workspace.root-finder": "1100.0.9",
39
+ "tempy": "3.0.0"
36
40
  },
37
41
  "engines": {
38
42
  "node": ">=22.13"