feat: merge configurations to root config

This commit is contained in:
Guz013
2023-08-04 16:10:24 -03:00
parent 4384f6143a
commit 1b2891b7ee
3 changed files with 74 additions and 9 deletions

View File

@@ -6,6 +6,7 @@ import c from 'picocolors';
import path from 'node:path';
import { createSpinner } from 'nanospinner';
import count from './lib/count.js';
import prompts from 'prompts';
export default class Cli {
@@ -54,12 +55,29 @@ export default class Cli {
return pkg;
});
spinner.success({ text:
'Detecting workspace configuration ' +
c.dim(`${count.packagesWithConfigs(packages)} configs founded`),
spinner.success({
text:
'Detecting workspace configuration ' +
c.dim(`${count.packagesWithConfigs(packages)} configs founded\n`),
});
packages = await processor.questionConfig(packages, configs.filter(c => c.manual));
const merge = this.args.mergeToRoot ?? packages.length > 1 ?
/** @type {{merge: boolean}} */
(await prompts({
name: 'merge',
message:
`Would you like to merge all configuration files into one root ${c.blue('eslint.config.js?')}` +
c.italic(c.dim('\nAll configurations will be applied to the entire workspace and packages')),
initial: true,
type: 'confirm',
})).merge : true;
console.log(c.dim('\nPlease select which options you prefer\n'));
packages = await processor.questionConfig(
merge ? workspace.mergePackages(packages) : packages,
configs.filter(c => c.manual),
);
const configsMaps = processor.generateConfigMap(packages);

View File

@@ -5,8 +5,7 @@
*/
function packagesWithConfigs(packages) {
return packages.map(p =>
Object.entries(p.config ?? {})
.filter(([, options]) => options.length > 0).length,
[...p.config?.values() ?? []].filter((options) => options.length > 0).length,
).reduce((partial, sum) => partial + sum, 0);
}

View File

@@ -59,7 +59,8 @@ export default class Workspace {
/**
* @param {string} directory - The directory to get the workspace from
* @param {string[]} [packagePatterns] - List of package patterns
* @param {string[] | false} [packagePatterns]
* List of package patterns (`false` to explicitly tell that this workspace is not a monorepo)
*/
constructor(directory, packagePatterns) {
this.dir = directory;
@@ -157,8 +158,6 @@ export default class Workspace {
async getPackages() {
const paths = await this.getPaths();
const packagePatterns = this.packagePatterns ?? await this.getPackagePatterns();
const packagePaths = paths.directories.filter(d => picomatch.isMatch(d, packagePatterns));
/** @type {import('./types').Package} */
const rootPackage = {
@@ -169,6 +168,11 @@ export default class Workspace {
directories: paths.directories,
};
if (this.packagePatterns === false) return [rootPackage];
const packagePatterns = this.packagePatterns ?? await this.getPackagePatterns();
const packagePaths = paths.directories.filter(d => picomatch.isMatch(d, packagePatterns));
/** @type {import('./types').Package[]} */
const packages = [];
@@ -196,4 +200,48 @@ export default class Workspace {
}
/**
* @param {import('./types').Package[]} packages - Packages to be merged into root
* @returns {[import('./types').Package]} A array containing only the root package
*/
mergePackages(packages) {
const rootPackage = packages.find(p => p.root) ?? packages[0];
const merged = packages.reduce((accumulated, pkg) => {
const files = [...new Set([
...accumulated.files,
...pkg.files.map(f => join(pkg.path, f)),
]
.map(p => p.replace(`${rootPackage.path}/`, '')),
)];
const directories = [...new Set([
...accumulated.directories,
...pkg.directories.map(d => join(pkg.path, d)),
]
.map(p => p.replace(`${rootPackage.path}/`, ''))),
];
const mergedConfig = new Map();
for (const [config, options] of pkg.config ?? []) {
const accumulatedOptions = accumulated.config?.get(config) ?? [];
mergedConfig.set(config, [...new Set([...options, ...accumulatedOptions])]);
}
return {
root: true,
path: rootPackage.path,
name: rootPackage.name,
files,
directories,
config: mergedConfig,
};
}, rootPackage);
return [merged];
}
}