Módulos del analizador
Cómo CodeAtlas escanea tu proyecto, construye un grafo arquitectónico y lo visualiza de forma interactiva.
Flujo del análisis
Seleccionar carpeta
El usuario elige la carpeta raíz del proyecto. Electron abre el diálogo nativo de selección mediante el canal IPC select-folder.
Validar y analizar
El proceso principal valida que la ruta exista, tenga permisos de lectura y sea una carpeta, lanza el análisis en un worker_threads dedicado (electron/analyzerWorker.ts) y reenvía al renderer los eventos de progreso. analyzeProject() nunca corre en el hilo principal, así que la ventana no se congela.
Escaneo del código
analyzer/index.ts orquesta los análisis — árbol de archivos, package.json, variables de entorno, rutas Express y NestJS e imports — recolectando los archivos fuente una sola vez para compartirlos entre detectores.
Construcción del grafo
graph.ts consolida todo en un ArchitectureGraph: un modelo de dominio serializable con nodos y relaciones tipados.
Visualización
La interfaz muestra el árbol de archivos, los paneles de datos y el mapa interactivo de módulos construido con React Flow.
Módulos del analizador
El analizador vive en src/analyzer/ y usa únicamente APIs de Node (fs y path), por lo que puede moverse a un worker o sustituirse sin reescribir la interfaz.
scanner.ts Árbol de archivos y package.json Recorre el proyecto ignorando dependencias y artefactos de build (node_modules, .git, dist…). Ordena carpetas antes que archivos y extrae la información de cada package.json: nombre, versión, scripts, dependencias y devDependencies. También recolecta una sola vez la lista de archivos fuente (collectSourceFiles()) que comparten los detectores.
envscan.ts Variables de entorno Detecta usos de process.env.X y process.env["X"] en código JS/TS y agrupa por nombre, indicando en qué archivos aparece cada variable.
routescan.ts Rutas Express Detecta llamadas .get(), .post(), .put(), .patch(), .delete(), .all() y .use() sobre receivers como app, router o *Router, registrando método HTTP, ruta, archivo y línea.
nestscan.ts Rutas NestJS Detecta decoradores @Controller, @Get, @Post, @Put, @Patch, @Delete, @Options, @Head y @All. Soporta decoradores multilínea, forma objeto ({ path: "x", version: "1" }) y parentesis balanceados con strings y escapes. Compone el prefijo del controlador con la subruta de cada método y registrando método HTTP, ruta completa, archivo y línea.
importscan.ts Imports y require Detecta imports ES estáticos y dinámicos, re-exports (export … from) y require(). Los specifiers relativos se resuelven probando el candidato directo, luego con cada extensión (.js, .jsx, .ts, .tsx, .mjs, .cjs, .json) y finalmente index con cada extensión en carpetas.
graph.ts Grafo arquitectónico Construye el modelo de dominio a partir de árbol, paquetes, variables, rutas e imports. Genera IDs estables y normalizados, independientes del sistema operativo.
types.ts Contratos del análisis Define los tipos compartidos: FileNode, PackageInfo, EnvVarUsage, RouteInfo, ImportInfo, los nodos y aristas del grafo, ArchitectureGraph, AnalysisResult y el modelo de progreso.
index.ts Orquestación analyzeProject(rootPath, onProgress) ejecuta los análisis en orden y devuelve un AnalysisResult completo, incluyendo el grafo arquitectónico. El callback de progreso avanza por 5 fases con pesos: scan (0%→45%), env (45%→62%), routes (62%→80%), imports (80%→93%), graph (93%→100%). Cada fase tiene un mensaje descriptivo en español.
Límites de los detectores
Los detectores son heurísticos basados en expresiones regulares, no en un AST real: pueden arrojar falsos positivos y negativos. Son útiles para orientarse en un proyecto desconocido, no para auditorías exhaustivas.
Express (routescan.ts) - Solo llamadas de una línea
- Solo rutas literales entre comillas
- Solo receptores app, router, api o terminados en Router/App
- app.use() y comentarios pueden generar falsos positivos
NestJS (nestscan.ts) - Decoradores solo al inicio de línea
- Argumentos de ruta solo literales
- Requiere un @Controller activo previo en el archivo
- Con varios @Controller, rige el último prefijo
Variables de entorno (envscan.ts) - Solo process.env.X y process.env["X"]
- No detecta destructuring ni acceso dinámico
- Los comentarios cuentan como uso
- No lee archivos .env
Imports (importscan.ts) - Solo comillas simples y dobles
- Imports multilínea no detectados
- node_modules y alias de tsconfig quedan sin target
- Los comentarios con imports se detectan
Escáner (scanner.ts) - Lista fija de carpetas ignoradas
- No sigue symlinks
- Archivos ocultos omitidos salvo .env
- Snapshot estático, sin watch
El detalle completo de cada límite está documentado en la sección Límites de los detectores heurísticos (v0.1) del README del repositorio.
Modelo de grafo
ArchitectureGraph es un modelo serializable (esquema v1) independiente de la visualización. Sus IDs y rutas están normalizados para que el mismo análisis sea estable en distintos sistemas operativos.
Tipos de nodo
- file Cada archivo del proyecto
- route Ruta Express detectada
- environment Variable de entorno usada
- package package.json del proyecto
- dependency Dependencia declarada (runtime o development)
Tipos de relación
- declares-route Un archivo declara una ruta
- uses-env Un archivo usa una variable de entorno
- depends-on Un package depende de una dependencia, con versión y scope
- imports Un archivo importa otro módulo
Visualización interactiva
El mapa de módulos se construye con React Flow en dos capas: el mapeo de datos y el lienzo.
graphMapper.ts Mapeo de datos buildFlowGraph() convierte el ArchitectureGraph en nodos y aristas de React Flow usando dagre para el layout jerárquico:
-
Layout direccional izquierda-a-derecha (
rankdir: 'LR') con posiciones deterministas -
Nodos de 220×64px, separación entre nodos (
nodesep: 36) y entre rangos (ranksep: 140) - El layout se determina por las conexiones del grafo, no por el tipo de nodo
- Colores por tipo: file (#4FB6A8), route (#C9A15A), environment (#D97757), package (#EDE6D6), dependency (#8A96A8)
| Nodo | Color | Arista | Color |
|---|---|---|---|
| file | #4FB6A8 | declares-route | #C9A15A |
| route | #C9A15A | declares-route | #C9A15A |
| environment | #D97757 | declares-route | #C9A15A |
| package | #EDE6D6 | declares-route | #C9A15A |
| dependency | #8A96A8 | declares-route | #C9A15A |
GraphView.tsx Lienzo interactivo Renderiza el grafo con React Flow: arrastra para moverte y usa la rueda para hacer zoom. Incluye minimapa coloreado por tipo de nodo, controles de zoom/encuadre, fondo de puntos y nodos personalizados con chip de tipo, etiqueta y detalle. Cada tipo de arista tiene su propio color y flecha.
TypeToggleBar Filtrado de tipos
Barra de toggles que permite mostrar u ocultar tipos de nodo en el mapa. Los nodos de tipo dependency están ocultos por defecto para reducir ruido visual.
- Cada chip muestra nombre del tipo, dot de color y conteo de nodos
- Al ocultar un tipo, las aristas conectadas también se eliminan del grafo
NodeDetails Panel de detalles Al hacer clic en un nodo, aparece un panel lateral con información detallada:
- Chip de tipo con color, título del nodo y botón "Abrir en editor"
- Filas de detalle específicas por tipo (ruta, método, versión, manifiesto)
- Listas "Depende de" y "Usado por" con aristas salientes/entrantes
computeHighlight() Sistema de highlight Cuando se selecciona un nodo, se resaltan sus dependencias directas y se atenúan los demás:
-
Nodo seleccionado: borde dorado y sombra (
module-node-selected) - Nodos no relacionados: atenuados con opacity 0.1
- Aristas relacionadas se animan, las no relacionadas se atenúan (opacity 0.08)
GraphOverview Panel de resumen Antes del mapa interactivo, se muestra un resumen del grafo con la versión del esquema, conteos por tipo de nodo, tipos de relación disponibles y relaciones de ejemplo (hasta 2 por tipo de arista).
Electron e IPC
main.ts Proceso principal
Crea la ventana y expone los canales IPC con validación de entradas. El análisis corre en un worker_threads dedicado:
Ciclo de vida de workers:
-
Conjunto
analysisWorkerspara rastrear workers activos -
Handler
before-quittermina todos los workers antes de cerrar -
Patrón
settledpara evitar resoluciones múltiples del Promise
analyzerWorker.ts Worker thread
Recibe {rootPath} via postMessage, ejecuta analyzeProject() y reporta:
-
{ type: 'progress', progress }para actualizaciones -
{ type: 'result', data }al completar -
{ type: 'error', error }si falla
preload.ts API segura
El renderer no accede directamente a Node.js. contextBridge expone una API mínima en window.codeatlas con selectFolder(), analyzeProject(path, onProgress), detectEditors() y openInEditor(), usando contextIsolation activo.
ensureDesktopIntegration() Integración en Linux
En Linux AppImage, crea un archivo .desktop en ~/.local/share/applications/, copia el icono a ~/.local/share/icons/hicolor/512x512/apps/ y ejecuta gtk-update-icon-cache. Es best-effort: si falla, la app arranca igual.
Pruebas
La suite usa proyectos temporales aislados: no analiza ni modifica repositorios reales.
npm run check verifica tipos, ejecuta las pruebas y construye la aplicación.
tests/analyzer/
- scanner.test.ts — árbol, conteos, orden e ignorados
- envscan.test.ts — agrupación y exclusiones
- routescan.test.ts — métodos HTTP y falsos positivos
- nestscan.test.ts — decoradores, multilínea, forma objeto
- importscan.test.ts — ES, require, re-exports y resolución
- graph.test.ts — IDs, nodos, aristas y deduplicación
- index.test.ts — integración de analyzeProject()
tests/graphview/
- mapper.test.ts — ids estables, posiciones deterministas
- selection.test.ts — computeHighlight, connectedEdges, nodeClassName
- Regiones por tipo y datos por nodo
- Colores de nodos y aristas
- Grafo vacío sin errores
tests/editors/
- registry.test.ts — comandos CLI de 16 editores
- Deep links VS Code, JetBrains, Xcode, Visual Studio
- Codificación de espacios y normalización de rutas
Estructura del proyecto
codeatlas/
├── electron/
│ ├── main.ts # Ventana, validación, IPC y worker
│ ├── analyzerWorker.ts # Análisis en worker_threads con progreso
│ └── preload.ts # API segura (window.codeatlas)
├── src/
│ ├── analyzer/
│ │ ├── scanner.ts # Árbol, package.json y fuente única
│ │ ├── envscan.ts # Variables de entorno
│ │ ├── routescan.ts # Rutas Express
│ │ ├── nestscan.ts # Rutas NestJS (decoradores avanzados)
│ │ ├── importscan.ts # Imports y require con resolución
│ │ ├── graph.ts # Grafo arquitectónico
│ │ ├── types.ts # Contratos del análisis
│ │ └── index.ts # analyzeProject() con progreso por fases
│ ├── editors/
│ │ └── registry.ts # 16 IDEs soportados y apertura
│ ├── components/
│ │ ├── TreeView.tsx # Árbol de archivos expandible
│ │ ├── GraphView.tsx # Mapa interactivo (React Flow)
│ │ ├── graphMapper.ts # Grafo → React Flow con dagre
│ │ └── graphLabels.ts # Etiquetas y colores
│ ├── App.tsx # Pantalla principal
│ ├── codeatlas.d.ts # Declaración global window.codeatlas
│ └── main.tsx
└── tests/
├── analyzer/ # Pruebas de los módulos
├── graphview/ # Pruebas del mapeo visual y selección
├── editors/ # Pruebas de registro de editores
└── helpers/ # Fixtures temporales