@nithin554/code-crawler 0.1.39 → 0.1.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +203 -47
  2. package/dist/crawler.d.ts +27 -1
  3. package/dist/crawler.js +360 -11
  4. package/dist/crawler.js.map +1 -1
  5. package/dist/graph/queries.d.ts +70 -4
  6. package/dist/graph/queries.js +125 -1
  7. package/dist/graph/queries.js.map +1 -1
  8. package/dist/graph/schema.d.ts +24 -2
  9. package/dist/graph/schema.js +9 -0
  10. package/dist/graph/schema.js.map +1 -1
  11. package/dist/parser/controlFlow.d.ts +27 -0
  12. package/dist/parser/controlFlow.js +82 -0
  13. package/dist/parser/controlFlow.js.map +1 -0
  14. package/dist/parser/language.d.ts +101 -2
  15. package/dist/parser/languages/index.js +4 -0
  16. package/dist/parser/languages/index.js.map +1 -1
  17. package/dist/parser/languages/java.js +160 -6
  18. package/dist/parser/languages/java.js.map +1 -1
  19. package/dist/parser/languages/python.d.ts +2 -0
  20. package/dist/parser/languages/python.js +956 -0
  21. package/dist/parser/languages/python.js.map +1 -0
  22. package/dist/parser/languages/typescript.d.ts +2 -0
  23. package/dist/parser/languages/typescript.js +1111 -0
  24. package/dist/parser/languages/typescript.js.map +1 -0
  25. package/dist/parser/moduleId.d.ts +35 -0
  26. package/dist/parser/moduleId.js +93 -0
  27. package/dist/parser/moduleId.js.map +1 -0
  28. package/dist/parser/treeSitter.d.ts +6 -0
  29. package/dist/parser/treeSitter.js +13 -2
  30. package/dist/parser/treeSitter.js.map +1 -1
  31. package/dist/resolver/common.d.ts +52 -0
  32. package/dist/resolver/common.js +624 -0
  33. package/dist/resolver/common.js.map +1 -0
  34. package/dist/resolver/dynamic.js +66 -1
  35. package/dist/resolver/dynamic.js.map +1 -1
  36. package/dist/resolver/genericResolver.d.ts +45 -0
  37. package/dist/resolver/genericResolver.js +235 -0
  38. package/dist/resolver/genericResolver.js.map +1 -0
  39. package/dist/resolver/types.d.ts +24 -1
  40. package/dist/resolver/types.js +50 -0
  41. package/dist/resolver/types.js.map +1 -1
  42. package/dist/server.js +108 -5
  43. package/dist/server.js.map +1 -1
  44. package/package.json +2 -2
package/README.md CHANGED
@@ -3,12 +3,18 @@
3
3
  **Static + dynamic call tracing MCP server backed by a persistent property graph of your codebase.**
4
4
 
5
5
  Code-Crawler indexes a project into a SQLite-backed property graph — files, packages,
6
- classes, methods, fields, imports, annotations, **call edges**, **virtual dispatch**, and
7
- **aspect advice** — then exposes that graph to LLM clients as MCP tools: find callers,
8
- trace call paths, explore neighborhoods, follow runtime dispatch, and search symbols
9
- across the whole codebase.
6
+ modules, classes, interfaces, methods, fields, imports, annotations/decorators, **call
7
+ edges**, **virtual dispatch**, **aspect advice**, and the wiring frameworks add
8
+ (**entry points**, **routes**, **injected dependencies**, **reflective lookups**) — then
9
+ exposes that graph to LLM clients as MCP tools: find callers, trace call paths, explore
10
+ neighborhoods, follow runtime dispatch, and search symbols across the whole codebase.
11
+
12
+ Supports **Java**, **Python**, and **TypeScript/JavaScript** projects, and can index all
13
+ three into the same graph.
10
14
 
11
15
  📖 **Documentation site:** <https://nithin554.github.io/code-crawler/>
