@fe-fast/code-sweeper
Version:
A lightweight JavaScript/TypeScript code cleaning tool
183 lines • 7.02 kB
JavaScript
import fs from 'fs-extra';
import path from 'path';
import { defaultConfig, configFileNames } from '../config/default.js';
export class ConfigManager {
constructor(customConfigPath) {
this.customConfigPath = customConfigPath;
this.configPath = this.findConfigFile();
}
async load() {
try {
if (await this.exists()) {
const configContent = await fs.readFile(this.configPath, 'utf-8');
const config = JSON.parse(configContent);
// Merge with default config to ensure all properties exist
return this.mergeWithDefaults(config);
}
}
catch (error) {
}
return defaultConfig;
}
async save(config) {
const configDir = path.dirname(this.configPath);
await fs.ensureDir(configDir);
const configContent = JSON.stringify(config, null, 2);
await fs.writeFile(this.configPath, configContent, 'utf-8');
}
async exists() {
return fs.pathExists(this.configPath);
}
getConfigPath() {
return this.configPath;
}
findConfigFile() {
// If custom config path is provided, use it
if (this.customConfigPath) {
return path.resolve(this.customConfigPath);
}
// Look for config files in current directory and parent directories
let currentDir = process.cwd();
const root = path.parse(currentDir).root;
while (currentDir !== root) {
for (const fileName of configFileNames) {
const configPath = path.join(currentDir, fileName);
if (fs.existsSync(configPath)) {
return configPath;
}
}
currentDir = path.dirname(currentDir);
}
// Default to .code-sweeper.json in current directory
return path.join(process.cwd(), '.code-sweeper.json');
}
mergeWithDefaults(config) {
return {
rules: {
...defaultConfig.rules,
...config.rules
},
include: config.include || defaultConfig.include,
exclude: config.exclude || defaultConfig.exclude,
parser: {
...defaultConfig.parser,
...config.parser
}
};
}
// Validate configuration
validateConfig(config) {
const errors = [];
// Check required properties
if (!config.rules || typeof config.rules !== 'object') {
errors.push('Missing or invalid "rules" property');
}
if (!config.include || !Array.isArray(config.include)) {
errors.push('Missing or invalid "include" property (should be an array)');
}
if (!config.exclude || !Array.isArray(config.exclude)) {
errors.push('Missing or invalid "exclude" property (should be an array)');
}
// Check rule properties
if (config.rules) {
const requiredRules = [
'removeUnusedImports',
'removeUnusedVariables',
'removeConsoleLog',
'removeDebugger',
'formatCode',
'renameToCamelCase'
];
for (const rule of requiredRules) {
if (typeof config.rules[rule] !== 'boolean') {
errors.push(`Rule "${rule}" should be a boolean`);
}
}
}
// Check parser config
if (config.parser) {
const parserProps = ['typescript', 'jsx', 'decorators', 'classProperties'];
for (const prop of parserProps) {
if (config.parser[prop] !== undefined && typeof config.parser[prop] !== 'boolean') {
errors.push(`Parser option "${prop}" should be a boolean`);
}
}
}
return {
valid: errors.length === 0,
errors
};
}
// Get configuration schema for documentation
getConfigSchema() {
return {
type: 'object',
properties: {
rules: {
type: 'object',
properties: {
removeUnusedImports: { type: 'boolean', description: 'Remove unused import statements' },
removeUnusedVariables: { type: 'boolean', description: 'Remove unused variable declarations' },
removeConsoleLog: { type: 'boolean', description: 'Remove console.log statements' },
removeDebugger: { type: 'boolean', description: 'Remove statements' },
formatCode: { type: 'boolean', description: 'Format code according to style rules' },
renameToCamelCase: { type: 'boolean', description: 'Rename variables to camelCase' }
},
required: ['removeUnusedImports', 'removeUnusedVariables', 'removeConsoleLog', 'removeDebugger']
},
include: {
type: 'array',
items: { type: 'string' },
description: 'File patterns to include in cleaning'
},
exclude: {
type: 'array',
items: { type: 'string' },
description: 'File patterns to exclude from cleaning'
},
parser: {
type: 'object',
properties: {
typescript: { type: 'boolean', description: 'Enable TypeScript parsing' },
jsx: { type: 'boolean', description: 'Enable JSX parsing' },
decorators: { type: 'boolean', description: 'Enable decorator syntax' },
classProperties: { type: 'boolean', description: 'Enable class properties syntax' }
}
}
},
required: ['rules', 'include', 'exclude']
};
}
// Create example configuration
createExampleConfig() {
return {
rules: {
removeUnusedImports: true,
removeUnusedVariables: true,
removeConsoleLog: true,
removeDebugger: true,
formatCode: false,
renameToCamelCase: false
},
include: [
'src/**/*.{js,ts,jsx,tsx}',
'components/**/*.{js,ts,jsx,tsx}',
'pages/**/*.{js,ts,jsx,tsx}'
],
exclude: [
'node_modules/**',
'dist/**',
'build/**',
'*.min.js',
'vendor/**'
],
parser: {
typescript: true,
jsx: true,
decorators: true,
classProperties: true
}
};
}
}
//# sourceMappingURL=ConfigManager.js.map