UNPKG

@samiyev/guardian

Version:

Research-backed code quality guardian for AI-assisted development. Detects hardcodes, secrets, circular deps, framework leaks, entity exposure, and 9 architecture violations. Enforces Clean Architecture/DDD principles. Works with GitHub Copilot, Cursor, W

177 lines 10.5 kB
#!/usr/bin/env node "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const commander_1 = require("commander"); const api_1 = require("../api"); const package_json_1 = require("../../package.json"); const constants_1 = require("./constants"); const constants_2 = require("../shared/constants"); const ViolationGrouper_1 = require("./groupers/ViolationGrouper"); const OutputFormatter_1 = require("./formatters/OutputFormatter"); const StatisticsFormatter_1 = require("./formatters/StatisticsFormatter"); const program = new commander_1.Command(); program .name(constants_1.CLI_COMMANDS.NAME) .description(constants_1.CLI_DESCRIPTIONS.MAIN) .version(package_json_1.version) .addHelpText(constants_1.CLI_HELP_TEXT.POSITION, constants_1.CLI_HELP_TEXT.EXAMPLES_HEADER + constants_1.CLI_HELP_TEXT.EXAMPLE_BASIC + constants_1.CLI_HELP_TEXT.EXAMPLE_CRITICAL + constants_1.CLI_HELP_TEXT.EXAMPLE_SEVERITY + constants_1.CLI_HELP_TEXT.EXAMPLE_LIMIT + constants_1.CLI_HELP_TEXT.EXAMPLE_NO_HARDCODE + constants_1.CLI_HELP_TEXT.EXAMPLE_NO_ARCHITECTURE + constants_1.CLI_HELP_TEXT.EXAMPLE_EXCLUDE + constants_1.CLI_HELP_TEXT.FIX_HEADER + constants_1.CLI_HELP_TEXT.FIX_HARDCODE + constants_1.CLI_HELP_TEXT.FIX_CIRCULAR + constants_1.CLI_HELP_TEXT.FIX_FRAMEWORK + constants_1.CLI_HELP_TEXT.FIX_NAMING + constants_1.CLI_HELP_TEXT.FIX_ENTITY + constants_1.CLI_HELP_TEXT.FIX_DEPENDENCY + constants_1.CLI_HELP_TEXT.FIX_REPOSITORY + constants_1.CLI_HELP_TEXT.FOOTER + constants_1.CLI_HELP_TEXT.AI_AGENT_HEADER + constants_1.CLI_HELP_TEXT.AI_AGENT_INTRO + constants_1.CLI_HELP_TEXT.AI_AGENT_STEP1 + constants_1.CLI_HELP_TEXT.AI_AGENT_STEP1_CMD + constants_1.CLI_HELP_TEXT.AI_AGENT_STEP2 + constants_1.CLI_HELP_TEXT.AI_AGENT_STEP2_DETAIL + constants_1.CLI_HELP_TEXT.AI_AGENT_STEP3 + constants_1.CLI_HELP_TEXT.AI_AGENT_STEP3_CMD + constants_1.CLI_HELP_TEXT.AI_AGENT_STEP4 + constants_1.CLI_HELP_TEXT.AI_AGENT_STEP4_CMDS + constants_1.CLI_HELP_TEXT.AI_AGENT_OUTPUT + constants_1.CLI_HELP_TEXT.AI_AGENT_OUTPUT_DETAIL + constants_1.CLI_HELP_TEXT.AI_AGENT_PRIORITY); program .command(constants_1.CLI_COMMANDS.CHECK) .description(constants_1.CLI_DESCRIPTIONS.CHECK) .argument(constants_1.CLI_ARGUMENTS.PATH, constants_1.CLI_DESCRIPTIONS.PATH_ARG) .option(constants_1.CLI_OPTIONS.EXCLUDE, constants_1.CLI_DESCRIPTIONS.EXCLUDE_OPTION, [...constants_1.DEFAULT_EXCLUDES]) .option(constants_1.CLI_OPTIONS.VERBOSE, constants_1.CLI_DESCRIPTIONS.VERBOSE_OPTION, false) .option(constants_1.CLI_OPTIONS.NO_HARDCODE, constants_1.CLI_DESCRIPTIONS.NO_HARDCODE_OPTION) .option(constants_1.CLI_OPTIONS.NO_ARCHITECTURE, constants_1.CLI_DESCRIPTIONS.NO_ARCHITECTURE_OPTION) .option(constants_1.CLI_OPTIONS.MIN_SEVERITY, constants_1.CLI_DESCRIPTIONS.MIN_SEVERITY_OPTION) .option(constants_1.CLI_OPTIONS.ONLY_CRITICAL, constants_1.CLI_DESCRIPTIONS.ONLY_CRITICAL_OPTION, false) .option(constants_1.CLI_OPTIONS.LIMIT, constants_1.CLI_DESCRIPTIONS.LIMIT_OPTION) .action(async (path, options) => { const grouper = new ViolationGrouper_1.ViolationGrouper(); const outputFormatter = new OutputFormatter_1.OutputFormatter(); const statsFormatter = new StatisticsFormatter_1.StatisticsFormatter(); try { console.log(constants_1.CLI_MESSAGES.ANALYZING); const result = await (0, api_1.analyzeProject)({ rootDir: path, exclude: options.exclude, }); const { metrics } = result; let { hardcodeViolations, violations, circularDependencyViolations, namingViolations, frameworkLeakViolations, entityExposureViolations, dependencyDirectionViolations, repositoryPatternViolations, aggregateBoundaryViolations, secretViolations, anemicModelViolations, } = result; const minSeverity = options.onlyCritical ? constants_2.SEVERITY_LEVELS.CRITICAL : options.minSeverity ? options.minSeverity.toLowerCase() : undefined; const limit = options.limit ? parseInt(options.limit, 10) : undefined; if (minSeverity) { violations = grouper.filterBySeverity(violations, minSeverity); hardcodeViolations = grouper.filterBySeverity(hardcodeViolations, minSeverity); circularDependencyViolations = grouper.filterBySeverity(circularDependencyViolations, minSeverity); namingViolations = grouper.filterBySeverity(namingViolations, minSeverity); frameworkLeakViolations = grouper.filterBySeverity(frameworkLeakViolations, minSeverity); entityExposureViolations = grouper.filterBySeverity(entityExposureViolations, minSeverity); dependencyDirectionViolations = grouper.filterBySeverity(dependencyDirectionViolations, minSeverity); repositoryPatternViolations = grouper.filterBySeverity(repositoryPatternViolations, minSeverity); aggregateBoundaryViolations = grouper.filterBySeverity(aggregateBoundaryViolations, minSeverity); secretViolations = grouper.filterBySeverity(secretViolations, minSeverity); anemicModelViolations = grouper.filterBySeverity(anemicModelViolations, minSeverity); statsFormatter.displaySeverityFilterMessage(options.onlyCritical, options.minSeverity); } statsFormatter.displayMetrics(metrics); if (options.architecture && violations.length > 0) { console.log(`\n${constants_1.CLI_MESSAGES.VIOLATIONS_HEADER} ${String(violations.length)} ${constants_1.CLI_LABELS.ARCHITECTURE_VIOLATIONS}`); outputFormatter.displayGroupedViolations(violations, (v, i) => { outputFormatter.formatArchitectureViolation(v, i); }, limit); } if (options.architecture && circularDependencyViolations.length > 0) { console.log(`\n${constants_1.CLI_MESSAGES.CIRCULAR_DEPS_HEADER} ${String(circularDependencyViolations.length)} ${constants_1.CLI_LABELS.CIRCULAR_DEPENDENCIES}`); outputFormatter.displayGroupedViolations(circularDependencyViolations, (cd, i) => { outputFormatter.formatCircularDependency(cd, i); }, limit); } if (options.architecture && namingViolations.length > 0) { console.log(`\n${constants_1.CLI_MESSAGES.NAMING_VIOLATIONS_HEADER} ${String(namingViolations.length)} ${constants_1.CLI_LABELS.NAMING_VIOLATIONS}`); outputFormatter.displayGroupedViolations(namingViolations, (nc, i) => { outputFormatter.formatNamingViolation(nc, i); }, limit); } if (options.architecture && frameworkLeakViolations.length > 0) { console.log(`\n🏗️ Found ${String(frameworkLeakViolations.length)} framework leak(s)`); outputFormatter.displayGroupedViolations(frameworkLeakViolations, (fl, i) => { outputFormatter.formatFrameworkLeak(fl, i); }, limit); } if (options.architecture && entityExposureViolations.length > 0) { console.log(`\n🎭 Found ${String(entityExposureViolations.length)} entity exposure(s)`); outputFormatter.displayGroupedViolations(entityExposureViolations, (ee, i) => { outputFormatter.formatEntityExposure(ee, i); }, limit); } if (options.architecture && dependencyDirectionViolations.length > 0) { console.log(`\n⚠️ Found ${String(dependencyDirectionViolations.length)} dependency direction violation(s)`); outputFormatter.displayGroupedViolations(dependencyDirectionViolations, (dd, i) => { outputFormatter.formatDependencyDirection(dd, i); }, limit); } if (options.architecture && repositoryPatternViolations.length > 0) { console.log(`\n📦 Found ${String(repositoryPatternViolations.length)} repository pattern violation(s)`); outputFormatter.displayGroupedViolations(repositoryPatternViolations, (rp, i) => { outputFormatter.formatRepositoryPattern(rp, i); }, limit); } if (options.architecture && aggregateBoundaryViolations.length > 0) { console.log(`\n🔒 Found ${String(aggregateBoundaryViolations.length)} aggregate boundary violation(s)`); outputFormatter.displayGroupedViolations(aggregateBoundaryViolations, (ab, i) => { outputFormatter.formatAggregateBoundary(ab, i); }, limit); } if (secretViolations.length > 0) { console.log(`\n🔐 Found ${String(secretViolations.length)} hardcoded secret(s) - CRITICAL SECURITY RISK`); outputFormatter.displayGroupedViolations(secretViolations, (sv, i) => { outputFormatter.formatSecretViolation(sv, i); }, limit); } if (anemicModelViolations.length > 0) { console.log(`\n🩺 Found ${String(anemicModelViolations.length)} anemic domain model(s)`); outputFormatter.displayGroupedViolations(anemicModelViolations, (am, i) => { outputFormatter.formatAnemicModelViolation(am, i); }, limit); } if (options.hardcode && hardcodeViolations.length > 0) { console.log(`\n${constants_1.CLI_MESSAGES.HARDCODE_VIOLATIONS_HEADER} ${String(hardcodeViolations.length)} ${constants_1.CLI_LABELS.HARDCODE_VIOLATIONS}`); outputFormatter.displayGroupedViolations(hardcodeViolations, (hc, i) => { outputFormatter.formatHardcodeViolation(hc, i); }, limit); } const totalIssues = violations.length + hardcodeViolations.length + circularDependencyViolations.length + namingViolations.length + frameworkLeakViolations.length + entityExposureViolations.length + dependencyDirectionViolations.length + repositoryPatternViolations.length + aggregateBoundaryViolations.length + secretViolations.length + anemicModelViolations.length; statsFormatter.displaySummary(totalIssues, options.verbose); } catch (error) { statsFormatter.displayError(error instanceof Error ? error.message : String(error)); } }); program.parse(); //# sourceMappingURL=index.js.map