@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
JavaScript
;
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