Files
supabase/apps/studio/data/platform/status-page-query.ts
Charis 8b8569bd1a feat(studio): status page client data layer + support form (#50984)
## Summary

* Adds the client query layer for `/api/status-page`
(`statusPageQueryOptions` in `data/platform/status-page-query.ts`) and a
shared normalization module (`lib/status-page/status-page.utils.ts`)
that maps the endpoint response into region- and project-creation-aware
`StatusItem`s — later PRs in this stack (assistant tool,
project-creation admonition, global banner) build on this same module.
* Wires the support form's status pill and incident admonition to the
new data behind the `incidentIoStatusPage` ConfigCat flag.
`useSupportStatus` branches between the new endpoint and the existing
`useIncidentStatusQuery`/`processIncidentData` path, both mapped to the
same `SupportStatus` shape.
* `IncidentAdmonition` becomes purely presentational; the status link
now points at the `pageUrl` returned by the endpoint instead of a
hardcoded URL.

Part of
[FE-4057](https://linear.app/supabase/issue/FE-4057/frontend-bannerbot-reconfigured)
— see Linear for full design context.

## Test plan

- [X] `pnpm --filter studio run typecheck`
- [X] `pnpm --filter studio run lint:ratchet`
- [X] `pnpm knip --workspace apps/studio`
- [X] `pnpm test:prettier`
- [X] `pnpm --filter studio exec vitest run` (touched files) — 70 tests
passing, including a flag-on case for `SupportFormPage`

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Support pages now display current incident and maintenance
information, including relevant status descriptions and links to the
status page.
* Status details can reflect items affecting a user’s region or
project-creation services. Upcoming maintenance is excluded from active
alerts.
* **Bug Fixes**
* Status labels and alerts now account for loading, errors, incidents,
and maintenance consistently across support pages.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-29 07:53:28 -04:00

59 lines
1.8 KiB
TypeScript

import { queryOptions } from '@tanstack/react-query'
import { platformKeys } from './keys'
import { BASE_PATH, IS_PLATFORM } from '@/lib/constants'
import {
StatusPageResponseSchema,
type StatusPageResponse,
} from '@/lib/status-page/status-page.schema'
import { ResponseError } from '@/types'
async function getStatusPage(signal?: AbortSignal): Promise<StatusPageResponse> {
const response = await fetch(`${BASE_PATH}/api/status-page`, {
signal,
method: 'GET',
credentials: 'omit',
})
if (!response.ok) {
const errorText = await response.text()
console.error('[getStatusPage] Failed:', response.status, errorText)
let retryAfter: number | undefined
const retryAfterHeader = response.headers.get('Retry-After')
if (retryAfterHeader !== null) {
const parsed = Number(retryAfterHeader)
if (Number.isFinite(parsed) && parsed > 0) retryAfter = parsed
}
throw new ResponseError(
`Failed to fetch status page: ${response.statusText}`,
response.status,
undefined,
retryAfter
)
}
const json = await response.json()
return StatusPageResponseSchema.parse(json)
}
export type StatusPageData = Awaited<ReturnType<typeof getStatusPage>>
export type StatusPageError = ResponseError
export const statusPageQueryOptions = () =>
queryOptions({
queryKey: platformKeys.statusPage(),
queryFn: ({ signal }) => getStatusPage(signal),
staleTime: 60_000,
refetchInterval: 5 * 60_000,
refetchOnWindowFocus: false,
retryDelay: (attemptIndex: number, error: StatusPageError) => {
if (error instanceof ResponseError && error.retryAfter) {
return error.retryAfter * 1000
}
return Math.min(1000 * 4 ** attemptIndex, 1000 * 60 * 5)
},
enabled: IS_PLATFORM,
})