import { useCallback, useEffect, useReducer } from "react"; import { Edition, LicenseInfo, checkEntitlement as checkEntitlementCmd, getEdition, readLicense, storeLicense, } from "../services/licenseService"; type LicenseStatus = "idle" | "loading" | "ready" | "validating" | "error"; interface LicenseState { status: LicenseStatus; edition: Edition; info: LicenseInfo | null; error: string | null; } type LicenseAction = | { type: "LOAD_START" } | { type: "LOAD_DONE"; edition: Edition; info: LicenseInfo | null } | { type: "VALIDATE_START" } | { type: "VALIDATE_DONE"; info: LicenseInfo } | { type: "ERROR"; error: string }; const initialState: LicenseState = { status: "idle", edition: "free", info: null, error: null, }; function reducer(state: LicenseState, action: LicenseAction): LicenseState { switch (action.type) { case "LOAD_START": return { ...state, status: "loading", error: null }; case "LOAD_DONE": return { status: "ready", edition: action.edition, info: action.info, error: null, }; case "VALIDATE_START": return { ...state, status: "validating", error: null }; case "VALIDATE_DONE": return { status: "ready", edition: action.info.edition, info: action.info, error: null, }; case "ERROR": return { ...state, status: "error", error: action.error }; } } export function useLicense() { const [state, dispatch] = useReducer(reducer, initialState); const refresh = useCallback(async () => { dispatch({ type: "LOAD_START" }); try { const [edition, info] = await Promise.all([getEdition(), readLicense()]); dispatch({ type: "LOAD_DONE", edition, info }); } catch (e) { dispatch({ type: "ERROR", error: e instanceof Error ? e.message : String(e), }); } }, []); const submitKey = useCallback(async (key: string) => { dispatch({ type: "VALIDATE_START" }); try { const info = await storeLicense(key); dispatch({ type: "VALIDATE_DONE", info }); return { ok: true as const, info }; } catch (e) { const message = e instanceof Error ? e.message : String(e); dispatch({ type: "ERROR", error: message }); return { ok: false as const, error: message }; } }, []); const checkEntitlement = useCallback( (feature: string) => checkEntitlementCmd(feature), [], ); useEffect(() => { void refresh(); }, [refresh]); return { state, refresh, submitKey, checkEntitlement }; }