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.
- package/FRAMEWORK-ADAPTERS.md +368 -351
- package/dist/adapters/astro-preprocessor.d.ts +25 -0
- package/dist/adapters/astro-preprocessor.d.ts.map +1 -0
- package/dist/adapters/astro-preprocessor.js +50 -0
- package/dist/adapters/astro-preprocessor.js.map +1 -0
- package/dist/adapters/astro.d.ts +13 -0
- package/dist/adapters/astro.d.ts.map +1 -0
- package/dist/adapters/astro.js +83 -0
- package/dist/adapters/astro.js.map +1 -0
- package/dist/adapters/detect-utils.d.ts +38 -0
- package/dist/adapters/detect-utils.d.ts.map +1 -0
- package/dist/adapters/detect-utils.js +95 -0
- package/dist/adapters/detect-utils.js.map +1 -0
- package/dist/adapters/nuxt.d.ts +20 -0
- package/dist/adapters/nuxt.d.ts.map +1 -1
- package/dist/adapters/nuxt.js +128 -13
- package/dist/adapters/nuxt.js.map +1 -1
- package/dist/adapters/svelte-preprocessor.d.ts +29 -0
- package/dist/adapters/svelte-preprocessor.d.ts.map +1 -0
- package/dist/adapters/svelte-preprocessor.js +83 -0
- package/dist/adapters/svelte-preprocessor.js.map +1 -0
- package/dist/adapters/svelte.d.ts +13 -0
- package/dist/adapters/svelte.d.ts.map +1 -0
- package/dist/adapters/svelte.js +96 -0
- package/dist/adapters/svelte.js.map +1 -0
- package/dist/adapters/vue.d.ts.map +1 -1
- package/dist/adapters/vue.js +87 -20
- package/dist/adapters/vue.js.map +1 -1
- package/dist/cli/hooks.d.ts +2 -2
- package/dist/cli/hooks.d.ts.map +1 -1
- package/dist/cli/hooks.js +104 -121
- package/dist/cli/hooks.js.map +1 -1
- package/dist/core/index-manager.d.ts.map +1 -1
- package/dist/core/index-manager.js +9 -2
- package/dist/core/index-manager.js.map +1 -1
- package/dist/core/indexing-worker.d.ts +2 -0
- package/dist/core/indexing-worker.d.ts.map +1 -1
- package/dist/core/indexing-worker.js +2 -0
- package/dist/core/indexing-worker.js.map +1 -1
- package/dist/core/watcher/file-watcher.d.ts +6 -0
- package/dist/core/watcher/file-watcher.d.ts.map +1 -1
- package/dist/core/watcher/file-watcher.js +11 -1
- package/dist/core/watcher/file-watcher.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/server/tools/index-repo.d.ts.map +1 -1
- package/dist/server/tools/index-repo.js +8 -2
- package/dist/server/tools/index-repo.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/FRAMEWORK-ADAPTERS.md
CHANGED
|
@@ -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
|
-
###
|
|
61
|
-
|
|
62
|
-
Detected by `
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
- `
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
- `
|
|
84
|
-
-
|
|
85
|
-
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
-
|
|
101
|
-
-
|
|
102
|
-
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
- `@Injectable` → `class` (
|
|
116
|
-
- `@
|
|
117
|
-
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
-
|
|
164
|
-
- `@
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
.
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
-
|
|
273
|
-
|
|
274
|
-
-
|
|
275
|
-
|
|
276
|
-
###
|
|
277
|
-
|
|
278
|
-
Detected by `
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
- `
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
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)
|