UI for Admin — Setup
The admin UI uses Orval to auto-generate the following from the Admin API's OpenAPI 3.1 spec (/api/v1/doc):
- TypeScript types (request / response / components)
- TanStack Query hooks (
useGetAdmins,useCreateAdmin, etc.) - Zod schemas (used for form validation)
Orval Configuration
// orval.config.ts
export default {
adminApi: {
input: 'http://localhost:8080/api/v1/doc',
output: {
target: 'src/api/generated/admin.ts',
client: 'react-query',
schemas: 'src/api/generated/model',
httpClient: 'fetch',
override: {
mutator: { path: 'src/api/client.ts', name: 'adminFetcher' },
},
},
},
adminApiZod: {
input: 'http://localhost:8080/api/v1/doc',
output: {
target: 'src/api/generated/admin.zod.ts',
client: 'zod',
},
},
}
Fetcher (src/api/client.ts)
- Routes to
/api/proxy/<path>on the same origin (does not access the Admin API directly) - Sends httpOnly cookies automatically via
credentials: 'same-origin' - Response envelope normalization: The Admin API mixes
{ success, data }and legacy top-level formats (see API for Admin). The fetcher absorbs the wrapper so hooks always receive an unwrapped payload - 401 retry: When
/api/proxy/<path>returns a 401, a single in-flight refresh Promise is created to coalesce parallel requests. On success, the original request is replayed
// src/api/client.ts
let refreshPromise: Promise<void> | null = null
export async function adminFetcher<T>(config: AdminFetchConfig): Promise<T> {
const res = await fetchWithCookies(config)
if (res.status !== 401) return normalizeEnvelope(res)
refreshPromise ??= refreshSession().finally(() => { refreshPromise = null })
await refreshPromise
const retried = await fetchWithCookies(config)
return normalizeEnvelope(retried)
}
Regenerating the API Client
| Command | Purpose |
|---|---|
bun run generate:api |
During local development. Start the Admin API with bun run dev-admin before running |
| CI check | Compares generated output against the OpenAPI spec. Build fails if they do not match |
How to Obtain the OpenAPI Spec (Cross-Repository Integration)
Because the Admin API lives in a separate repository (GenAI-Guinness-backend), a strategy for fetching the OpenAPI spec must be established.
| Approach | Timing | Pros / Cons |
|---|---|---|
| Start the local backend and fetch from it | During development | Reflects the latest spec immediately. Requires developers to set up the backend |
| Backend CI publishes the OpenAPI JSON as an artifact; UI side pins the version | Staging and beyond | Reproducible. Risk of version drift |
Default policy: Use approach 1 during development. Switch to approach 2 once the backend stabilizes at v1.