()
| 178 | }; |
| 179 | |
| 180 | const Explore = () => { |
| 181 | const [searchParams] = useSearchParams(); |
| 182 | const location = useLocation(); |
| 183 | const { owner, repo, "*": gitlabSplat } = useParams(); |
| 184 | const isGitlabRoute = location.pathname.startsWith("/gitlab/"); |
| 185 | const repoRef = isGitlabRoute |
| 186 | ? repoRefFromRoute("gitlab", undefined, undefined, gitlabSplat) |
| 187 | : repoRefFromRoute("github", owner, repo); |
| 188 | const [graphData, setGraphData] = useState<any>(null); |
| 189 | const graphDataRef = useRef<any>(null); |
| 190 | useEffect(() => { |
| 191 | graphDataRef.current = graphData; |
| 192 | }, [graphData]); |
| 193 | const [loading, setLoading] = useState(false); |
| 194 | const [error, setError] = useState<string | null>(null); |
| 195 | const [progressText, setProgressText] = useState(""); |
| 196 | const [progressValue, setProgressValue] = useState(0); |
| 197 | const [workerLogs, setWorkerLogs] = useState<string[]>([]); |
| 198 | |
| 199 | // Connection parameters for "Playground" mode (CLI/Database) |
| 200 | const backend = searchParams.get("backend") || ""; |
| 201 | const repoPath = searchParams.get("repo_path") || ""; |
| 202 | const cypherQuery = searchParams.get("cypher_query") || ""; |
| 203 | const bundleUrl = searchParams.get("bundle_url") || ""; |
| 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 | { |
nothing calls this directly
no test coverage detected