M2-T06: scaffold React SPA frontend with typed OpenAPI client
- Vite + React 18 + TypeScript + Mantine + TanStack Query + react-router-dom - typed client: openapi-typescript -> src/api/schema.d.ts (committed), openapi-fetch - fetch wrapper middleware: cookies, X-CSRF-Token on writes, 401 -> /login, non-401 errors carry parsed JSON body - SessionProvider/useSession (GET /api/session), ProtectedRoute skeleton - app shell (Mantine + router) with placeholder login/home/config pages + gear nav - dev proxy to FastAPI; vitest smoke test; frontend README - npm scripts: dev/build/preview/lint/typecheck/test/codegen
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Module-level CSRF token holder.
|
||||
*
|
||||
* The token is populated by SessionProvider after a successful GET /api/session.
|
||||
* The fetch client middleware reads it on every non-GET/HEAD request.
|
||||
*
|
||||
* Per the project CSRF contract (m2-frontend-v2.md §3.2, orchestrator-decisions.md §3):
|
||||
* - Server checks presence/non-empty only, does NOT validate the value.
|
||||
* - Sending an empty-string or stale value will result in a 403; callers must
|
||||
* ensure setCsrfToken() is called before issuing write requests.
|
||||
*/
|
||||
|
||||
let _csrfToken = ''
|
||||
|
||||
/** Store the CSRF token returned by GET /api/session. */
|
||||
export function setCsrfToken(token: string): void {
|
||||
_csrfToken = token
|
||||
}
|
||||
|
||||
/** Return the current CSRF token (may be empty string if not yet set). */
|
||||
export function getCsrfToken(): string {
|
||||
return _csrfToken
|
||||
}
|
||||
Reference in New Issue
Block a user