import { analyze, getAdapterForFile } from './analyzer'; import { formatConsole, formatJSON, formatSARIF } from './reporter'; import { loadConfig } from './config'; import { getAllPrincipleRules } from './rules'; interface CLIOptions { files: string[]; format: 'console' | 'json' | 'sarif'; changedOnly: boolean; showScore: boolean; } const VALID_FORMATS: readonly string[] = ['json', 'console', 'sarif'] as const; export function parseArgs(args: string[]): CLIOptions { const options: CLIOptions = { files: [], format: 'console', changedOnly: false, showScore: false }; for (let i = 0; i < args.length; i++) { switch (args[i]) { case '--files': const next = args[++i]; if (next) options.files = next.split(' ').filter(f => f.trim()); break; case '--format': const fmt = args[++i]; if (fmt && VALID_FORMATS.includes(fmt)) options.format = fmt as 'json' | 'console' | 'sarif'; break; case '--changed-only': options.changedOnly = true; break; case '--show-score': options.showScore = true; break; default: if (!args[i].startsWith('--')) options.files.push(args[i]); } } return options; } function getAllRules() { return getAllPrincipleRules(); } export { getAllRules }; export async function main(args: string[]): Promise { const options = parseArgs(args); if (options.files.length === 0) { console.error('Usage: principles-checker --files ... [--format console|json|sarif] [--changed-only]'); return 1; } await loadConfig(); const rules = getAllRules(); const result = await analyze(options.files, rules, getAdapterForFile); const formatters: Record string> = { json: formatJSON, sarif: formatSARIF, console: formatConsole, }; console.log(formatters[options.format](result)); return result.summary.totalViolations > 0 ? 1 : 0; } // Support both CJS (require.main === module) and ESM (import.meta.url) runtimes. // npx tsx loads files via import() making require.main unreliable. function isDirectExecution(): boolean { if (typeof require !== 'undefined' && require.main === module) { return true; } if (typeof import.meta !== 'undefined' && import.meta.url && process.argv[1]) { const fileUrl = `file://${process.argv[1]}`; return import.meta.url === fileUrl || import.meta.url.endsWith(`/${process.argv[1]}`); } return false; } const args = process.argv.slice(2); if (isDirectExecution()) { main(args) .then(exitCode => { if (exitCode !== 0) { process.exit(exitCode); } }) .catch(err => { console.error('Analysis failed:', err.message); process.exit(1); }); }