|
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'; |
9 | 4 |
|
10 | 5 | export default {
|
11 |
| - utils: {getPackages}, |
| 6 | + utils: {getProjects}, |
12 | 7 | rules: {
|
13 | 8 | 'scope-enum': (ctx) =>
|
14 |
| - getPackages(ctx).then((packages) => [2, 'always', packages]), |
| 9 | + getProjects(ctx).then((packages) => [2, 'always', packages]), |
15 | 10 | },
|
16 | 11 | };
|
17 | 12 |
|
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 | +} |
27 | 26 |
|
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 | + }); |
32 | 36 |
|
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 | + } |
35 | 48 |
|
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 | + }); |
40 | 54 |
|
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 | + ); |
47 | 60 |
|
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) || {}); |
57 | 62 | }
|
58 | 63 |
|
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(); |
70 | 79 | }
|
0 commit comments