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:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user