16
+ 📘 **Task-oriented guide:** [`USAGE.md`](USAGE.md)
17
+ 🗺️ **Roadmap:** [`ROADMAP.md`](ROADMAP.md)
12
18
 
13
19
  ```
14
20
  ┌─────────────────────── MCP (stdio) ───────────────────────┐
@@ -41,18 +47,36 @@ and answers them instantly with bounded recursive SQL queries.
41
47
 
42
48
  ## Features
43
49
 
44
- - **Java-first** via the `tree-sitter-java` grammar (WASM — no native build step).
45
- The parser/resolver layer is designed so more languages plug in per-language config modules.
50
+ - **Three languages, one graph**: Java (`tree-sitter-java`), Python
51
+ (`tree-sitter-python`), and TypeScript/JavaScript (`tree-sitter-typescript`,
52
+ `tree-sitter-tsx`, `tree-sitter-javascript`) — all WASM, no native build step.
53
+ Language is detected per file, so a polyglot repo lands in a single graph.
46
54
  - **Dynamic tracing on a static graph** — `DYNAMIC_DISPATCH` edges connect interface/base
47
55
  calls to every override in the project, and `ADVISES` edges weave AspectJ/Spring AOP
48
56
  advice into execution traces (`before`, `after`, `around`, `after-returning`,
49
57
  `after-throwing`, named `@Pointcut` references, `&&`/`||`/`!` and `execution`, `within`,
50
58
  `@annotation`, `@within`, `target`, `this`, `args` primitives).
51
- - **Annotations as first-class nodes** — `@Transactional`, `@Cacheable`, `@Async`, `@Retryable`
52
- and friends become `annotation` nodes with `ANNOTATED_WITH` edges, so you can query
53
- decorators on types, methods, and fields.
59
+ - **Run-time indirection is named, not lost** — Java reflection/`ServiceLoader`, Python
60
+ `getattr`/`importlib`, and JS `require`/dynamic `import()` produce `REFLECTS` edges to
61
+ the resolved symbol when the target is statically determinable, or to a
62
+ `__reflect__:` marker when it is not.
63
+ - **Framework wiring** — dependency injection (`@Autowired`, NestJS constructor
64
+ injection, FastAPI `Depends`) becomes `INJECTS` edges, and HTTP routes
65
+ (`@GetMapping`, `@RequestMapping`, NestJS `@Controller`/`@Get`, FastAPI/Flask
66
+ decorators, Express `app.get`) become `ROUTES` edges to the handler, which is also
67
+ marked as an entry point.
68
+ - **Control flow on call edges** — every `CALLS` edge records whether the call is
69
+ conditional and the compact source text of its enclosing guards/loops, so an agent can
70
+ tell a happy path from an error path without reading the file.
71
+ - **External dependencies are explicit** — third-party imports and runtime globals
72
+ become package-level `external_symbol` nodes with `REFERENCES` edges and a
73
+ `find_external_dependencies` summary, distinct from project code.
74
+ - **Annotations as first-class nodes** — `@Transactional`, `@Cacheable`, `@Async`,
75
+ `@Retryable`, Python decorators, and TS decorators become `annotation` nodes with
76
+ `ANNOTATED_WITH` edges, so you can query decorators on types, methods, and fields.
54
77
  - **Call resolution heuristics** that go beyond naive string matching:
55
78
  receiver types inferred from locals, parameters, fields, `new T()` expressions,
79
+ `self`/`this` scoping, dotted paths (`service.repo.find`), loop-variable element types,
56
80
  bare/`this`/`super` calls, static/qualified calls, and superclass chains.
57
81
  Unresolvable calls become `unknown_symbol` phantom nodes with `resolved:false` edges,
58
82
  so the graph stays traversable.
@@ -70,7 +94,7 @@ Requires Node.js ≥ 20.
70
94
  ```bash
71
95
  npm install
72
96
  npm run build # tsc → dist/
