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

110 lines 4.79 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HardcodeDetector = void 0; const constants_1 = require("../../shared/constants"); const CodeParser_1 = require("../parsers/CodeParser"); const AstBooleanAnalyzer_1 = require("../strategies/AstBooleanAnalyzer"); const AstConfigObjectAnalyzer_1 = require("../strategies/AstConfigObjectAnalyzer"); const AstContextChecker_1 = require("../strategies/AstContextChecker"); const AstNumberAnalyzer_1 = require("../strategies/AstNumberAnalyzer"); const AstStringAnalyzer_1 = require("../strategies/AstStringAnalyzer"); const ConstantsFileChecker_1 = require("../strategies/ConstantsFileChecker"); const AstTreeTraverser_1 = require("./AstTreeTraverser"); /** * Detects hardcoded values (magic numbers and strings) in TypeScript/JavaScript code * * This detector uses Abstract Syntax Tree (AST) analysis via tree-sitter to identify * configuration values, URLs, timeouts, ports, and other constants that should be * extracted to configuration files. AST-based detection provides more accurate context * understanding and reduces false positives compared to regex-based approaches. * * The detector uses a modular architecture with specialized components: * - AstContextChecker: Checks if nodes are in specific contexts (exports, types, etc.) * - AstNumberAnalyzer: Analyzes number literals to detect magic numbers * - AstStringAnalyzer: Analyzes string literals to detect magic strings * - AstTreeTraverser: Traverses the AST and coordinates analyzers * * @example * ```typescript * const detector = new HardcodeDetector() * const code = ` * const timeout = 5000 * const url = "http://localhost:8080" * ` * const violations = detector.detectAll(code, 'config.ts') * // Returns array of HardcodedValue objects * ``` */ class HardcodeDetector { constantsChecker; parser; traverser; constructor() { this.constantsChecker = new ConstantsFileChecker_1.ConstantsFileChecker(); this.parser = new CodeParser_1.CodeParser(); const contextChecker = new AstContextChecker_1.AstContextChecker(); const numberAnalyzer = new AstNumberAnalyzer_1.AstNumberAnalyzer(contextChecker); const stringAnalyzer = new AstStringAnalyzer_1.AstStringAnalyzer(contextChecker); const booleanAnalyzer = new AstBooleanAnalyzer_1.AstBooleanAnalyzer(contextChecker); const configObjectAnalyzer = new AstConfigObjectAnalyzer_1.AstConfigObjectAnalyzer(contextChecker); this.traverser = new AstTreeTraverser_1.AstTreeTraverser(numberAnalyzer, stringAnalyzer, booleanAnalyzer, configObjectAnalyzer); } /** * Detects all hardcoded values (both numbers and strings) in the given code * * @param code - Source code to analyze * @param filePath - File path for context (used in violation reports) * @returns Array of detected hardcoded values with suggestions */ detectAll(code, filePath) { if (this.constantsChecker.isConstantsFile(filePath)) { return []; } const tree = this.parseCode(code, filePath); return this.traverser.traverse(tree, code); } /** * Detects magic numbers in code * * @param code - Source code to analyze * @param filePath - File path (used for constants file check) * @returns Array of detected magic numbers */ detectMagicNumbers(code, filePath) { if (this.constantsChecker.isConstantsFile(filePath)) { return []; } const tree = this.parseCode(code, filePath); const allViolations = this.traverser.traverse(tree, code); return allViolations.filter((v) => v.isMagicNumber()); } /** * Detects magic strings in code * * @param code - Source code to analyze * @param filePath - File path (used for constants file check) * @returns Array of detected magic strings */ detectMagicStrings(code, filePath) { if (this.constantsChecker.isConstantsFile(filePath)) { return []; } const tree = this.parseCode(code, filePath); const allViolations = this.traverser.traverse(tree, code); return allViolations.filter((v) => v.isMagicString()); } /** * Parses code based on file extension */ parseCode(code, filePath) { if (filePath.endsWith(constants_1.FILE_EXTENSIONS.TYPESCRIPT_JSX)) { return this.parser.parseTsx(code); } else if (filePath.endsWith(constants_1.FILE_EXTENSIONS.TYPESCRIPT)) { return this.parser.parseTypeScript(code); } return this.parser.parseJavaScript(code); } } exports.HardcodeDetector = HardcodeDetector; //# sourceMappingURL=HardcodeDetector.js.map