urzeye f881996e1a
fix(auth): recover from setup status timeouts (#4371)
* fix(auth): recover from setup status timeouts

* test(auth): cover setup status recovery flows

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-07-26 10:05:05 +08:00

50 lines
1.4 KiB
TypeScript

import { AUTH_REQUEST_TIMEOUT_MS } from "./constants";
import { parseAuthError } from "./types";
export type SetupStatusResponse = {
needs_setup?: boolean;
registration_enabled?: boolean;
};
export type SetupStatusCheck = {
checked: boolean;
status: SetupStatusResponse | null;
};
export const setupStatusFetchInit = {
cache: "no-store",
credentials: "include",
} satisfies RequestInit;
export async function fetchSetupStatus(): Promise<SetupStatusResponse> {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), AUTH_REQUEST_TIMEOUT_MS);
try {
const response = await fetch("/api/v1/auth/setup-status", {
...setupStatusFetchInit,
signal: controller.signal,
});
if (!response.ok) {
throw new Error(`setup-status failed: ${response.status}`);
}
return (await response.json()) as SetupStatusResponse;
} finally {
clearTimeout(timeout);
}
}
export function isSystemAlreadyInitializedError(data: unknown): boolean {
return parseAuthError(data).code === "system_already_initialized";
}
export function canCreateRegularAccount(check: SetupStatusCheck): boolean {
// registration_enabled is absent on older Gateways; treat that as allowed so
// the signup entry only disappears when the backend actively closes it.
return (
check.checked &&
check.status?.needs_setup !== true &&
check.status?.registration_enabled !== false
);
}