73
- npm test # vitest (80 tests)
97
+ npm test # vitest (125 tests)
74
98
  ```
75
99
 
76
100
  ## CLI
@@ -129,10 +153,15 @@ if green, **auto-releases**:
129
153
  Point the client at the same command. The typical flow for an LLM agent:
130
154
 
131
155
  1. `crawl_project` the repo once.
132
- 2. `search_symbols` to locate the symbol of interest.
133
- 3. `get_callers` / `get_callees` / `trace_path` to reason about the call graph.
134
- 4. `trace_execution` to follow runtime dispatch and aspect advice; `find_aspects`,
156
+ 2. `find_entry_points` to see where execution actually starts (routes, listeners, mains).
157
+ 3. `search_symbols` to locate the symbol of interest.
158
+ 4. `get_callers` / `get_callees` / `trace_path` to reason about the call graph.
159
+ 5. `trace_execution` to follow runtime dispatch and aspect advice; `find_aspects`,
135
160
  `get_decorators`, and `find_annotated` to inspect behaviour-changing annotations.
161
+ 6. `find_routes`, `find_injections`, `find_reflections`, and `find_external_dependencies`
162
+ to map framework wiring and third-party surface.
163
+
164
+ See [`USAGE.md`](USAGE.md) for the full task-oriented walkthrough.
136
165
 
137
166
  ## MCP surface
138
167
 
@@ -154,6 +183,11 @@ Point the client at the same command. The typical flow for an LLM agent:
154
183
  | `find_annotated` | Every symbol annotated with a given annotation |
155
184
  | `find_hotspots` | Rank methods by fan-in, fan-out, and advice interceptions |
156
185
  | `find_dead_code` | Methods with no incoming call/dispatch/advice edges |
186
+ | `find_entry_points` | Framework-invoked roots: HTTP routes, listeners, schedulers, CLI mains, tests |
187
+ | `find_routes` | HTTP route → handler mappings (`@GetMapping`, NestJS, FastAPI, Express) |
188
+ | `find_injections` | DI-supplied dependencies (`@Autowired`, NestJS, FastAPI `Depends`) |
189
+ | `find_reflections` | Run-time lookups: `Class.forName`, `getattr`, `importlib`, dynamic `import()` |
190
+ | `find_external_dependencies` | Third-party packages with reference and file counts |
157
191
  | `get_subgraph` | Neighborhood extraction for visualization |
158
192
  | `get_schema` | Describe the graph model |
159
193
  | `clear_index` | Reset the database |
@@ -163,15 +197,18 @@ Point the client at the same command. The typical flow for an LLM agent:
163
197
 
164
198
  ## Graph model
165
199
 
166
- **Nodes** — `kind` is one of `file | package | class | interface | enum | method |
167
- constructor | field | import | aspect | annotation_type | annotation | unknown_symbol`.
168
- Every node has a globally unique `qualifiedName` and a JSON `properties` blob
169
- (signature, modifiers, lines, annotations, ...).
200
+ **Nodes** — `kind` is one of `file | package | module | class | interface | enum | method |
201
+ constructor | field | import | external_symbol | aspect | annotation_type | annotation |
202
+ unknown_symbol`. Every node has a globally unique `qualifiedName` and a JSON `properties`
203
+ blob (signature, modifiers, lines, annotations, ...).
170
204
 
171
205
  **Edges** — `kind` is one of `CALLS | DECLARED_IN | CONTAINS | IMPLEMENTS | EXTENDS |
172
- IMPORTS | REFERENCES | DYNAMIC_DISPATCH | ADVISES | ANNOTATED_WITH`. `CALLS` edges carry
173
- `line`, `resolved`, and `confidence`; `ANNOTATED_WITH` edges carry `line` and `arguments`;
174
- `ADVISES` edges carry `adviceKind` and the resolved `pointcut`.
206
+ IMPORTS | REFERENCES | DYNAMIC_DISPATCH | ADVISES | ANNOTATED_WITH | REFLECTS | INJECTS |
207
+ ROUTES`. `CALLS` edges carry `line`, `resolved`, `confidence`, and — when the call sits
208
+ behind control flow — `conditional`, `controlFlow`, and `guards`; `ANNOTATED_WITH` edges
209
+ carry `line` and `arguments`; `ADVISES` edges carry `adviceKind` and the resolved
210
+ `pointcut`; `INJECTS` carries `injectedName` and `framework`; `REFLECTS` carries
211
+ `mechanism`; `REFERENCES` carries `external`.
175
212
 
