mirror of
https://github.com/supabase/supabase.git
synced 2026-10-09 11:25:06 +03:00
Pin each browser session to the deployment that served it, so a long-lived dashboard session never 404s on a lazily-loaded chunk or changes version mid-session. Session cookie (no expiry) → next visit gets latest. - vite.config: inline VERCEL_DEPLOYMENT_ID + VERCEL_SKEW_PROTECTION_ENABLED. - router.tsx (TanStack-only): set a session __vdpl cookie scoped to BASE_PATH on client boot (platform + skew-enabled only); plus a vite:preloadError backstop that clears the pin and reloads if a chunk 404s (e.g. the pinned deployment aged out), with a time-window guard against reload loops. - deployment-commit-query: fetch the version-check endpoint with credentials:'omit' so the __vdpl cookie isn't sent and the edge serves the LATEST deployment — the update popup keeps detecting new versions while the session stays pinned. Stays on the basePath URL (root /api is the marketing site in prod). - use-check-latest-deploy: the Refresh button clears __vdpl before reloading so it lands on latest (no-op on the Next build, which sets no cookie). Requires enabling Skew Protection + System Env Vars in the Vercel project, and a Maximum Age comfortably above typical session length.
31 lines
1.3 KiB
TypeScript
31 lines
1.3 KiB
TypeScript
import { useQuery } from '@tanstack/react-query'
|
|
|
|
import { fetchHandler } from '@/data/fetchers'
|
|
import { BASE_PATH } from '@/lib/constants'
|
|
import type { ResponseError, UseCustomQueryOptions } from '@/types'
|
|
|
|
export async function getDeploymentCommit() {
|
|
// `credentials: 'omit'` drops cookies for this one request — including the
|
|
// `__vdpl` skew-protection pin (TanStack, see router.tsx). With no pin cookie,
|
|
// Vercel's edge routes it to the LATEST deployment, so this check can detect a
|
|
// newer version even while the rest of the session stays pinned. The endpoint
|
|
// is public (no auth needed), and we keep the basePath URL so it still routes
|
|
// to studio in production (root `/api/*` there is the marketing site).
|
|
const response = await fetchHandler(`${BASE_PATH}/api/get-deployment-commit`, {
|
|
credentials: 'omit',
|
|
})
|
|
return (await response.json()) as { commitSha: string; commitTime: string }
|
|
}
|
|
|
|
export type DeploymentCommitData = Awaited<ReturnType<typeof getDeploymentCommit>>
|
|
|
|
export const useDeploymentCommitQuery = <TData = DeploymentCommitData>({
|
|
enabled = true,
|
|
...options
|
|
}: UseCustomQueryOptions<DeploymentCommitData, ResponseError, TData> = {}) =>
|
|
useQuery<DeploymentCommitData, ResponseError, TData>({
|
|
queryKey: ['deployment-commit'],
|
|
queryFn: () => getDeploymentCommit(),
|
|
...options,
|
|
})
|