Add JS, Go, and Rust detectors
Some checks failed
CI / test (push) Has been cancelled

This commit is contained in:
2026-01-31 17:11:28 +00:00
parent 1aa2435bcd
commit f6bd9a04b3

View File

@@ -0,0 +1,124 @@
"""JavaScript endpoint detector for Express and Fastify."""
import re
from pathlib import Path
from typing import Optional
from docgen.models import Endpoint, HTTPMethod
from docgen.detectors.base import BaseDetector
class JavaScriptDetector(BaseDetector):
"""Detector for JavaScript web frameworks."""
extensions = [".js", ".ts", ".jsx", ".tsx"]
framework_name = "javascript"
EXPRESS_PATTERN = re.compile(
r'(app|router)\.(get|post|put|patch|delete|options|head)\s*\(\s*["\']([^"\']+)["\']',
re.MULTILINE,
)
EXPRESS_APP_ROUTE_PATTERN = re.compile(
r'(app|router)\.(route)\s*\(\s*["\']([^"\']+)["\'][\s\S]*?\.((?:get|post|put|patch|delete|options|head))\s*\(',
re.MULTILINE,
)
FASTIFY_PATTERN = re.compile(
r'(?:fastify|instance)\s*\.\s*(get|post|put|patch|delete|options|head)\s*\(\s*["\']([^"\']+)["\']',
re.MULTILINE,
)
FASTIFY_DECORATOR_PATTERN = re.compile(
r'@?(?:get|post|put|patch|delete|options|head)\s*\(\s*["\']([^"\']+)["\']',
re.MULTILINE,
)
METHOD_MAP = {
"get": HTTPMethod.GET,
"post": HTTPMethod.POST,
"put": HTTPMethod.PUT,
"patch": HTTPMethod.PATCH,
"delete": HTTPMethod.DELETE,
"options": HTTPMethod.OPTIONS,
"head": HTTPMethod.HEAD,
}
def detect_endpoints(self, file_path: Path) -> list[Endpoint]:
"""Detect endpoints in a JavaScript/TypeScript file."""
content = file_path.read_text()
endpoints = []
framework = self._detect_framework(content)
if framework == "fastify":
endpoints.extend(self._detect_fastify(content, file_path))
else:
endpoints.extend(self._detect_express(content, file_path))
return endpoints
def _detect_framework(self, content: str) -> Optional[str]:
"""Auto-detect the JavaScript framework."""
if "from '@fastify/" in content or "from 'fastify'" in content or "import fastify" in content:
return "fastify"
if 'require("fastify")' in content or "require('fastify')" in content:
return "fastify"
if "from 'express'" in content or "import express" in content:
return "express"
return None
def _detect_express(self, content: str, file_path: Path) -> list[Endpoint]:
"""Detect Express endpoints."""
endpoints = []
for match in self.EXPRESS_PATTERN.finditer(content):
router, method, path = match.groups()
endpoint = Endpoint(
path=path,
method=self.METHOD_MAP.get(method.lower(), HTTPMethod.GET),
summary=f"{method.upper()} {path}",
file_path=str(file_path),
line_number=content[:match.start()].count("\n") + 1,
)
endpoints.append(endpoint)
for match in self.EXPRESS_APP_ROUTE_PATTERN.finditer(content):
router, path, sub_method = match.groups()
endpoint = Endpoint(
path=path,
method=self.METHOD_MAP.get(sub_method.lower(), HTTPMethod.GET),
summary=f"{sub_method.upper()} {path}",
file_path=str(file_path),
line_number=content[:match.start()].count("\n") + 1,
)
endpoints.append(endpoint)
return endpoints
def _detect_fastify(self, content: str, file_path: Path) -> list[Endpoint]:
"""Detect Fastify endpoints."""
endpoints = []
for match in self.FASTIFY_PATTERN.finditer(content):
method, path = match.groups()
endpoint = Endpoint(
path=path,
method=self.METHOD_MAP.get(method.lower(), HTTPMethod.GET),
summary=f"{method.upper()} {path}",
file_path=str(file_path),
line_number=content[:match.start()].count("\n") + 1,
)
endpoints.append(endpoint)
for match in self.FASTIFY_DECORATOR_PATTERN.finditer(content):
path = match.group(1)
endpoint = Endpoint(
path=path,
method=HTTPMethod.GET,
summary=f"GET {path}",
file_path=str(file_path),
line_number=content[:match.start()].count("\n") + 1,
)
endpoints.append(endpoint)
return endpoints