Skip to content

Commit 689a79f

Browse files
authored
Support pnpm workspaces (#574)
1 parent 99a4f7d commit 689a79f

File tree

11 files changed

+84
-0
lines changed

11 files changed

+84
-0
lines changed

lib/package.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { existsSync, readFileSync } from 'node:fs';
22
import { join, relative } from 'node:path';
33
import { PackageJson } from 'type-fest';
4+
import { load } from 'js-yaml';
45

56
// Class to represent all of the information we need to know about a package in a workspace.
67
export class Package {
@@ -9,14 +10,27 @@ export class Package {
910
pathPackageJson: string; // Absolute path to package.json.
1011
packageJson: PackageJson;
1112
packageJsonEndsInNewline: boolean;
13+
pnpmWorkspacePackages?: string[];
1214

1315
constructor(path: string, pathWorkspace: string) {
1416
this.path = path;
1517
this.pathWorkspace = pathWorkspace;
18+
19+
// package.json
1620
this.pathPackageJson = join(path, 'package.json');
1721
const packageJsonContents = readFileSync(this.pathPackageJson, 'utf8');
1822
this.packageJsonEndsInNewline = packageJsonContents.endsWith('\n');
1923
this.packageJson = JSON.parse(packageJsonContents);
24+
25+
// pnpm-workspace.yaml
26+
const pnpmWorkspacePath = join(path, 'pnpm-workspace.yaml');
27+
if (existsSync(pnpmWorkspacePath)) {
28+
const pnpmWorkspaceContents = readFileSync(pnpmWorkspacePath, 'utf8');
29+
const pnpmWorkspaceYaml = load(pnpmWorkspaceContents) as {
30+
packages?: string[];
31+
};
32+
this.pnpmWorkspacePackages = pnpmWorkspaceYaml.packages;
33+
}
2034
}
2135

2236
get name() {
@@ -49,6 +63,16 @@ export class Package {
4963
throw new TypeError('package.json `workspaces` is not a string array.');
5064
}
5165
}
66+
67+
if (this.pnpmWorkspacePackages) {
68+
if (!Array.isArray(this.pnpmWorkspacePackages)) {
69+
throw new TypeError(
70+
'pnpm-workspace.yaml `packages` is not a string array.'
71+
);
72+
}
73+
return this.pnpmWorkspacePackages;
74+
}
75+
5276
return [];
5377
}
5478

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,12 @@
4040
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --colors --coverage"
4141
},
4242
"dependencies": {
43+
"@types/js-yaml": "^4.0.5",
4344
"chalk": "^5.0.1",
4445
"commander": "^9.0.0",
4546
"edit-json-file": "^1.7.0",
4647
"globby": "^13.1.1",
48+
"js-yaml": "^4.1.0",
4749
"semver": "^7.3.5",
4850
"table": "^6.7.1",
4951
"type-fest": "^2.1.0"

test/fixtures/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ export const FIXTURE_PATH_WORKSPACE_PACKAGE_NOT_AN_ARRAY = join(
6464
FIXTURE_PATH,
6565
'workspace-packages-not-an-array'
6666
);
67+
export const FIXTURE_PATH_WORKSPACE_PNPM = join(FIXTURE_PATH, 'workspace-pnpm');
68+
export const FIXTURE_PATH_WORKSPACE_PNPM_PACKAGES_WRONG_TYPE = join(
69+
FIXTURE_PATH,
70+
'workspace-pnpm-packages-wrong-type'
71+
);
6772
export const FIXTURE_PATH_NESTED_WORKSPACES = join(
6873
FIXTURE_PATH,
6974
'nested-workspaces'
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"name": "foo"
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"name": "package1"
3+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
packages: 'foo'
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"name": "foo"
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"name": "package1"
3+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
packages:
2+
# all packages in direct subdirs of packages/
3+
- 'packages/*'
4+
# all packages in subdirs of components/
5+
- 'components/**'
6+
# exclude packages that are inside test directories
7+
- '!**/test/**'

test/lib/workspace-test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import {
88
FIXTURE_PATH_VALID_NOHOIST_WITH_NODE_MODULES,
99
FIXTURE_PATH_WORKSPACE_NOT_AN_ARRAY,
1010
FIXTURE_PATH_WORKSPACE_PACKAGE_NOT_AN_ARRAY,
11+
FIXTURE_PATH_WORKSPACE_PNPM,
12+
FIXTURE_PATH_WORKSPACE_PNPM_PACKAGES_WRONG_TYPE,
1113
FIXTURE_PATH_NESTED_WORKSPACES,
1214
} from '../fixtures/index.js';
1315

@@ -184,6 +186,18 @@ describe('Utils | workspace', function () {
184186
);
185187
});
186188

189+
it('behaves correctly with pnpm workspaces', function () {
190+
expect(
191+
getPackages(FIXTURE_PATH_WORKSPACE_PNPM, [], [], [], []).map(
192+
(package_) => package_.path
193+
)
194+
).toStrictEqual(
195+
['.', 'packages/package1'].map((path) =>
196+
join(FIXTURE_PATH_WORKSPACE_PNPM, path)
197+
)
198+
);
199+
});
200+
187201
it('does not include packages in node_modules from nohoist usage (or crash from malformed package.json in node_modules test fixture)', function () {
188202
expect(
189203
getPackages(
@@ -231,5 +245,19 @@ describe('Utils | workspace', function () {
231245
'"package.json `workspaces.packages` is not a string array."'
232246
);
233247
});
248+
249+
it('throws with fixture that has pnpm-workspace.yaml but invalid type for packages', function () {
250+
expect(() =>
251+
getPackages(
252+
FIXTURE_PATH_WORKSPACE_PNPM_PACKAGES_WRONG_TYPE,
253+
[],
254+
[],
255+
[],
256+
[]
257+
)
258+
).toThrowErrorMatchingInlineSnapshot(
259+
'"pnpm-workspace.yaml `packages` is not a string array."'
260+
);
261+
});
234262
});
235263
});

0 commit comments

Comments
 (0)