Navegador

navegador / docs / guide / framework-enrichment.md
1
# Framework Enrichment
2
3
## What enrichment does
4
5
After ingestion, navegador's graph contains generic structural nodes: `Function`, `Class`, `File`, `Import`. Enrichment promotes those generic nodes to **semantic types** that reflect how the code is actually used.
6
7
For example, a Django view function becomes a `View` node. A pytest function becomes a `Test` node. A Flask route decorator triggers creation of a `Route` node with the URL pattern extracted.
8
9
This lets you ask questions that wouldn't be possible from structure alone:
10
11
```bash
12
# without enrichment: grep for "def test_"
13
# with enrichment: query the graph by semantic type
14
navegador query "MATCH (t:Test) RETURN t.name, t.file ORDER BY t.file"
15
16
# find all API routes
17
navegador query "MATCH (r:Route) RETURN r.method, r.path, r.handler ORDER BY r.path"
18
```
19
20
---
21
22
## How it works
23
24
Enrichment runs as a post-ingest pass. It reads existing nodes and edges, applies framework-specific pattern matching (decorator names, base class names, naming conventions), and:
25
26
1. Adds semantic labels to matched nodes (e.g., adds `View` label to Django view functions)
27
2. Creates typed edges where the framework implies relationships (e.g., `HANDLES` from a `Route` to its handler function)
28
3. Extracts framework-specific properties (e.g., HTTP method and URL pattern from route decorators)
29
30
Enrichment is **non-destructive** — it never removes or modifies existing nodes, only adds labels and edges.
31
32
---
33
34
## Supported frameworks
35
36
| Framework | Language | Detected patterns | Semantic types added |
37
|---|---|---|---|
38
| Django | Python | `View` subclasses, `urlpatterns`, `@login_required` | `View`, `Route`, `Model`, `Form`, `Middleware` |
39
| Flask | Python | `@app.route`, `@blueprint.route`, `MethodView` | `Route`, `View`, `Blueprint` |
40
| FastAPI | Python | `@router.get/post/put/delete/patch`, `APIRouter` | `Route`, `Schema`, `Dependency` |
41
| pytest | Python | `def test_*`, `@pytest.mark.*`, `conftest.py` | `Test`, `Fixture`, `TestSuite` |
42
| SQLAlchemy | Python | `Base` subclasses, `Column`, `relationship()` | `Model`, `Column`, `Relation` |
43
| Next.js | TypeScript | `pages/`, `app/`, `getServerSideProps` | `Page`, `Route`, `ServerComponent` |
44
| Express | JavaScript | `app.get/post/put/delete`, `Router` | `Route`, `Middleware` |
45
| NestJS | TypeScript | `@Controller`, `@Injectable`, `@Module` | `Controller`, `Service`, `Module` |
46
| **Terraform** | HCL | `main.tf`, `variables.tf`, `outputs.tf` | Cross-file module resolution, provider grouping |
47
| **Chef** | Ruby | `metadata.rb`, `Berksfile` | `chef_recipe`, `chef_resource`, `chef_cookbook`, `chef_include` |
48
49
!!! note
50
Framework detection is automatic when `--framework auto` is used (the default). Navegador inspects imports and decorator patterns to identify which frameworks are present.
51
52
---
53
54
## Usage
55
56
### Auto-detect and enrich all frameworks
57
58
```bash
59
navegador enrich ./src
60
```
61
62
This runs after ingestion and enriches everything it can detect automatically.
63
64
### Enrich immediately after ingestion
65
66
```bash
67
navegador ingest ./src && navegador enrich ./src
68
```
69
70
Or use the `--enrich` flag on ingest:
71
72
```bash
73
navegador ingest ./src --enrich
74
```
75
76
### Target a specific framework
77
78
```bash
79
navegador enrich ./src --framework django
80
navegador enrich ./src --framework fastapi
81
navegador enrich ./src --framework pytest
82
```
83
84
Valid values: `django`, `flask`, `fastapi`, `pytest`, `sqlalchemy`, `nextjs`, `express`, `nestjs`, `terraform`, `chef`, `auto` (default).
85
86
### JSON output
87
88
```bash
89
navegador enrich ./src --json
90
```
91
92
Returns a summary of labels and edges added per framework.
93
94
---
95
96
## Querying enriched nodes
97
98
Once enriched, the semantic types are queryable via Cypher:
99
100
```bash
101
# all FastAPI routes with their HTTP methods
102
navegador query "MATCH (r:Route) RETURN r.method, r.path, r.handler ORDER BY r.path"
103
104
# all SQLAlchemy models and their columns
105
navegador query "MATCH (m:Model)-[:HAS_COLUMN]->(c:Column) RETURN m.name, c.name, c.type ORDER BY m.name"
106
107
# all pytest tests that reference a specific function
108
navegador query "MATCH (t:Test)-[:CALLS]->(f:Function {name: 'process_payment'}) RETURN t.name, t.file"
109
110
# all Django views governed by a rule
111
navegador query "MATCH (r:Rule)-[:GOVERNS]->(v:View) RETURN r.name, v.name, v.file"
112
```
113
114
---
115
116
## Adding custom enrichers
117
118
Enrichers are subclasses of `FrameworkEnricher`. Create one to add support for an internal framework or library.
119
120
### 1. Create the enricher
121
122
```python
123
# myproject/enrichers/celery.py
124
from navegador.enrichment.base import FrameworkEnricher, EnrichmentResult
125
from navegador.graph import GraphStore
126
127
class CeleryEnricher(FrameworkEnricher):
128
name = "celery"
129
130
def detect(self, store: GraphStore) -> bool:
131
"""Return True if this framework is present in the graph."""
132
results = store.query(
133
"MATCH (i:Import {name: 'celery'}) RETURN count(i) AS n"
134
)
135
return results[0]["n"] > 0
136
137
def enrich(self, store: GraphStore) -> EnrichmentResult:
138
"""Add semantic labels and edges for Celery tasks."""
139
# Find functions decorated with @shared_task or @app.task
140
tasks = store.query(
141
"MATCH (d:Decorator)-[:DECORATES]->(f:Function) "
142
"WHERE d.name IN ['shared_task', 'task'] "
143
"RETURN f.id, f.name"
144
)
145
labels_added = 0
146
for row in tasks:
147
store.query(
148
"MATCH (f:Function) WHERE id(f) = $id "
149
"SET f:Task",
150
params={"id": row["f.id"]}
151
)
152
labels_added += 1
153
154
return EnrichmentResult(labels_added=labels_added, edges_added=0)
155
```
156
157
### 2. Register the enricher
158
159
```python
160
# myproject/enrichers/__init__.py
161
from navegador.enrichment.registry import register_enricher
162
from .celery import CeleryEnricher
163
164
register_enricher(CeleryEnricher())
165
```
166
167
### 3. Load at startup
168
169
Import the registration module before running enrichment. In a CLI wrapper or agent hook:
170
171
```python
172
import myproject.enrichers # registers the enricher
173
from navegador.enrichment import run_enrichment
174
from navegador.graph import GraphStore
175
176
store = GraphStore.sqlite(".navegador/navegador.db")
177
result = run_enrichment(store, framework="celery")
178
print(f"Added {result.labels_added} labels")
179
```
180
181
Or pass the module path to the CLI via `NAVEGADOR_ENRICHERS`:
182
183
```bash
184
NAVEGADOR_ENRICHERS=myproject.enrichers navegador enrich ./src --framework celery
185
```
186

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button