Skip to content

Commit 0494d09

Browse files
authored
fix(misc): check for packages existence to detect pnpm workspaces setup (#32474)
## Current Behavior When detecting whether a workspace is set up with pnpm workspaces, we only check for the existence of the `pnpm-workspace.yaml` file. While most of the time that's enough, it's not entirely correct because that file can exist without a `packages` entry and solely contain other settings. ## Expected Behavior When detecting whether a workspace is set up with pnpm workspaces, we should check for the existence of the `pnpm-workspace.yaml` file and the `packages` entry.
1 parent 900bb27 commit 0494d09

File tree

6 files changed

+50
-37
lines changed

6 files changed

+50
-37
lines changed

packages/expo/src/executors/build/build.impl.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
detectPackageManager,
33
ExecutorContext,
4+
isWorkspacesEnabled,
45
names,
56
PackageManager,
67
readJsonFile,
@@ -121,11 +122,7 @@ function copyPackageJsonAndLock(
121122
const packageJson = pathResolve(workspaceRoot, 'package.json');
122123
const rootPackageJson = readJsonFile<PackageJson>(packageJson);
123124
// do not copy package.json and lock file if workspaces are enabled
124-
if (
125-
(packageManager === 'pnpm' &&
126-
existsSync(pathResolve(workspaceRoot, 'pnpm-workspace.yaml'))) ||
127-
rootPackageJson.workspaces
128-
) {
125+
if (isWorkspacesEnabled(packageManager, workspaceRoot)) {
129126
// no resource taken, no resource cleaned up
130127
return () => {};
131128
}

packages/js/src/utils/package-manager-workspaces.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,18 @@ export function isUsingPackageManagerWorkspaces(tree: Tree): boolean {
5353
export function isWorkspacesEnabled(tree: Tree): boolean {
5454
const packageManager = detectPackageManager(tree.root);
5555
if (packageManager === 'pnpm') {
56-
return tree.exists('pnpm-workspace.yaml');
56+
if (!tree.exists('pnpm-workspace.yaml')) {
57+
return false;
58+
}
59+
60+
try {
61+
const content = tree.read('pnpm-workspace.yaml', 'utf-8');
62+
const { load } = require('@zkochan/js-yaml');
63+
const { packages } = load(content) ?? {};
64+
return packages !== undefined;
65+
} catch {
66+
return false;
67+
}
5768
}
5869

5970
// yarn and npm both use the same 'workspaces' property in package.json

packages/nx/src/command-line/init/implementation/utils.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,15 @@ export function printFinalMessage({
346346
export function isMonorepo(packageJson: PackageJson) {
347347
if (!!packageJson.workspaces) return true;
348348

349-
if (existsSync('pnpm-workspace.yaml') || existsSync('pnpm-workspace.yml'))
350-
return true;
349+
try {
350+
const content = readFileSync('pnpm-workspace.yaml', 'utf-8');
351+
const { load } = require('@zkochan/js-yaml');
352+
const { packages } = load(content) ?? {};
353+
354+
if (packages) {
355+
return true;
356+
}
357+
} catch {}
351358

352359
if (existsSync('lerna.json')) return true;
353360

packages/nx/src/utils/package-manager.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { exec, execSync } from 'child_process';
2-
import { copyFileSync, existsSync, writeFileSync } from 'fs';
2+
import { copyFileSync, existsSync, readFileSync, writeFileSync } from 'fs';
33
import {
44
Pair,
55
ParsedNode,
@@ -80,7 +80,18 @@ export function isWorkspacesEnabled(
8080
root: string = workspaceRoot
8181
): boolean {
8282
if (packageManager === 'pnpm') {
83-
return existsSync(join(root, 'pnpm-workspace.yaml'));
83+
if (!existsSync(join(root, 'pnpm-workspace.yaml'))) {
84+
return false;
85+
}
86+
87+
try {
88+
const content = readFileSync(join(root, 'pnpm-workspace.yaml'), 'utf-8');
89+
const { load } = require('@zkochan/js-yaml');
90+
const { packages } = load(content) ?? {};
91+
return packages !== undefined;
92+
} catch {
93+
return false;
94+
}
8495
}
8596

8697
// yarn and npm both use the same 'workspaces' property in package.json

packages/workspace/src/utilities/package-manager-workspaces.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,18 @@ export function isUsingPackageManagerWorkspaces(tree: Tree): boolean {
3737
export function isWorkspacesEnabled(tree: Tree): boolean {
3838
const packageManager = detectPackageManager(tree.root);
3939
if (packageManager === 'pnpm') {
40-
return tree.exists('pnpm-workspace.yaml');
40+
if (!tree.exists('pnpm-workspace.yaml')) {
41+
return false;
42+
}
43+
44+
try {
45+
const content = tree.read('pnpm-workspace.yaml', 'utf-8');
46+
const { load } = require('@zkochan/js-yaml');
47+
const { packages } = load(content) ?? {};
48+
return packages !== undefined;
49+
} catch {
50+
return false;
51+
}
4152
}
4253

4354
// yarn and npm both use the same 'workspaces' property in package.json

packages/workspace/src/utilities/typescript/ts-solution-setup.ts

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,12 @@
1-
import {
2-
detectPackageManager,
3-
globAsync,
4-
readJson,
5-
type Tree,
6-
workspaceRoot,
7-
} from '@nx/devkit';
1+
import { globAsync, readJson, type Tree, workspaceRoot } from '@nx/devkit';
82
import { dirname } from 'node:path/posix';
93
import { FsTree } from 'nx/src/generators/tree';
10-
import { type PackageJson } from 'nx/src/utils/package-json';
114
import {
125
getPackageManagerWorkspacesPatterns,
136
isProjectIncludedInPackageManagerWorkspaces,
7+
isUsingPackageManagerWorkspaces,
148
} from '../package-manager-workspaces';
159

16-
function isUsingPackageManagerWorkspaces(tree: Tree): boolean {
17-
return isWorkspacesEnabled(tree);
18-
}
19-
20-
function isWorkspacesEnabled(tree: Tree): boolean {
21-
const packageManager = detectPackageManager(tree.root);
22-
if (packageManager === 'pnpm') {
23-
return tree.exists('pnpm-workspace.yaml');
24-
}
25-
26-
// yarn and npm both use the same 'workspaces' property in package.json
27-
if (tree.exists('package.json')) {
28-
const packageJson = readJson<PackageJson>(tree, 'package.json');
29-
return !!packageJson?.workspaces;
30-
}
31-
return false;
32-
}
33-
3410
/**
3511
* The TS solution setup requires:
3612
* - `tsconfig.base.json`: TS config with common compiler options needed by the

0 commit comments

Comments
 (0)