Skip to content
File

Blob: src/client/lib/config.ts

typescript36 lines
1import { createContext, use } from "react";
2 
3export type SocialProvider = "github" | "google";
4 
5// Public client config served by /api/config. The worker fails closed
6// with 503 when Turnstile is not configured; consumers see an explicit
7// `unavailable` state so they can render an actionable error instead of
8// an indefinite loading spinner.
9export type ClientConfig =
10 | {
11 status: "ok";
12 turnstileSiteKey: string;
13 issuer: string;
14 socialProviders: SocialProvider[];
15 operatorName: string;
16 operatorContactEmail: string;
17 }
18 | { status: "unavailable" };
19 
20// `null` while the initial fetch is in flight; resolves to the
21// ClientConfig union once /api/config has answered. Consumers that need
22// to render before resolution (sign-in, invite-accept) handle the
23// `null` case by falling back to a loading-state placeholder.
24export type ClientConfigState = ClientConfig | null;
25 
26// Created in this stable .ts module so Vite Fast Refresh of the Provider
27// component does not recreate the context instance and orphan consumers.
28export const ClientConfigContext = createContext<ClientConfigState>(null);
29 
30// Returns:
31// - `null` while the initial /api/config fetch is in flight
32// - `{ status: "ok", ... }` when the worker answered with a usable payload
33// - `{ status: "unavailable" }` when /api/config returned 503 or the
34// fetch threw
35export const useClientConfig = (): ClientConfigState => use(ClientConfigContext);