176
213
  Id scheme:
177
214
 
@@ -184,6 +221,13 @@ Id scheme:
184
221
  | annotation | `@Transactional` |
185
222
  | import | `__import__:java.util.List` |
186
223
  | unresolved call | `__unknown__:System.out.println` |
224
+ | Python/TS module | `module:app.service` |
225
+ | module-level function | `module:app.api#read_order` |
226
+ | module-level field | `module:app.service$AUDIT_LOG` |
227
+ | inline arrow handler | `module:src.routes#<anonymous@7>` |
228
+ | external package | `ext:fastapi` |
229
+ | reflective marker | `__reflect__:./plugins/${name}` |
230
+ | injection marker | `__inject__:Repo` |
187
231
 
188
232
  ## Dynamic behaviour
189
233
 
@@ -236,7 +280,79 @@ Framework decorators (`@Transactional`, `@Cacheable`, `@Async`, `@Retryable`,
236
280
  `@PreAuthorize`, `@Scheduled`, ...) are additionally flagged `decorator: true` so
237
281
  `get_decorators` and `find_annotated` can surface runtime-semantic annotations.
238
282
 
239
- ## Java resolution heuristics
283
+ Python decorators and TypeScript decorators are modelled the same way: `@router.get(...)`,
284
+ `@injectable`, `@Controller(...)`, `@Get(':id')` and friends land in `annotations` on the
285
+ declaring type/method, and framework ones additionally produce routes, injections, or
286
+ entry-point marks.
287
+
288
+ ### Reflection and run-time indirection
289
+
290
+ Lookups the compiler cannot see through are recorded as `REFLECTS` edges. When the target
291
+ is statically determinable — a string literal, a literal prefix plus a variable
292
+ (`importlib.import_module("app.plugins." + name)`), `getattr(obj, "run")`,
293
+ `require("./x")` — the edge points at the resolved symbol. Otherwise it points at a
294
+ `__reflect__:` marker carrying the `mechanism`:
295
+
296
+ ```text
297
+ module:app.dynamic#load_plugin --REFLECTS--> __reflect__:app.plugins. (importlib.import_module)
298
+ module:src.dynamic#loadPlugin --REFLECTS--> __reflect__:./plugins/${name} (import())
299
+ ```
300
+
301
+ Dynamic module prefixes that belong to the project's own namespace stay in-project; only
302
+ genuinely foreign packages become external dependencies.
303
+
304
+ ### Dependency injection
305
+
306
+ Dependencies the framework supplies are `INJECTS` edges instead of missing calls
307
+ (`find_injections`):
308
+
309
+ | Framework | Detected from |
310
+ | --- | --- |
311
+ | Spring | `@Autowired` fields/methods/constructors |
312
+ | NestJS | constructor parameters with decorators; `@Injectable()` classes |
313
+ | FastAPI | `Depends(...)` parameters |
314
+ | dependency-injector | constructor parameters of `@injectable` classes |
315
+ | plain TS/JS | constructor parameters typed with a project class |
316
+
317
+ Primitive and structural parameter types (`string`, `{ id: string }`, `list[str]`) are
318
+ counted but produce no edge, so `@Body() body: { id: string }` does not pollute the graph.
319
+
320
+ ### Framework entry points and routes
321
+
322
+ Methods a framework invokes have no source-level caller, so marking them keeps dead-code
323
+ analysis honest and gives `trace_execution` a root (`find_entry_points`, `find_routes`):
324
+
325
+ | Language | Recognised |
326
+ | --- | --- |
327
+ | Java | `@GetMapping`, `@PostMapping`, `@RequestMapping`, `@Scheduled`, `@EventListener`, listener annotations, tests, `main` |
328
+ | Python | FastAPI (`@router.get`, `@app.post`), Flask (`@bp.route`), `if __name__ == "__main__"`, `pytest` tests |
329
+ | TypeScript | NestJS `@Controller` + `@Get`/`@Post`/... , Express `app.get('/x', handler)`, Jest tests |
330
+
331
+ Express handlers written inline get a synthetic method node
332
+ (`module:src.routes#<anonymous@7>`) so their body still gets call edges, containment, and
333
+ a route edge.
334
+
335
+ ### Control flow on call edges
336
+
337
+ Each `CALLS` edge records whether it is guarded:
338
+
339
+ ```json
340
+ {
341
+ "kind": "CALLS",
342
+ "source": "app.repository.OrderRepository#create",
343
+ "target": "ext:builtins",
344
+ "properties": { "line": 14, "conditional": true, "controlFlow": ["branch", "loop"],
345
+ "guards": ["row.get(\"id\") == order_id", "self.rows"] }
346
+ }
347
+ ```
348
+
349
+ `controlFlow` uses `branch | loop | exception | predicate`. Guards are source text, not
350
+ symbolic constraints: they tell an agent *that* a call is conditional and *what* the
351
+ condition looked like, without pretending to model its truth value.
352
+
353
+ ## Resolution heuristics
354
+
355
+ Java:
240
356
 
