aja-codeintel 0.1.8__tar.gz → 0.2.0__tar.gz

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 (108) hide show
  1. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/PKG-INFO +98 -5
  2. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/README.md +97 -4
  3. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/aja_codeintel.egg-info/PKG-INFO +98 -5
  4. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/aja_codeintel.egg-info/SOURCES.txt +9 -1
  5. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/nav/open_cmd.py +1 -3
  6. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/project/__init__.py +7 -1
  7. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/project/endpoints_cmd.py +1 -1
  8. aja_codeintel-0.2.0/codeintel_cli/commands/project/entire_cmd.py +417 -0
  9. aja_codeintel-0.2.0/codeintel_cli/commands/project/fastapi_cmd.py +144 -0
  10. aja_codeintel-0.2.0/codeintel_cli/commands/project/overview_cmd.py +1356 -0
  11. aja_codeintel-0.2.0/codeintel_cli/commands/project/trace_cmd.py +738 -0
  12. aja_codeintel-0.2.0/codeintel_cli/endpoints/fastapi_scanner.py +1220 -0
  13. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/endpoints/python_web.py +18 -18
  14. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/lang/java/method_index.py +2 -2
  15. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/lang/java/models.py +2 -15
  16. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/lang/python/models.py +1 -14
  17. aja_codeintel-0.2.0/codeintel_cli/lang/shared_models.py +19 -0
  18. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/scanner/scanner.py +24 -1
  19. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/pyproject.toml +1 -1
  20. aja_codeintel-0.2.0/tests/test_entire_cmd.py +208 -0
  21. aja_codeintel-0.2.0/tests/test_fastapi_scanner.py +544 -0
  22. aja_codeintel-0.2.0/tests/test_trace_cmd.py +270 -0
  23. aja_codeintel-0.1.8/codeintel_cli/commands/project/overview_cmd.py +0 -689
  24. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/LICENSE +0 -0
  25. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/aja_codeintel.egg-info/dependency_links.txt +0 -0
  26. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/aja_codeintel.egg-info/entry_points.txt +0 -0
  27. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/aja_codeintel.egg-info/requires.txt +0 -0
  28. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/aja_codeintel.egg-info/top_level.txt +0 -0
  29. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/__init__.py +0 -0
  30. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/__main__.py +0 -0
  31. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/cli.py +0 -0
  32. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/__init__.py +0 -0
  33. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/graph/__init__.py +0 -0
  34. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/graph/deps_cmd.py +0 -0
  35. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/graph/related_cmd.py +0 -0
  36. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/graph/relsymbols_cmd.py +0 -0
  37. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/graph/reverse_related_cmd.py +0 -0
  38. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/nav/__init__.py +0 -0
  39. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/nav/copy_cmd.py +0 -0
  40. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/nav/where_cmd.py +0 -0
  41. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/project/context_cmd.py +0 -0
  42. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/project/debug_cmd.py +0 -0
  43. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/project/errors_cmd.py +0 -0
  44. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/project/folder_cmd.py +0 -0
  45. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/project/frontend_cmd.py +0 -0
  46. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/project/imports_cmd.py +0 -0
  47. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/project/models_cmd.py +0 -0
  48. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/project/modeltree_cmd.py +0 -0
  49. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/project/new.py +0 -0
  50. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/project/resolve_cmd.py +0 -0
  51. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/project/scan_cmd.py +0 -0
  52. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/project/servicemap_cmd.py +0 -0
  53. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/project/tree_cmd.py +0 -0
  54. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/project/types_cmd.py +0 -0
  55. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/commands/project/version_cmd.py +0 -0
  56. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/context/java_context.py +0 -0
  57. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/context/java_rel.py +0 -0
  58. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/context/java_service.py +0 -0
  59. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/context/python_context.py +0 -0
  60. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/context/python_rel.py +0 -0
  61. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/context/python_service.py +0 -0
  62. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/core/fuzzy.py +0 -0
  63. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/core/opener.py +0 -0
  64. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/core/project.py +0 -0
  65. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/core/resolve_folder.py +0 -0
  66. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/core/resolve_model_target.py +0 -0
  67. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/core/resolve_target.py +0 -0
  68. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/core/timing.py +0 -0
  69. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/core/where.py +0 -0
  70. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/db/__init__.py +0 -0
  71. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/db/cache.py +0 -0
  72. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/db/operations.py +0 -0
  73. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/db/schema.py +0 -0
  74. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/endpoints/__init__.py +0 -0
  75. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/endpoints/java_spring.py +0 -0
  76. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/endpoints/models.py +0 -0
  77. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/endpoints/openapi_spec.py +0 -0
  78. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/endpoints/scan.py +0 -0
  79. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/errors.py +0 -0
  80. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/frontend/__init__.py +0 -0
  81. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/frontend/server.py +0 -0
  82. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/graph/__init__.py +0 -0
  83. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/graph/builder.py +0 -0
  84. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/graph/query.py +0 -0
  85. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/graph/traverse.py +0 -0
  86. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/lang/__init__.py +0 -0
  87. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/lang/java/__init__.py +0 -0
  88. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/lang/java/ast_engine.py +0 -0
  89. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/lang/java/auth.py +0 -0
  90. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/lang/java/base_path.py +0 -0
  91. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/lang/java/call_graph.py +0 -0
  92. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/lang/java/engine.py +0 -0
  93. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/lang/java/enums.py +0 -0
  94. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/lang/java/pagination.py +0 -0
  95. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/lang/java/resolve.py +0 -0
  96. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/lang/java/types.py +0 -0
  97. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/lang/java/validation.py +0 -0
  98. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/lang/python/__init__.py +0 -0
  99. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/lang/python/engine.py +0 -0
  100. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/lang/router.py +0 -0
  101. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/parser/imports.py +0 -0
  102. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/parser/resolve.py +0 -0
  103. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/parser/symbols.py +0 -0
  104. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/scanner/__init__.py +0 -0
  105. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/terminal/__init__.py +0 -0
  106. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/terminal/error_parser.py +0 -0
  107. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/codeintel_cli/terminal/printer.py +0 -0
  108. {aja_codeintel-0.1.8 → aja_codeintel-0.2.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aja-codeintel
3
- Version: 0.1.8
3
+ Version: 0.2.0
4
4
  Summary: CodeIntel CLI tool
5
5
  Author: Shiva Areti
6
6
  License: MIT License
@@ -340,6 +340,99 @@ aja models
340
340
 
341
341
  ---
342
342
 
343
+ ### `aja fastapi-scan .`
344
+
345
+ **What it does:** Full FastAPI project scan — resolves complete route paths including `APIRouter` prefixes and `include_router` prefix stacking, extracts Pydantic DTOs (with required/optional fields, default values, nested models), and extracts SQLAlchemy entity models (columns, types, primary keys, foreign keys, relationships). Produces structured JSON matching the same schema as the Java Spring Boot scanner.
346
+
347
+ **When to use it:** Deep analysis of a FastAPI codebase. Generating API + data model inventory. Feeding structured metadata into AI tools or documentation pipelines.
348
+
349
+ ```bash
350
+ # JSON report (default) — same schema as Java scanner
351
+ aja fastapi-scan .
352
+
353
+ # Human-readable text
354
+ aja fastapi-scan . --format text
355
+
356
+ # Only paths under /api
357
+ aja fastapi-scan . --only-api
358
+
359
+ # Skip DTOs or models from output
360
+ aja fastapi-scan . --no-dtos
361
+ aja fastapi-scan . --no-models
362
+ ```
363
+
364
+ **Output schema (JSON):**
365
+ ```json
366
+ {
367
+ "endpoints": [
368
+ {
369
+ "method": "POST",
370
+ "path": "/api/v1/users",
371
+ "file": "app/routers/users.py",
372
+ "line": 24,
373
+ "handler": "create_user",
374
+ "framework": "fastapi",
375
+ "controller": "CreateUserRequest"
376
+ }
377
+ ],
378
+ "dtos": [
379
+ {
380
+ "name": "CreateUserRequest",
381
+ "file": "app/schemas/user.py",
382
+ "kind": "pydantic",
383
+ "bases": ["BaseModel"],
384
+ "fields": [
385
+ { "name": "name", "type": "str", "required": true, "default": null },
386
+ { "name": "email", "type": "str", "required": true, "default": null },
387
+ { "name": "age", "type": "Optional[int]","required": false, "default": "None" }
388
+ ]
389
+ }
390
+ ],
391
+ "models": [
392
+ {
393
+ "name": "User",
394
+ "file": "app/models/user.py",
395
+ "kind": "sqlalchemy",
396
+ "table": "users",
397
+ "columns": [
398
+ { "name": "id", "type": "Integer", "primary_key": true, "foreign_key": null },
399
+ { "name": "email", "type": "String", "primary_key": false, "foreign_key": null }
400
+ ],
401
+ "relationships": [
402
+ { "name": "posts", "target": "Post", "kind": "relationship" }
403
+ ]
404
+ }
405
+ ]
406
+ }
407
+ ```
408
+
409
+ **What the FastAPI scanner resolves:**
410
+
411
+ | Pattern | Resolved path |
412
+ |---|---|
413
+ | `APIRouter(prefix="/users")` + `@router.get("/")` | `/users` |
414
+ | `app.include_router(router, prefix="/api")` | `/api/users` |
415
+ | `app.include_router(router, prefix="/v1")` + router prefix `/api` | `/v1/api/users` |
416
+ | `@router.api_route("/ping", methods=["GET","HEAD"])` | `GET /ping` + `HEAD /ping` |
417
+
418
+ **What the Pydantic extractor captures:**
419
+
420
+ - `class X(BaseModel)` — direct BaseModel subclass
421
+ - `class X(SomeBase)` — inherited from another Pydantic model in the same project
422
+ - Required vs optional fields (`Optional[T]`, `T | None`, `Field(...)`, no default)
423
+ - Default values including `Field(default=…)`
424
+ - List types (`List[str]`, `list[int]`)
425
+
426
+ **What the SQLAlchemy extractor captures:**
427
+
428
+ - Classic declarative style: `Column(Integer, primary_key=True)`
429
+ - Modern mapped style: `id: Mapped[int] = mapped_column(primary_key=True)`
430
+ - Foreign keys: `Column(Integer, ForeignKey("users.id"))`
431
+ - Relationships: `relationship("Post", back_populates="author")`
432
+ - `__tablename__`
433
+
434
+ ---
435
+
343
436
  ### `aja copy <file>`
344
437
 
345
438
  **What it does:** Copies the full contents of a file (or multiple files) to your clipboard — ready to paste into a code review, chat, or AI tool.
@@ -377,10 +470,10 @@ Prints the current AJA version.
377
470
 
378
471
  ## Supported Languages
379
472
 
380
- | Language | Analysis | Imports | Symbols | Services | Models |
381
- |----------|----------|---------|---------|----------|--------|
382
- | Java | ✅ | ✅ | ✅ | ✅ | ✅ |
383
- | Python | ✅ | ✅ | ✅ | ✅ | ✅ |
473
+ | Language | Analysis | Imports | Symbols | Services | Models | Endpoints |
474
+ |----------|----------|---------|---------|----------|--------|-----------|
475
+ | Java (Spring Boot) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
476
+ | Python (FastAPI) | ✅ | ✅ | ✅ | ✅ | ✅ (Pydantic + SQLAlchemy) | ✅ (prefix-resolved) |
384
477
 
385
478
  > Static analysis only — no compilation, no runtime, no build tools required.
386
479
 
@@ -303,6 +303,99 @@ aja models
303
303
 
304
304
  ---
305
305
 
306
+ ### `aja fastapi-scan .`
307
+
308
+ **What it does:** Full FastAPI project scan — resolves complete route paths including `APIRouter` prefixes and `include_router` prefix stacking, extracts Pydantic DTOs (with required/optional fields, default values, nested models), and extracts SQLAlchemy entity models (columns, types, primary keys, foreign keys, relationships). Produces structured JSON matching the same schema as the Java Spring Boot scanner.
309
+
310
+ **When to use it:** Deep analysis of a FastAPI codebase. Generating API + data model inventory. Feeding structured metadata into AI tools or documentation pipelines.
311
+
312
+ ```bash
313
+ # JSON report (default) — same schema as Java scanner
314
+ aja fastapi-scan .
315
+
316
+ # Human-readable text
317
+ aja fastapi-scan . --format text
318
+
319
+ # Only paths under /api
320
+ aja fastapi-scan . --only-api
321
+
322
+ # Skip DTOs or models from output
323
+ aja fastapi-scan . --no-dtos
324
+ aja fastapi-scan . --no-models
325
+ ```
326
+
327
+ **Output schema (JSON):**
328
+ ```json
329
+ {
330
+ "endpoints": [
331
+ {
332
+ "method": "POST",
333
+ "path": "/api/v1/users",
334
+ "file": "app/routers/users.py",
335
+ "line": 24,
336
+ "handler": "create_user",
337
+ "framework": "fastapi",
338
+ "controller": "CreateUserRequest"
339
+ }
340
+ ],
341
+ "dtos": [
342
+ {
343
+ "name": "CreateUserRequest",
344
+ "file": "app/schemas/user.py",
345
+ "kind": "pydantic",
346
+ "bases": ["BaseModel"],
347
+ "fields": [
348
+ { "name": "name", "type": "str", "required": true, "default": null },
349
+ { "name": "email", "type": "str", "required": true, "default": null },
350
+ { "name": "age", "type": "Optional[int]","required": false, "default": "None" }
351
+ ]
352
+ }
353
+ ],
354
+ "models": [
355
+ {
356
+ "name": "User",
357
+ "file": "app/models/user.py",
358
+ "kind": "sqlalchemy",
359
+ "table": "users",
360
+ "columns": [
361
+ { "name": "id", "type": "Integer", "primary_key": true, "foreign_key": null },
362
+ { "name": "email", "type": "String", "primary_key": false, "foreign_key": null }
363
+ ],
364
+ "relationships": [
365
+ { "name": "posts", "target": "Post", "kind": "relationship" }
366
+ ]
367
+ }
368
+ ]
369
+ }
370
+ ```
371
+
372
+ **What the FastAPI scanner resolves:**
373
+
374
+ | Pattern | Resolved path |
375
+ |---|---|
376
+ | `APIRouter(prefix="/users")` + `@router.get("/")` | `/users` |
377
+ | `app.include_router(router, prefix="/api")` | `/api/users` |
378
+ | `app.include_router(router, prefix="/v1")` + router prefix `/api` | `/v1/api/users` |
379
+ | `@router.api_route("/ping", methods=["GET","HEAD"])` | `GET /ping` + `HEAD /ping` |
380
+
381
+ **What the Pydantic extractor captures:**
382
+
383
+ - `class X(BaseModel)` — direct BaseModel subclass
384
+ - `class X(SomeBase)` — inherited from another Pydantic model in the same project
385
+ - Required vs optional fields (`Optional[T]`, `T | None`, `Field(...)`, no default)
386
+ - Default values including `Field(default=…)`
387
+ - List types (`List[str]`, `list[int]`)
388
+
389
+ **What the SQLAlchemy extractor captures:**
390
+
391
+ - Classic declarative style: `Column(Integer, primary_key=True)`
392
+ - Modern mapped style: `id: Mapped[int] = mapped_column(primary_key=True)`
393
+ - Foreign keys: `Column(Integer, ForeignKey("users.id"))`
394
+ - Relationships: `relationship("Post", back_populates="author")`
395
+ - `__tablename__`
396
+
397
+ ---
398
+
306
399
  ### `aja copy <file>`
307
400
 
308
401
  **What it does:** Copies the full contents of a file (or multiple files) to your clipboard — ready to paste into a code review, chat, or AI tool.
@@ -340,10 +433,10 @@ Prints the current AJA version.
340
433
 
341
434
  ## Supported Languages
342
435
 
343
- | Language | Analysis | Imports | Symbols | Services | Models |
344
- |----------|----------|---------|---------|----------|--------|
345
- | Java | ✅ | ✅ | ✅ | ✅ | ✅ |
346
- | Python | ✅ | ✅ | ✅ | ✅ | ✅ |
436
+ | Language | Analysis | Imports | Symbols | Services | Models | Endpoints |
437
+ |----------|----------|---------|---------|----------|--------|-----------|
438
+ | Java (Spring Boot) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
439
+ | Python (FastAPI) | ✅ | ✅ | ✅ | ✅ | ✅ (Pydantic + SQLAlchemy) | ✅ (prefix-resolved) |
347
440
 
348
441
  > Static analysis only — no compilation, no runtime, no build tools required.
349
442
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aja-codeintel
3
- Version: 0.1.8
3
+ Version: 0.2.0
4
4
  Summary: CodeIntel CLI tool
5
5
  Author: Shiva Areti
6
6
  License: MIT License
@@ -340,6 +340,99 @@ aja models
340
340
 
341
341
  ---
342
342
 
343
+ ### `aja fastapi-scan .`
344
+
345
+ **What it does:** Full FastAPI project scan — resolves complete route paths including `APIRouter` prefixes and `include_router` prefix stacking, extracts Pydantic DTOs (with required/optional fields, default values, nested models), and extracts SQLAlchemy entity models (columns, types, primary keys, foreign keys, relationships). Produces structured JSON matching the same schema as the Java Spring Boot scanner.
346
+
347
+ **When to use it:** Deep analysis of a FastAPI codebase. Generating API + data model inventory. Feeding structured metadata into AI tools or documentation pipelines.
348
+
349
+ ```bash
350
+ # JSON report (default) — same schema as Java scanner
351
+ aja fastapi-scan .
352
+
353
+ # Human-readable text
354
+ aja fastapi-scan . --format text
355
+
356
+ # Only paths under /api
357
+ aja fastapi-scan . --only-api
358
+
359
+ # Skip DTOs or models from output
360
+ aja fastapi-scan . --no-dtos
361
+ aja fastapi-scan . --no-models
362
+ ```
363
+
364
+ **Output schema (JSON):**
365
+ ```json
366
+ {
367
+ "endpoints": [
368
+ {
369
+ "method": "POST",
370
+ "path": "/api/v1/users",
371
+ "file": "app/routers/users.py",
372
+ "line": 24,
373
+ "handler": "create_user",
374
+ "framework": "fastapi",
375
+ "controller": "CreateUserRequest"
376
+ }
377
+ ],
378
+ "dtos": [
379
+ {
380
+ "name": "CreateUserRequest",
381
+ "file": "app/schemas/user.py",
382
+ "kind": "pydantic",
383
+ "bases": ["BaseModel"],
384
+ "fields": [
385
+ { "name": "name", "type": "str", "required": true, "default": null },
386
+ { "name": "email", "type": "str", "required": true, "default": null },
387
+ { "name": "age", "type": "Optional[int]","required": false, "default": "None" }
388
+ ]
389
+ }
390
+ ],
391
+ "models": [
392
+ {
393
+ "name": "User",
394
+ "file": "app/models/user.py",
395
+ "kind": "sqlalchemy",
396
+ "table": "users",
397
+ "columns": [
398
+ { "name": "id", "type": "Integer", "primary_key": true, "foreign_key": null },
399
+ { "name": "email", "type": "String", "primary_key": false, "foreign_key": null }
400
+ ],
401
+ "relationships": [
402
+ { "name": "posts", "target": "Post", "kind": "relationship" }
403
+ ]
404
+ }
405
+ ]
406
+ }
407
+ ```
408
+
409
+ **What the FastAPI scanner resolves:**
410
+
411
+ | Pattern | Resolved path |
412
+ |---|---|
413
+ | `APIRouter(prefix="/users")` + `@router.get("/")` | `/users` |
414
+ | `app.include_router(router, prefix="/api")` | `/api/users` |
415
+ | `app.include_router(router, prefix="/v1")` + router prefix `/api` | `/v1/api/users` |
416
+ | `@router.api_route("/ping", methods=["GET","HEAD"])` | `GET /ping` + `HEAD /ping` |
417
+
418
+ **What the Pydantic extractor captures:**
419
+
420
+ - `class X(BaseModel)` — direct BaseModel subclass
421
+ - `class X(SomeBase)` — inherited from another Pydantic model in the same project
422
+ - Required vs optional fields (`Optional[T]`, `T | None`, `Field(...)`, no default)
423
+ - Default values including `Field(default=…)`
424
+ - List types (`List[str]`, `list[int]`)
425
+
426
+ **What the SQLAlchemy extractor captures:**
427
+
428
+ - Classic declarative style: `Column(Integer, primary_key=True)`
429
+ - Modern mapped style: `id: Mapped[int] = mapped_column(primary_key=True)`
430
+ - Foreign keys: `Column(Integer, ForeignKey("users.id"))`
431
+ - Relationships: `relationship("Post", back_populates="author")`
432
+ - `__tablename__`
433
+
434
+ ---
435
+
343
436
  ### `aja copy <file>`
344
437
 
345
438
  **What it does:** Copies the full contents of a file (or multiple files) to your clipboard — ready to paste into a code review, chat, or AI tool.
@@ -377,10 +470,10 @@ Prints the current AJA version.
377
470
 
378
471
  ## Supported Languages
379
472
 
380
- | Language | Analysis | Imports | Symbols | Services | Models |
381
- |----------|----------|---------|---------|----------|--------|
382
- | Java | ✅ | ✅ | ✅ | ✅ | ✅ |
383
- | Python | ✅ | ✅ | ✅ | ✅ | ✅ |
473
+ | Language | Analysis | Imports | Symbols | Services | Models | Endpoints |
474
+ |----------|----------|---------|---------|----------|--------|-----------|
475
+ | Java (Spring Boot) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
476
+ | Python (FastAPI) | ✅ | ✅ | ✅ | ✅ | ✅ (Pydantic + SQLAlchemy) | ✅ (prefix-resolved) |
384
477
 
385
478
  > Static analysis only — no compilation, no runtime, no build tools required.
386
479
 
@@ -25,7 +25,9 @@ codeintel_cli/commands/project/__init__.py
25
25
  codeintel_cli/commands/project/context_cmd.py
26
26
  codeintel_cli/commands/project/debug_cmd.py
27
27
  codeintel_cli/commands/project/endpoints_cmd.py
28
+ codeintel_cli/commands/project/entire_cmd.py
28
29
  codeintel_cli/commands/project/errors_cmd.py
30
+ codeintel_cli/commands/project/fastapi_cmd.py
29
31
  codeintel_cli/commands/project/folder_cmd.py
30
32
  codeintel_cli/commands/project/frontend_cmd.py
31
33
  codeintel_cli/commands/project/imports_cmd.py
@@ -36,6 +38,7 @@ codeintel_cli/commands/project/overview_cmd.py
36
38
  codeintel_cli/commands/project/resolve_cmd.py
37
39
  codeintel_cli/commands/project/scan_cmd.py
38
40
  codeintel_cli/commands/project/servicemap_cmd.py
41
+ codeintel_cli/commands/project/trace_cmd.py
39
42
  codeintel_cli/commands/project/tree_cmd.py
40
43
  codeintel_cli/commands/project/types_cmd.py
41
44
  codeintel_cli/commands/project/version_cmd.py
@@ -58,6 +61,7 @@ codeintel_cli/db/cache.py
58
61
  codeintel_cli/db/operations.py
59
62
  codeintel_cli/db/schema.py
60
63
  codeintel_cli/endpoints/__init__.py
64
+ codeintel_cli/endpoints/fastapi_scanner.py
61
65
  codeintel_cli/endpoints/java_spring.py
62
66
  codeintel_cli/endpoints/models.py
63
67
  codeintel_cli/endpoints/openapi_spec.py
@@ -71,6 +75,7 @@ codeintel_cli/graph/query.py
71
75
  codeintel_cli/graph/traverse.py
72
76
  codeintel_cli/lang/__init__.py
73
77
  codeintel_cli/lang/router.py
78
+ codeintel_cli/lang/shared_models.py
74
79
  codeintel_cli/lang/java/__init__.py
75
80
  codeintel_cli/lang/java/ast_engine.py
76
81
  codeintel_cli/lang/java/auth.py
@@ -94,4 +99,7 @@ codeintel_cli/scanner/__init__.py
94
99
  codeintel_cli/scanner/scanner.py
95
100
  codeintel_cli/terminal/__init__.py
96
101
  codeintel_cli/terminal/error_parser.py
97
- codeintel_cli/terminal/printer.py
102
+ codeintel_cli/terminal/printer.py
103
+ tests/test_entire_cmd.py
104
+ tests/test_fastapi_scanner.py
105
+ tests/test_trace_cmd.py
@@ -13,6 +13,4 @@ def register_open(app: typer.Typer) -> None:
13
13
  yes: bool = typer.Option(False, "--yes", "-y", help="Open without confirmation"),
14
14
  ):
