Primeros pasos

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

1

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.

2

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.

3

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.

4

Construcción del grafo

graph.ts consolida todo en un ArchitectureGraph: un modelo de dominio serializable con nodos y relaciones tipados.

5

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:

select-folder — diálogo nativo de selección de carpeta
analyze-project — valida la ruta (existe, legible, es carpeta) y ejecuta analyzeProject() en un worker
analyze-progress — eventos de progreso del análisis hacia el renderer
detect-editors — detecta los IDEs instalados
open-in-editor — abre un archivo y línea en el IDE preferido

Ciclo de vida de workers:

  • Conjunto analysisWorkers para rastrear workers activos
  • Handler before-quit termina todos los workers antes de cerrar
  • Patrón settled para 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 test
$ npm run check

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

Siguientes pasos