feat: Implement automated OpenAPI type generation

Add automated type synchronization from backend OpenAPI schema to frontend TypeScript types to prevent type drift and ensure runtime safety.

Changes:
- Add openapi-typescript as dev dependency
- Create npm scripts for type generation (generate:types) and validation (validate:types)
- Integrate type generation into build pipeline (runs before TypeScript compilation)
- Generate frontend/src/types/generated.ts from backend OpenAPI schema
- Add frontend/scripts/validate-types.sh for CI/CD validation
- Update Web-Development.md with type generation workflow documentation
- Update Backend-Development.md with OpenAPI schema sync requirements

Workflow:
1. Backend automatically exposes OpenAPI schema at /api/openapi.json (FastAPI built-in)
2. Frontend build runs 'npm run generate:types' to generate types from schema
3. Generated types are committed to version control
4. CI can run 'npm run validate:types' to fail builds if types drift

Fixes critical type safety issue where frontend types were manually maintained
and could become out of sync with backend Pydantic models.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-04-30 21:00:05 +02:00
parent c4ede71fa6
commit 59c92f9a83
6 changed files with 8962 additions and 2 deletions

View File

@@ -293,10 +293,31 @@ async def get_jails(state: JailServiceStateDep) -> JailListResponse:
# Good — pass db=None on GET so geo_service never commits
result = await geo_service.lookup_batch(ips, http_session, db=None)
# Bad — triggers INSERT + COMMIT per IP inside a GET handler
# Bad — triggers INSERT + COMMIT per GET inside a GET handler
result = await geo_service.lookup_batch(ips, http_session, db=app_db)
```
### OpenAPI Schema Synchronization
**Critical:** The OpenAPI schema is the single source of truth for frontend types. When you add, modify, or remove endpoints or response models:
1. **FastAPI automatically updates the schema** based on your Pydantic models and endpoint definitions.
2. **The frontend regenerates types** from the schema on every build: `npm run generate:types`.
3. **Ensure your Pydantic models are accurate** — they are directly serialized into the schema and used to generate frontend types.
4. **Test type generation locally** before committing:
```bash
cd frontend
npm run generate:types # Generates src/types/generated.ts
npm run build # Build should succeed if types match
```
5. **The backend must be running** for type generation to work (the tool fetches `/api/openapi.json`).
6. **Commit generated types** alongside backend changes — they must always be in sync.
**Never:**
- Manually edit `src/types/generated.ts` on the frontend — regenerate from the schema instead.
- Commit backend changes without ensuring the frontend can regenerate types.
- Assume the OpenAPI schema is correct — validate your Pydantic model's `field` descriptions and types are as intended.
```python
from fastapi import APIRouter, Depends, HTTPException, status
from app.models.jail import JailResponse, JailListResponse
@@ -310,6 +331,7 @@ async def list_jails(service: JailService = Depends()) -> JailListResponse:
return JailListResponse(jails=jails)
```
### Dependency Layering: Enforcing the Repository Boundary
The **repository boundary** separates database-aware code from application logic. This is enforced through dependency injection.