@boost/config
Version:
Powerful convention based finder, loader, and manager of both configuration and ignore files.
72 lines (61 loc) • 1.9 kB
text/typescript
import fs from 'node:fs';
import { Path } from '@boost/common';
import type { Blueprint, Schemas } from '@boost/common/optimal';
import { color } from '@boost/internal';
import { Finder } from './Finder';
import type { IgnoreFile, IgnoreFinderOptions } from './types';
export class IgnoreFinder extends Finder<IgnoreFile, IgnoreFinderOptions> {
blueprint(schemas: Schemas): Blueprint<IgnoreFinderOptions> {
const { bool, string } = schemas;
return {
errorIfNoRootFound: bool(true),
name: string().required().camelCase(),
};
}
/**
* Find a single ignore file in the provided directory.
*/
// eslint-disable-next-line @typescript-eslint/require-await
async findFilesInDir(dir: Path): Promise<Path[]> {
const files: Path[] = [];
const path = dir.append(this.getFileName());
if (path.exists()) {
files.push(path);
}
this.debug.invariant(
files.length > 0,
`Finding ignore files in ${color.filePath(dir.path())}`,
files.map((file) => file.name()).join(', '),
'No files',
);
return files;
}
/**
* Return an ignore specific file.
*/
getFileName(): string {
return `.${this.options.name.toLowerCase()}ignore`;
}
/**
* Load and parse a list of found files into a list of ignore patterns.
*/
async resolveFiles(basePath: Path, foundFiles: Path[]): Promise<IgnoreFile[]> {
this.debug('Resolving %d ignore files', foundFiles.length);
return Promise.all(
foundFiles.map(async (filePath) => {
const contents = await this.cache.cacheFileContents(filePath, () =>
fs.promises.readFile(filePath.path(), 'utf8'),
);
const ignore = contents
.split('\n')
.map((line) => line.trim())
.filter((line) => line !== '' && !line.startsWith('#'));
return {
ignore,
path: filePath,
source: this.isRootDir(filePath.parent()) ? ('root' as const) : ('branch' as const),
};
}),
);
}
}