CreaRack-SL

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_typeDescripción
js_moduleFichero .ts/.tsx completo (1 por archivo)
functionFunciones declaradas + arrow functions top-level
classClases declaradas; también enums (con metadata.kind='enum')
methodMétodos de clase + constructores
schemaInterfaces 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:

Pathapp
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_typeDescripción
containsmódulo → función/clase/schema; clase → método
importsmódulo → módulo (imports locales resueltos a ts:<path>; externos a npm:<pkg>)
inheritsclase → clase padre (de extends/implements)
callsfunció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 IGNORE en 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
FlagTipoDefaultDescripción
--rootsstring+['functions','src']Directorios a indexar relativos al repo root
--output FILEstring—Escribe payload JSON a archivo
--pushboolfalsePOST al handler MCP bib_index_ast
--mcp-url URLstring$BIB_MCP_URLURL del endpoint MCP
--mcp-token TKstring$BIB_MCP_TOKENToken de autenticación
--statsboolfalseImprime estadísticas sin push
--replace-appsbooltrueActiva 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étricaValor
nodes_created669
nodes_updated0
edges_created718
errors0
duration2.221s

Grafo post-backfill

node_typeTotalDelta TS
js_module136+136
function1.328+342
schema389+191
endpoints495—
models95—
classes308—
Total3.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_app por-app en reindexaciones incrementales.
  • CI: añadir step de reindexación automática tras merge a main cuando 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]]