241
357
  1. **Constructor calls** (`new Foo(...)`) → resolve `Foo` → `#<init>` (default ctor if implicit).
242
358
  2. **Bare / `this.` / `super.` calls** → enclosing type + superclass chain.
@@ -246,53 +362,93 @@ Framework decorators (`@Transactional`, `@Cacheable`, `@Async`, `@Retryable`,
246
362
  5. **Otherwise** → phantom `unknown_symbol` node, `resolved:false`, with the inference
247
363
  failure reason attached to the edge.
248
364
 
365
+ Python and TypeScript add module-aware resolution on top of the same pipeline:
366
+
367
+ 1. **Import-aware scope** — `from app.repository import OrderRepository` maps the local
368
+ name to `app.repository.OrderRepository`; relative and project modules are resolved by
369
+ suffix, bare specifiers fall back to package roots.
370
+ 2. **`self.x` / `this.x`** resolve against the enclosing class's fields; a receiver that
371
+ starts with `self`/`this`/`cls`/`super` never becomes an external package.
372
+ 3. **Dotted receivers** (`service.repo.find`) are walked segment by segment: the first
373
+ segment resolves to a type, the next to a field on it, and container members such as
374
+ `list.append` are recognised as builtin rather than unknown.
375
+ 4. **Locals** are typed from parameters, annotated assignments, `new T()`, and inferred
376
+ loop/variable element types (`for row in self.rows:` → `row: dict`).
377
+ 5. **Module functions** (`module:app.api#read_order`) participate in dispatch, routes, and
378
+ entry-point marking exactly like class methods.
379
+
249
380
  Each resolved edge carries a `confidence` score and a human-readable `reason` trace
250
381
  (e.g. `via local orders: OrderService`), so LLM clients can weigh how much to trust it.
251
382
 
252
- ## Roadmap: multi-language
383
+ ## Implemented languages
253
384
 
254
- The parsing layer is language-agnostic. Adding a language requires:
385
+ | Language | Extensions | Extracted | Dynamic features |
386
+ | --- | --- | --- | --- |
387
+ | Java | `.java` | packages, classes, interfaces, enums, records, annotations, constructors, methods, fields | virtual dispatch, AspectJ/Spring AOP advice, `@Autowired`, `@RequestMapping` family, `Class.forName`, `ServiceLoader` |
388
+ | Python | `.py` | modules, classes, functions, methods, fields, decorators | `@injectable`/`Depends` injection, FastAPI/Flask routes, `getattr`, `importlib`, `__main__`, tests |
389
+ | TypeScript | `.ts`, `.tsx` | modules, classes, interfaces, type aliases, enums, methods, fields, arrow functions | NestJS/Angular decorators, DI constructor injection, NestJS/Express routes, `import()`, `require()` |
390
+ | JavaScript | `.js`, `.jsx`, `.mjs`, `.cjs` | modules, classes, functions, fields | decorators, Express routes, `require()` |
391
+
392
+ Crawling a directory mixes all of them automatically — language is chosen per file from
393
+ the extension, and a single crawl can return `languages: ["java", "python", "typescript"]`.
394
+
395
+ Adding a language requires:
255
396
 
256
397
  1. `src/parser/languages/<lang>.ts` — a `LanguageConfig` implementing `parseFile`
257
- (package/module extraction, type/member extraction, raw call sites, local type tables).
398
+ (module/package extraction, type/member extraction, raw call sites, local type tables).
258
399
  2. Register it in `src/parser/languages/index.ts`.
259
- 3. `src/resolver/<lang>Resolver.ts` — translate raw call sites into resolved targets
260
- using the shared `TypeIndex`.
400
+ 3. Optionally a `src/resolver/<lang>Resolver.ts`; most languages work with the shared
401
+ `src/resolver/genericResolver.ts` and only override language-specific builtins.
261
402
 
262
- Natural next targets: **Python** (native AST or tree-sitter-python), **TypeScript/JavaScript**
263
- (tree-sitter-typescript), and **Go** (tree-sitter-go). The graph schema, store, traversal
264
- queries, and MCP surface all stay the same.
403
+ The graph schema, store, traversal queries, and MCP surface stay the same for every
404
+ language. Natural next targets: Go, C#, Ruby, Rust.
265
405
 
266
- Planned enhancements:
406
+ Not yet modelled, by design:
267
407
 
268
- - Package-level dependency graphs (module boundaries, cycle detection).
269
- - Test coverage mapping (which tests exercise a given symbol).
270
- - Incremental crawling (watch mode) and git-blame aware invalidation.
408
+ - Value flow and branch feasibility — edges say *that* a call is conditional and record
409
+ the guard text, not which branch is taken.
410
+ - Cross-repository resolution — libraries outside the crawled tree are summarised as
411
+ `ext:` packages rather than crawled.
412
+ - Fully dynamic targets (`getattr(obj, name)`, `require(userInput)`) point at a
413
+ `__reflect__:` marker instead of a symbol; there is nothing static to point at.
414
+ - Runtime DI graphs assembled from configuration files rather than code.
271
415
 
272
416
  ## Architecture
273
417
 
274
418
  ```
275
419
  src/
276
- ├── index.ts CLI (crawl | status | query | serve)
277
- ├── server.ts MCP server: tools, resources, prompt (thin handlers)
278
- ├── crawler.ts file discovery → parse → index → resolve → persist
279
- ├── config.ts env-overridable configuration
420
+ ├── index.ts CLI (crawl | status | query | serve)
421
+ ├── server.ts MCP server: tools, resources, prompt (thin handlers)
422
+ ├── crawler.ts file discovery → parse → index → resolve → persist
423
+ ├── config.ts env-overridable configuration
280
424
  ├── graph/
281
- │ ├── schema.ts node/edge kinds, id scheme, property shapes
282
- │ ├── store.ts better-sqlite3 schema + idempotent file-scoped upserts
283
- │ └── queries.ts recursive-CTE traversal (callers/callees/path/subgraph)
425
+ │ ├── schema.ts node/edge kinds, id scheme, property shapes
426
+ │ ├── store.ts better-sqlite3 schema + idempotent file-scoped upserts
427
+ │ └── queries.ts recursive-CTE traversal (callers/callees/path/subgraph)
284
428
  ├── parser/
285
- │ ├── language.ts LanguageConfig contract
286
- │ ├── treeSitter.ts WASM runtime + grammar loading + CST walk helpers
429
+ │ ├── language.ts LanguageConfig contract
430
+ │ ├── treeSitter.ts WASM runtime + grammar loading + CST walk helpers
431
+ │ ├── controlFlow.ts enclosing branch/loop/try/catch + guard text
432
+ │ ├── moduleId.ts import-aware module id derivation
287
433
  │ └── languages/
288
- │ ├── index.ts language registry
289
- │ └── java.ts Java structural extraction
434
+ │ ├── index.ts language registry + per-file language detection
435
+ │ ├── java.ts Java structural extraction
436
+ │ ├── python.ts Python structural extraction
437
+ │ └── typescript.ts TypeScript, TSX and JavaScript extraction
290
438
  └── resolver/
291
- ├── types.ts TypeIndex (global name/method index) + ResolvedCall
292
- ├── dynamic.ts virtual dispatch + AspectJ pointcut matching/advice edges
293
- └── javaResolver.ts Java call-target resolution heuristics
439
+ ├── types.ts TypeIndex (global name/method index) + ResolvedCall
440
+ ├── common.ts builtin types, external packages, receiver inference
441
+ ├── dynamic.ts virtual dispatch + AspectJ pointcut matching/advice edges
442
+ ├── genericResolver.ts shared resolution for module-based languages
443
+ └── javaResolver.ts Java call-target resolution heuristics
294
444
  ```
295
445
 
446
+ ## Roadmap
447
+
448
+ Language-agnostic architecture, more languages, and better resolution are tracked in
449
+ [`ROADMAP.md`](ROADMAP.md). The near-term focus is making a new language a one-module
450
+ change, then using that to add Go, C#, and Kotlin.
451
+
296
452
  ## Documentation site
297
453
 
298
454
  The static documentation site in `docs/` is deployed to GitHub Pages by
package/dist/crawler.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { GraphStore } from "./graph/store.js";
2
2
  import type { GraphEdge, GraphNode } from "./graph/schema.js";
3
- import type { ParsedFile } from "./parser/language.js";
3
+ import type { EntryPointInfo, ParsedFile } from "./parser/language.js";
4
4
  import { buildTypeIndex } from "./resolver/types.js";
5
5
  /**
6
6
  * Project crawler: discover source files, parse them, build a global type
@@ -29,6 +29,16 @@ export interface CrawlResult {
29
29
  aspects: number;
30
30
  /** Number of annotation/decorator usages indexed. */
31
31
  decorators: number;
32
+ /** Framework-invoked roots (routes, listeners, schedulers, CLI, tests). */
33
+ entryPoints: number;
34
+ /** Framework-supplied dependency edges. */
35
+ injections: number;
36
+ /** Run-time lookup edges (reflection, dynamic import, getattr). */
37
+ reflections: number;
38
+ /** Distinct external packages/specifiers referenced by the project. */
39
+ externalDependencies: number;
40
+ /** Route registrations mapped to handler methods. */
41
+ routes: number;
32
42
  languages: string[];
33
43
  durationMs: number;
34
44
  }
@@ -45,6 +55,22 @@ export declare function buildCallEdges(parsed: ParsedFile, index: ReturnType<typ
45
55
  phantomNodes: GraphNode[];
46
56
  resolved: number;
47
57
  unresolved: number;
58
+ external: number;
59
+ externalPackages: Set<string>;
60
+ };
61
+ /**
62
+ * Framework wiring that the language parsers surface but the plain call
63
+ * resolver cannot see: external dependencies, dependency injection,
64
+ * reflective lookups and route registrations.
65
+ */
66
+ export declare function buildDependencyGraph(parsed: ParsedFile, index: ReturnType<typeof buildTypeIndex>, knownNodeIds: Set<string>): {
67
+ nodes: GraphNode[];
68
+ edges: GraphEdge[];
69
+ entryPointMarks: Map<string, EntryPointInfo>;
70
+ injections: number;
71
+ reflections: number;
72
+ routes: number;
73
+ externalDependencies: Set<string>;
48
74
  };
49
75
  /**
50
76
  * Crawl a project directory and index it into the store.