UNPKG

evermark-sdk

Version:

Unified SDK for robust image handling and content management with storage orchestration

170 lines 6.29 kB
import { useState, useEffect, useRef, useCallback } from 'react'; import { resolveImageSources } from '../../core/url-resolver.js'; import { ImageLoader, CORSHandler, PerformanceMonitor } from '../../browser/index.js'; /** * React hook for loading images with intelligent fallbacks */ export function useImageLoader(input, options = {}) { const { autoLoad = true, resolution, supabase, ...loaderOptions } = options; // State const [imageUrl, setImageUrl] = useState(null); const [isLoading, setIsLoading] = useState(false); const [hasError, setHasError] = useState(false); const [error, setError] = useState(null); const [currentSource, setCurrentSource] = useState(null); const [fromCache, setFromCache] = useState(false); const [loadTime, setLoadTime] = useState(null); const [attempts, setAttempts] = useState([]); // Refs const loaderRef = useRef(null); const corsHandlerRef = useRef(null); const performanceRef = useRef(null); // Initialize services useEffect(() => { // Initialize CORS handler if Supabase config provided if (supabase) { corsHandlerRef.current = new CORSHandler({ supabaseUrl: supabase.url, supabaseAnonKey: supabase.anonKey }); } // Initialize performance monitor performanceRef.current = new PerformanceMonitor(); // Initialize image loader loaderRef.current = new ImageLoader({ debug: false, timeout: 8000, maxRetries: 2, ...loaderOptions }); return () => { loaderRef.current?.abort(); }; }, [supabase?.url, supabase?.anonKey]); // Load function const load = useCallback(async () => { if (!loaderRef.current) return; try { setIsLoading(true); setHasError(false); setError(null); setAttempts([]); // Resolve image sources const sources = resolveImageSources(input, resolution); if (sources.length === 0) { throw new Error('No valid image sources found'); } // Process sources through CORS handler if available const processedSources = await Promise.all(sources.map(async (source) => { if (corsHandlerRef.current?.isSupabaseStorageUrl(source.url)) { const authenticatedUrl = await corsHandlerRef.current.authenticateSupabaseRequest(source.url); return { ...source, url: authenticatedUrl }; } return source; })); setCurrentSource(processedSources[0]?.url || null); // Load image const result = await loaderRef.current.loadImage(processedSources); // Update attempts const attemptResults = result.attempts?.map((attempt) => { const base = { url: attempt.source.url, success: attempt.status === 'success' }; return attempt.error !== undefined ? { ...base, error: attempt.error } : base; }) || []; setAttempts(attemptResults); if (result.success && result.imageUrl) { setImageUrl(result.imageUrl); setFromCache(result.fromCache || false); setLoadTime(result.loadTime || null); setCurrentSource(result.imageUrl); // Record performance metrics if (performanceRef.current && result.source) { performanceRef.current.recordLoad({ url: result.imageUrl, source: result.source.metadata?.storageProvider || 'unknown', startTime: Date.now() - (result.loadTime || 0), endTime: Date.now(), loadTime: result.loadTime || 0, fromCache: result.fromCache || false, success: true, retryCount: (result.attempts?.length || 1) - 1 }); } } else { throw new Error(result.error || 'Failed to load image'); } } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Unknown error'; setError(errorMessage); setHasError(true); setImageUrl(null); setCurrentSource(null); // Record failed load if (performanceRef.current) { performanceRef.current.recordLoad({ url: input.supabaseUrl || 'unknown', source: 'unknown', startTime: Date.now(), endTime: Date.now(), loadTime: 0, fromCache: false, success: false, error: errorMessage, retryCount: 0 }); } } finally { setIsLoading(false); } }, [input, resolution]); // Retry function const retry = useCallback(() => { load(); }, [load]); // Reset function const reset = useCallback(() => { setImageUrl(null); setIsLoading(false); setHasError(false); setError(null); setCurrentSource(null); setFromCache(false); setLoadTime(null); setAttempts([]); loaderRef.current?.abort(); }, []); // Auto-load effect useEffect(() => { if (autoLoad && (input.supabaseUrl || input.thumbnailUrl || input.ipfsHash)) { load(); } }, [autoLoad, input.supabaseUrl, input.thumbnailUrl, input.ipfsHash, load]); // Cleanup on unmount useEffect(() => { return () => { loaderRef.current?.abort(); }; }, []); return { imageUrl, isLoading, hasError, error, currentSource, fromCache, loadTime, attempts, load, retry, reset }; } //# sourceMappingURL=useImageLoader.js.map