(
url: string,
onProgress?: (loaded: number, total: number) => void
)
| 204 | |
| 205 | // Helper to fetch files using a sequential pool of robust CORS proxies |
| 206 | const fetchWithFallbackProxies = async ( |
| 207 | url: string, |
| 208 | onProgress?: (loaded: number, total: number) => void |
| 209 | ): Promise<Response> => { |
| 210 | if (!url) throw new Error("URL is empty"); |
| 211 | |
| 212 | // Try direct fetch first (essential for localhost, relative URLs, or CORS-enabled endpoints) |
| 213 | try { |
| 214 | const res = onProgress ? await fetchWithProgress(url, onProgress) : await fetch(url); |
| 215 | if (res.ok) return res; |
| 216 | } catch (e) { |
| 217 | console.warn("Direct fetch failed, falling back to CORS proxies...", e); |
| 218 | } |
| 219 | |
| 220 | // 1. Check raw githubusercontent.com to bypass proxy using jsDelivr CDN directly |
| 221 | if (url.includes("raw.githubusercontent.com")) { |
| 222 | const match = url.match(/raw\.githubusercontent\.com\/([^\/]+)\/([^\/]+)\/([^\/]+)\/(.+)$/); |
| 223 | if (match) { |
| 224 | const [_, ownerName, repoName, branch, filepath] = match; |
| 225 | const jsdelivrUrl = `https://cdn.jsdelivr.net/gh/${ownerName}/${repoName}@${branch}/${filepath}`; |
| 226 | try { |
| 227 | const res = onProgress ? await fetchWithProgress(jsdelivrUrl, onProgress) : await fetch(jsdelivrUrl); |
| 228 | if (res.ok) return res; |
| 229 | } catch (e) { |
| 230 | console.warn("jsDelivr CDN fetch failed, falling back to CORS proxies...", e); |
| 231 | } |
| 232 | } |
| 233 | } |
| 234 | |
| 235 | const proxies = [ |
| 236 | // Proxy 1: corsproxy.io (Very fast, prefix-based) |
| 237 | { |
| 238 | url: (u: string) => `https://corsproxy.io/?${encodeURIComponent(u)}`, |
| 239 | type: 'direct' as const |
| 240 | }, |
| 241 | // Proxy 2: CodeTabs (Fast and supports redirects well) |
| 242 | { |
| 243 | url: (u: string) => `https://api.codetabs.com/v1/proxy?quest=${encodeURIComponent(u)}`, |
| 244 | type: 'direct' as const |
| 245 | }, |
| 246 | // Proxy 3: allorigins.win JSON endpoint (Handles S3 redirects perfectly via server-side base64 encoding!) |
| 247 | { |
| 248 | url: (u: string) => `https://api.allorigins.win/get?url=${encodeURIComponent(u)}`, |
| 249 | type: 'json-base64' as const |
| 250 | }, |
| 251 | // Proxy 4: allorigins.win raw (Alternative fallback) |
| 252 | { |
| 253 | url: (u: string) => `https://api.allorigins.win/raw?url=${encodeURIComponent(u)}`, |
| 254 | type: 'direct' as const |
| 255 | }, |
| 256 | // Proxy 5: thingproxy.freeboard.io (Fallback proxy) |
| 257 | { |
| 258 | url: (u: string) => `https://thingproxy.freeboard.io/fetch/${u}`, |
| 259 | type: 'direct' as const |
| 260 | } |
| 261 | ]; |
| 262 | |
| 263 | let lastError: any = null; |
no test coverage detected