purecontext-mcp 1.5.2 → 1.7.0

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 (53) hide show
  1. package/FRAMEWORK-ADAPTERS.md +368 -351
  2. package/dist/adapters/astro-preprocessor.d.ts +25 -0
  3. package/dist/adapters/astro-preprocessor.d.ts.map +1 -0
  4. package/dist/adapters/astro-preprocessor.js +50 -0
  5. package/dist/adapters/astro-preprocessor.js.map +1 -0
  6. package/dist/adapters/astro.d.ts +13 -0
  7. package/dist/adapters/astro.d.ts.map +1 -0
  8. package/dist/adapters/astro.js +83 -0
  9. package/dist/adapters/astro.js.map +1 -0
  10. package/dist/adapters/detect-utils.d.ts +38 -0
  11. package/dist/adapters/detect-utils.d.ts.map +1 -0
  12. package/dist/adapters/detect-utils.js +95 -0
  13. package/dist/adapters/detect-utils.js.map +1 -0
  14. package/dist/adapters/nuxt.d.ts +20 -0
  15. package/dist/adapters/nuxt.d.ts.map +1 -1
  16. package/dist/adapters/nuxt.js +128 -13
  17. package/dist/adapters/nuxt.js.map +1 -1
  18. package/dist/adapters/svelte-preprocessor.d.ts +29 -0
  19. package/dist/adapters/svelte-preprocessor.d.ts.map +1 -0
  20. package/dist/adapters/svelte-preprocessor.js +83 -0
  21. package/dist/adapters/svelte-preprocessor.js.map +1 -0
  22. package/dist/adapters/svelte.d.ts +13 -0
  23. package/dist/adapters/svelte.d.ts.map +1 -0
  24. package/dist/adapters/svelte.js +96 -0
  25. package/dist/adapters/svelte.js.map +1 -0
  26. package/dist/adapters/vue.d.ts.map +1 -1
  27. package/dist/adapters/vue.js +87 -20
  28. package/dist/adapters/vue.js.map +1 -1
  29. package/dist/cli/hooks.d.ts +2 -2
  30. package/dist/cli/hooks.d.ts.map +1 -1
  31. package/dist/cli/hooks.js +104 -121
  32. package/dist/cli/hooks.js.map +1 -1
  33. package/dist/core/index-manager.d.ts.map +1 -1
  34. package/dist/core/index-manager.js +9 -2
  35. package/dist/core/index-manager.js.map +1 -1
  36. package/dist/core/indexing-worker.d.ts +2 -0
  37. package/dist/core/indexing-worker.d.ts.map +1 -1
  38. package/dist/core/indexing-worker.js +2 -0
  39. package/dist/core/indexing-worker.js.map +1 -1
  40. package/dist/core/watcher/file-watcher.d.ts +6 -0
  41. package/dist/core/watcher/file-watcher.d.ts.map +1 -1
  42. package/dist/core/watcher/file-watcher.js +11 -1
  43. package/dist/core/watcher/file-watcher.js.map +1 -1
  44. package/dist/index.d.ts +2 -0
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +2 -0
  47. package/dist/index.js.map +1 -1
  48. package/dist/server/tools/index-repo.d.ts.map +1 -1
  49. package/dist/server/tools/index-repo.js +8 -2
  50. package/dist/server/tools/index-repo.js.map +1 -1
  51. package/dist/version.d.ts +1 -1
  52. package/dist/version.js +1 -1
  53. package/package.json +1 -1
