@dthreads/atlas
Advanced tools
| import { | ||
| ATLAS_VERSION | ||
| } from "./chunk-YALK4AYO.js"; | ||
| // src/core/types.ts | ||
| var graphNodeTypes = [ | ||
| "project", | ||
| "folder", | ||
| "file", | ||
| "package", | ||
| "module", | ||
| "controller", | ||
| "service", | ||
| "provider", | ||
| "repository", | ||
| "use_case", | ||
| "port", | ||
| "adapter", | ||
| "entity", | ||
| "dto", | ||
| "method", | ||
| "function", | ||
| "route", | ||
| "guard", | ||
| "pipe", | ||
| "interceptor", | ||
| "middleware", | ||
| "decorator", | ||
| "database", | ||
| "table", | ||
| "column", | ||
| "model", | ||
| "environment_variable", | ||
| "external_api", | ||
| "message_broker", | ||
| "message_topic", | ||
| "queue", | ||
| "processor", | ||
| "schema", | ||
| "index", | ||
| "constraint", | ||
| "migration", | ||
| "materialized_view", | ||
| "scheduled_job", | ||
| "workflow", | ||
| "pipeline_job", | ||
| "build_stage", | ||
| "container_image", | ||
| "container", | ||
| "deployment", | ||
| "infrastructure_service", | ||
| "ingress", | ||
| "config_map", | ||
| "secret", | ||
| "environment", | ||
| "config", | ||
| "test", | ||
| "library", | ||
| "risk" | ||
| ]; | ||
| var graphEdgeTypes = [ | ||
| "contains", | ||
| "imports", | ||
| "exports", | ||
| "declares", | ||
| "provides", | ||
| "injects", | ||
| "implements", | ||
| "calls", | ||
| "uses", | ||
| "reads", | ||
| "writes", | ||
| "handles", | ||
| "depends_on", | ||
| "decorates", | ||
| "validates", | ||
| "returns", | ||
| "references", | ||
| "connects_to", | ||
| "tests", | ||
| "has_method", | ||
| "has_column", | ||
| "publishes_to", | ||
| "delivers_to", | ||
| "enqueues", | ||
| "processes", | ||
| "creates", | ||
| "alters", | ||
| "drops", | ||
| "indexes", | ||
| "schedules", | ||
| "triggers", | ||
| "builds", | ||
| "publishes", | ||
| "deploys", | ||
| "exposes", | ||
| "configures", | ||
| "runs_in", | ||
| "targets" | ||
| ]; | ||
| // src/core/graph.ts | ||
| var validNodeTypes = new Set(graphNodeTypes); | ||
| var validEdgeTypes = new Set(graphEdgeTypes); | ||
| var GraphBuilder = class { | ||
| nodes = /* @__PURE__ */ new Map(); | ||
| edges = /* @__PURE__ */ new Map(); | ||
| addNode(node) { | ||
| const current = this.nodes.get(node.id); | ||
| if (!current) { | ||
| this.nodes.set(node.id, node); | ||
| return node; | ||
| } | ||
| const merged = { | ||
| ...current, | ||
| ...node, | ||
| metadata: { ...current.metadata, ...node.metadata } | ||
| }; | ||
| this.nodes.set(node.id, merged); | ||
| return merged; | ||
| } | ||
| addEdge(edge) { | ||
| if (!this.nodes.has(edge.from) || !this.nodes.has(edge.to)) return null; | ||
| const key = `${edge.from}|${edge.type}|${edge.to}|${edge.label ?? ""}`; | ||
| const id = edge.id ?? `edge:${encodeURIComponent(key)}`; | ||
| const result = { ...edge, id }; | ||
| this.edges.set(key, result); | ||
| return result; | ||
| } | ||
| hasNode(id) { | ||
| return this.nodes.has(id); | ||
| } | ||
| validate() { | ||
| const errors = []; | ||
| for (const node of this.nodes.values()) { | ||
| if (!validNodeTypes.has(String(node.type))) errors.push(`${node.id}: invalid node type ${String(node.type)}`); | ||
| } | ||
| for (const edge of this.edges.values()) { | ||
| if (!validEdgeTypes.has(String(edge.type))) errors.push(`${edge.id}: invalid edge type ${String(edge.type)}`); | ||
| if (!this.nodes.has(edge.from)) errors.push(`${edge.id}: missing source ${edge.from}`); | ||
| if (!this.nodes.has(edge.to)) errors.push(`${edge.id}: missing target ${edge.to}`); | ||
| } | ||
| return errors; | ||
| } | ||
| toGraph(project) { | ||
| const nodes = [...this.nodes.values()].sort((a, b) => a.id.localeCompare(b.id)); | ||
| const edges = [...this.edges.values()].sort((a, b) => a.id.localeCompare(b.id)); | ||
| return { version: ATLAS_VERSION, project, nodes, edges, stats: buildStats(nodes, edges) }; | ||
| } | ||
| }; | ||
| function increment(target, key) { | ||
| target[key] = (target[key] ?? 0) + 1; | ||
| } | ||
| function buildStats(nodes, edges) { | ||
| const byNodeType = /* @__PURE__ */ Object.create(null); | ||
| const byEdgeType = /* @__PURE__ */ Object.create(null); | ||
| for (const node of nodes) increment(byNodeType, node.type); | ||
| for (const edge of edges) increment(byEdgeType, edge.type); | ||
| return { totalNodes: nodes.length, totalEdges: edges.length, byNodeType, byEdgeType }; | ||
| } | ||
| var GraphQuery = class { | ||
| constructor(graph) { | ||
| this.graph = graph; | ||
| this.nodeMap = new Map(graph.nodes.map((node) => [node.id, node])); | ||
| for (const node of graph.nodes) { | ||
| const typed = this.nodesByType.get(node.type) ?? []; | ||
| typed.push(node); | ||
| this.nodesByType.set(node.type, typed); | ||
| } | ||
| for (const edge of graph.edges) { | ||
| this.edgeMap.set(edge.id, edge); | ||
| const incoming = this.incomingMap.get(edge.to) ?? []; | ||
| incoming.push(edge); | ||
| this.incomingMap.set(edge.to, incoming); | ||
| const outgoing = this.outgoingMap.get(edge.from) ?? []; | ||
| outgoing.push(edge); | ||
| this.outgoingMap.set(edge.from, outgoing); | ||
| } | ||
| } | ||
| graph; | ||
| nodeMap; | ||
| edgeMap = /* @__PURE__ */ new Map(); | ||
| incomingMap = /* @__PURE__ */ new Map(); | ||
| outgoingMap = /* @__PURE__ */ new Map(); | ||
| nodesByType = /* @__PURE__ */ new Map(); | ||
| findNode(query) { | ||
| const needle = query.trim().toLowerCase(); | ||
| if (!needle) return []; | ||
| return this.graph.nodes.filter((node) => searchableNode(node).includes(needle)).sort((a, b) => scoreNode(b, needle) - scoreNode(a, needle)).slice(0, 100); | ||
| } | ||
| search(query) { | ||
| const needle = query.trim().toLowerCase(); | ||
| if (!needle) return []; | ||
| return this.findNode(query).map((node) => ({ | ||
| node, | ||
| score: scoreNode(node, needle), | ||
| matches: matchingFields(node, needle) | ||
| })); | ||
| } | ||
| getNode(id) { | ||
| return this.nodeMap.get(id) ?? null; | ||
| } | ||
| getIncoming(id) { | ||
| return this.incomingMap.get(id) ?? []; | ||
| } | ||
| getOutgoing(id) { | ||
| return this.outgoingMap.get(id) ?? []; | ||
| } | ||
| findRoutes() { | ||
| return this.byType("route"); | ||
| } | ||
| findServices() { | ||
| return this.byType("service"); | ||
| } | ||
| findControllers() { | ||
| return this.byType("controller"); | ||
| } | ||
| findTables() { | ||
| return this.byType("table"); | ||
| } | ||
| findSchemas() { | ||
| return this.byType("schema"); | ||
| } | ||
| findIndexes() { | ||
| return this.byType("index"); | ||
| } | ||
| findConstraints() { | ||
| return this.byType("constraint"); | ||
| } | ||
| findMigrations() { | ||
| return this.byType("migration"); | ||
| } | ||
| findScheduledJobs() { | ||
| return this.byType("scheduled_job"); | ||
| } | ||
| findWorkflows() { | ||
| return this.byType("workflow"); | ||
| } | ||
| findDeployments() { | ||
| return this.byType("deployment"); | ||
| } | ||
| findEnvironments() { | ||
| return this.byType("environment"); | ||
| } | ||
| findExternalApis() { | ||
| return this.byType("external_api"); | ||
| } | ||
| findMessageTopics() { | ||
| return this.byType("message_topic"); | ||
| } | ||
| findQueues() { | ||
| return this.byType("queue"); | ||
| } | ||
| findProcessors() { | ||
| return this.byType("processor"); | ||
| } | ||
| findTableProfile(tableId) { | ||
| const table = this.nodeMap.get(tableId); | ||
| if (!table || table.type !== "table") return { nodes: [], edges: [] }; | ||
| const edgeTypes = /* @__PURE__ */ new Set(["has_column", "indexes", "contains", "references", "reads", "writes", "creates", "alters", "drops"]); | ||
| const edges = [...this.getIncoming(tableId), ...this.getOutgoing(tableId)].filter((edge) => edgeTypes.has(edge.type)); | ||
| const ids = /* @__PURE__ */ new Set([tableId, ...edges.flatMap((edge) => [edge.from, edge.to])]); | ||
| return { nodes: [...ids].map((id) => this.nodeMap.get(id)).filter(Boolean), edges }; | ||
| } | ||
| getNeighbors(nodeId, depth = 1) { | ||
| if (!this.nodeMap.has(nodeId)) return { nodes: [], edges: [] }; | ||
| const nodeIds = /* @__PURE__ */ new Set([nodeId]); | ||
| const edgeIds = /* @__PURE__ */ new Set(); | ||
| let frontier = [nodeId]; | ||
| for (let level = 0; level < Math.max(0, depth) && frontier.length; level += 1) { | ||
| const next = []; | ||
| for (const id of frontier) { | ||
| for (const edge of [...this.getIncoming(id), ...this.getOutgoing(id)]) { | ||
| edgeIds.add(edge.id); | ||
| const neighbor = edge.from === id ? edge.to : edge.from; | ||
| if (!nodeIds.has(neighbor)) { | ||
| nodeIds.add(neighbor); | ||
| next.push(neighbor); | ||
| } | ||
| } | ||
| } | ||
| frontier = next; | ||
| } | ||
| return { | ||
| nodes: [...nodeIds].map((id) => this.nodeMap.get(id)).filter(Boolean), | ||
| edges: [...edgeIds].map((id) => this.edgeMap.get(id)).filter(Boolean) | ||
| }; | ||
| } | ||
| findFlowFromRoute(routeId) { | ||
| return this.walk(routeId, "outgoing", 12, /* @__PURE__ */ new Set([ | ||
| "handles", | ||
| "calls", | ||
| "reads", | ||
| "writes", | ||
| "uses", | ||
| "connects_to", | ||
| "validates", | ||
| "returns", | ||
| "publishes_to", | ||
| "delivers_to", | ||
| "enqueues", | ||
| "processes" | ||
| ])); | ||
| } | ||
| findAsyncFlow(rootId) { | ||
| const root = this.nodeMap.get(rootId); | ||
| if (!root || !["message_topic", "queue"].includes(root.type)) return { nodes: [], edges: [] }; | ||
| const flow = this.walk(rootId, "outgoing", 12, /* @__PURE__ */ new Set([ | ||
| "delivers_to", | ||
| "calls", | ||
| "reads", | ||
| "writes", | ||
| "uses", | ||
| "connects_to", | ||
| "publishes_to", | ||
| "enqueues", | ||
| "processes" | ||
| ])); | ||
| const nodeIds = new Set(flow.nodes.map((node) => node.id)); | ||
| const edgeIds = new Set(flow.edges.map((edge) => edge.id)); | ||
| for (const edge of this.getIncoming(rootId).filter((item) => ["publishes_to", "enqueues"].includes(item.type))) { | ||
| nodeIds.add(edge.from); | ||
| edgeIds.add(edge.id); | ||
| } | ||
| return { | ||
| nodes: [...nodeIds].map((id) => this.nodeMap.get(id)).filter(Boolean), | ||
| edges: [...edgeIds].map((id) => this.edgeMap.get(id)).filter(Boolean) | ||
| }; | ||
| } | ||
| findDependencies(nodeId, depth = 2) { | ||
| return this.walk(nodeId, "outgoing", depth); | ||
| } | ||
| findDependents(nodeId, depth = 2) { | ||
| return this.walk(nodeId, "incoming", depth); | ||
| } | ||
| byType(type) { | ||
| return this.nodesByType.get(type) ?? []; | ||
| } | ||
| walk(startId, direction, depth, allowedTypes) { | ||
| if (!this.nodeMap.has(startId)) return { nodes: [], edges: [] }; | ||
| const nodeIds = /* @__PURE__ */ new Set([startId]); | ||
| const edgeIds = /* @__PURE__ */ new Set(); | ||
| let frontier = [startId]; | ||
| for (let level = 0; level < Math.max(0, depth) && frontier.length; level += 1) { | ||
| const next = []; | ||
| for (const id of frontier) { | ||
| const edges = direction === "outgoing" ? this.getOutgoing(id) : this.getIncoming(id); | ||
| for (const edge of edges) { | ||
| if (allowedTypes && !allowedTypes.has(edge.type)) continue; | ||
| edgeIds.add(edge.id); | ||
| const neighbor = direction === "outgoing" ? edge.to : edge.from; | ||
| if (!nodeIds.has(neighbor)) { | ||
| nodeIds.add(neighbor); | ||
| next.push(neighbor); | ||
| } | ||
| } | ||
| } | ||
| frontier = next; | ||
| } | ||
| return { | ||
| nodes: [...nodeIds].map((id) => this.nodeMap.get(id)).filter(Boolean), | ||
| edges: [...edgeIds].map((id) => this.edgeMap.get(id)).filter(Boolean) | ||
| }; | ||
| } | ||
| }; | ||
| function searchableNode(node) { | ||
| return [node.id, node.type, node.label, node.name, node.file, JSON.stringify(node.metadata ?? {})].filter(Boolean).join(" ").toLowerCase(); | ||
| } | ||
| function scoreNode(node, needle) { | ||
| const label = node.label.toLowerCase(); | ||
| if (label === needle) return 100; | ||
| if (label.startsWith(needle)) return 80; | ||
| if (node.id.toLowerCase().includes(needle)) return 60; | ||
| return 20; | ||
| } | ||
| function matchingFields(node, needle) { | ||
| const fields = { | ||
| id: node.id, | ||
| label: node.label, | ||
| name: node.name ?? "", | ||
| type: node.type, | ||
| file: node.file ?? "", | ||
| metadata: JSON.stringify(node.metadata ?? {}) | ||
| }; | ||
| return Object.entries(fields).filter(([, value]) => value.toLowerCase().includes(needle)).map(([key]) => key); | ||
| } | ||
| export { | ||
| graphNodeTypes, | ||
| graphEdgeTypes, | ||
| GraphBuilder, | ||
| buildStats, | ||
| GraphQuery | ||
| }; | ||
| //# sourceMappingURL=chunk-RZYFC6FA.js.map |
| {"version":3,"sources":["../src/core/types.ts","../src/core/graph.ts"],"sourcesContent":["export const graphNodeTypes = [\n \"project\", \"folder\", \"file\", \"package\", \"module\", \"controller\", \"service\",\n \"provider\", \"repository\", \"use_case\", \"port\", \"adapter\", \"entity\", \"dto\", \"method\", \"function\", \"route\",\n \"guard\", \"pipe\", \"interceptor\", \"middleware\", \"decorator\", \"database\",\n \"table\", \"column\", \"model\", \"environment_variable\", \"external_api\",\n \"message_broker\", \"message_topic\", \"queue\", \"processor\",\n \"schema\", \"index\", \"constraint\", \"migration\", \"materialized_view\",\n \"scheduled_job\", \"workflow\", \"pipeline_job\", \"build_stage\", \"container_image\",\n \"container\", \"deployment\", \"infrastructure_service\", \"ingress\", \"config_map\",\n \"secret\", \"environment\", \"config\", \"test\", \"library\", \"risk\",\n] as const;\n\nexport const graphEdgeTypes = [\n \"contains\", \"imports\", \"exports\", \"declares\", \"provides\", \"injects\", \"implements\", \"calls\",\n \"uses\", \"reads\", \"writes\", \"handles\", \"depends_on\", \"decorates\", \"validates\",\n \"returns\", \"references\", \"connects_to\", \"tests\", \"has_method\", \"has_column\",\n \"publishes_to\", \"delivers_to\", \"enqueues\", \"processes\",\n \"creates\", \"alters\", \"drops\", \"indexes\", \"schedules\", \"triggers\", \"builds\",\n \"publishes\", \"deploys\", \"exposes\", \"configures\", \"runs_in\", \"targets\",\n] as const;\n\nexport type GraphNodeType = (typeof graphNodeTypes)[number];\nexport type GraphEdgeType = (typeof graphEdgeTypes)[number];\nexport type GraphSourceType =\n | \"static_analysis\"\n | \"ast\"\n | \"config\"\n | \"package_json\"\n | \"heuristic\"\n | \"runtime\"\n | \"manual\";\n\nexport interface SourceLocation {\n file: string;\n startLine?: number;\n endLine?: number;\n}\n\nexport interface GraphNode {\n id: string;\n type: GraphNodeType;\n label: string;\n name?: string;\n file?: string;\n language?: string;\n framework?: string;\n sourceLocation?: SourceLocation;\n confidence?: number;\n source?: GraphSourceType;\n metadata?: Record<string, unknown>;\n}\n\nexport interface GraphEdge {\n id: string;\n from: string;\n to: string;\n type: GraphEdgeType;\n label?: string;\n confidence?: number;\n source?: GraphSourceType;\n metadata?: Record<string, unknown>;\n}\n\nexport interface DetectedStack {\n name: string;\n confidence: number;\n evidence: string[];\n}\n\nexport interface GraphStats {\n totalNodes: number;\n totalEdges: number;\n byNodeType: Partial<Record<GraphNodeType, number>>;\n byEdgeType: Partial<Record<GraphEdgeType, number>>;\n}\n\nexport interface ArchitectureGraph {\n version: string;\n project: {\n name: string;\n root: string;\n detectedStacks: string[];\n createdAt: string;\n };\n nodes: GraphNode[];\n edges: GraphEdge[];\n stats: GraphStats;\n}\n\nexport interface ScannedFile {\n absolutePath: string;\n path: string;\n extension: string;\n size: number;\n hash?: string;\n lastModified: string;\n}\n\nexport interface ScanMetadata {\n version: string;\n projectName: string;\n projectRoot: string;\n scanStartedAt: string;\n scanFinishedAt: string;\n durationMs: number;\n filesScanned: number;\n filesIgnored: number;\n filesHashed?: number;\n filesReused?: number;\n cacheHit?: boolean;\n inputFingerprint?: string;\n analysisCacheVersion?: number;\n viewerFingerprint?: string;\n runtimeEvents?: number;\n runtimeMergedAt?: string;\n runtimeFingerprint?: string;\n detectedStacks: DetectedStack[];\n}\n\nexport type RiskSeverity = \"low\" | \"medium\" | \"high\" | \"critical\";\n\nexport interface ArchitectureRisk {\n id: string;\n type: string;\n severity: RiskSeverity;\n title: string;\n description: string;\n recommendation: string;\n nodeId?: string;\n file?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface GraphSubgraph {\n nodes: GraphNode[];\n edges: GraphEdge[];\n}\n\nexport interface GraphSearchResult {\n node: GraphNode;\n score: number;\n matches: string[];\n}\n\nexport type ScanProgressStage =\n | \"scan_files\"\n | \"detect_stack\"\n | \"parse_architecture\"\n | \"build_graph\"\n | \"detect_risks\"\n | \"write_outputs\";\n\nexport interface ScanProgress {\n stage: ScanProgressStage;\n message: string;\n}\n\nexport interface ScanOptions {\n projectPath: string;\n outputPath?: string;\n incremental?: boolean;\n debug?: boolean;\n onProgress?: (progress: ScanProgress) => void;\n}\n\nexport interface ScanResult {\n graph: ArchitectureGraph;\n metadata: ScanMetadata;\n risks: ArchitectureRisk[];\n outputPath: string;\n}\n\nexport interface RuntimeTraceNode {\n id: string;\n type: GraphNodeType;\n label?: string;\n file?: string;\n}\n\nexport interface RuntimeTraceEvent {\n from: string;\n to: string;\n type: GraphEdgeType;\n timestamp?: string;\n count?: number;\n durationMs?: number;\n fromNode?: RuntimeTraceNode;\n toNode?: RuntimeTraceNode;\n metadata?: Record<string, unknown>;\n}\n","import type {\n ArchitectureGraph,\n GraphEdge,\n GraphEdgeType,\n GraphNode,\n GraphSearchResult,\n GraphStats,\n GraphSubgraph,\n} from \"./types.js\";\nimport { graphEdgeTypes, graphNodeTypes } from \"./types.js\";\nimport { ATLAS_VERSION } from \"../version.js\";\n\nconst validNodeTypes = new Set<string>(graphNodeTypes);\nconst validEdgeTypes = new Set<string>(graphEdgeTypes);\n\nexport class GraphBuilder {\n readonly nodes = new Map<string, GraphNode>();\n readonly edges = new Map<string, GraphEdge>();\n\n addNode(node: GraphNode): GraphNode {\n const current = this.nodes.get(node.id);\n if (!current) {\n this.nodes.set(node.id, node);\n return node;\n }\n const merged = {\n ...current,\n ...node,\n metadata: { ...current.metadata, ...node.metadata },\n };\n this.nodes.set(node.id, merged);\n return merged;\n }\n\n addEdge(edge: Omit<GraphEdge, \"id\"> & { id?: string }): GraphEdge | null {\n if (!this.nodes.has(edge.from) || !this.nodes.has(edge.to)) return null;\n const key = `${edge.from}|${edge.type}|${edge.to}|${edge.label ?? \"\"}`;\n const id = edge.id ?? `edge:${encodeURIComponent(key)}`;\n const result: GraphEdge = { ...edge, id };\n this.edges.set(key, result);\n return result;\n }\n\n hasNode(id: string): boolean {\n return this.nodes.has(id);\n }\n\n validate(): string[] {\n const errors: string[] = [];\n for (const node of this.nodes.values()) {\n if (!validNodeTypes.has(String(node.type))) errors.push(`${node.id}: invalid node type ${String(node.type)}`);\n }\n for (const edge of this.edges.values()) {\n if (!validEdgeTypes.has(String(edge.type))) errors.push(`${edge.id}: invalid edge type ${String(edge.type)}`);\n if (!this.nodes.has(edge.from)) errors.push(`${edge.id}: missing source ${edge.from}`);\n if (!this.nodes.has(edge.to)) errors.push(`${edge.id}: missing target ${edge.to}`);\n }\n return errors;\n }\n\n toGraph(project: ArchitectureGraph[\"project\"]): ArchitectureGraph {\n const nodes = [...this.nodes.values()].sort((a, b) => a.id.localeCompare(b.id));\n const edges = [...this.edges.values()].sort((a, b) => a.id.localeCompare(b.id));\n return { version: ATLAS_VERSION, project, nodes, edges, stats: buildStats(nodes, edges) };\n }\n}\n\nfunction increment<T extends string>(target: Partial<Record<T, number>>, key: T) {\n target[key] = (target[key] ?? 0) + 1;\n}\n\nexport function buildStats(nodes: GraphNode[], edges: GraphEdge[]): GraphStats {\n const byNodeType: GraphStats[\"byNodeType\"] = Object.create(null) as GraphStats[\"byNodeType\"];\n const byEdgeType: GraphStats[\"byEdgeType\"] = Object.create(null) as GraphStats[\"byEdgeType\"];\n for (const node of nodes) increment(byNodeType, node.type);\n for (const edge of edges) increment(byEdgeType, edge.type);\n return { totalNodes: nodes.length, totalEdges: edges.length, byNodeType, byEdgeType };\n}\n\nexport class GraphQuery {\n private readonly nodeMap: Map<string, GraphNode>;\n private readonly edgeMap = new Map<string, GraphEdge>();\n private readonly incomingMap = new Map<string, GraphEdge[]>();\n private readonly outgoingMap = new Map<string, GraphEdge[]>();\n private readonly nodesByType = new Map<GraphNode[\"type\"], GraphNode[]>();\n\n constructor(readonly graph: ArchitectureGraph) {\n this.nodeMap = new Map(graph.nodes.map((node) => [node.id, node]));\n for (const node of graph.nodes) {\n const typed = this.nodesByType.get(node.type) ?? [];\n typed.push(node);\n this.nodesByType.set(node.type, typed);\n }\n for (const edge of graph.edges) {\n this.edgeMap.set(edge.id, edge);\n const incoming = this.incomingMap.get(edge.to) ?? [];\n incoming.push(edge);\n this.incomingMap.set(edge.to, incoming);\n const outgoing = this.outgoingMap.get(edge.from) ?? [];\n outgoing.push(edge);\n this.outgoingMap.set(edge.from, outgoing);\n }\n }\n\n findNode(query: string): GraphNode[] {\n const needle = query.trim().toLowerCase();\n if (!needle) return [];\n return this.graph.nodes\n .filter((node) => searchableNode(node).includes(needle))\n .sort((a, b) => scoreNode(b, needle) - scoreNode(a, needle))\n .slice(0, 100);\n }\n\n search(query: string): GraphSearchResult[] {\n const needle = query.trim().toLowerCase();\n if (!needle) return [];\n return this.findNode(query).map((node) => ({\n node,\n score: scoreNode(node, needle),\n matches: matchingFields(node, needle),\n }));\n }\n\n getNode(id: string): GraphNode | null {\n return this.nodeMap.get(id) ?? null;\n }\n\n getIncoming(id: string): GraphEdge[] {\n return this.incomingMap.get(id) ?? [];\n }\n\n getOutgoing(id: string): GraphEdge[] {\n return this.outgoingMap.get(id) ?? [];\n }\n\n findRoutes(): GraphNode[] { return this.byType(\"route\"); }\n findServices(): GraphNode[] { return this.byType(\"service\"); }\n findControllers(): GraphNode[] { return this.byType(\"controller\"); }\n findTables(): GraphNode[] { return this.byType(\"table\"); }\n findSchemas(): GraphNode[] { return this.byType(\"schema\"); }\n findIndexes(): GraphNode[] { return this.byType(\"index\"); }\n findConstraints(): GraphNode[] { return this.byType(\"constraint\"); }\n findMigrations(): GraphNode[] { return this.byType(\"migration\"); }\n findScheduledJobs(): GraphNode[] { return this.byType(\"scheduled_job\"); }\n findWorkflows(): GraphNode[] { return this.byType(\"workflow\"); }\n findDeployments(): GraphNode[] { return this.byType(\"deployment\"); }\n findEnvironments(): GraphNode[] { return this.byType(\"environment\"); }\n findExternalApis(): GraphNode[] { return this.byType(\"external_api\"); }\n findMessageTopics(): GraphNode[] { return this.byType(\"message_topic\"); }\n findQueues(): GraphNode[] { return this.byType(\"queue\"); }\n findProcessors(): GraphNode[] { return this.byType(\"processor\"); }\n\n findTableProfile(tableId: string): GraphSubgraph {\n const table = this.nodeMap.get(tableId);\n if (!table || table.type !== \"table\") return { nodes: [], edges: [] };\n const edgeTypes = new Set<GraphEdgeType>([\"has_column\", \"indexes\", \"contains\", \"references\", \"reads\", \"writes\", \"creates\", \"alters\", \"drops\"]);\n const edges = [...this.getIncoming(tableId), ...this.getOutgoing(tableId)]\n .filter((edge) => edgeTypes.has(edge.type));\n const ids = new Set([tableId, ...edges.flatMap((edge) => [edge.from, edge.to])]);\n return { nodes: [...ids].map((id) => this.nodeMap.get(id)).filter(Boolean) as GraphNode[], edges };\n }\n\n getNeighbors(nodeId: string, depth = 1): GraphSubgraph {\n if (!this.nodeMap.has(nodeId)) return { nodes: [], edges: [] };\n const nodeIds = new Set([nodeId]);\n const edgeIds = new Set<string>();\n let frontier = [nodeId];\n for (let level = 0; level < Math.max(0, depth) && frontier.length; level += 1) {\n const next: string[] = [];\n for (const id of frontier) {\n for (const edge of [...this.getIncoming(id), ...this.getOutgoing(id)]) {\n edgeIds.add(edge.id);\n const neighbor = edge.from === id ? edge.to : edge.from;\n if (!nodeIds.has(neighbor)) { nodeIds.add(neighbor); next.push(neighbor); }\n }\n }\n frontier = next;\n }\n return {\n nodes: [...nodeIds].map((id) => this.nodeMap.get(id)).filter(Boolean) as GraphNode[],\n edges: [...edgeIds].map((id) => this.edgeMap.get(id)).filter(Boolean) as GraphEdge[],\n };\n }\n\n findFlowFromRoute(routeId: string): GraphSubgraph {\n return this.walk(routeId, \"outgoing\", 12, new Set([\n \"handles\", \"calls\", \"reads\", \"writes\", \"uses\", \"connects_to\", \"validates\", \"returns\",\n \"publishes_to\", \"delivers_to\", \"enqueues\", \"processes\",\n ]));\n }\n\n findAsyncFlow(rootId: string): GraphSubgraph {\n const root = this.nodeMap.get(rootId);\n if (!root || ![\"message_topic\", \"queue\"].includes(root.type)) return { nodes: [], edges: [] };\n const flow = this.walk(rootId, \"outgoing\", 12, new Set([\n \"delivers_to\", \"calls\", \"reads\", \"writes\", \"uses\", \"connects_to\", \"publishes_to\", \"enqueues\", \"processes\",\n ]));\n const nodeIds = new Set(flow.nodes.map((node) => node.id));\n const edgeIds = new Set(flow.edges.map((edge) => edge.id));\n for (const edge of this.getIncoming(rootId).filter((item) => [\"publishes_to\", \"enqueues\"].includes(item.type))) {\n nodeIds.add(edge.from);\n edgeIds.add(edge.id);\n }\n return {\n nodes: [...nodeIds].map((id) => this.nodeMap.get(id)).filter(Boolean) as GraphNode[],\n edges: [...edgeIds].map((id) => this.edgeMap.get(id)).filter(Boolean) as GraphEdge[],\n };\n }\n\n findDependencies(nodeId: string, depth = 2): GraphSubgraph {\n return this.walk(nodeId, \"outgoing\", depth);\n }\n\n findDependents(nodeId: string, depth = 2): GraphSubgraph {\n return this.walk(nodeId, \"incoming\", depth);\n }\n\n private byType(type: GraphNode[\"type\"]): GraphNode[] {\n return this.nodesByType.get(type) ?? [];\n }\n\n private walk(\n startId: string,\n direction: \"incoming\" | \"outgoing\",\n depth: number,\n allowedTypes?: Set<GraphEdgeType>,\n ): GraphSubgraph {\n if (!this.nodeMap.has(startId)) return { nodes: [], edges: [] };\n const nodeIds = new Set([startId]);\n const edgeIds = new Set<string>();\n let frontier = [startId];\n for (let level = 0; level < Math.max(0, depth) && frontier.length; level += 1) {\n const next: string[] = [];\n for (const id of frontier) {\n const edges = direction === \"outgoing\" ? this.getOutgoing(id) : this.getIncoming(id);\n for (const edge of edges) {\n if (allowedTypes && !allowedTypes.has(edge.type)) continue;\n edgeIds.add(edge.id);\n const neighbor = direction === \"outgoing\" ? edge.to : edge.from;\n if (!nodeIds.has(neighbor)) {\n nodeIds.add(neighbor);\n next.push(neighbor);\n }\n }\n }\n frontier = next;\n }\n return {\n nodes: [...nodeIds].map((id) => this.nodeMap.get(id)).filter(Boolean) as GraphNode[],\n edges: [...edgeIds].map((id) => this.edgeMap.get(id)).filter(Boolean) as GraphEdge[],\n };\n }\n}\n\nfunction searchableNode(node: GraphNode): string {\n return [node.id, node.type, node.label, node.name, node.file, JSON.stringify(node.metadata ?? {})]\n .filter(Boolean)\n .join(\" \")\n .toLowerCase();\n}\n\nfunction scoreNode(node: GraphNode, needle: string): number {\n const label = node.label.toLowerCase();\n if (label === needle) return 100;\n if (label.startsWith(needle)) return 80;\n if (node.id.toLowerCase().includes(needle)) return 60;\n return 20;\n}\n\nfunction matchingFields(node: GraphNode, needle: string): string[] {\n const fields = {\n id: node.id,\n label: node.label,\n name: node.name ?? \"\",\n type: node.type,\n file: node.file ?? \"\",\n metadata: JSON.stringify(node.metadata ?? {}),\n };\n return Object.entries(fields).filter(([, value]) => value.toLowerCase().includes(needle)).map(([key]) => key);\n}\n"],"mappings":";;;;;AAAO,IAAM,iBAAiB;AAAA,EAC5B;AAAA,EAAW;AAAA,EAAU;AAAA,EAAQ;AAAA,EAAW;AAAA,EAAU;AAAA,EAAc;AAAA,EAChE;AAAA,EAAY;AAAA,EAAc;AAAA,EAAY;AAAA,EAAQ;AAAA,EAAW;AAAA,EAAU;AAAA,EAAO;AAAA,EAAU;AAAA,EAAY;AAAA,EAChG;AAAA,EAAS;AAAA,EAAQ;AAAA,EAAe;AAAA,EAAc;AAAA,EAAa;AAAA,EAC3D;AAAA,EAAS;AAAA,EAAU;AAAA,EAAS;AAAA,EAAwB;AAAA,EACpD;AAAA,EAAkB;AAAA,EAAiB;AAAA,EAAS;AAAA,EAC5C;AAAA,EAAU;AAAA,EAAS;AAAA,EAAc;AAAA,EAAa;AAAA,EAC9C;AAAA,EAAiB;AAAA,EAAY;AAAA,EAAgB;AAAA,EAAe;AAAA,EAC5D;AAAA,EAAa;AAAA,EAAc;AAAA,EAA0B;AAAA,EAAW;AAAA,EAChE;AAAA,EAAU;AAAA,EAAe;AAAA,EAAU;AAAA,EAAQ;AAAA,EAAW;AACxD;AAEO,IAAM,iBAAiB;AAAA,EAC5B;AAAA,EAAY;AAAA,EAAW;AAAA,EAAW;AAAA,EAAY;AAAA,EAAY;AAAA,EAAW;AAAA,EAAc;AAAA,EACnF;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAU;AAAA,EAAW;AAAA,EAAc;AAAA,EAAa;AAAA,EACjE;AAAA,EAAW;AAAA,EAAc;AAAA,EAAe;AAAA,EAAS;AAAA,EAAc;AAAA,EAC/D;AAAA,EAAgB;AAAA,EAAe;AAAA,EAAY;AAAA,EAC3C;AAAA,EAAW;AAAA,EAAU;AAAA,EAAS;AAAA,EAAW;AAAA,EAAa;AAAA,EAAY;AAAA,EAClE;AAAA,EAAa;AAAA,EAAW;AAAA,EAAW;AAAA,EAAc;AAAA,EAAW;AAC9D;;;ACPA,IAAM,iBAAiB,IAAI,IAAY,cAAc;AACrD,IAAM,iBAAiB,IAAI,IAAY,cAAc;AAE9C,IAAM,eAAN,MAAmB;AAAA,EACf,QAAQ,oBAAI,IAAuB;AAAA,EACnC,QAAQ,oBAAI,IAAuB;AAAA,EAE5C,QAAQ,MAA4B;AAClC,UAAM,UAAU,KAAK,MAAM,IAAI,KAAK,EAAE;AACtC,QAAI,CAAC,SAAS;AACZ,WAAK,MAAM,IAAI,KAAK,IAAI,IAAI;AAC5B,aAAO;AAAA,IACT;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,GAAG;AAAA,MACH,UAAU,EAAE,GAAG,QAAQ,UAAU,GAAG,KAAK,SAAS;AAAA,IACpD;AACA,SAAK,MAAM,IAAI,KAAK,IAAI,MAAM;AAC9B,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ,MAAiE;AACvE,QAAI,CAAC,KAAK,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,KAAK,MAAM,IAAI,KAAK,EAAE,EAAG,QAAO;AACnE,UAAM,MAAM,GAAG,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,EAAE,IAAI,KAAK,SAAS,EAAE;AACpE,UAAM,KAAK,KAAK,MAAM,QAAQ,mBAAmB,GAAG,CAAC;AACrD,UAAM,SAAoB,EAAE,GAAG,MAAM,GAAG;AACxC,SAAK,MAAM,IAAI,KAAK,MAAM;AAC1B,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ,IAAqB;AAC3B,WAAO,KAAK,MAAM,IAAI,EAAE;AAAA,EAC1B;AAAA,EAEA,WAAqB;AACnB,UAAM,SAAmB,CAAC;AAC1B,eAAW,QAAQ,KAAK,MAAM,OAAO,GAAG;AACtC,UAAI,CAAC,eAAe,IAAI,OAAO,KAAK,IAAI,CAAC,EAAG,QAAO,KAAK,GAAG,KAAK,EAAE,uBAAuB,OAAO,KAAK,IAAI,CAAC,EAAE;AAAA,IAC9G;AACA,eAAW,QAAQ,KAAK,MAAM,OAAO,GAAG;AACtC,UAAI,CAAC,eAAe,IAAI,OAAO,KAAK,IAAI,CAAC,EAAG,QAAO,KAAK,GAAG,KAAK,EAAE,uBAAuB,OAAO,KAAK,IAAI,CAAC,EAAE;AAC5G,UAAI,CAAC,KAAK,MAAM,IAAI,KAAK,IAAI,EAAG,QAAO,KAAK,GAAG,KAAK,EAAE,oBAAoB,KAAK,IAAI,EAAE;AACrF,UAAI,CAAC,KAAK,MAAM,IAAI,KAAK,EAAE,EAAG,QAAO,KAAK,GAAG,KAAK,EAAE,oBAAoB,KAAK,EAAE,EAAE;AAAA,IACnF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ,SAA0D;AAChE,UAAM,QAAQ,CAAC,GAAG,KAAK,MAAM,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,GAAG,cAAc,EAAE,EAAE,CAAC;AAC9E,UAAM,QAAQ,CAAC,GAAG,KAAK,MAAM,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,GAAG,cAAc,EAAE,EAAE,CAAC;AAC9E,WAAO,EAAE,SAAS,eAAe,SAAS,OAAO,OAAO,OAAO,WAAW,OAAO,KAAK,EAAE;AAAA,EAC1F;AACF;AAEA,SAAS,UAA4B,QAAoC,KAAQ;AAC/E,SAAO,GAAG,KAAK,OAAO,GAAG,KAAK,KAAK;AACrC;AAEO,SAAS,WAAW,OAAoB,OAAgC;AAC7E,QAAM,aAAuC,uBAAO,OAAO,IAAI;AAC/D,QAAM,aAAuC,uBAAO,OAAO,IAAI;AAC/D,aAAW,QAAQ,MAAO,WAAU,YAAY,KAAK,IAAI;AACzD,aAAW,QAAQ,MAAO,WAAU,YAAY,KAAK,IAAI;AACzD,SAAO,EAAE,YAAY,MAAM,QAAQ,YAAY,MAAM,QAAQ,YAAY,WAAW;AACtF;AAEO,IAAM,aAAN,MAAiB;AAAA,EAOtB,YAAqB,OAA0B;AAA1B;AACnB,SAAK,UAAU,IAAI,IAAI,MAAM,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AACjE,eAAW,QAAQ,MAAM,OAAO;AAC9B,YAAM,QAAQ,KAAK,YAAY,IAAI,KAAK,IAAI,KAAK,CAAC;AAClD,YAAM,KAAK,IAAI;AACf,WAAK,YAAY,IAAI,KAAK,MAAM,KAAK;AAAA,IACvC;AACA,eAAW,QAAQ,MAAM,OAAO;AAC9B,WAAK,QAAQ,IAAI,KAAK,IAAI,IAAI;AAC9B,YAAM,WAAW,KAAK,YAAY,IAAI,KAAK,EAAE,KAAK,CAAC;AACnD,eAAS,KAAK,IAAI;AAClB,WAAK,YAAY,IAAI,KAAK,IAAI,QAAQ;AACtC,YAAM,WAAW,KAAK,YAAY,IAAI,KAAK,IAAI,KAAK,CAAC;AACrD,eAAS,KAAK,IAAI;AAClB,WAAK,YAAY,IAAI,KAAK,MAAM,QAAQ;AAAA,IAC1C;AAAA,EACF;AAAA,EAhBqB;AAAA,EANJ;AAAA,EACA,UAAU,oBAAI,IAAuB;AAAA,EACrC,cAAc,oBAAI,IAAyB;AAAA,EAC3C,cAAc,oBAAI,IAAyB;AAAA,EAC3C,cAAc,oBAAI,IAAoC;AAAA,EAoBvE,SAAS,OAA4B;AACnC,UAAM,SAAS,MAAM,KAAK,EAAE,YAAY;AACxC,QAAI,CAAC,OAAQ,QAAO,CAAC;AACrB,WAAO,KAAK,MAAM,MACf,OAAO,CAAC,SAAS,eAAe,IAAI,EAAE,SAAS,MAAM,CAAC,EACtD,KAAK,CAAC,GAAG,MAAM,UAAU,GAAG,MAAM,IAAI,UAAU,GAAG,MAAM,CAAC,EAC1D,MAAM,GAAG,GAAG;AAAA,EACjB;AAAA,EAEA,OAAO,OAAoC;AACzC,UAAM,SAAS,MAAM,KAAK,EAAE,YAAY;AACxC,QAAI,CAAC,OAAQ,QAAO,CAAC;AACrB,WAAO,KAAK,SAAS,KAAK,EAAE,IAAI,CAAC,UAAU;AAAA,MACzC;AAAA,MACA,OAAO,UAAU,MAAM,MAAM;AAAA,MAC7B,SAAS,eAAe,MAAM,MAAM;AAAA,IACtC,EAAE;AAAA,EACJ;AAAA,EAEA,QAAQ,IAA8B;AACpC,WAAO,KAAK,QAAQ,IAAI,EAAE,KAAK;AAAA,EACjC;AAAA,EAEA,YAAY,IAAyB;AACnC,WAAO,KAAK,YAAY,IAAI,EAAE,KAAK,CAAC;AAAA,EACtC;AAAA,EAEA,YAAY,IAAyB;AACnC,WAAO,KAAK,YAAY,IAAI,EAAE,KAAK,CAAC;AAAA,EACtC;AAAA,EAEA,aAA0B;AAAE,WAAO,KAAK,OAAO,OAAO;AAAA,EAAG;AAAA,EACzD,eAA4B;AAAE,WAAO,KAAK,OAAO,SAAS;AAAA,EAAG;AAAA,EAC7D,kBAA+B;AAAE,WAAO,KAAK,OAAO,YAAY;AAAA,EAAG;AAAA,EACnE,aAA0B;AAAE,WAAO,KAAK,OAAO,OAAO;AAAA,EAAG;AAAA,EACzD,cAA2B;AAAE,WAAO,KAAK,OAAO,QAAQ;AAAA,EAAG;AAAA,EAC3D,cAA2B;AAAE,WAAO,KAAK,OAAO,OAAO;AAAA,EAAG;AAAA,EAC1D,kBAA+B;AAAE,WAAO,KAAK,OAAO,YAAY;AAAA,EAAG;AAAA,EACnE,iBAA8B;AAAE,WAAO,KAAK,OAAO,WAAW;AAAA,EAAG;AAAA,EACjE,oBAAiC;AAAE,WAAO,KAAK,OAAO,eAAe;AAAA,EAAG;AAAA,EACxE,gBAA6B;AAAE,WAAO,KAAK,OAAO,UAAU;AAAA,EAAG;AAAA,EAC/D,kBAA+B;AAAE,WAAO,KAAK,OAAO,YAAY;AAAA,EAAG;AAAA,EACnE,mBAAgC;AAAE,WAAO,KAAK,OAAO,aAAa;AAAA,EAAG;AAAA,EACrE,mBAAgC;AAAE,WAAO,KAAK,OAAO,cAAc;AAAA,EAAG;AAAA,EACtE,oBAAiC;AAAE,WAAO,KAAK,OAAO,eAAe;AAAA,EAAG;AAAA,EACxE,aAA0B;AAAE,WAAO,KAAK,OAAO,OAAO;AAAA,EAAG;AAAA,EACzD,iBAA8B;AAAE,WAAO,KAAK,OAAO,WAAW;AAAA,EAAG;AAAA,EAEjE,iBAAiB,SAAgC;AAC/C,UAAM,QAAQ,KAAK,QAAQ,IAAI,OAAO;AACtC,QAAI,CAAC,SAAS,MAAM,SAAS,QAAS,QAAO,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE;AACpE,UAAM,YAAY,oBAAI,IAAmB,CAAC,cAAc,WAAW,YAAY,cAAc,SAAS,UAAU,WAAW,UAAU,OAAO,CAAC;AAC7I,UAAM,QAAQ,CAAC,GAAG,KAAK,YAAY,OAAO,GAAG,GAAG,KAAK,YAAY,OAAO,CAAC,EACtE,OAAO,CAAC,SAAS,UAAU,IAAI,KAAK,IAAI,CAAC;AAC5C,UAAM,MAAM,oBAAI,IAAI,CAAC,SAAS,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,KAAK,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC;AAC/E,WAAO,EAAE,OAAO,CAAC,GAAG,GAAG,EAAE,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,EAAE,CAAC,EAAE,OAAO,OAAO,GAAkB,MAAM;AAAA,EACnG;AAAA,EAEA,aAAa,QAAgB,QAAQ,GAAkB;AACrD,QAAI,CAAC,KAAK,QAAQ,IAAI,MAAM,EAAG,QAAO,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE;AAC7D,UAAM,UAAU,oBAAI,IAAI,CAAC,MAAM,CAAC;AAChC,UAAM,UAAU,oBAAI,IAAY;AAChC,QAAI,WAAW,CAAC,MAAM;AACtB,aAAS,QAAQ,GAAG,QAAQ,KAAK,IAAI,GAAG,KAAK,KAAK,SAAS,QAAQ,SAAS,GAAG;AAC7E,YAAM,OAAiB,CAAC;AACxB,iBAAW,MAAM,UAAU;AACzB,mBAAW,QAAQ,CAAC,GAAG,KAAK,YAAY,EAAE,GAAG,GAAG,KAAK,YAAY,EAAE,CAAC,GAAG;AACrE,kBAAQ,IAAI,KAAK,EAAE;AACnB,gBAAM,WAAW,KAAK,SAAS,KAAK,KAAK,KAAK,KAAK;AACnD,cAAI,CAAC,QAAQ,IAAI,QAAQ,GAAG;AAAE,oBAAQ,IAAI,QAAQ;AAAG,iBAAK,KAAK,QAAQ;AAAA,UAAG;AAAA,QAC5E;AAAA,MACF;AACA,iBAAW;AAAA,IACb;AACA,WAAO;AAAA,MACL,OAAO,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,EAAE,CAAC,EAAE,OAAO,OAAO;AAAA,MACpE,OAAO,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,EAAE,CAAC,EAAE,OAAO,OAAO;AAAA,IACtE;AAAA,EACF;AAAA,EAEA,kBAAkB,SAAgC;AAChD,WAAO,KAAK,KAAK,SAAS,YAAY,IAAI,oBAAI,IAAI;AAAA,MAChD;AAAA,MAAW;AAAA,MAAS;AAAA,MAAS;AAAA,MAAU;AAAA,MAAQ;AAAA,MAAe;AAAA,MAAa;AAAA,MAC3E;AAAA,MAAgB;AAAA,MAAe;AAAA,MAAY;AAAA,IAC7C,CAAC,CAAC;AAAA,EACJ;AAAA,EAEA,cAAc,QAA+B;AAC3C,UAAM,OAAO,KAAK,QAAQ,IAAI,MAAM;AACpC,QAAI,CAAC,QAAQ,CAAC,CAAC,iBAAiB,OAAO,EAAE,SAAS,KAAK,IAAI,EAAG,QAAO,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE;AAC5F,UAAM,OAAO,KAAK,KAAK,QAAQ,YAAY,IAAI,oBAAI,IAAI;AAAA,MACrD;AAAA,MAAe;AAAA,MAAS;AAAA,MAAS;AAAA,MAAU;AAAA,MAAQ;AAAA,MAAe;AAAA,MAAgB;AAAA,MAAY;AAAA,IAChG,CAAC,CAAC;AACF,UAAM,UAAU,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC;AACzD,UAAM,UAAU,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC;AACzD,eAAW,QAAQ,KAAK,YAAY,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,gBAAgB,UAAU,EAAE,SAAS,KAAK,IAAI,CAAC,GAAG;AAC9G,cAAQ,IAAI,KAAK,IAAI;AACrB,cAAQ,IAAI,KAAK,EAAE;AAAA,IACrB;AACA,WAAO;AAAA,MACL,OAAO,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,EAAE,CAAC,EAAE,OAAO,OAAO;AAAA,MACpE,OAAO,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,EAAE,CAAC,EAAE,OAAO,OAAO;AAAA,IACtE;AAAA,EACF;AAAA,EAEA,iBAAiB,QAAgB,QAAQ,GAAkB;AACzD,WAAO,KAAK,KAAK,QAAQ,YAAY,KAAK;AAAA,EAC5C;AAAA,EAEA,eAAe,QAAgB,QAAQ,GAAkB;AACvD,WAAO,KAAK,KAAK,QAAQ,YAAY,KAAK;AAAA,EAC5C;AAAA,EAEQ,OAAO,MAAsC;AACnD,WAAO,KAAK,YAAY,IAAI,IAAI,KAAK,CAAC;AAAA,EACxC;AAAA,EAEQ,KACN,SACA,WACA,OACA,cACe;AACf,QAAI,CAAC,KAAK,QAAQ,IAAI,OAAO,EAAG,QAAO,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE;AAC9D,UAAM,UAAU,oBAAI,IAAI,CAAC,OAAO,CAAC;AACjC,UAAM,UAAU,oBAAI,IAAY;AAChC,QAAI,WAAW,CAAC,OAAO;AACvB,aAAS,QAAQ,GAAG,QAAQ,KAAK,IAAI,GAAG,KAAK,KAAK,SAAS,QAAQ,SAAS,GAAG;AAC7E,YAAM,OAAiB,CAAC;AACxB,iBAAW,MAAM,UAAU;AACzB,cAAM,QAAQ,cAAc,aAAa,KAAK,YAAY,EAAE,IAAI,KAAK,YAAY,EAAE;AACnF,mBAAW,QAAQ,OAAO;AACxB,cAAI,gBAAgB,CAAC,aAAa,IAAI,KAAK,IAAI,EAAG;AAClD,kBAAQ,IAAI,KAAK,EAAE;AACnB,gBAAM,WAAW,cAAc,aAAa,KAAK,KAAK,KAAK;AAC3D,cAAI,CAAC,QAAQ,IAAI,QAAQ,GAAG;AAC1B,oBAAQ,IAAI,QAAQ;AACpB,iBAAK,KAAK,QAAQ;AAAA,UACpB;AAAA,QACF;AAAA,MACF;AACA,iBAAW;AAAA,IACb;AACA,WAAO;AAAA,MACL,OAAO,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,EAAE,CAAC,EAAE,OAAO,OAAO;AAAA,MACpE,OAAO,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,EAAE,CAAC,EAAE,OAAO,OAAO;AAAA,IACtE;AAAA,EACF;AACF;AAEA,SAAS,eAAe,MAAyB;AAC/C,SAAO,CAAC,KAAK,IAAI,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,KAAK,MAAM,KAAK,UAAU,KAAK,YAAY,CAAC,CAAC,CAAC,EAC9F,OAAO,OAAO,EACd,KAAK,GAAG,EACR,YAAY;AACjB;AAEA,SAAS,UAAU,MAAiB,QAAwB;AAC1D,QAAM,QAAQ,KAAK,MAAM,YAAY;AACrC,MAAI,UAAU,OAAQ,QAAO;AAC7B,MAAI,MAAM,WAAW,MAAM,EAAG,QAAO;AACrC,MAAI,KAAK,GAAG,YAAY,EAAE,SAAS,MAAM,EAAG,QAAO;AACnD,SAAO;AACT;AAEA,SAAS,eAAe,MAAiB,QAA0B;AACjE,QAAM,SAAS;AAAA,IACb,IAAI,KAAK;AAAA,IACT,OAAO,KAAK;AAAA,IACZ,MAAM,KAAK,QAAQ;AAAA,IACnB,MAAM,KAAK;AAAA,IACX,MAAM,KAAK,QAAQ;AAAA,IACnB,UAAU,KAAK,UAAU,KAAK,YAAY,CAAC,CAAC;AAAA,EAC9C;AACA,SAAO,OAAO,QAAQ,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,MAAM,YAAY,EAAE,SAAS,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,MAAM,GAAG;AAC9G;","names":[]} |
| // src/version.ts | ||
| var ATLAS_VERSION = "0.4.0"; | ||
| export { | ||
| ATLAS_VERSION | ||
| }; | ||
| //# sourceMappingURL=chunk-YALK4AYO.js.map |
| {"version":3,"sources":["../src/version.ts"],"sourcesContent":["export const ATLAS_VERSION = \"0.4.0\";\n"],"mappings":";AAAO,IAAM,gBAAgB;","names":[]} |
| import { | ||
| GraphQuery | ||
| } from "./chunk-RZYFC6FA.js"; | ||
| import "./chunk-YALK4AYO.js"; | ||
| // src/mcp/server.ts | ||
| import { readFile } from "fs/promises"; | ||
| import { resolve } from "path"; | ||
| import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; | ||
| import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; | ||
| import * as z from "zod/v4"; | ||
| async function startMcpServer(projectPath, outputPath = ".atlas") { | ||
| const graphPath = resolve(projectPath, outputPath, "graph.json"); | ||
| const graph = JSON.parse(await readFile(graphPath, "utf8")); | ||
| const query = new GraphQuery(graph); | ||
| const server = new McpServer({ name: "atlas", version: graph.version }); | ||
| const result = (data) => ({ | ||
| content: [{ type: "text", text: JSON.stringify(data, null, 2) }], | ||
| structuredContent: data | ||
| }); | ||
| server.registerTool("atlas_find_node", { | ||
| description: "Find architecture nodes by name, label, type, file, route, or metadata.", | ||
| inputSchema: { query: z.string().min(1) } | ||
| }, async ({ query: value }) => result({ results: query.findNode(value) })); | ||
| server.registerTool("atlas_get_node", { | ||
| description: "Get one node and its incoming, outgoing, and method relationships.", | ||
| inputSchema: { id: z.string().min(1) } | ||
| }, async ({ id }) => { | ||
| const node = query.getNode(id); | ||
| const outgoing = query.getOutgoing(id); | ||
| const methods = outgoing.filter((edge) => edge.type === "has_method").map((edge) => query.getNode(edge.to)).filter(Boolean); | ||
| return result({ node, incoming: query.getIncoming(id), outgoing, methods }); | ||
| }); | ||
| server.registerTool("atlas_get_dependencies", { | ||
| description: "Traverse outgoing architecture dependencies from a node.", | ||
| inputSchema: { id: z.string().min(1), depth: z.number().int().min(1).max(10).default(2) } | ||
| }, async ({ id, depth }) => result({ graph: query.findDependencies(id, depth) })); | ||
| server.registerTool("atlas_get_dependents", { | ||
| description: "Traverse incoming architecture dependents of a node.", | ||
| inputSchema: { id: z.string().min(1), depth: z.number().int().min(1).max(10).default(2) } | ||
| }, async ({ id, depth }) => result({ graph: query.findDependents(id, depth) })); | ||
| server.registerTool("atlas_find_routes", { description: "List all detected HTTP routes." }, async () => result({ routes: query.findRoutes() })); | ||
| server.registerTool("atlas_find_flow", { | ||
| description: "Find a route and return its route-to-controller-to-service-to-data flow.", | ||
| inputSchema: { query: z.string().min(1) } | ||
| }, async ({ query: value }) => { | ||
| const route = query.findNode(value).find((node) => node.type === "route"); | ||
| return result({ route: route ?? null, flow: route ? query.findFlowFromRoute(route.id) : { nodes: [], edges: [] } }); | ||
| }); | ||
| server.registerTool("atlas_find_tables", { description: "List detected database tables." }, async () => result({ tables: query.findTables() })); | ||
| server.registerTool("atlas_find_data_model", { description: "List schemas, tables, indexes, constraints, migrations, and ClickHouse structures." }, async () => result({ | ||
| schemas: query.findSchemas(), | ||
| tables: query.findTables(), | ||
| indexes: query.findIndexes(), | ||
| constraints: query.findConstraints(), | ||
| migrations: query.findMigrations() | ||
| })); | ||
| server.registerTool("atlas_get_table_profile", { | ||
| description: "Return a table with its columns, indexes, constraints, relations, migrations, readers, and writers.", | ||
| inputSchema: { query: z.string().min(1) } | ||
| }, async ({ query: value }) => { | ||
| const table = query.findNode(value).find((node) => node.type === "table"); | ||
| return result({ table: table ?? null, profile: table ? query.findTableProfile(table.id) : { nodes: [], edges: [] } }); | ||
| }); | ||
| server.registerTool("atlas_find_migrations", { description: "List migrations and the structures they create, alter, or drop." }, async () => result({ migrations: query.findMigrations() })); | ||
| server.registerTool("atlas_find_external_apis", { description: "List detected external API hosts." }, async () => result({ externalApis: query.findExternalApis() })); | ||
| server.registerTool("atlas_find_async_flows", { | ||
| description: "List detected Kafka or RabbitMQ topics, Bull/BullMQ queues, and background processors." | ||
| }, async () => result({ topics: query.findMessageTopics(), queues: query.findQueues(), processors: query.findProcessors() })); | ||
| server.registerTool("atlas_find_async_flow", { | ||
| description: "Find a message topic or queue and return publishers, consumers, processors, and downstream calls.", | ||
| inputSchema: { query: z.string().min(1) } | ||
| }, async ({ query: value }) => { | ||
| const root = query.findNode(value).find((node) => ["message_topic", "queue"].includes(node.type)); | ||
| return result({ root: root ?? null, flow: root ? query.findAsyncFlow(root.id) : { nodes: [], edges: [] } }); | ||
| }); | ||
| server.registerTool("atlas_find_schedules", { description: "List cron, interval, timeout, repeatable queue, and Kubernetes scheduled jobs." }, async () => result({ schedules: query.findScheduledJobs() })); | ||
| server.registerTool("atlas_find_delivery", { description: "List CI/CD workflows and runtime deployments." }, async () => result({ workflows: query.findWorkflows(), deployments: query.findDeployments() })); | ||
| server.registerTool("atlas_find_environments", { description: "List detected development, staging, production, and custom runtime environments." }, async () => result({ environments: query.findEnvironments() })); | ||
| server.registerTool("atlas_search", { | ||
| description: "Search the complete architecture graph.", | ||
| inputSchema: { query: z.string().min(1) } | ||
| }, async ({ query: value }) => result({ results: query.search(value) })); | ||
| server.registerTool("atlas_project_summary", { description: "Return project identity and graph statistics." }, async () => result({ project: graph.project, stats: graph.stats })); | ||
| await server.connect(new StdioServerTransport()); | ||
| console.error(`Atlas MCP server ready: ${graphPath}`); | ||
| } | ||
| export { | ||
| startMcpServer | ||
| }; | ||
| //# sourceMappingURL=server-F6FACXZS.js.map |
| {"version":3,"sources":["../src/mcp/server.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport * as z from \"zod/v4\";\nimport { GraphQuery } from \"../core/graph.js\";\nimport type { ArchitectureGraph } from \"../core/types.js\";\n\nexport async function startMcpServer(projectPath: string, outputPath = \".atlas\"): Promise<void> {\n const graphPath = resolve(projectPath, outputPath, \"graph.json\");\n const graph = JSON.parse(await readFile(graphPath, \"utf8\")) as ArchitectureGraph;\n const query = new GraphQuery(graph);\n const server = new McpServer({ name: \"atlas\", version: graph.version });\n const result = (data: Record<string, unknown>) => ({\n content: [{ type: \"text\" as const, text: JSON.stringify(data, null, 2) }],\n structuredContent: data,\n });\n\n server.registerTool(\"atlas_find_node\", {\n description: \"Find architecture nodes by name, label, type, file, route, or metadata.\",\n inputSchema: { query: z.string().min(1) },\n }, async ({ query: value }) => result({ results: query.findNode(value) }));\n\n server.registerTool(\"atlas_get_node\", {\n description: \"Get one node and its incoming, outgoing, and method relationships.\",\n inputSchema: { id: z.string().min(1) },\n }, async ({ id }) => {\n const node = query.getNode(id);\n const outgoing = query.getOutgoing(id);\n const methods = outgoing.filter((edge) => edge.type === \"has_method\").map((edge) => query.getNode(edge.to)).filter(Boolean);\n return result({ node, incoming: query.getIncoming(id), outgoing, methods });\n });\n\n server.registerTool(\"atlas_get_dependencies\", {\n description: \"Traverse outgoing architecture dependencies from a node.\",\n inputSchema: { id: z.string().min(1), depth: z.number().int().min(1).max(10).default(2) },\n }, async ({ id, depth }) => result({ graph: query.findDependencies(id, depth) }));\n\n server.registerTool(\"atlas_get_dependents\", {\n description: \"Traverse incoming architecture dependents of a node.\",\n inputSchema: { id: z.string().min(1), depth: z.number().int().min(1).max(10).default(2) },\n }, async ({ id, depth }) => result({ graph: query.findDependents(id, depth) }));\n\n server.registerTool(\"atlas_find_routes\", { description: \"List all detected HTTP routes.\" }, async () => result({ routes: query.findRoutes() }));\n\n server.registerTool(\"atlas_find_flow\", {\n description: \"Find a route and return its route-to-controller-to-service-to-data flow.\",\n inputSchema: { query: z.string().min(1) },\n }, async ({ query: value }) => {\n const route = query.findNode(value).find((node) => node.type === \"route\");\n return result({ route: route ?? null, flow: route ? query.findFlowFromRoute(route.id) : { nodes: [], edges: [] } });\n });\n\n server.registerTool(\"atlas_find_tables\", { description: \"List detected database tables.\" }, async () => result({ tables: query.findTables() }));\n server.registerTool(\"atlas_find_data_model\", { description: \"List schemas, tables, indexes, constraints, migrations, and ClickHouse structures.\" }, async () => result({\n schemas: query.findSchemas(), tables: query.findTables(), indexes: query.findIndexes(), constraints: query.findConstraints(), migrations: query.findMigrations(),\n }));\n server.registerTool(\"atlas_get_table_profile\", {\n description: \"Return a table with its columns, indexes, constraints, relations, migrations, readers, and writers.\",\n inputSchema: { query: z.string().min(1) },\n }, async ({ query: value }) => {\n const table = query.findNode(value).find((node) => node.type === \"table\");\n return result({ table: table ?? null, profile: table ? query.findTableProfile(table.id) : { nodes: [], edges: [] } });\n });\n server.registerTool(\"atlas_find_migrations\", { description: \"List migrations and the structures they create, alter, or drop.\" }, async () => result({ migrations: query.findMigrations() }));\n server.registerTool(\"atlas_find_external_apis\", { description: \"List detected external API hosts.\" }, async () => result({ externalApis: query.findExternalApis() }));\n\n server.registerTool(\"atlas_find_async_flows\", {\n description: \"List detected Kafka or RabbitMQ topics, Bull/BullMQ queues, and background processors.\",\n }, async () => result({ topics: query.findMessageTopics(), queues: query.findQueues(), processors: query.findProcessors() }));\n\n server.registerTool(\"atlas_find_async_flow\", {\n description: \"Find a message topic or queue and return publishers, consumers, processors, and downstream calls.\",\n inputSchema: { query: z.string().min(1) },\n }, async ({ query: value }) => {\n const root = query.findNode(value).find((node) => [\"message_topic\", \"queue\"].includes(node.type));\n return result({ root: root ?? null, flow: root ? query.findAsyncFlow(root.id) : { nodes: [], edges: [] } });\n });\n\n server.registerTool(\"atlas_find_schedules\", { description: \"List cron, interval, timeout, repeatable queue, and Kubernetes scheduled jobs.\" }, async () => result({ schedules: query.findScheduledJobs() }));\n server.registerTool(\"atlas_find_delivery\", { description: \"List CI/CD workflows and runtime deployments.\" }, async () => result({ workflows: query.findWorkflows(), deployments: query.findDeployments() }));\n server.registerTool(\"atlas_find_environments\", { description: \"List detected development, staging, production, and custom runtime environments.\" }, async () => result({ environments: query.findEnvironments() }));\n\n server.registerTool(\"atlas_search\", {\n description: \"Search the complete architecture graph.\",\n inputSchema: { query: z.string().min(1) },\n }, async ({ query: value }) => result({ results: query.search(value) }));\n\n server.registerTool(\"atlas_project_summary\", { description: \"Return project identity and graph statistics.\" }, async () => result({ project: graph.project, stats: graph.stats }));\n\n await server.connect(new StdioServerTransport());\n console.error(`Atlas MCP server ready: ${graphPath}`);\n}\n"],"mappings":"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","names":[]} |
| #!/usr/bin/env node | ||
| import { | ||
| ATLAS_VERSION | ||
| } from "../chunk-DWXUUWMF.js"; | ||
| } from "../chunk-YALK4AYO.js"; | ||
@@ -56,3 +56,3 @@ // src/cli/index.ts | ||
| program.command("mcp").description("Start the Atlas MCP server over stdio").option("-p, --path <path>", "project root", ".").option("-o, --output <path>", "Atlas output directory relative to the project", ".atlas").action(async ({ path, output }) => { | ||
| const { startMcpServer } = await import("../server-WM7LIGZ5.js"); | ||
| const { startMcpServer } = await import("../server-F6FACXZS.js"); | ||
| await startMcpServer(resolve(path), output); | ||
@@ -59,0 +59,0 @@ }); |
+1
-1
| { | ||
| "name": "@dthreads/atlas", | ||
| "version": "0.3.0", | ||
| "version": "0.4.0", | ||
| "description": "Architecture intelligence for NestJS codebases.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
+9
-3
@@ -254,6 +254,12 @@ # Atlas | ||
| request and asynchronous flows, complete data catalog and focused table ERD, | ||
| migrations, scheduled jobs, source files, risks, and Delivery & Runtime. Delivery | ||
| switches independently between development, staging, and production, so unrelated | ||
| environment topology is not mixed into one unreadable map. | ||
| migrations, scheduled jobs, source files, risks, deployment, runtime topology, | ||
| environment comparison, and configuration contracts. | ||
| Operations are deliberately separated. **Deployment** follows CI/CD jobs, Docker | ||
| build stages, images, and releases. **Runtime** follows ingress, services, workloads, | ||
| containers, ConfigMaps, and Secret names. Both switch independently between | ||
| development, staging, and production. **Environments** compares those scopes without | ||
| mixing their complete topologies into one unreadable map. Secret values are never | ||
| stored or displayed. | ||
| Large scenes use adaptive detail: off-screen elements are not rendered, distant | ||
@@ -260,0 +266,0 @@ cards switch to a lightweight form, edge labels appear when useful, and animation |
| import { | ||
| ATLAS_VERSION | ||
| } from "./chunk-DWXUUWMF.js"; | ||
| // src/core/types.ts | ||
| var graphNodeTypes = [ | ||
| "project", | ||
| "folder", | ||
| "file", | ||
| "package", | ||
| "module", | ||
| "controller", | ||
| "service", | ||
| "provider", | ||
| "repository", | ||
| "use_case", | ||
| "port", | ||
| "adapter", | ||
| "entity", | ||
| "dto", | ||
| "method", | ||
| "function", | ||
| "route", | ||
| "guard", | ||
| "pipe", | ||
| "interceptor", | ||
| "middleware", | ||
| "decorator", | ||
| "database", | ||
| "table", | ||
| "column", | ||
| "model", | ||
| "environment_variable", | ||
| "external_api", | ||
| "message_broker", | ||
| "message_topic", | ||
| "queue", | ||
| "processor", | ||
| "schema", | ||
| "index", | ||
| "constraint", | ||
| "migration", | ||
| "materialized_view", | ||
| "scheduled_job", | ||
| "workflow", | ||
| "pipeline_job", | ||
| "build_stage", | ||
| "container_image", | ||
| "container", | ||
| "deployment", | ||
| "infrastructure_service", | ||
| "ingress", | ||
| "config_map", | ||
| "secret", | ||
| "environment", | ||
| "config", | ||
| "test", | ||
| "library", | ||
| "risk" | ||
| ]; | ||
| var graphEdgeTypes = [ | ||
| "contains", | ||
| "imports", | ||
| "exports", | ||
| "declares", | ||
| "provides", | ||
| "injects", | ||
| "implements", | ||
| "calls", | ||
| "uses", | ||
| "reads", | ||
| "writes", | ||
| "handles", | ||
| "depends_on", | ||
| "decorates", | ||
| "validates", | ||
| "returns", | ||
| "references", | ||
| "connects_to", | ||
| "tests", | ||
| "has_method", | ||
| "has_column", | ||
| "publishes_to", | ||
| "delivers_to", | ||
| "enqueues", | ||
| "processes", | ||
| "creates", | ||
| "alters", | ||
| "drops", | ||
| "indexes", | ||
| "schedules", | ||
| "triggers", | ||
| "builds", | ||
| "publishes", | ||
| "deploys", | ||
| "exposes", | ||
| "configures", | ||
| "runs_in", | ||
| "targets" | ||
| ]; | ||
| // src/core/graph.ts | ||
| var validNodeTypes = new Set(graphNodeTypes); | ||
| var validEdgeTypes = new Set(graphEdgeTypes); | ||
| var GraphBuilder = class { | ||
| nodes = /* @__PURE__ */ new Map(); | ||
| edges = /* @__PURE__ */ new Map(); | ||
| addNode(node) { | ||
| const current = this.nodes.get(node.id); | ||
| if (!current) { | ||
| this.nodes.set(node.id, node); | ||
| return node; | ||
| } | ||
| const merged = { | ||
| ...current, | ||
| ...node, | ||
| metadata: { ...current.metadata, ...node.metadata } | ||
| }; | ||
| this.nodes.set(node.id, merged); | ||
| return merged; | ||
| } | ||
| addEdge(edge) { | ||
| if (!this.nodes.has(edge.from) || !this.nodes.has(edge.to)) return null; | ||
| const key = `${edge.from}|${edge.type}|${edge.to}|${edge.label ?? ""}`; | ||
| const id = edge.id ?? `edge:${encodeURIComponent(key)}`; | ||
| const result = { ...edge, id }; | ||
| this.edges.set(key, result); | ||
| return result; | ||
| } | ||
| hasNode(id) { | ||
| return this.nodes.has(id); | ||
| } | ||
| validate() { | ||
| const errors = []; | ||
| for (const node of this.nodes.values()) { | ||
| if (!validNodeTypes.has(String(node.type))) errors.push(`${node.id}: invalid node type ${String(node.type)}`); | ||
| } | ||
| for (const edge of this.edges.values()) { | ||
| if (!validEdgeTypes.has(String(edge.type))) errors.push(`${edge.id}: invalid edge type ${String(edge.type)}`); | ||
| if (!this.nodes.has(edge.from)) errors.push(`${edge.id}: missing source ${edge.from}`); | ||
| if (!this.nodes.has(edge.to)) errors.push(`${edge.id}: missing target ${edge.to}`); | ||
| } | ||
| return errors; | ||
| } | ||
| toGraph(project) { | ||
| const nodes = [...this.nodes.values()].sort((a, b) => a.id.localeCompare(b.id)); | ||
| const edges = [...this.edges.values()].sort((a, b) => a.id.localeCompare(b.id)); | ||
| return { version: ATLAS_VERSION, project, nodes, edges, stats: buildStats(nodes, edges) }; | ||
| } | ||
| }; | ||
| function increment(target, key) { | ||
| target[key] = (target[key] ?? 0) + 1; | ||
| } | ||
| function buildStats(nodes, edges) { | ||
| const byNodeType = /* @__PURE__ */ Object.create(null); | ||
| const byEdgeType = /* @__PURE__ */ Object.create(null); | ||
| for (const node of nodes) increment(byNodeType, node.type); | ||
| for (const edge of edges) increment(byEdgeType, edge.type); | ||
| return { totalNodes: nodes.length, totalEdges: edges.length, byNodeType, byEdgeType }; | ||
| } | ||
| var GraphQuery = class { | ||
| constructor(graph) { | ||
| this.graph = graph; | ||
| this.nodeMap = new Map(graph.nodes.map((node) => [node.id, node])); | ||
| for (const node of graph.nodes) { | ||
| const typed = this.nodesByType.get(node.type) ?? []; | ||
| typed.push(node); | ||
| this.nodesByType.set(node.type, typed); | ||
| } | ||
| for (const edge of graph.edges) { | ||
| this.edgeMap.set(edge.id, edge); | ||
| const incoming = this.incomingMap.get(edge.to) ?? []; | ||
| incoming.push(edge); | ||
| this.incomingMap.set(edge.to, incoming); | ||
| const outgoing = this.outgoingMap.get(edge.from) ?? []; | ||
| outgoing.push(edge); | ||
| this.outgoingMap.set(edge.from, outgoing); | ||
| } | ||
| } | ||
| graph; | ||
| nodeMap; | ||
| edgeMap = /* @__PURE__ */ new Map(); | ||
| incomingMap = /* @__PURE__ */ new Map(); | ||
| outgoingMap = /* @__PURE__ */ new Map(); | ||
| nodesByType = /* @__PURE__ */ new Map(); | ||
| findNode(query) { | ||
| const needle = query.trim().toLowerCase(); | ||
| if (!needle) return []; | ||
| return this.graph.nodes.filter((node) => searchableNode(node).includes(needle)).sort((a, b) => scoreNode(b, needle) - scoreNode(a, needle)).slice(0, 100); | ||
| } | ||
| search(query) { | ||
| const needle = query.trim().toLowerCase(); | ||
| if (!needle) return []; | ||
| return this.findNode(query).map((node) => ({ | ||
| node, | ||
| score: scoreNode(node, needle), | ||
| matches: matchingFields(node, needle) | ||
| })); | ||
| } | ||
| getNode(id) { | ||
| return this.nodeMap.get(id) ?? null; | ||
| } | ||
| getIncoming(id) { | ||
| return this.incomingMap.get(id) ?? []; | ||
| } | ||
| getOutgoing(id) { | ||
| return this.outgoingMap.get(id) ?? []; | ||
| } | ||
| findRoutes() { | ||
| return this.byType("route"); | ||
| } | ||
| findServices() { | ||
| return this.byType("service"); | ||
| } | ||
| findControllers() { | ||
| return this.byType("controller"); | ||
| } | ||
| findTables() { | ||
| return this.byType("table"); | ||
| } | ||
| findSchemas() { | ||
| return this.byType("schema"); | ||
| } | ||
| findIndexes() { | ||
| return this.byType("index"); | ||
| } | ||
| findConstraints() { | ||
| return this.byType("constraint"); | ||
| } | ||
| findMigrations() { | ||
| return this.byType("migration"); | ||
| } | ||
| findScheduledJobs() { | ||
| return this.byType("scheduled_job"); | ||
| } | ||
| findWorkflows() { | ||
| return this.byType("workflow"); | ||
| } | ||
| findDeployments() { | ||
| return this.byType("deployment"); | ||
| } | ||
| findEnvironments() { | ||
| return this.byType("environment"); | ||
| } | ||
| findExternalApis() { | ||
| return this.byType("external_api"); | ||
| } | ||
| findMessageTopics() { | ||
| return this.byType("message_topic"); | ||
| } | ||
| findQueues() { | ||
| return this.byType("queue"); | ||
| } | ||
| findProcessors() { | ||
| return this.byType("processor"); | ||
| } | ||
| findTableProfile(tableId) { | ||
| const table = this.nodeMap.get(tableId); | ||
| if (!table || table.type !== "table") return { nodes: [], edges: [] }; | ||
| const edgeTypes = /* @__PURE__ */ new Set(["has_column", "indexes", "contains", "references", "reads", "writes", "creates", "alters", "drops"]); | ||
| const edges = [...this.getIncoming(tableId), ...this.getOutgoing(tableId)].filter((edge) => edgeTypes.has(edge.type)); | ||
| const ids = /* @__PURE__ */ new Set([tableId, ...edges.flatMap((edge) => [edge.from, edge.to])]); | ||
| return { nodes: [...ids].map((id) => this.nodeMap.get(id)).filter(Boolean), edges }; | ||
| } | ||
| getNeighbors(nodeId, depth = 1) { | ||
| if (!this.nodeMap.has(nodeId)) return { nodes: [], edges: [] }; | ||
| const nodeIds = /* @__PURE__ */ new Set([nodeId]); | ||
| const edgeIds = /* @__PURE__ */ new Set(); | ||
| let frontier = [nodeId]; | ||
| for (let level = 0; level < Math.max(0, depth) && frontier.length; level += 1) { | ||
| const next = []; | ||
| for (const id of frontier) { | ||
| for (const edge of [...this.getIncoming(id), ...this.getOutgoing(id)]) { | ||
| edgeIds.add(edge.id); | ||
| const neighbor = edge.from === id ? edge.to : edge.from; | ||
| if (!nodeIds.has(neighbor)) { | ||
| nodeIds.add(neighbor); | ||
| next.push(neighbor); | ||
| } | ||
| } | ||
| } | ||
| frontier = next; | ||
| } | ||
| return { | ||
| nodes: [...nodeIds].map((id) => this.nodeMap.get(id)).filter(Boolean), | ||
| edges: [...edgeIds].map((id) => this.edgeMap.get(id)).filter(Boolean) | ||
| }; | ||
| } | ||
| findFlowFromRoute(routeId) { | ||
| return this.walk(routeId, "outgoing", 12, /* @__PURE__ */ new Set([ | ||
| "handles", | ||
| "calls", | ||
| "reads", | ||
| "writes", | ||
| "uses", | ||
| "connects_to", | ||
| "validates", | ||
| "returns", | ||
| "publishes_to", | ||
| "delivers_to", | ||
| "enqueues", | ||
| "processes" | ||
| ])); | ||
| } | ||
| findAsyncFlow(rootId) { | ||
| const root = this.nodeMap.get(rootId); | ||
| if (!root || !["message_topic", "queue"].includes(root.type)) return { nodes: [], edges: [] }; | ||
| const flow = this.walk(rootId, "outgoing", 12, /* @__PURE__ */ new Set([ | ||
| "delivers_to", | ||
| "calls", | ||
| "reads", | ||
| "writes", | ||
| "uses", | ||
| "connects_to", | ||
| "publishes_to", | ||
| "enqueues", | ||
| "processes" | ||
| ])); | ||
| const nodeIds = new Set(flow.nodes.map((node) => node.id)); | ||
| const edgeIds = new Set(flow.edges.map((edge) => edge.id)); | ||
| for (const edge of this.getIncoming(rootId).filter((item) => ["publishes_to", "enqueues"].includes(item.type))) { | ||
| nodeIds.add(edge.from); | ||
| edgeIds.add(edge.id); | ||
| } | ||
| return { | ||
| nodes: [...nodeIds].map((id) => this.nodeMap.get(id)).filter(Boolean), | ||
| edges: [...edgeIds].map((id) => this.edgeMap.get(id)).filter(Boolean) | ||
| }; | ||
| } | ||
| findDependencies(nodeId, depth = 2) { | ||
| return this.walk(nodeId, "outgoing", depth); | ||
| } | ||
| findDependents(nodeId, depth = 2) { | ||
| return this.walk(nodeId, "incoming", depth); | ||
| } | ||
| byType(type) { | ||
| return this.nodesByType.get(type) ?? []; | ||
| } | ||
| walk(startId, direction, depth, allowedTypes) { | ||
| if (!this.nodeMap.has(startId)) return { nodes: [], edges: [] }; | ||
| const nodeIds = /* @__PURE__ */ new Set([startId]); | ||
| const edgeIds = /* @__PURE__ */ new Set(); | ||
| let frontier = [startId]; | ||
| for (let level = 0; level < Math.max(0, depth) && frontier.length; level += 1) { | ||
| const next = []; | ||
| for (const id of frontier) { | ||
| const edges = direction === "outgoing" ? this.getOutgoing(id) : this.getIncoming(id); | ||
| for (const edge of edges) { | ||
| if (allowedTypes && !allowedTypes.has(edge.type)) continue; | ||
| edgeIds.add(edge.id); | ||
| const neighbor = direction === "outgoing" ? edge.to : edge.from; | ||
| if (!nodeIds.has(neighbor)) { | ||
| nodeIds.add(neighbor); | ||
| next.push(neighbor); | ||
| } | ||
| } | ||
| } | ||
| frontier = next; | ||
| } | ||
| return { | ||
| nodes: [...nodeIds].map((id) => this.nodeMap.get(id)).filter(Boolean), | ||
| edges: [...edgeIds].map((id) => this.edgeMap.get(id)).filter(Boolean) | ||
| }; | ||
| } | ||
| }; | ||
| function searchableNode(node) { | ||
| return [node.id, node.type, node.label, node.name, node.file, JSON.stringify(node.metadata ?? {})].filter(Boolean).join(" ").toLowerCase(); | ||
| } | ||
| function scoreNode(node, needle) { | ||
| const label = node.label.toLowerCase(); | ||
| if (label === needle) return 100; | ||
| if (label.startsWith(needle)) return 80; | ||
| if (node.id.toLowerCase().includes(needle)) return 60; | ||
| return 20; | ||
| } | ||
| function matchingFields(node, needle) { | ||
| const fields = { | ||
| id: node.id, | ||
| label: node.label, | ||
| name: node.name ?? "", | ||
| type: node.type, | ||
| file: node.file ?? "", | ||
| metadata: JSON.stringify(node.metadata ?? {}) | ||
| }; | ||
| return Object.entries(fields).filter(([, value]) => value.toLowerCase().includes(needle)).map(([key]) => key); | ||
| } | ||
| export { | ||
| graphNodeTypes, | ||
| graphEdgeTypes, | ||
| GraphBuilder, | ||
| buildStats, | ||
| GraphQuery | ||
| }; | ||
| //# sourceMappingURL=chunk-4WKRCGRX.js.map |
| {"version":3,"sources":["../src/core/types.ts","../src/core/graph.ts"],"sourcesContent":["export const graphNodeTypes = [\n \"project\", \"folder\", \"file\", \"package\", \"module\", \"controller\", \"service\",\n \"provider\", \"repository\", \"use_case\", \"port\", \"adapter\", \"entity\", \"dto\", \"method\", \"function\", \"route\",\n \"guard\", \"pipe\", \"interceptor\", \"middleware\", \"decorator\", \"database\",\n \"table\", \"column\", \"model\", \"environment_variable\", \"external_api\",\n \"message_broker\", \"message_topic\", \"queue\", \"processor\",\n \"schema\", \"index\", \"constraint\", \"migration\", \"materialized_view\",\n \"scheduled_job\", \"workflow\", \"pipeline_job\", \"build_stage\", \"container_image\",\n \"container\", \"deployment\", \"infrastructure_service\", \"ingress\", \"config_map\",\n \"secret\", \"environment\", \"config\", \"test\", \"library\", \"risk\",\n] as const;\n\nexport const graphEdgeTypes = [\n \"contains\", \"imports\", \"exports\", \"declares\", \"provides\", \"injects\", \"implements\", \"calls\",\n \"uses\", \"reads\", \"writes\", \"handles\", \"depends_on\", \"decorates\", \"validates\",\n \"returns\", \"references\", \"connects_to\", \"tests\", \"has_method\", \"has_column\",\n \"publishes_to\", \"delivers_to\", \"enqueues\", \"processes\",\n \"creates\", \"alters\", \"drops\", \"indexes\", \"schedules\", \"triggers\", \"builds\",\n \"publishes\", \"deploys\", \"exposes\", \"configures\", \"runs_in\", \"targets\",\n] as const;\n\nexport type GraphNodeType = (typeof graphNodeTypes)[number];\nexport type GraphEdgeType = (typeof graphEdgeTypes)[number];\nexport type GraphSourceType =\n | \"static_analysis\"\n | \"ast\"\n | \"config\"\n | \"package_json\"\n | \"heuristic\"\n | \"runtime\"\n | \"manual\";\n\nexport interface SourceLocation {\n file: string;\n startLine?: number;\n endLine?: number;\n}\n\nexport interface GraphNode {\n id: string;\n type: GraphNodeType;\n label: string;\n name?: string;\n file?: string;\n language?: string;\n framework?: string;\n sourceLocation?: SourceLocation;\n confidence?: number;\n source?: GraphSourceType;\n metadata?: Record<string, unknown>;\n}\n\nexport interface GraphEdge {\n id: string;\n from: string;\n to: string;\n type: GraphEdgeType;\n label?: string;\n confidence?: number;\n source?: GraphSourceType;\n metadata?: Record<string, unknown>;\n}\n\nexport interface DetectedStack {\n name: string;\n confidence: number;\n evidence: string[];\n}\n\nexport interface GraphStats {\n totalNodes: number;\n totalEdges: number;\n byNodeType: Partial<Record<GraphNodeType, number>>;\n byEdgeType: Partial<Record<GraphEdgeType, number>>;\n}\n\nexport interface ArchitectureGraph {\n version: string;\n project: {\n name: string;\n root: string;\n detectedStacks: string[];\n createdAt: string;\n };\n nodes: GraphNode[];\n edges: GraphEdge[];\n stats: GraphStats;\n}\n\nexport interface ScannedFile {\n absolutePath: string;\n path: string;\n extension: string;\n size: number;\n hash?: string;\n lastModified: string;\n}\n\nexport interface ScanMetadata {\n version: string;\n projectName: string;\n projectRoot: string;\n scanStartedAt: string;\n scanFinishedAt: string;\n durationMs: number;\n filesScanned: number;\n filesIgnored: number;\n filesHashed?: number;\n filesReused?: number;\n cacheHit?: boolean;\n inputFingerprint?: string;\n analysisCacheVersion?: number;\n viewerFingerprint?: string;\n runtimeEvents?: number;\n runtimeMergedAt?: string;\n runtimeFingerprint?: string;\n detectedStacks: DetectedStack[];\n}\n\nexport type RiskSeverity = \"low\" | \"medium\" | \"high\" | \"critical\";\n\nexport interface ArchitectureRisk {\n id: string;\n type: string;\n severity: RiskSeverity;\n title: string;\n description: string;\n recommendation: string;\n nodeId?: string;\n file?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface GraphSubgraph {\n nodes: GraphNode[];\n edges: GraphEdge[];\n}\n\nexport interface GraphSearchResult {\n node: GraphNode;\n score: number;\n matches: string[];\n}\n\nexport type ScanProgressStage =\n | \"scan_files\"\n | \"detect_stack\"\n | \"parse_architecture\"\n | \"build_graph\"\n | \"detect_risks\"\n | \"write_outputs\";\n\nexport interface ScanProgress {\n stage: ScanProgressStage;\n message: string;\n}\n\nexport interface ScanOptions {\n projectPath: string;\n outputPath?: string;\n incremental?: boolean;\n debug?: boolean;\n onProgress?: (progress: ScanProgress) => void;\n}\n\nexport interface ScanResult {\n graph: ArchitectureGraph;\n metadata: ScanMetadata;\n risks: ArchitectureRisk[];\n outputPath: string;\n}\n\nexport interface RuntimeTraceNode {\n id: string;\n type: GraphNodeType;\n label?: string;\n file?: string;\n}\n\nexport interface RuntimeTraceEvent {\n from: string;\n to: string;\n type: GraphEdgeType;\n timestamp?: string;\n count?: number;\n durationMs?: number;\n fromNode?: RuntimeTraceNode;\n toNode?: RuntimeTraceNode;\n metadata?: Record<string, unknown>;\n}\n","import type {\n ArchitectureGraph,\n GraphEdge,\n GraphEdgeType,\n GraphNode,\n GraphSearchResult,\n GraphStats,\n GraphSubgraph,\n} from \"./types.js\";\nimport { graphEdgeTypes, graphNodeTypes } from \"./types.js\";\nimport { ATLAS_VERSION } from \"../version.js\";\n\nconst validNodeTypes = new Set<string>(graphNodeTypes);\nconst validEdgeTypes = new Set<string>(graphEdgeTypes);\n\nexport class GraphBuilder {\n readonly nodes = new Map<string, GraphNode>();\n readonly edges = new Map<string, GraphEdge>();\n\n addNode(node: GraphNode): GraphNode {\n const current = this.nodes.get(node.id);\n if (!current) {\n this.nodes.set(node.id, node);\n return node;\n }\n const merged = {\n ...current,\n ...node,\n metadata: { ...current.metadata, ...node.metadata },\n };\n this.nodes.set(node.id, merged);\n return merged;\n }\n\n addEdge(edge: Omit<GraphEdge, \"id\"> & { id?: string }): GraphEdge | null {\n if (!this.nodes.has(edge.from) || !this.nodes.has(edge.to)) return null;\n const key = `${edge.from}|${edge.type}|${edge.to}|${edge.label ?? \"\"}`;\n const id = edge.id ?? `edge:${encodeURIComponent(key)}`;\n const result: GraphEdge = { ...edge, id };\n this.edges.set(key, result);\n return result;\n }\n\n hasNode(id: string): boolean {\n return this.nodes.has(id);\n }\n\n validate(): string[] {\n const errors: string[] = [];\n for (const node of this.nodes.values()) {\n if (!validNodeTypes.has(String(node.type))) errors.push(`${node.id}: invalid node type ${String(node.type)}`);\n }\n for (const edge of this.edges.values()) {\n if (!validEdgeTypes.has(String(edge.type))) errors.push(`${edge.id}: invalid edge type ${String(edge.type)}`);\n if (!this.nodes.has(edge.from)) errors.push(`${edge.id}: missing source ${edge.from}`);\n if (!this.nodes.has(edge.to)) errors.push(`${edge.id}: missing target ${edge.to}`);\n }\n return errors;\n }\n\n toGraph(project: ArchitectureGraph[\"project\"]): ArchitectureGraph {\n const nodes = [...this.nodes.values()].sort((a, b) => a.id.localeCompare(b.id));\n const edges = [...this.edges.values()].sort((a, b) => a.id.localeCompare(b.id));\n return { version: ATLAS_VERSION, project, nodes, edges, stats: buildStats(nodes, edges) };\n }\n}\n\nfunction increment<T extends string>(target: Partial<Record<T, number>>, key: T) {\n target[key] = (target[key] ?? 0) + 1;\n}\n\nexport function buildStats(nodes: GraphNode[], edges: GraphEdge[]): GraphStats {\n const byNodeType: GraphStats[\"byNodeType\"] = Object.create(null) as GraphStats[\"byNodeType\"];\n const byEdgeType: GraphStats[\"byEdgeType\"] = Object.create(null) as GraphStats[\"byEdgeType\"];\n for (const node of nodes) increment(byNodeType, node.type);\n for (const edge of edges) increment(byEdgeType, edge.type);\n return { totalNodes: nodes.length, totalEdges: edges.length, byNodeType, byEdgeType };\n}\n\nexport class GraphQuery {\n private readonly nodeMap: Map<string, GraphNode>;\n private readonly edgeMap = new Map<string, GraphEdge>();\n private readonly incomingMap = new Map<string, GraphEdge[]>();\n private readonly outgoingMap = new Map<string, GraphEdge[]>();\n private readonly nodesByType = new Map<GraphNode[\"type\"], GraphNode[]>();\n\n constructor(readonly graph: ArchitectureGraph) {\n this.nodeMap = new Map(graph.nodes.map((node) => [node.id, node]));\n for (const node of graph.nodes) {\n const typed = this.nodesByType.get(node.type) ?? [];\n typed.push(node);\n this.nodesByType.set(node.type, typed);\n }\n for (const edge of graph.edges) {\n this.edgeMap.set(edge.id, edge);\n const incoming = this.incomingMap.get(edge.to) ?? [];\n incoming.push(edge);\n this.incomingMap.set(edge.to, incoming);\n const outgoing = this.outgoingMap.get(edge.from) ?? [];\n outgoing.push(edge);\n this.outgoingMap.set(edge.from, outgoing);\n }\n }\n\n findNode(query: string): GraphNode[] {\n const needle = query.trim().toLowerCase();\n if (!needle) return [];\n return this.graph.nodes\n .filter((node) => searchableNode(node).includes(needle))\n .sort((a, b) => scoreNode(b, needle) - scoreNode(a, needle))\n .slice(0, 100);\n }\n\n search(query: string): GraphSearchResult[] {\n const needle = query.trim().toLowerCase();\n if (!needle) return [];\n return this.findNode(query).map((node) => ({\n node,\n score: scoreNode(node, needle),\n matches: matchingFields(node, needle),\n }));\n }\n\n getNode(id: string): GraphNode | null {\n return this.nodeMap.get(id) ?? null;\n }\n\n getIncoming(id: string): GraphEdge[] {\n return this.incomingMap.get(id) ?? [];\n }\n\n getOutgoing(id: string): GraphEdge[] {\n return this.outgoingMap.get(id) ?? [];\n }\n\n findRoutes(): GraphNode[] { return this.byType(\"route\"); }\n findServices(): GraphNode[] { return this.byType(\"service\"); }\n findControllers(): GraphNode[] { return this.byType(\"controller\"); }\n findTables(): GraphNode[] { return this.byType(\"table\"); }\n findSchemas(): GraphNode[] { return this.byType(\"schema\"); }\n findIndexes(): GraphNode[] { return this.byType(\"index\"); }\n findConstraints(): GraphNode[] { return this.byType(\"constraint\"); }\n findMigrations(): GraphNode[] { return this.byType(\"migration\"); }\n findScheduledJobs(): GraphNode[] { return this.byType(\"scheduled_job\"); }\n findWorkflows(): GraphNode[] { return this.byType(\"workflow\"); }\n findDeployments(): GraphNode[] { return this.byType(\"deployment\"); }\n findEnvironments(): GraphNode[] { return this.byType(\"environment\"); }\n findExternalApis(): GraphNode[] { return this.byType(\"external_api\"); }\n findMessageTopics(): GraphNode[] { return this.byType(\"message_topic\"); }\n findQueues(): GraphNode[] { return this.byType(\"queue\"); }\n findProcessors(): GraphNode[] { return this.byType(\"processor\"); }\n\n findTableProfile(tableId: string): GraphSubgraph {\n const table = this.nodeMap.get(tableId);\n if (!table || table.type !== \"table\") return { nodes: [], edges: [] };\n const edgeTypes = new Set<GraphEdgeType>([\"has_column\", \"indexes\", \"contains\", \"references\", \"reads\", \"writes\", \"creates\", \"alters\", \"drops\"]);\n const edges = [...this.getIncoming(tableId), ...this.getOutgoing(tableId)]\n .filter((edge) => edgeTypes.has(edge.type));\n const ids = new Set([tableId, ...edges.flatMap((edge) => [edge.from, edge.to])]);\n return { nodes: [...ids].map((id) => this.nodeMap.get(id)).filter(Boolean) as GraphNode[], edges };\n }\n\n getNeighbors(nodeId: string, depth = 1): GraphSubgraph {\n if (!this.nodeMap.has(nodeId)) return { nodes: [], edges: [] };\n const nodeIds = new Set([nodeId]);\n const edgeIds = new Set<string>();\n let frontier = [nodeId];\n for (let level = 0; level < Math.max(0, depth) && frontier.length; level += 1) {\n const next: string[] = [];\n for (const id of frontier) {\n for (const edge of [...this.getIncoming(id), ...this.getOutgoing(id)]) {\n edgeIds.add(edge.id);\n const neighbor = edge.from === id ? edge.to : edge.from;\n if (!nodeIds.has(neighbor)) { nodeIds.add(neighbor); next.push(neighbor); }\n }\n }\n frontier = next;\n }\n return {\n nodes: [...nodeIds].map((id) => this.nodeMap.get(id)).filter(Boolean) as GraphNode[],\n edges: [...edgeIds].map((id) => this.edgeMap.get(id)).filter(Boolean) as GraphEdge[],\n };\n }\n\n findFlowFromRoute(routeId: string): GraphSubgraph {\n return this.walk(routeId, \"outgoing\", 12, new Set([\n \"handles\", \"calls\", \"reads\", \"writes\", \"uses\", \"connects_to\", \"validates\", \"returns\",\n \"publishes_to\", \"delivers_to\", \"enqueues\", \"processes\",\n ]));\n }\n\n findAsyncFlow(rootId: string): GraphSubgraph {\n const root = this.nodeMap.get(rootId);\n if (!root || ![\"message_topic\", \"queue\"].includes(root.type)) return { nodes: [], edges: [] };\n const flow = this.walk(rootId, \"outgoing\", 12, new Set([\n \"delivers_to\", \"calls\", \"reads\", \"writes\", \"uses\", \"connects_to\", \"publishes_to\", \"enqueues\", \"processes\",\n ]));\n const nodeIds = new Set(flow.nodes.map((node) => node.id));\n const edgeIds = new Set(flow.edges.map((edge) => edge.id));\n for (const edge of this.getIncoming(rootId).filter((item) => [\"publishes_to\", \"enqueues\"].includes(item.type))) {\n nodeIds.add(edge.from);\n edgeIds.add(edge.id);\n }\n return {\n nodes: [...nodeIds].map((id) => this.nodeMap.get(id)).filter(Boolean) as GraphNode[],\n edges: [...edgeIds].map((id) => this.edgeMap.get(id)).filter(Boolean) as GraphEdge[],\n };\n }\n\n findDependencies(nodeId: string, depth = 2): GraphSubgraph {\n return this.walk(nodeId, \"outgoing\", depth);\n }\n\n findDependents(nodeId: string, depth = 2): GraphSubgraph {\n return this.walk(nodeId, \"incoming\", depth);\n }\n\n private byType(type: GraphNode[\"type\"]): GraphNode[] {\n return this.nodesByType.get(type) ?? [];\n }\n\n private walk(\n startId: string,\n direction: \"incoming\" | \"outgoing\",\n depth: number,\n allowedTypes?: Set<GraphEdgeType>,\n ): GraphSubgraph {\n if (!this.nodeMap.has(startId)) return { nodes: [], edges: [] };\n const nodeIds = new Set([startId]);\n const edgeIds = new Set<string>();\n let frontier = [startId];\n for (let level = 0; level < Math.max(0, depth) && frontier.length; level += 1) {\n const next: string[] = [];\n for (const id of frontier) {\n const edges = direction === \"outgoing\" ? this.getOutgoing(id) : this.getIncoming(id);\n for (const edge of edges) {\n if (allowedTypes && !allowedTypes.has(edge.type)) continue;\n edgeIds.add(edge.id);\n const neighbor = direction === \"outgoing\" ? edge.to : edge.from;\n if (!nodeIds.has(neighbor)) {\n nodeIds.add(neighbor);\n next.push(neighbor);\n }\n }\n }\n frontier = next;\n }\n return {\n nodes: [...nodeIds].map((id) => this.nodeMap.get(id)).filter(Boolean) as GraphNode[],\n edges: [...edgeIds].map((id) => this.edgeMap.get(id)).filter(Boolean) as GraphEdge[],\n };\n }\n}\n\nfunction searchableNode(node: GraphNode): string {\n return [node.id, node.type, node.label, node.name, node.file, JSON.stringify(node.metadata ?? {})]\n .filter(Boolean)\n .join(\" \")\n .toLowerCase();\n}\n\nfunction scoreNode(node: GraphNode, needle: string): number {\n const label = node.label.toLowerCase();\n if (label === needle) return 100;\n if (label.startsWith(needle)) return 80;\n if (node.id.toLowerCase().includes(needle)) return 60;\n return 20;\n}\n\nfunction matchingFields(node: GraphNode, needle: string): string[] {\n const fields = {\n id: node.id,\n label: node.label,\n name: node.name ?? \"\",\n type: node.type,\n file: node.file ?? \"\",\n metadata: JSON.stringify(node.metadata ?? {}),\n };\n return Object.entries(fields).filter(([, value]) => value.toLowerCase().includes(needle)).map(([key]) => key);\n}\n"],"mappings":"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","names":[]} |
| // src/version.ts | ||
| var ATLAS_VERSION = "0.3.0"; | ||
| export { | ||
| ATLAS_VERSION | ||
| }; | ||
| //# sourceMappingURL=chunk-DWXUUWMF.js.map |
| {"version":3,"sources":["../src/version.ts"],"sourcesContent":["export const ATLAS_VERSION = \"0.3.0\";\n"],"mappings":";AAAO,IAAM,gBAAgB;","names":[]} |
| import { | ||
| GraphQuery | ||
| } from "./chunk-4WKRCGRX.js"; | ||
| import "./chunk-DWXUUWMF.js"; | ||
| // src/mcp/server.ts | ||
| import { readFile } from "fs/promises"; | ||
| import { resolve } from "path"; | ||
| import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; | ||
| import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; | ||
| import * as z from "zod/v4"; | ||
| async function startMcpServer(projectPath, outputPath = ".atlas") { | ||
| const graphPath = resolve(projectPath, outputPath, "graph.json"); | ||
| const graph = JSON.parse(await readFile(graphPath, "utf8")); | ||
| const query = new GraphQuery(graph); | ||
| const server = new McpServer({ name: "atlas", version: graph.version }); | ||
| const result = (data) => ({ | ||
| content: [{ type: "text", text: JSON.stringify(data, null, 2) }], | ||
| structuredContent: data | ||
| }); | ||
| server.registerTool("atlas_find_node", { | ||
| description: "Find architecture nodes by name, label, type, file, route, or metadata.", | ||
| inputSchema: { query: z.string().min(1) } | ||
| }, async ({ query: value }) => result({ results: query.findNode(value) })); | ||
| server.registerTool("atlas_get_node", { | ||
| description: "Get one node and its incoming, outgoing, and method relationships.", | ||
| inputSchema: { id: z.string().min(1) } | ||
| }, async ({ id }) => { | ||
| const node = query.getNode(id); | ||
| const outgoing = query.getOutgoing(id); | ||
| const methods = outgoing.filter((edge) => edge.type === "has_method").map((edge) => query.getNode(edge.to)).filter(Boolean); | ||
| return result({ node, incoming: query.getIncoming(id), outgoing, methods }); | ||
| }); | ||
| server.registerTool("atlas_get_dependencies", { | ||
| description: "Traverse outgoing architecture dependencies from a node.", | ||
| inputSchema: { id: z.string().min(1), depth: z.number().int().min(1).max(10).default(2) } | ||
| }, async ({ id, depth }) => result({ graph: query.findDependencies(id, depth) })); | ||
| server.registerTool("atlas_get_dependents", { | ||
| description: "Traverse incoming architecture dependents of a node.", | ||
| inputSchema: { id: z.string().min(1), depth: z.number().int().min(1).max(10).default(2) } | ||
| }, async ({ id, depth }) => result({ graph: query.findDependents(id, depth) })); | ||
| server.registerTool("atlas_find_routes", { description: "List all detected HTTP routes." }, async () => result({ routes: query.findRoutes() })); | ||
| server.registerTool("atlas_find_flow", { | ||
| description: "Find a route and return its route-to-controller-to-service-to-data flow.", | ||
| inputSchema: { query: z.string().min(1) } | ||
| }, async ({ query: value }) => { | ||
| const route = query.findNode(value).find((node) => node.type === "route"); | ||
| return result({ route: route ?? null, flow: route ? query.findFlowFromRoute(route.id) : { nodes: [], edges: [] } }); | ||
| }); | ||
| server.registerTool("atlas_find_tables", { description: "List detected database tables." }, async () => result({ tables: query.findTables() })); | ||
| server.registerTool("atlas_find_data_model", { description: "List schemas, tables, indexes, constraints, migrations, and ClickHouse structures." }, async () => result({ | ||
| schemas: query.findSchemas(), | ||
| tables: query.findTables(), | ||
| indexes: query.findIndexes(), | ||
| constraints: query.findConstraints(), | ||
| migrations: query.findMigrations() | ||
| })); | ||
| server.registerTool("atlas_get_table_profile", { | ||
| description: "Return a table with its columns, indexes, constraints, relations, migrations, readers, and writers.", | ||
| inputSchema: { query: z.string().min(1) } | ||
| }, async ({ query: value }) => { | ||
| const table = query.findNode(value).find((node) => node.type === "table"); | ||
| return result({ table: table ?? null, profile: table ? query.findTableProfile(table.id) : { nodes: [], edges: [] } }); | ||
| }); | ||
| server.registerTool("atlas_find_migrations", { description: "List migrations and the structures they create, alter, or drop." }, async () => result({ migrations: query.findMigrations() })); | ||
| server.registerTool("atlas_find_external_apis", { description: "List detected external API hosts." }, async () => result({ externalApis: query.findExternalApis() })); | ||
| server.registerTool("atlas_find_async_flows", { | ||
| description: "List detected Kafka or RabbitMQ topics, Bull/BullMQ queues, and background processors." | ||
| }, async () => result({ topics: query.findMessageTopics(), queues: query.findQueues(), processors: query.findProcessors() })); | ||
| server.registerTool("atlas_find_async_flow", { | ||
| description: "Find a message topic or queue and return publishers, consumers, processors, and downstream calls.", | ||
| inputSchema: { query: z.string().min(1) } | ||
| }, async ({ query: value }) => { | ||
| const root = query.findNode(value).find((node) => ["message_topic", "queue"].includes(node.type)); | ||
| return result({ root: root ?? null, flow: root ? query.findAsyncFlow(root.id) : { nodes: [], edges: [] } }); | ||
| }); | ||
| server.registerTool("atlas_find_schedules", { description: "List cron, interval, timeout, repeatable queue, and Kubernetes scheduled jobs." }, async () => result({ schedules: query.findScheduledJobs() })); | ||
| server.registerTool("atlas_find_delivery", { description: "List CI/CD workflows and runtime deployments." }, async () => result({ workflows: query.findWorkflows(), deployments: query.findDeployments() })); | ||
| server.registerTool("atlas_find_environments", { description: "List detected development, staging, production, and custom runtime environments." }, async () => result({ environments: query.findEnvironments() })); | ||
| server.registerTool("atlas_search", { | ||
| description: "Search the complete architecture graph.", | ||
| inputSchema: { query: z.string().min(1) } | ||
| }, async ({ query: value }) => result({ results: query.search(value) })); | ||
| server.registerTool("atlas_project_summary", { description: "Return project identity and graph statistics." }, async () => result({ project: graph.project, stats: graph.stats })); | ||
| await server.connect(new StdioServerTransport()); | ||
| console.error(`Atlas MCP server ready: ${graphPath}`); | ||
| } | ||
| export { | ||
| startMcpServer | ||
| }; | ||
| //# sourceMappingURL=server-WM7LIGZ5.js.map |
| {"version":3,"sources":["../src/mcp/server.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport * as z from \"zod/v4\";\nimport { GraphQuery } from \"../core/graph.js\";\nimport type { ArchitectureGraph } from \"../core/types.js\";\n\nexport async function startMcpServer(projectPath: string, outputPath = \".atlas\"): Promise<void> {\n const graphPath = resolve(projectPath, outputPath, \"graph.json\");\n const graph = JSON.parse(await readFile(graphPath, \"utf8\")) as ArchitectureGraph;\n const query = new GraphQuery(graph);\n const server = new McpServer({ name: \"atlas\", version: graph.version });\n const result = (data: Record<string, unknown>) => ({\n content: [{ type: \"text\" as const, text: JSON.stringify(data, null, 2) }],\n structuredContent: data,\n });\n\n server.registerTool(\"atlas_find_node\", {\n description: \"Find architecture nodes by name, label, type, file, route, or metadata.\",\n inputSchema: { query: z.string().min(1) },\n }, async ({ query: value }) => result({ results: query.findNode(value) }));\n\n server.registerTool(\"atlas_get_node\", {\n description: \"Get one node and its incoming, outgoing, and method relationships.\",\n inputSchema: { id: z.string().min(1) },\n }, async ({ id }) => {\n const node = query.getNode(id);\n const outgoing = query.getOutgoing(id);\n const methods = outgoing.filter((edge) => edge.type === \"has_method\").map((edge) => query.getNode(edge.to)).filter(Boolean);\n return result({ node, incoming: query.getIncoming(id), outgoing, methods });\n });\n\n server.registerTool(\"atlas_get_dependencies\", {\n description: \"Traverse outgoing architecture dependencies from a node.\",\n inputSchema: { id: z.string().min(1), depth: z.number().int().min(1).max(10).default(2) },\n }, async ({ id, depth }) => result({ graph: query.findDependencies(id, depth) }));\n\n server.registerTool(\"atlas_get_dependents\", {\n description: \"Traverse incoming architecture dependents of a node.\",\n inputSchema: { id: z.string().min(1), depth: z.number().int().min(1).max(10).default(2) },\n }, async ({ id, depth }) => result({ graph: query.findDependents(id, depth) }));\n\n server.registerTool(\"atlas_find_routes\", { description: \"List all detected HTTP routes.\" }, async () => result({ routes: query.findRoutes() }));\n\n server.registerTool(\"atlas_find_flow\", {\n description: \"Find a route and return its route-to-controller-to-service-to-data flow.\",\n inputSchema: { query: z.string().min(1) },\n }, async ({ query: value }) => {\n const route = query.findNode(value).find((node) => node.type === \"route\");\n return result({ route: route ?? null, flow: route ? query.findFlowFromRoute(route.id) : { nodes: [], edges: [] } });\n });\n\n server.registerTool(\"atlas_find_tables\", { description: \"List detected database tables.\" }, async () => result({ tables: query.findTables() }));\n server.registerTool(\"atlas_find_data_model\", { description: \"List schemas, tables, indexes, constraints, migrations, and ClickHouse structures.\" }, async () => result({\n schemas: query.findSchemas(), tables: query.findTables(), indexes: query.findIndexes(), constraints: query.findConstraints(), migrations: query.findMigrations(),\n }));\n server.registerTool(\"atlas_get_table_profile\", {\n description: \"Return a table with its columns, indexes, constraints, relations, migrations, readers, and writers.\",\n inputSchema: { query: z.string().min(1) },\n }, async ({ query: value }) => {\n const table = query.findNode(value).find((node) => node.type === \"table\");\n return result({ table: table ?? null, profile: table ? query.findTableProfile(table.id) : { nodes: [], edges: [] } });\n });\n server.registerTool(\"atlas_find_migrations\", { description: \"List migrations and the structures they create, alter, or drop.\" }, async () => result({ migrations: query.findMigrations() }));\n server.registerTool(\"atlas_find_external_apis\", { description: \"List detected external API hosts.\" }, async () => result({ externalApis: query.findExternalApis() }));\n\n server.registerTool(\"atlas_find_async_flows\", {\n description: \"List detected Kafka or RabbitMQ topics, Bull/BullMQ queues, and background processors.\",\n }, async () => result({ topics: query.findMessageTopics(), queues: query.findQueues(), processors: query.findProcessors() }));\n\n server.registerTool(\"atlas_find_async_flow\", {\n description: \"Find a message topic or queue and return publishers, consumers, processors, and downstream calls.\",\n inputSchema: { query: z.string().min(1) },\n }, async ({ query: value }) => {\n const root = query.findNode(value).find((node) => [\"message_topic\", \"queue\"].includes(node.type));\n return result({ root: root ?? null, flow: root ? query.findAsyncFlow(root.id) : { nodes: [], edges: [] } });\n });\n\n server.registerTool(\"atlas_find_schedules\", { description: \"List cron, interval, timeout, repeatable queue, and Kubernetes scheduled jobs.\" }, async () => result({ schedules: query.findScheduledJobs() }));\n server.registerTool(\"atlas_find_delivery\", { description: \"List CI/CD workflows and runtime deployments.\" }, async () => result({ workflows: query.findWorkflows(), deployments: query.findDeployments() }));\n server.registerTool(\"atlas_find_environments\", { description: \"List detected development, staging, production, and custom runtime environments.\" }, async () => result({ environments: query.findEnvironments() }));\n\n server.registerTool(\"atlas_search\", {\n description: \"Search the complete architecture graph.\",\n inputSchema: { query: z.string().min(1) },\n }, async ({ query: value }) => result({ results: query.search(value) }));\n\n server.registerTool(\"atlas_project_summary\", { description: \"Return project identity and graph statistics.\" }, async () => result({ project: graph.project, stats: graph.stats }));\n\n await server.connect(new StdioServerTransport());\n console.error(`Atlas MCP server ready: ${graphPath}`);\n}\n"],"mappings":"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","names":[]} |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
1369644
0.52%381
1.6%