- Deleted `I18N_IMPLEMENTATION_PLAN.md` and `PROJECT_PROGRESS.md` to declutter the repository. - These documents were finalized, no longer relevant, and superseded by implemented features and external references.
9.7 KiB
MSW Auto-Generation from OpenAPI
Overview
MSW (Mock Service Worker) handlers are automatically generated from your OpenAPI specification, ensuring perfect synchronization between your backend API and demo mode.
Architecture
Backend API Changes
↓
npm run generate:api
↓
┌─────────────────────────────────────┐
│ 1. Fetches OpenAPI spec │
│ 2. Generates TypeScript API client │
│ 3. Generates MSW handlers │
└─────────────────────────────────────┘
↓
src/mocks/handlers/
├── generated.ts (AUTO-GENERATED - DO NOT EDIT)
├── overrides.ts (CUSTOM LOGIC - EDIT AS NEEDED)
└── index.ts (MERGES BOTH)
How It Works
1. Automatic Generation
When you run:
npm run generate:api
The system:
- Fetches
/api/v1/openapi.jsonfrom backend - Generates TypeScript API client (
src/lib/api/generated/) - NEW: Generates MSW handlers (
src/mocks/handlers/generated.ts)
2. Generated Handlers
The generator (scripts/generate-msw-handlers.ts) creates handlers with:
Smart Response Logic:
- Auth endpoints → Use
validateCredentials()andsetCurrentUser() - User endpoints → Use
currentUserand mock data - Admin endpoints → Check
is_superuser+ return paginated data - Generic endpoints → Return success response
Example Generated Handler:
/**
* Login
*/
http.post(`${API_BASE_URL}/api/v1/auth/login`, async ({ request, params }) => {
await delay(NETWORK_DELAY);
const body = (await request.json()) as any;
const user = validateCredentials(body.email, body.password);
if (!user) {
return HttpResponse.json(
{ detail: 'Incorrect email or password' },
{ status: 401 }
);
}
const accessToken = `demo-access-${user.id}-${Date.now()}`;
const refreshToken = `demo-refresh-${user.id}-${Date.now()}`;
setCurrentUser(user);
return HttpResponse.json({
access_token: accessToken,
refresh_token: refreshToken,
token_type: 'bearer',
expires_in: 900,
});
}),
3. Custom Overrides
For complex logic that can't be auto-generated, use overrides.ts:
// src/mocks/handlers/overrides.ts
export const overrideHandlers = [
// Example: Simulate rate limiting
http.post(`${API_BASE_URL}/api/v1/auth/login`, async ({ request }) => {
// 10% chance of rate limit
if (Math.random() < 0.1) {
return HttpResponse.json({ detail: 'Too many login attempts' }, { status: 429 });
}
// Fall through to generated handler
}),
// Example: Complex validation
http.post(`${API_BASE_URL}/api/v1/users`, async ({ request }) => {
const body = await request.json();
// Custom validation logic
if (body.email.endsWith('@blocked.com')) {
return HttpResponse.json({ detail: 'Email domain not allowed' }, { status: 400 });
}
// Fall through to generated handler
}),
];
Override Precedence: Overrides are applied FIRST, so they take precedence over generated handlers.
Benefits
✅ Zero Manual Work
Before:
# Backend adds new endpoint
# 1. Run npm run generate:api
# 2. Manually add MSW handler
# 3. Test demo mode
# 4. Fix bugs
# 5. Repeat for every endpoint change
After:
# Backend adds new endpoint
npm run generate:api # Done! MSW auto-synced
✅ Always In Sync
- OpenAPI spec is single source of truth
- Generator reads same spec as API client
- Impossible to have mismatched endpoints
- New endpoints automatically available in demo mode
✅ Type-Safe
// Generated handlers use your mock data
import { validateCredentials, currentUser } from '../data/users';
import { sampleOrganizations } from '../data/organizations';
import { adminStats } from '../data/stats';
// Everything is typed!
✅ Batteries Included
Generated handlers include:
- ✅ Network delays (300ms - realistic UX)
- ✅ Auth checks (401/403 responses)
- ✅ Pagination support
- ✅ Path parameters
- ✅ Request body parsing
- ✅ Proper HTTP methods
File Structure
frontend/
├── scripts/
│ ├── generate-api-client.sh # Main generation script
│ └── generate-msw-handlers.ts # MSW handler generator
│
├── src/
│ ├── lib/api/generated/ # Auto-generated API client
│ │ ├── client.gen.ts
│ │ ├── sdk.gen.ts
│ │ └── types.gen.ts
│ │
│ └── mocks/
│ ├── browser.ts # MSW setup
│ ├── data/ # Mock data (EDIT THESE)
│ │ ├── users.ts
│ │ ├── organizations.ts
│ │ └── stats.ts
│ └── handlers/
│ ├── generated.ts # ⚠️ AUTO-GENERATED
│ ├── overrides.ts # ✅ EDIT FOR CUSTOM LOGIC
│ └── index.ts # Merges both
Workflow
Adding New Backend Endpoint
- Add endpoint to backend (FastAPI route)
- Regenerate clients:
cd frontend npm run generate:api - Test demo mode:
NEXT_PUBLIC_DEMO_MODE=true npm run dev - Done! New endpoint automatically works in demo mode
Customizing Handler Behavior
If generated handler doesn't fit your needs:
- Add override in
src/mocks/handlers/overrides.ts - Keep generated handler (don't edit
generated.ts) - Override takes precedence automatically
Example:
// overrides.ts
export const overrideHandlers = [
// Override auto-generated login to add 2FA simulation
http.post(`${API_BASE_URL}/api/v1/auth/login`, async ({ request }) => {
const body = await request.json();
// Simulate 2FA requirement for admin users
if (body.email.includes('admin') && !body.two_factor_code) {
return HttpResponse.json({ detail: 'Two-factor authentication required' }, { status: 403 });
}
// Fall through to generated handler
}),
];
Updating Mock Data
Mock data is separate from handlers:
// src/mocks/data/users.ts
export const demoUser: UserResponse = {
id: 'demo-user-id-1',
email: 'demo@example.com',
first_name: 'Demo',
last_name: 'User',
// ... add more fields as backend evolves
};
To update:
- Edit
data/*.tsfiles - Handlers automatically use updated data
- No regeneration needed!
Generator Internals
The generator (scripts/generate-msw-handlers.ts) does:
-
Parse OpenAPI spec
const spec = JSON.parse(fs.readFileSync(specPath, 'utf-8')); -
For each endpoint:
- Convert path params:
{id}→:id - Determine handler category (auth/users/admin)
- Generate appropriate mock response
- Add network delay
- Include error handling
- Convert path params:
-
Write generated file:
fs.writeFileSync('src/mocks/handlers/generated.ts', handlerCode);
Troubleshooting
Generated handler doesn't work
Check:
- Is backend running? (
npm run generate:apirequires backend) - Check console for
[MSW]warnings - Verify
generated.tsexists and has your endpoint - Check path parameters match exactly
Debug:
# See what endpoints were generated
cat src/mocks/handlers/generated.ts | grep "http\."
Need custom behavior
Don't edit generated.ts! Use overrides instead:
// overrides.ts
export const overrideHandlers = [
http.post(`${API_BASE_URL}/your/endpoint`, async ({ request }) => {
// Your custom logic
}),
];
Regeneration fails
# Manual regeneration
cd frontend
curl -s http://localhost:8000/api/v1/openapi.json > /tmp/openapi.json
npx tsx scripts/generate-msw-handlers.ts /tmp/openapi.json
Best Practices
✅ Do
- Run
npm run generate:apiafter backend changes - Use
overrides.tsfor complex logic - Keep mock data in
data/files - Test demo mode regularly
- Commit
overrides.tsto git
❌ Don't
- Don't edit
generated.tsmanually (changes will be overwritten) - Don't commit
generated.tsto git (it's auto-generated) - Don't duplicate logic between overrides and generated
- Don't skip regeneration after API changes
Advanced: Generator Customization
Want to customize the generator itself?
Edit scripts/generate-msw-handlers.ts:
function generateMockResponse(path: string, method: string, operation: any): string {
// Your custom generation logic
if (path.includes('/your-special-endpoint')) {
return `
// Your custom handler code
`;
}
// ... rest of generation logic
}
Comparison
Before (Manual)
// Had to manually write this for EVERY endpoint:
http.post(`${API_BASE_URL}/api/v1/auth/login`, async ({ request }) => {
// 50 lines of code...
}),
http.get(`${API_BASE_URL}/api/v1/users/me`, async ({ request }) => {
// 30 lines of code...
}),
// ... repeat for 31+ endpoints
// ... manually update when backend changes
// ... easy to forget endpoints
// ... prone to bugs
After (Automated)
npm run generate:api # Done! All 31+ endpoints handled automatically
Manual Code: 1500+ lines Automated: 1 command Time Saved: Hours per API change Bugs: Near zero (generated from spec)
See Also
- DEMO_MODE.md - Complete demo mode guide
- API_INTEGRATION.md - API client docs
Summary
This template is batteries-included.
Your API client and MSW handlers stay perfectly synchronized with zero manual work.
Just run npm run generate:api and everything updates automatically.
That's the power of OpenAPI + automation! 🚀