@@ -1,351 +1,368 @@
1
- # Framework Adapters
2
-
3
- A language handler knows what a function or class looks like. A framework adapter knows that `app.get('/users/:id', ...)` is actually a **route**, that a Vue Single File Component is a **component**, and that a Django `models.Model` subclass is a **model** with a table behind it.
4
-
5
- PureContext ships with adapters for the frameworks most production codebases are written against. They run automatically — drop the index on a NestJS project and `/users` routes show up as first-class symbols you can search for by path, not just by handler-function name.
6
-
7
- This page is the user-facing tour. For parameter-level details (exact regex patterns, full `frameworkMeta` shapes), see the [reference manual](docs/08-framework-adapters.md).
8
-
9
- ---
10
-
11
- ## How adapters change what you see
12
-
13
- Without an adapter, searching for "user routes" in an Express app returns *function names* — `handleGetUser`, `createUserHandler`, `usersRouter` — and you have to read each one to confirm it's actually a route.
14
-
15
- With the Express adapter active, the same search returns:
16
-
17
- ```
18
- search_symbols(query: "users") →
19
-
20
- GET /users src/routes/users.ts route
21
- POST /users src/routes/users.ts route
22
- GET /users/:id src/routes/users.ts route
23
- DELETE /users/:id src/routes/users.ts route
24
- ```
25
-
26
- That's the difference. Adapters extract the *intent* of code (a route, a component, an ORM entity) rather than just its syntactic shape.
27
-
28
- ---
29
-
30
- ## Auto-detection
31
-
32
- Adapters are detected from project config — `package.json`, `composer.json`, `Gemfile`, `pubspec.yaml`, `go.mod`, `Cargo.toml`, `pom.xml`, `build.gradle`. If you have `react` in dependencies, the React adapter runs. If `manage.py` sits at the project root, the Django adapter runs.
33
-
34
- You don't usually need to configure anything. If you do:
35
-
36
- ```json
37
- {
38
- "adapters": "auto" // default
39
- "adapters": "none" // disable all adapters
40
- "adapters": ["vue", "nuxt"] // explicit allow-list
41
- }
42
- ```
43
-
44
- Multiple adapters run side by side. A Vue + Nuxt project activates both. A Nest app that also uses TypeORM gets routes from Nest *and* entities from TypeORM.
45
-
46
- ---
47
-
48
- ## JavaScript and TypeScript
49
-
50
- ### Vue 3
51
-
52
- Detected by `vue` in `package.json` or any `.vue` file present.
53
-
54
- Extracts from Single File Components:
55
- - The component itself (named from `defineComponent` or filename) → `component`
56
- - Exported `useFoo` functions → `composable`
57
-
58
- Useful for: jumping to a `<MyButton>` mentioned in a template, or finding every composable that touches the auth store.
59
-
60
- ### Nuxt
61
-
62
- Detected by `nuxt.config.ts` / `.js` / `.mts` / `.mjs`.
63
-
64
- Layers Nuxt's conventional routing on top of the Vue adapter:
65
- - `pages/blog/[slug].vue` → `route /blog/:slug`
66
- - `server/api/users.get.ts` `route GET /api/users`
67
- - `middleware/auth.ts` and `plugins/*` → `middleware`
68
- - Composables in `composables/` are flagged with `nuxt_auto_import: true`
69
-
70
- ### React
71
-
72
- Detected by `react` in `package.json`. This adapter doesn't extract new symbols — it *enriches* what the TypeScript handler already found:
73
- - PascalCase functions that return JSX → `component`
74
- - `useFoo` functions → `hook`
75
-
76
- So `MyButton` shows up as a `component` rather than a generic `function`, and `useAuth` shows up as a `hook` rather than a generic `function`.
77
-
78
- ### Next.js
79
-
80
- Detected by `next.config.*` or `next` in dependencies. Supports both routers:
81
-
82
- **Pages Router** (`pages/`):
83
- - `pages/blog/[slug].tsx` → `route /blog/:slug`
84
- - Detects `getServerSideProps` (SSR) and `getStaticProps` (SSG)
85
- - API routes from `pages/api/`
86
-
87
- **App Router** (`app/`):
88
- - `app/(marketing)/about/page.tsx` → `route /about` (route groups stripped)
89
- - `'use client'` directive flagged on metadata
90
- - API routes from `app/**/route.ts` with HTTP method exports
91
-
92
- **Middleware** (`middleware.ts`) → `middleware` symbol with the matcher config.
93
-
94
- ### Angular
95
-
96
- Detected by `@angular/core`. Decorated classes become first-class:
97
- - `@Component` `component` (with `selector`)
98
- - `@Injectable` → `class` (service)
99
- - `@NgModule` `class` (module)
100
- - `@Directive` → `component`
101
- - `@Pipe` `component` (with the pipe name)
102
- - `RouterModule.forRoot` / `forChild` configs → `route` symbols
103
-
104
- ### NestJS
105
-
106
- Detected by `@nestjs/core`. Combines the controller prefix with each method's path:
107
-
108
- ```typescript
109
- @Controller('users')
110
- class UsersController {
111
- @Get(':id') findOne() { ... } // → route GET /users/:id
112
- }
113
- ```
114
-
115
- - `@Injectable` → `class` (with `nestjs_provider: true`)
116
- - `@Module` → `class` (with `nestjs_module: true`)
117
- - Guards and `CanActivate` implementations → `middleware`
118
-
119
- ### Express
120
-
121
- Detected by `express`. Extracts string-literal route registrations:
122
-
123
- ```javascript
124
- app.get('/path', handler) // → route GET /path
125
- router.post('/path', handler) // → route POST /path
126
- app.use('/path', middleware) // → middleware /path
127
- ```
128
-
129
- Dynamic paths built from variables or template literals are skipped — there's no reliable way to recover the runtime value from static analysis.
130
-
131
- ### Fastify
132
-
133
- Detected by `fastify`. Same pattern as Express: `fastify.get(path, handler)` → `route`.
134
-
135
- ---
136
-
137
- ## Python
138
-
139
- ### Django
140
-
141
- Detected by `manage.py` at the project root, or `django` in requirements.
142
-
143
- - `models.Model` subclasses`model` (with field types: `CharField`, `ForeignKey`, etc.)
144
- - Class-based views (`APIView`, `ViewSet`, etc.) → `view`
145
- - Function-based views with `@login_required` / `@api_view` → `view`
146
- - `path(...)` / `re_path(...)` in `urls.py` `route`
147
- - `@receiver(post_save)` → `signal`
148
-
149
- ### FastAPI
150
-
151
- Detected by `fastapi`. Extracts decorated handlers:
152
-
153
- ```python
154
- @app.get('/items/{id}') # → route GET /items/{id}
155
- @router.post('/items') # → route POST /items
156
- ```
157
-
158
- FastAPI's `{param}` path syntax is preserved as-is in the route metadata.
159
-
160
- ### Flask
161
-
162
- Detected by `Flask`. Extracts:
163
- - `@app.route('/path')` → `route`
164
- - `@app.get`, `@app.post`, etc. → `route`
165
- - Blueprint routes (`@bp.route(...)`) → `route`
166
- - Class-based views inheriting `MethodView` → `view`
167
-
168
- Flask's `<int:user_id>` path syntax is preserved.
169
-
170
- ---
171
-
172
- ## Go
173
-
174
- ### Gin, Echo, Fiber
175
-
176
- Detected by their respective `go.mod` entries. All three follow the same pattern — `r.GET("/path", handler)` becomes a `route`. Route groups apply their prefix to children.
177
-
178
- The Fiber adapter handles title-cased methods (`app.Get`, `app.Post`); Gin and Echo use lowercase methods.
179
-
180
- ---
181
-
182
- ## PHP
183
-
184
- ### Laravel
185
-
186
- Detected by `laravel/framework` in `composer.json`.
187
-
188
- - `Route::get('/path', ...)` → `route`
189
- - `Route::resource('users', Controller::class)` → expands into the seven CRUD routes (index/show/create/store/edit/update/destroy)
190
- - `Route::group(['prefix' => '/api'], ...)` → prefix applied to children
191
- - `class User extends Model` → `model`
192
- - Controller public methods → `view` (action)
193
- - Middleware classes `middleware`
194
-
195
- ### Symfony
196
-
197
- Detected by `symfony/framework-bundle`. Supports both routing styles:
198
-
199
- ```php
200
- #[Route('/path', methods: ['GET'])] // PHP 8 attributes
201
- @Route('/path') // docblock annotations
202
- ```
203
-
204
- Both produce `route` symbols.
205
-
206
- ---
207
-
208
- ## Ruby
209
-
210
- ### Rails
211
-
212
- Detected by `gem 'rails'` in `Gemfile`.
213
-
214
- - `ApplicationRecord` subclasses → `model` (with `has_many` associations captured)
215
- - Controller public methods → `view` (action)
216
- - `get '/path'`, `resources :users` in `routes.rb` → `route` (resources expand to the seven REST actions)
217
-
218
- ### Sinatra
219
-
220
- Detected by `gem 'sinatra'` or `require 'sinatra'`. `get '/path' do ... end` → `route`.
221
-
222
- ---
223
-
224
- ## Kotlin
225
-
226
- ### Ktor
227
-
228
- Detected by `io.ktor`. Extracts from the routing DSL:
229
-
230
- ```kotlin
231
- route("/api") {
232
- get("/users") { ... } //route /api/users
233
- }
234
- authenticate { ... } // → frameworkMeta.authenticated: true
235
- ```
236
-
237
- ### Spring (Kotlin)
238
-
239
- Detected by `org.springframework.boot`. Same extraction as Spring Boot below — adapter handles both Java and Kotlin sources.
240
-
241
- ---
242
-
243
- ## Rust
244
-
245
- ### Axum
246
-
247
- Detected by `axum` in `Cargo.toml`. Extracts router chains:
248
-
249
- ```rust
250
- .route("/users", get(list_users))
251
- .route("/users/:id", get(get_user))
252
- .layer(auth_middleware) // → middleware
253
- ```
254
-
255
- ### Actix-web
256
-
257
- Detected by `actix-web`. Extracts attribute macros: `#[get("/path")]` → `route`. `.wrap(...)` calls become `middleware`.
258
-
259
- ### Rocket
260
-
261
- Detected by `rocket`. Extracts `#[get("/path")]` → `route`. `#[catch(404)]` becomes an error catcher, and `Fairing` implementations become middleware.
262
-
263
- ---
264
-
265
- ## Java
266
-
267
- ### Spring Boot
268
-
269
- Detected by `spring-boot-starter` in build files.
270
-
271
- - `@GetMapping` / `@PostMapping` (combined with class-level `@RequestMapping` prefix) → `route`
272
- - `@Service`, `@Component`, `@Repository` → beans with bean metadata
273
- - `@Bean` factory methods → tracked as bean producers
274
- - `@Scheduled` methods scheduled tasks
275
-
276
- ### Micronaut
277
-
278
- Detected by `io.micronaut`. `@Get("/path")`, `@Post(...)` → `route`. `@Client` interfaces are captured.
279
-
280
- ### Quarkus
281
-
282
- Detected by `io.quarkus`. JAX-RS `@GET` + `@Path` combinations → `route`. `@ApplicationScoped` → bean.
283
-
284
- ---
285
-
286
- ## ORM adapters
287
-
288
- ORMs sit slightly off the routing-adapter spine because they don't add routes they add *entities*, which downstream queries (`find_references`, `get_blast_radius`) treat the same as any other symbol.
289
-
290
- | Adapter | Detected by | Extracts |
291
- |---------|-------------|----------|
292
- | **Hibernate** (Java) | `hibernate-core` / `jakarta.persistence` | `@Entity` classes, table name, columns with types and nullability, `@OneToMany` / `@ManyToOne` relationships, named queries |
293
- | **SQLAlchemy** (Python) | `sqlalchemy` | `Base` / `DeclarativeBase` subclasses, `__tablename__`, `Column(Type)` fields, `relationship()` associations, `@hybrid_property`. Supports both 1.x and 2.0 (`mapped_column`) styles. |
294
- | **Django ORM** | `manage.py` | `models.Model` subclasses with field types (`CharField`, `IntegerField`, `ForeignKey`, `ManyToManyField`, etc.) |
295
- | **Prisma** | `prisma` in `package.json` or `schema.prisma` present | Model definitions and relations from `schema.prisma` |
296
- | **TypeORM** | `typeorm` in `package.json` | `@Entity` classes and `@Column` / `@Relation` fields |
297
-
298
- Once entities are first-class symbols, you can ask "what writes to the `users` table?" the same way you'd ask "what calls `validateToken`?".
299
-
300
- ---
301
-
302
- ## Mobile
303
-
304
- ### Flutter
305
-
306
- Detected by `sdk: flutter` in `pubspec.yaml`. Extracts from `.dart` files:
307
-
308
- - `StatelessWidget` subclasses → `widget`
309
- - `StatefulWidget` subclasses `widget` (linked to the State class)
310
- - `ChangeNotifier` subclasses `class` with `flutter_notifier: true`
311
-
312
- ---
313
-
314
- ## Disabling an adapter
315
-
316
- If an adapter is misclassifying things in your project, turn it off:
317
-
318
- ```json
319
- {
320
- "adapters": ["vue", "react"] // explicit list — others stay off
321
- }
322
- ```
323
-
324
- Or to disable framework extraction entirely:
325
-
326
- ```json
327
- {
328
- "adapters": "none"
329
- }
330
- ```
331
-
332
- The language handler still runs — you'll still get functions and classes, you just won't get `route` / `component` / `model` annotations on top.
333
-
334
- ---
335
-
336
- ## Adding a new adapter
337
-
338
- Adapters follow the same three-layer rule as language handlers (Core → Handlers → Adapters; never the reverse). To add one:
339
-
340
- 1. Create a file in `src/adapters/`, implementing `FrameworkAdapter`
341
- 2. `detect(projectRoot)` returns true if the framework is present
342
- 3. `extractFrameworkSymbols(tree, source, filePath)` returns the framework-specific symbols
343
- 4. Optionally `enrichMetadata(symbol)` to add `frameworkMeta` to existing symbols
344
- 5. Add tests against fixture projects in `test/adapters/`
345
-
346
- See `docs/25-architecture-overview.md` for the architecture rules and `src/adapters/vue.ts` for a good reference implementation.
347
-
348
- ---
349
-
350
- → Full parameter-level reference: [docs/08-framework-adapters.md](docs/08-framework-adapters.md)
351
- → The language handlers that adapters sit on top of: [LANGUAGE-SUPPORT.md](LANGUAGE-SUPPORT.md)
1
+ # Framework Adapters
2
+
3
+ A language handler knows what a function or class looks like. A framework adapter knows that `app.get('/users/:id', ...)` is actually a **route**, that a Vue Single File Component is a **component**, and that a Django `models.Model` subclass is a **model** with a table behind it.
4
+
5
+ PureContext ships with adapters for the frameworks most production codebases are written against. They run automatically — drop the index on a NestJS project and `/users` routes show up as first-class symbols you can search for by path, not just by handler-function name.
6
+
7
+ This page is the user-facing tour. For parameter-level details (exact regex patterns, full `frameworkMeta` shapes), see the [reference manual](docs/08-framework-adapters.md).
8
+
9
+ ---
10
+
11
+ ## How adapters change what you see
12
+
13
+ Without an adapter, searching for "user routes" in an Express app returns *function names* — `handleGetUser`, `createUserHandler`, `usersRouter` — and you have to read each one to confirm it's actually a route.
14
+
15
+ With the Express adapter active, the same search returns:
16
+
17
+ ```
18
+ search_symbols(query: "users") →
19
+
20
+ GET /users src/routes/users.ts route
21
+ POST /users src/routes/users.ts route
22
+ GET /users/:id src/routes/users.ts route
23
+ DELETE /users/:id src/routes/users.ts route
24
+ ```
25
+
26
+ That's the difference. Adapters extract the *intent* of code (a route, a component, an ORM entity) rather than just its syntactic shape.
27
+
28
+ ---
29
+
30
+ ## Auto-detection
31
+
32
+ Adapters are detected from project config — `package.json`, `composer.json`, `Gemfile`, `pubspec.yaml`, `go.mod`, `Cargo.toml`, `pom.xml`, `build.gradle`. If you have `react` in dependencies, the React adapter runs. If `manage.py` sits at the project root, the Django adapter runs.
33
+
34
+ You don't usually need to configure anything. If you do:
35
+
36
+ ```json
37
+ {
38
+ "adapters": "auto" // default
39
+ "adapters": "none" // disable all adapters
40
+ "adapters": ["vue", "nuxt"] // explicit allow-list
41
+ }
42
+ ```
43
+
44
+ Multiple adapters run side by side. A Vue + Nuxt project activates both. A Nest app that also uses TypeORM gets routes from Nest *and* entities from TypeORM.
45
+
46
+ ---
47
+
48
+ ## JavaScript and TypeScript
49
+
50
+ ### Vue 3
51
+
52
+ Detected by `vue` in `package.json` or any `.vue` file present.
53
+
54
+ Extracts from Single File Components:
55
+ - The component itself (named from `defineComponent` or filename) → `component`
56
+ - Exported `useFoo` functions → `composable`
57
+
58
+ Useful for: jumping to a `<MyButton>` mentioned in a template, or finding every composable that touches the auth store.
59
+
60
+ ### Svelte
61
+
62
+ Detected by `svelte` / `@sveltejs/*` in `package.json`, a `svelte.config.*` file, or any `.svelte` file present (including monorepo sub-apps).
63
+
64
+ Extracts from Svelte components:
65
+ - The component itself (named from filename) → `component`
66
+ - Symbols inside `<script>` / `<script context="module">` blocks (parsed by the TS/JS handler)
67
+ - Exported `useFoo` functions → `composable`
68
+
69
+ ### Astro
70
+
71
+ Detected by `astro` / `@astrojs/*` in `package.json`, an `astro.config.*` file, or any `.astro` file present (including monorepo sub-apps).
72
+
73
+ Extracts from Astro components:
74
+ - The component itself (named from filename) → `component`
75
+ - Symbols declared in the leading `---` frontmatter (parsed as TypeScript)
76
+
77
+ ### Nuxt
78
+
79
+ Detected by `nuxt.config.ts` / `.js` / `.mts` / `.mjs`.
80
+
81
+ Layers Nuxt's conventional routing on top of the Vue adapter:
82
+ - `pages/blog/[slug].vue` `route /blog/:slug`
83
+ - `server/api/users.get.ts` → `route GET /api/users`
84
+ - `middleware/auth.ts` and `plugins/*` → `middleware`
85
+ - Composables in `composables/` are flagged with `nuxt_auto_import: true`
86
+
87
+ ### React
88
+
89
+ Detected by `react` in `package.json`. This adapter doesn't extract new symbols — it *enriches* what the TypeScript handler already found:
90
+ - PascalCase functions that return JSX `component`
91
+ - `useFoo` functions → `hook`
92
+
93
+ So `MyButton` shows up as a `component` rather than a generic `function`, and `useAuth` shows up as a `hook` rather than a generic `function`.
94
+
95
+ ### Next.js
96
+
97
+ Detected by `next.config.*` or `next` in dependencies. Supports both routers:
98
+
99
+ **Pages Router** (`pages/`):
100
+ - `pages/blog/[slug].tsx` → `route /blog/:slug`
101
+ - Detects `getServerSideProps` (SSR) and `getStaticProps` (SSG)
102
+ - API routes from `pages/api/`
103
+
104
+ **App Router** (`app/`):
105
+ - `app/(marketing)/about/page.tsx` → `route /about` (route groups stripped)
106
+ - `'use client'` directive flagged on metadata
107
+ - API routes from `app/**/route.ts` with HTTP method exports
108
+
109
+ **Middleware** (`middleware.ts`) → `middleware` symbol with the matcher config.
110
+
111
+ ### Angular
112
+
113
+ Detected by `@angular/core`. Decorated classes become first-class:
114
+ - `@Component` → `component` (with `selector`)
115
+ - `@Injectable` → `class` (service)
116
+ - `@NgModule` → `class` (module)
117
+ - `@Directive` → `component`
118
+ - `@Pipe` → `component` (with the pipe name)
119
+ - `RouterModule.forRoot` / `forChild` configs → `route` symbols
120
+
121
+ ### NestJS
122
+
123
+ Detected by `@nestjs/core`. Combines the controller prefix with each method's path:
124
+
125
+ ```typescript
126
+ @Controller('users')
127
+ class UsersController {
128
+ @Get(':id') findOne() { ... } // → route GET /users/:id
129
+ }
130
+ ```
131
+
132
+ - `@Injectable` → `class` (with `nestjs_provider: true`)
133
+ - `@Module` `class` (with `nestjs_module: true`)
134
+ - Guards and `CanActivate` implementations → `middleware`
135
+
136
+ ### Express
137
+
138
+ Detected by `express`. Extracts string-literal route registrations:
139
+
140
+ ```javascript
141
+ app.get('/path', handler) // route GET /path
142
+ router.post('/path', handler) // → route POST /path
143
+ app.use('/path', middleware) //middleware /path
144
+ ```
145
+
146
+ Dynamic paths built from variables or template literals are skipped — there's no reliable way to recover the runtime value from static analysis.
147
+
148
+ ### Fastify
149
+
150
+ Detected by `fastify`. Same pattern as Express: `fastify.get(path, handler)` → `route`.
151
+
152
+ ---
153
+
154
+ ## Python
155
+
156
+ ### Django
157
+
158
+ Detected by `manage.py` at the project root, or `django` in requirements.
159
+
160
+ - `models.Model` subclasses → `model` (with field types: `CharField`, `ForeignKey`, etc.)
161
+ - Class-based views (`APIView`, `ViewSet`, etc.) → `view`
162
+ - Function-based views with `@login_required` / `@api_view` → `view`
163
+ - `path(...)` / `re_path(...)` in `urls.py` → `route`
164
+ - `@receiver(post_save)` → `signal`
165
+
166
+ ### FastAPI
167
+
168
+ Detected by `fastapi`. Extracts decorated handlers:
169
+
170
+ ```python
171
+ @app.get('/items/{id}') # → route GET /items/{id}
172
+ @router.post('/items') # → route POST /items
173
+ ```
174
+
175
+ FastAPI's `{param}` path syntax is preserved as-is in the route metadata.
176
+
177
+ ### Flask
178
+
179
+ Detected by `Flask`. Extracts:
180
+ - `@app.route('/path')` → `route`
181
+ - `@app.get`, `@app.post`, etc. → `route`
182
+ - Blueprint routes (`@bp.route(...)`) → `route`
183
+ - Class-based views inheriting `MethodView` → `view`
184
+
185
+ Flask's `<int:user_id>` path syntax is preserved.
186
+
187
+ ---
188
+
189
+ ## Go
190
+
191
+ ### Gin, Echo, Fiber
192
+
193
+ Detected by their respective `go.mod` entries. All three follow the same pattern — `r.GET("/path", handler)` becomes a `route`. Route groups apply their prefix to children.
194
+
195
+ The Fiber adapter handles title-cased methods (`app.Get`, `app.Post`); Gin and Echo use lowercase methods.
196
+
197
+ ---
198
+
199
+ ## PHP
200
+
201
+ ### Laravel
202
+
203
+ Detected by `laravel/framework` in `composer.json`.
204
+
205
+ - `Route::get('/path', ...)` → `route`
206
+ - `Route::resource('users', Controller::class)` → expands into the seven CRUD routes (index/show/create/store/edit/update/destroy)
207
+ - `Route::group(['prefix' => '/api'], ...)` → prefix applied to children
208
+ - `class User extends Model` → `model`
209
+ - Controller public methods → `view` (action)
210
+ - Middleware classes → `middleware`
211
+
212
+ ### Symfony
213
+
214
+ Detected by `symfony/framework-bundle`. Supports both routing styles:
215
+
216
+ ```php
217
+ #[Route('/path', methods: ['GET'])] // PHP 8 attributes
218
+ @Route('/path') // docblock annotations
219
+ ```
220
+
221
+ Both produce `route` symbols.
222
+
223
+ ---
224
+
225
+ ## Ruby
226
+
227
+ ### Rails
228
+
229
+ Detected by `gem 'rails'` in `Gemfile`.
230
+
231
+ - `ApplicationRecord` subclasses → `model` (with `has_many` associations captured)
232
+ - Controller public methods`view` (action)
233
+ - `get '/path'`, `resources :users` in `routes.rb` → `route` (resources expand to the seven REST actions)
234
+
235
+ ### Sinatra
236
+
237
+ Detected by `gem 'sinatra'` or `require 'sinatra'`. `get '/path' do ... end` → `route`.
238
+
239
+ ---
240
+
241
+ ## Kotlin
242
+
243
+ ### Ktor
244
+
245
+ Detected by `io.ktor`. Extracts from the routing DSL:
246
+
247
+ ```kotlin
248
+ route("/api") {
249
+ get("/users") { ... } // → route /api/users
250
+ }
251
+ authenticate { ... } // → frameworkMeta.authenticated: true
252
+ ```
253
+
254
+ ### Spring (Kotlin)
255
+
256
+ Detected by `org.springframework.boot`. Same extraction as Spring Boot below — adapter handles both Java and Kotlin sources.
257
+
258
+ ---
259
+
260
+ ## Rust
261
+
262
+ ### Axum
263
+
264
+ Detected by `axum` in `Cargo.toml`. Extracts router chains:
265
+
266
+ ```rust
267
+ .route("/users", get(list_users))
268
+ .route("/users/:id", get(get_user))
269
+ .layer(auth_middleware) // middleware
270
+ ```
271
+
272
+ ### Actix-web
273
+
274
+ Detected by `actix-web`. Extracts attribute macros: `#[get("/path")]` → `route`. `.wrap(...)` calls become `middleware`.
275
+
276
+ ### Rocket
277
+
278
+ Detected by `rocket`. Extracts `#[get("/path")]` → `route`. `#[catch(404)]` becomes an error catcher, and `Fairing` implementations become middleware.
279
+
280
+ ---
281
+
282
+ ## Java
283
+
284
+ ### Spring Boot
285
+
286
+ Detected by `spring-boot-starter` in build files.
287
+
288
+ - `@GetMapping` / `@PostMapping` (combined with class-level `@RequestMapping` prefix) `route`
289
+ - `@Service`, `@Component`, `@Repository` → beans with bean metadata
290
+ - `@Bean` factory methods tracked as bean producers
291
+ - `@Scheduled` methods → scheduled tasks
292
+
293
+ ### Micronaut
294
+
295
+ Detected by `io.micronaut`. `@Get("/path")`, `@Post(...)` `route`. `@Client` interfaces are captured.
296
+
297
+ ### Quarkus
298
+
299
+ Detected by `io.quarkus`. JAX-RS `@GET` + `@Path` combinations → `route`. `@ApplicationScoped` → bean.
300
+
301
+ ---
302
+
303
+ ## ORM adapters
304
+
305
+ ORMs sit slightly off the routing-adapter spine because they don't add routes — they add *entities*, which downstream queries (`find_references`, `get_blast_radius`) treat the same as any other symbol.
306
+
307
+ | Adapter | Detected by | Extracts |
308
+ |---------|-------------|----------|
309
+ | **Hibernate** (Java) | `hibernate-core` / `jakarta.persistence` | `@Entity` classes, table name, columns with types and nullability, `@OneToMany` / `@ManyToOne` relationships, named queries |
310
+ | **SQLAlchemy** (Python) | `sqlalchemy` | `Base` / `DeclarativeBase` subclasses, `__tablename__`, `Column(Type)` fields, `relationship()` associations, `@hybrid_property`. Supports both 1.x and 2.0 (`mapped_column`) styles. |
311
+ | **Django ORM** | `manage.py` | `models.Model` subclasses with field types (`CharField`, `IntegerField`, `ForeignKey`, `ManyToManyField`, etc.) |
312
+ | **Prisma** | `prisma` in `package.json` or `schema.prisma` present | Model definitions and relations from `schema.prisma` |
313
+ | **TypeORM** | `typeorm` in `package.json` | `@Entity` classes and `@Column` / `@Relation` fields |
314
+
315
+ Once entities are first-class symbols, you can ask "what writes to the `users` table?" the same way you'd ask "what calls `validateToken`?".
316
+
317
+ ---
318
+
319
+ ## Mobile
320
+
321
+ ### Flutter
322
+
323
+ Detected by `sdk: flutter` in `pubspec.yaml`. Extracts from `.dart` files:
324
+
325
+ - `StatelessWidget` subclasses → `widget`
326
+ - `StatefulWidget` subclasses → `widget` (linked to the State class)
327
+ - `ChangeNotifier` subclasses → `class` with `flutter_notifier: true`
328
+
329
+ ---
330
+
331
+ ## Disabling an adapter
332
+
333
+ If an adapter is misclassifying things in your project, turn it off:
334
+
335
+ ```json
336
+ {
337
+ "adapters": ["vue", "react"] // explicit list — others stay off
338
+ }
339
+ ```
340
+
341
+ Or to disable framework extraction entirely:
342
+
343
+ ```json
344
+ {
345
+ "adapters": "none"
346
+ }
347
+ ```
348
+
349
+ The language handler still runs — you'll still get functions and classes, you just won't get `route` / `component` / `model` annotations on top.
350
+
351
+ ---
352
+
353
+ ## Adding a new adapter
354
+
355
+ Adapters follow the same three-layer rule as language handlers (Core → Handlers → Adapters; never the reverse). To add one:
356
+
357
+ 1. Create a file in `src/adapters/`, implementing `FrameworkAdapter`
358
+ 2. `detect(projectRoot)` returns true if the framework is present
359
+ 3. `extractFrameworkSymbols(tree, source, filePath)` returns the framework-specific symbols
360
+ 4. Optionally `enrichMetadata(symbol)` to add `frameworkMeta` to existing symbols
361
+ 5. Add tests against fixture projects in `test/adapters/`
362
+
363
+ See `docs/25-architecture-overview.md` for the architecture rules and `src/adapters/vue.ts` for a good reference implementation.
364
+
365
+ ---
366
+
367
+ → Full parameter-level reference: [docs/08-framework-adapters.md](docs/08-framework-adapters.md)
368
+ → The language handlers that adapters sit on top of: [LANGUAGE-SUPPORT.md](LANGUAGE-SUPPORT.md)