15
15
  target, _root = resolve_target_file(query)
16
-
17
- if yes or typer.confirm(f"Open this file?\n{target}"):
18
- open_file(target)
16
+ open_file(target)
@@ -19,6 +19,9 @@ def register_project_commands(app: typer.Typer) -> None:
19
19
  from .frontend_cmd import register_frontend
20
20
  from .errors_cmd import register_errors
21
21
  from .debug_cmd import register_debug
22
+ from .fastapi_cmd import register_fastapi_scan
23
+ from .trace_cmd import register_trace
24
+ from .entire_cmd import register_entire
22
25
 
23
26
  register_overview(app)
24
27
  register_models(app)
@@ -35,4 +38,7 @@ def register_project_commands(app: typer.Typer) -> None:
35
38
  register_version(app)
36
39
  register_frontend(app)
37
40
  register_errors(app)
38
- register_debug(app)
41
+ register_debug(app)
42
+ register_fastapi_scan(app)
43
+ register_trace(app)
44
+ register_entire(app)
@@ -14,7 +14,7 @@ from ...core.project import find_project_root
14
14
  from ...endpoints.java_spring import extract_spring_endpoints
15
15
  from ...endpoints.python_web import extract_python_endpoints
16
16
  from ...endpoints.scan import EndpointScanOptions, iter_supported_source_files
17
- from ...endpoints.openapi_spec import extract_openapi_endpoints # NEW
17
+ from ...endpoints.openapi_spec import extract_openapi_endpoints
18
18
  from ...errors import InvalidPathError
19
19
 
20
20