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

150 lines 5.57 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AggregatePathAnalyzer = void 0; const detectorPatterns_1 = require("../constants/detectorPatterns"); const paths_1 = require("../constants/paths"); /** * Analyzes file paths and imports to extract aggregate information * * Handles path normalization, aggregate extraction, and entity name detection * for aggregate boundary validation. */ class AggregatePathAnalyzer { folderRegistry; constructor(folderRegistry) { this.folderRegistry = folderRegistry; } /** * Extracts the aggregate name from a file path * * Handles patterns like: * - domain/aggregates/order/Order.ts → 'order' * - domain/order/Order.ts → 'order' * - domain/entities/order/Order.ts → 'order' */ extractAggregateFromPath(filePath) { const normalizedPath = this.normalizePath(filePath); const segments = this.getPathSegmentsAfterDomain(normalizedPath); if (!segments || segments.length < 2) { return undefined; } return this.findAggregateInSegments(segments); } /** * Extracts the aggregate name from an import path */ extractAggregateFromImport(importPath) { const normalizedPath = importPath.replace(paths_1.IMPORT_PATTERNS.QUOTE, "").toLowerCase(); const segments = normalizedPath.split("/").filter((seg) => seg !== ".." && seg !== "."); if (segments.length === 0) { return undefined; } return this.findAggregateInImportSegments(segments); } /** * Extracts the entity name from an import path */ extractEntityName(importPath) { const normalizedPath = importPath.replace(paths_1.IMPORT_PATTERNS.QUOTE, ""); const segments = normalizedPath.split("/"); const lastSegment = segments[segments.length - 1]; if (lastSegment) { return lastSegment.replace(/\.(ts|js)$/, ""); } return undefined; } /** * Normalizes a file path for consistent processing */ normalizePath(filePath) { return filePath.toLowerCase().replace(/\\/g, "/"); } /** * Gets path segments after the 'domain' folder */ getPathSegmentsAfterDomain(normalizedPath) { const domainMatch = /(?:^|\/)(domain)\//.exec(normalizedPath); if (!domainMatch) { return undefined; } const domainEndIndex = domainMatch.index + domainMatch[0].length; const pathAfterDomain = normalizedPath.substring(domainEndIndex); return pathAfterDomain.split("/").filter(Boolean); } /** * Finds aggregate name in path segments after domain folder */ findAggregateInSegments(segments) { if (this.folderRegistry.isEntityFolder(segments[0])) { return this.extractFromEntityFolder(segments); } const aggregate = segments[0]; if (this.folderRegistry.isNonAggregateFolder(aggregate)) { return undefined; } return aggregate; } /** * Extracts aggregate from entity folder structure */ extractFromEntityFolder(segments) { if (segments.length < 3) { return undefined; } const aggregate = segments[1]; if (this.folderRegistry.isNonAggregateFolder(aggregate)) { return undefined; } return aggregate; } /** * Finds aggregate in import path segments */ findAggregateInImportSegments(segments) { const aggregateFromDomainFolder = this.findAggregateAfterDomainFolder(segments); if (aggregateFromDomainFolder) { return aggregateFromDomainFolder; } return this.findAggregateFromSecondLastSegment(segments); } /** * Finds aggregate after 'domain' or 'aggregates' folder in import */ findAggregateAfterDomainFolder(segments) { for (let i = 0; i < segments.length; i++) { const isDomainOrAggregatesFolder = segments[i] === detectorPatterns_1.DDD_FOLDER_NAMES.DOMAIN || segments[i] === detectorPatterns_1.DDD_FOLDER_NAMES.AGGREGATES; if (!isDomainOrAggregatesFolder) { continue; } if (i + 1 >= segments.length) { continue; } const nextSegment = segments[i + 1]; const isEntityOrAggregateFolder = this.folderRegistry.isEntityFolder(nextSegment) || nextSegment === detectorPatterns_1.DDD_FOLDER_NAMES.AGGREGATES; if (isEntityOrAggregateFolder) { return i + 2 < segments.length ? segments[i + 2] : undefined; } return nextSegment; } return undefined; } /** * Extracts aggregate from second-to-last segment if applicable */ findAggregateFromSecondLastSegment(segments) { if (segments.length >= 2) { const secondLastSegment = segments[segments.length - 2]; if (!this.folderRegistry.isEntityFolder(secondLastSegment) && !this.folderRegistry.isValueObjectFolder(secondLastSegment) && !this.folderRegistry.isAllowedFolder(secondLastSegment) && secondLastSegment !== detectorPatterns_1.DDD_FOLDER_NAMES.DOMAIN) { return secondLastSegment; } } return undefined; } } exports.AggregatePathAnalyzer = AggregatePathAnalyzer; //# sourceMappingURL=AggregatePathAnalyzer.js.map