bib_ast_ts.mjs — Extractor TypeScript AST para el grafo de conocimiento
bib_ast_ts.mjs — Extractor TypeScript AST para el grafo de conocimiento
Script CLI Node.js (ESM) que analiza archivos .ts/.tsx del workspace usando la TypeScript Compiler API nativa y emite {nodes, edges} al grafo de conocimiento de la Biblioteca (Supercontexto). Es el equivalente TypeScript de CreaRack-Pro/scripts/bib_ast.py.
Introducido en Fase 7 · sesión 23 (F7.4 + F7.5), cierra el gap estructural del grafo: antes de este script solo existían nodos Python (~3.170 nodos); tras el backfill inicial se añadieron +669 nodos TS y 718 edges, llevando el grafo total a 3.839 nodos.
Ubicación
scripts/bib_ast_ts.mjs
Dependencias
typescript@^6.0.2— ya presente en el workspace, sin nuevas deps.- Node.js built-ins:
node:fs,node:path,node:crypto,node:util(parseArgs).
Diseño
Prefix qualified_name
Todos los nodos TypeScript usan el prefijo ts:<path>::<name>, que no colisiona con el dot-path Python (racks.models.Rack). Ejemplo:
ts:src/components/HealthWidget.tsx::HealthWidget
ts:functions/api/mcp/handlers/wiki.ts::checkWiki
node_types emitidos
| node_type | Descripción |
|---|---|
js_module | Fichero .ts/.tsx completo (1 por archivo) |
function | Funciones declaradas + arrow functions top-level |
class | Clases declaradas; también enums (con metadata.kind='enum') |
method | Métodos de clase + constructores |
schema | Interfaces TypeScript + type aliases (metadata.kind distingue) |
Detección de React components: si returns_jsx=true y el nombre empieza por mayúscula, el nodo function lleva metadata.is_component=true.
Campo app
El campo app se deriva del primer segmento del path relativo, con overrides:
| Path | app |
|---|---|
functions/api/mcp/** | functions-mcp |
functions/api/** | functions-api |
functions/_lib/** | functions-lib |
functions/** (resto) | functions |
src/components/** | components |
src/lib/** | lib |
src/pages/** | pages |
src/content/** | content |
src/layouts/** | layouts |
Edges emitidos (v1)
| edge_type | Descripción |
|---|---|
contains | módulo → función/clase/schema; clase → método |
imports | módulo → módulo (imports locales resueltos a ts:<path>; externos a npm:<pkg>) |
inherits | clase → clase padre (de extends/implements) |
calls | función/método → función (solo resolución local en v1; cross-module descartado) |
v1 sin type-checker: las calls cross-module que no se pueden resolver localmente se descartan con
INSERT OR IGNOREen el handler MCP (no crea edges sin nodo destino existente).
Clase principal: TSExtractor
TSExtractor(filePath, relPath, sourceFile, source)
├── run() → { nodes, edges }
├── visit(node) — dispatcher de nodos AST top-level
├── handleImport() — resuelve imports, carga tabla de bindings
├── handleFunction() — funciones declaradas + arrow functions
├── handleClass() — clases + herencia + métodos
├── handleMethod() — métodos de clase
├── handleInterfaceOrType() — interfaces y type aliases → schema
├── handleEnum() — enums → class con metadata.kind='enum'
├── visitBody() — recorre cuerpo para detectar calls
└── resolveRef() — resuelve identificador a qualified_name
CLI
# Solo estadísticas (sin push)
node scripts/bib_ast_ts.mjs --stats
# Escribir JSON a archivo
node scripts/bib_ast_ts.mjs --output /tmp/ts-graph.json
# Push al handler MCP
node scripts/bib_ast_ts.mjs --push --mcp-url https://workspace.crearack.com/api/mcp --mcp-token $BIB_MCP_TOKEN
# Sobreescribir directorios (default: functions src)
node scripts/bib_ast_ts.mjs --roots functions src/components --stats
| Flag | Tipo | Default | Descripción |
|---|---|---|---|
--roots | string+ | ['functions','src'] | Directorios a indexar relativos al repo root |
--output FILE | string | — | Escribe payload JSON a archivo |
--push | bool | false | POST al handler MCP bib_index_ast |
--mcp-url URL | string | $BIB_MCP_URL | URL del endpoint MCP |
--mcp-token TK | string | $BIB_MCP_TOKEN | Token de autenticación |
--stats | bool | false | Imprime estadísticas sin push |
--replace-apps | bool | true | Activa replace_app en el payload (v1: omitido) |
Directorios excluidos
node_modules, .astro, .wrangler, .vercel, dist, build, .cache, public, coverage, __pycache__.
Archivos excluidos por patrón
*.test.ts, *.spec.ts, *.d.ts (declarations), *.config.ts.
Guard “HTTP 200 ≠ éxito” (Regla 15)
El script comprueba el campo errors[] de la respuesta MCP tras el push. Si errors.length > 0, termina con exit(3). Si el payload no es vacío pero nodes_created + nodes_updated + edges_created === 0, emite un WARN (puede ser 2ª ejecución idempotente) sin salir en error.
Backfill F7.5 — Resultado inicial
Ejecutado el 2026-04-24 (Run 4278):
| Métrica | Valor |
|---|---|
| nodes_created | 669 |
| nodes_updated | 0 |
| edges_created | 718 |
| errors | 0 |
| duration | 2.221s |
Grafo post-backfill
| node_type | Total | Delta TS |
|---|---|---|
js_module | 136 | +136 |
function | 1.328 | +342 |
schema | 389 | +191 |
| endpoints | 495 | — |
| models | 95 | — |
| classes | 308 | — |
| Total | 3.839 | +669 |
Validación gap-closure
bib_search_nodes('checkWiki') → 1 hit (antes: 0)
bib_search_nodes('HealthWidget') → 5 hits (antes: 0)
bib_search_nodes('fetchBiblioteca*') → 1 hit (antes: 0)
Integración con bib_index_ast
El payload se envía como:
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "bib_index_ast",
"arguments": {
"ast_json": { "nodes": [...], "edges": [...] }
}
}
}
El campo replace_app se omite en v1 del backfill (los nodos TS con prefix ts: no colisionan con Python). Para reindexaciones parciales por app, se puede activar iterando y filtrando el subset.
Evolución prevista
- v2: integrar TypeScript type-checker para resolver calls cross-module.
- v2: activar
replace_apppor-app en reindexaciones incrementales. - CI: añadir step de reindexación automática tras merge a
maincuando se modifiquen archivos.ts/.tsx.
Véase también
- [[feature—biblioteca—graphify-typescript-coverage]]
- [[concept—supercontexto—grafo-de-conocimiento]]
- [[entity—biblioteca—tool—bib-index-ast]]
- [[runbook—biblioteca—reindexar-typescript]]
- [[decision—20260424—typescript-compiler-api-extractor]]