stock-bot/tools/coverage-cli/src/config.ts

153 lines
No EOL
3.8 KiB
TypeScript

import { readFileSync, existsSync } from 'fs';
import { resolve, join } from 'path';
import type { CoverageConfig, CLIOptions } from './types';
const DEFAULT_CONFIG: CoverageConfig = {
exclude: [
'**/node_modules/**',
'**/dist/**',
'**/build/**',
'**/coverage/**',
'**/*.test.ts',
'**/*.test.js',
'**/*.spec.ts',
'**/*.spec.js',
'**/test/**',
'**/tests/**',
'**/__tests__/**',
'**/__mocks__/**',
'**/setup.ts',
'**/setup.js',
],
reporters: ['terminal'],
thresholds: {
lines: 80,
functions: 80,
branches: 80,
statements: 80,
},
outputDir: 'coverage',
};
export function loadConfig(options: CLIOptions): CoverageConfig {
let config = { ...DEFAULT_CONFIG };
// Load from config file
const configPath = options.config || findConfigFile();
if (configPath && existsSync(configPath)) {
try {
const fileConfig = JSON.parse(readFileSync(configPath, 'utf-8'));
config = mergeConfig(config, fileConfig);
} catch (error) {
console.warn(`Warning: Failed to load config from ${configPath}:`, error);
}
}
// Override with CLI options
if (options.exclude && options.exclude.length > 0) {
config.exclude = options.exclude;
}
if (options.include && options.include.length > 0) {
config.include = options.include;
}
if (options.reporters && options.reporters.length > 0) {
config.reporters = options.reporters as any[];
}
if (options.outputDir) {
config.outputDir = options.outputDir;
}
// Handle thresholds
if (options.threshold !== undefined) {
config.thresholds = {
lines: options.threshold,
functions: options.threshold,
branches: options.threshold,
statements: options.threshold,
};
}
if (options.thresholdLines !== undefined) {
config.thresholds.lines = options.thresholdLines;
}
if (options.thresholdFunctions !== undefined) {
config.thresholds.functions = options.thresholdFunctions;
}
if (options.thresholdBranches !== undefined) {
config.thresholds.branches = options.thresholdBranches;
}
if (options.thresholdStatements !== undefined) {
config.thresholds.statements = options.thresholdStatements;
}
if (options.packages) {
config.packages = options.packages;
}
// Find workspace root
config.workspaceRoot = findWorkspaceRoot();
return config;
}
function findConfigFile(): string | null {
const configNames = ['.coveragerc.json', '.coveragerc', 'coverage.config.json'];
const searchDirs = [process.cwd(), ...getParentDirs(process.cwd())];
for (const dir of searchDirs) {
for (const name of configNames) {
const path = join(dir, name);
if (existsSync(path)) {
return path;
}
}
}
return null;
}
function findWorkspaceRoot(): string {
const searchDirs = [process.cwd(), ...getParentDirs(process.cwd())];
for (const dir of searchDirs) {
// Check for common workspace indicators
if (
existsSync(join(dir, 'package.json')) &&
(existsSync(join(dir, 'packages')) ||
existsSync(join(dir, 'apps')) ||
existsSync(join(dir, 'libs')))
) {
return dir;
}
}
return process.cwd();
}
function getParentDirs(dir: string): string[] {
const parents: string[] = [];
let current = resolve(dir);
let parent = resolve(current, '..');
while (parent !== current) {
parents.push(parent);
current = parent;
parent = resolve(current, '..');
}
return parents;
}
function mergeConfig(base: CoverageConfig, override: Partial<CoverageConfig>): CoverageConfig {
return {
...base,
...override,
thresholds: {
...base.thresholds,
...(override.thresholds || {}),
},
};
}