50 lines
1.8 KiB
TypeScript
50 lines
1.8 KiB
TypeScript
import { useQuery } from "@tanstack/react-query";
|
|
import { configStatusQuery } from "@/lib/queries";
|
|
import type { ConfigStatus } from "@/lib/types";
|
|
|
|
/**
|
|
* Configuration authority as the UI must treat it: three states, never two.
|
|
*
|
|
* `undefined` is not database mode. Until `/api/config/status` answers, the
|
|
* running process may be file-managed, and a form rendered on that guess
|
|
* invites edits the server will reject. So a page shows neither an editable
|
|
* form nor a definition list until the query resolves, and a failed query is
|
|
* an explicit error with a way to retry.
|
|
*/
|
|
export type Authority =
|
|
| { state: "pending" }
|
|
| { state: "failed"; error: unknown; retry: () => void }
|
|
| { state: "resolved"; status: ConfigStatus };
|
|
|
|
/**
|
|
* The running server's configuration status. Every page may call this — it is
|
|
* the shared `["configStatus"]` key, so one subscription serves them all from
|
|
* cache.
|
|
*/
|
|
export function useAuthority(): Authority {
|
|
const query = useQuery(configStatusQuery());
|
|
if (query.isPending) return { state: "pending" };
|
|
if (query.isError) {
|
|
return {
|
|
state: "failed",
|
|
error: query.error,
|
|
retry: () => void query.refetch(),
|
|
};
|
|
}
|
|
return { state: "resolved", status: query.data };
|
|
}
|
|
|
|
/**
|
|
* True unless the server has said the database owns the configuration.
|
|
*
|
|
* The lock is global and it fails closed: pending, failed and `managed_file`
|
|
* all read as locked, because only a resolved database authority proves a
|
|
* configuration mutation can succeed. Runtime actions — pause, update now,
|
|
* reload certificates, deleting an observed client, login and logout — do not
|
|
* consult it; they work under every authority.
|
|
*/
|
|
export function useReadOnlyConfig(): boolean {
|
|
const authority = useAuthority();
|
|
return !(authority.state === "resolved" && authority.status.authority === "database");
|
|
}
|