-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Summary
Extract HTTP route definitions from TypeScript/JavaScript web framework files using tree-sitter. Supports Express and Next.js App Router.
New file
src/specleft/discovery/miners/typescript/routes.py
import uuid
from specleft.discovery.models import SupportedLanguage, MinerResult, DiscoveredItem, ItemKind, ApiRouteMeta
from specleft.discovery.context import MinerContext
class TypeScriptRouteMiner:
miner_id = uuid.UUID("b06e8c32-c793-41dc-91de-12635d6c4f69")
name = "typescript_api_routes"
languages = frozenset({SupportedLanguage.TYPESCRIPT, SupportedLanguage.JAVASCRIPT})
def mine(self, ctx: MinerContext) -> MinerResult: ...Framework detection
Read from ctx.frameworks.get(SupportedLanguage.TYPESCRIPT, []) / ctx.frameworks.get(SupportedLanguage.JAVASCRIPT, []). Do NOT re-parse package.json.
Detection strategies per framework
Express:
Tree-sitter query on ctx.file_index.files_by_language(SupportedLanguage.TYPESCRIPT) + JAVASCRIPT: call expressions where callee is member expression on app/router, method is get|post|put|patch|delete|use. First string argument is path.
Next.js App Router (file-based):
Use ctx.file_index.files_matching("**/app/**/route.ts", "**/app/**/route.js"). Named exports export async function GET(request) — HTTP method from export name. Path inferred from file path relative to app/: app/users/[id]/route.ts → /users/{id}.
Typed metadata
Each item's metadata dict must conform to ApiRouteMeta:
ApiRouteMeta(
http_method = "DELETE",
path = "/api/users/{id}",
framework = "nextjs",
handler_name = "DELETE",
is_file_based_route = True,
)name: "{METHOD} {path}"
language: SupportedLanguage.TYPESCRIPT or SupportedLanguage.JAVASCRIPT based on file extension
Acceptance criteria
-
router.get("/health", handler)→ item withmethod=GET,path=/health,framework=express -
.tsfiles getSupportedLanguage.TYPESCRIPT;.jsfiles getSupportedLanguage.JAVASCRIPT - Each item's
metadatavalidates againstApiRouteMeta -
app/api/users/[id]/route.tsexportingfunction DELETE→method=DELETE,path=/api/users/{id},is_file_based_route=True - Next.js file with multiple exports (
GET,POST) produces 2 separate items - Uses
ctx.file_indexandctx.frameworks— no direct filesystem or manifest parsing - Tests in
tests/discovery/miners/test_typescript_routes.py - Update scenarios and tests in
features/feature-spec-discovery.mdto cover the functionality introduced by this issue