useApiKeyVerification.ts
1 import { useCallback, useState } from 'react' 2 import { verifyApiKey } from '../services/claude.js' 3 import { getAnthropicApiKey, isDefaultApiKey } from '../utils/config.js' 4 5 export type VerificationStatus = 6 | 'loading' 7 | 'valid' 8 | 'invalid' 9 | 'missing' 10 | 'error' 11 12 export type ApiKeyVerificationResult = { 13 status: VerificationStatus 14 reverify: () => Promise<void> 15 error: Error | null 16 } 17 18 export function useApiKeyVerification(): ApiKeyVerificationResult { 19 const [status, setStatus] = useState<VerificationStatus>(() => { 20 const apiKey = getAnthropicApiKey() 21 return apiKey ? 'loading' : 'missing' 22 }) 23 const [error, setError] = useState<Error | null>(null) 24 25 const verify = useCallback(async (): Promise<void> => { 26 if (isDefaultApiKey()) { 27 setStatus('valid') 28 return 29 } 30 31 const apiKey = getAnthropicApiKey() 32 if (!apiKey) { 33 const newStatus = 'missing' as const 34 setStatus(newStatus) 35 return 36 } 37 38 try { 39 const isValid = await verifyApiKey(apiKey) 40 const newStatus = isValid ? 'valid' : 'invalid' 41 setStatus(newStatus) 42 return 43 } catch (error) { 44 // This happens when there an error response from the API but it's not an invalid API key error 45 // In this case, we still mark the API key as invalid - but we also log the error so we can 46 // display it to the user to be more helpful 47 setError(error as Error) 48 const newStatus = 'error' as const 49 setStatus(newStatus) 50 return 51 } 52 }, []) 53 54 return { 55 status, 56 reverify: verify, 57 error, 58 } 59 }