Skip to content

Commit f412600

Browse files
committed
fix(config-lerna-scopes): remove deprecated @lerna/project dependency
1 parent 73f23f9 commit f412600

File tree

33 files changed

+3090
-3778
lines changed

33 files changed

+3090
-3778
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
{
2-
"lerna": "4",
32
"version": "1.0.0",
43
"packages": ["packages/*"]
54
}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
{
22
"name": "basic",
3-
"version": "1.0.0",
4-
"devDependencies": {
5-
"lerna": "^4.0.0",
6-
"@lerna/project": "^4.0.0"
7-
}
3+
"version": "1.0.0"
84
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"name": "a",
2+
"name": "@commitlint-lerna-scopes/basic-a",
33
"version": "1.0.0"
44
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"name": "b",
2+
"name": "@commitlint-lerna-scopes/basic-b",
33
"version": "1.0.0"
44
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
{
2-
"lerna": "4",
32
"version": "1.0.0",
43
"packages": ["packages/*"]
54
}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
{
22
"name": "empty",
3-
"version": "1.0.0",
4-
"devDependencies": {
5-
"lerna": "^4.0.0",
6-
"@lerna/project": "^4.0.0"
7-
}
3+
"version": "1.0.0"
84
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
{
2-
"lerna": "4",
32
"version": "1.0.0",
43
"packages": ["packages/*"]
54
}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
{
22
"name": "basic",
3-
"version": "1.0.0",
4-
"devDependencies": {
5-
"lerna": "^4.0.0",
6-
"@lerna/project": "^4.0.0"
7-
}
3+
"version": "1.0.0"
84
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"name": "a",
2+
"name": "@commitlint-lerna-scopes/modules-a",
33
"version": "1.0.0"
44
}

@commitlint/config-lerna-scopes/fixtures/nested-workspaces/@packages/a/nested-a/node_modules/dependency-a/package.json

-4
This file was deleted.

@commitlint/config-lerna-scopes/fixtures/nested-workspaces/@packages/a/nested-a/package.json

-4
This file was deleted.

@commitlint/config-lerna-scopes/fixtures/nested-workspaces/@packages/b/nested-b/node_modules/dependency-b/package.json

-4
This file was deleted.

@commitlint/config-lerna-scopes/fixtures/nested-workspaces/@packages/b/nested-b/package.json

-4
This file was deleted.

@commitlint/config-lerna-scopes/fixtures/nested-workspaces/package.json

-11
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"version": "1.0.0",
3+
"packages": ["packages/**"]
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "nested-workspaces",
3+
"version": "1.0.0"
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "@commitlint-lerna-scopes/nested-a",
3+
"version": "1.0.0"
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "@commitlint-lerna-scopes/nested-b",
3+
"version": "1.0.0"
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "@commitlint-lerna-scopes/nested-c",
3+
"version": "1.0.0"
4+
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
{
2-
"name": "@packages/a",
32
"version": "1.0.0"
43
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "no-packages-declaration",
3+
"version": "1.0.0",
4+
"workspaces": ["./packages/*"]
5+
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"name": "@packages/a",
2+
"name": "@commitlint-lerna-scopes/scoped-a",
33
"version": "1.0.0"
44
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"name": "@packages/b",
2+
"name": "@commitlint-lerna-scopes/scoped-b",
33
"version": "1.0.0"
44
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
{
2-
"lerna": "4",
32
"version": "1.0.0",
4-
"packages": ["@packages/*"]
3+
"packages": ["@packages/**"]
54
}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
{
22
"name": "scoped",
3-
"version": "1.0.0",
4-
"devDependencies": {
5-
"lerna": "^4.0.0",
6-
"@lerna/project": "^4.0.0"
7-
}
3+
"version": "1.0.0"
84
}

@commitlint/config-lerna-scopes/fixtures/yarn/@packages/b/package.json

-4
This file was deleted.

@commitlint/config-lerna-scopes/fixtures/yarn/package.json

-11
This file was deleted.
+64-55
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,79 @@
1-
import {createRequire} from 'module';
2-
import Path from 'path';
3-
4-
import {globSync} from 'glob';
5-
import importFrom from 'import-from';
6-
import semver from 'semver';
7-
8-
const require = createRequire(import.meta.url);
1+
import path from 'node:path';
2+
import fs from 'node:fs/promises';
3+
import fg from 'fast-glob';
94

105
export default {
11-
utils: {getPackages},
6+
utils: {getProjects},
127
rules: {
138
'scope-enum': (ctx) =>
14-
getPackages(ctx).then((packages) => [2, 'always', packages]),
9+
getProjects(ctx).then((packages) => [2, 'always', packages]),
1510
},
1611
};
1712

18-
function getPackages(context) {
19-
return Promise.resolve()
20-
.then(() => {
21-
const ctx = context || {};
22-
const cwd = ctx.cwd || process.cwd();
23-
24-
const {workspaces} = require(Path.join(cwd, 'package.json'));
25-
if (Array.isArray(workspaces) && workspaces.length) {
26-
// use yarn workspaces
13+
/**
14+
* Turn glob paths with potential 'package.json' ending always into paths
15+
* with a package.json ending to find monorepo packages
16+
* @param {string[]} patterns
17+
* @returns A list of glob paths to resolve package.json files
18+
*/
19+
function normalizePatterns(patterns) {
20+
const normalizedPatterns = [];
21+
for (const pattern of patterns) {
22+
normalizedPatterns.push(pattern.replace(/\/?$/, '/package.json'));
23+
}
24+
return normalizedPatterns;
25+
}
2726

28-
const wsGlobs = workspaces.flatMap((ws) => {
29-
const path = Path.posix.join(ws, 'package.json');
30-
return globSync(path, {cwd, ignore: ['**/node_modules/**']});
31-
});
27+
/**
28+
* Find all package.json contents in the defined cwd
29+
* @param {string} cwd
30+
* @returns A list of parsed package.json files as objects
31+
*/
32+
async function findPackages(cwd) {
33+
const json = await fs.readFile(path.join(cwd, 'lerna.json'), {
34+
encoding: 'utf-8',
35+
});
3236

33-
return wsGlobs.map((pJson) => require(Path.join(cwd, pJson)));
34-
}
37+
const packages = JSON.parse(json)?.packages || [];
38+
if (packages.length === 0) {
39+
console.warn(
40+
[
41+
`The lerna.json configuration is missing a valid "packages" field. To fix this issue you should either:`,
42+
` - define one or more paths within the "packages" field in lerna.json`,
43+
` - use the "@commitlint/config-workspace-scopes" plugin if you are using npm/yarn workspaces`,
44+
].join('\n')
45+
);
46+
return [];
47+
}
3548

36-
const lernaVersion = getLernaVersion(cwd);
37-
if (semver.lt(lernaVersion, '3.0.0')) {
38-
const Repository = importFrom(cwd, 'lerna/lib/Repository');
39-
const PackageUtilities = importFrom(cwd, 'lerna/lib/PackageUtilities');
49+
const patterns = normalizePatterns(packages);
50+
const entries = await fg(patterns, {
51+
cwd,
52+
ignore: ['**/node_modules/**', '**/bower_components/**'],
53+
});
4054

41-
const repository = new Repository(cwd);
42-
return PackageUtilities.getPackages({
43-
packageConfigs: repository.packageConfigs,
44-
rootPath: cwd,
45-
});
46-
}
55+
const pkgJsons = await Promise.all(
56+
Array.from(new Set(entries.map((entry) => path.join(cwd, entry)))).map(
57+
(pkgPath) => fs.readFile(pkgPath, {encoding: 'utf-8'})
58+
)
59+
);
4760

48-
const {getPackages} = importFrom(cwd, '@lerna/project');
49-
return getPackages(cwd);
50-
})
51-
.then((packages) => {
52-
return packages
53-
.map((pkg) => pkg.name)
54-
.filter(Boolean)
55-
.map((name) => (name.charAt(0) === '@' ? name.split('/')[1] : name));
56-
});
61+
return pkgJsons.map((pkgJson) => JSON.parse(pkgJson) || {});
5762
}
5863

59-
function getLernaVersion(cwd) {
60-
const moduleEntrypoint = require.resolve('lerna', {
61-
paths: [cwd],
62-
});
63-
const moduleDir = Path.join(
64-
moduleEntrypoint.slice(0, moduleEntrypoint.lastIndexOf('node_modules')),
65-
'node_modules',
66-
'lerna'
67-
);
68-
const modulePackageJson = Path.join(moduleDir, 'package.json');
69-
return require(modulePackageJson).version;
64+
async function getProjects(context) {
65+
const ctx = context || {};
66+
const cwd = ctx.cwd || process.cwd();
67+
68+
const packages = await findPackages(cwd);
69+
70+
return packages
71+
.reduce((pkgNames, pkg) => {
72+
const name = pkg.name;
73+
if (name) {
74+
pkgNames.push(name.charAt(0) === '@' ? name.split('/')[1] : name);
75+
}
76+
return pkgNames;
77+
}, [])
78+
.sort();
7079
}

@commitlint/config-lerna-scopes/index.test.js

+20-16
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {test, expect} from 'vitest';
1+
import {test, expect, vi} from 'vitest';
22
import path from 'path';
33
import {fileURLToPath} from 'url';
44

@@ -58,44 +58,48 @@ test('returns empty value for empty lerna repository', async () => {
5858
expect(value).toEqual([]);
5959
});
6060

61+
test('returns all packages for nested lerna packages repository', async () => {
62+
const {'scope-enum': fn} = config.rules;
63+
const cwd = await npm.bootstrap('fixtures/nested', __dirname);
64+
const [, , value] = await fn({cwd});
65+
expect(value).toEqual(['nested-a', 'nested-b', 'nested-c']);
66+
});
67+
6168
test('returns expected value for basic lerna repository', async () => {
6269
const {'scope-enum': fn} = config.rules;
6370
const cwd = await npm.bootstrap('fixtures/basic', __dirname);
6471

6572
const [, , value] = await fn({cwd});
66-
expect(value).toEqual(['a', 'b']);
73+
expect(value).toEqual(['basic-a', 'basic-b']);
6774
});
6875

6976
test('returns expected value for lerna repository containing modules', async () => {
7077
const {'scope-enum': fn} = config.rules;
7178
const cwd = await npm.bootstrap('fixtures/modules', __dirname);
7279

7380
const [, , value] = await fn({cwd});
74-
expect(value).toEqual(['a']);
81+
expect(value).toEqual(['modules-a']);
7582
});
7683

7784
test('returns expected value for scoped lerna repository', async () => {
7885
const {'scope-enum': fn} = config.rules;
7986
const cwd = await npm.bootstrap('fixtures/scoped', __dirname);
8087

8188
const [, , value] = await fn({cwd});
82-
expect(value).toEqual(['a', 'b']);
89+
expect(value).toEqual(['scoped-a', 'scoped-b']);
8390
});
8491

85-
test('returns expected value for yarn workspaces', async () => {
92+
test('shows a warning for missing packages declaration in lerna.json', async () => {
8693
const {'scope-enum': fn} = config.rules;
87-
const cwd = path.join(__dirname, 'fixtures', 'yarn');
88-
const [, , value] = await fn({cwd});
89-
expect(value.sort()).toEqual(['a', 'b']);
90-
});
94+
const cwd = await npm.bootstrap(
95+
'fixtures/no-packages-declaration',
96+
__dirname
97+
);
98+
const consoleWarnSpy = vi.spyOn(console, 'warn');
9199

92-
test('returns expected value for yarn workspaces has nested packages', async () => {
93-
const {'scope-enum': fn} = config.rules;
94-
const cwd = await npm.bootstrap('fixtures/nested-workspaces', __dirname);
100+
await fn({cwd});
95101

96-
const [, , value] = await fn({cwd});
97-
expect(value).toEqual(expect.arrayContaining(['nested-a', 'nested-b']));
98-
expect(value).toEqual(
99-
expect.not.arrayContaining(['dependency-a', 'dependency-b'])
102+
expect(consoleWarnSpy).toHaveBeenCalledWith(
103+
expect.stringContaining(`is missing a valid "packages" field`)
100104
);
101105
});

0 commit comments

Comments
 (0)