import { useEffect, useState } from "react"; import { RemoteH5File, RemoteH5FileLindi } from "../remote-h5-file"; import type { RemoteH5FileX } from "../remote-h5-file"; import { extractAssetId, lindiIndexExists, lindiUrlForAsset, resolveDandiDownloadUrl, } from "./dandi"; export type BackendMode = "direct" | "lindi"; export type BackendState = { file?: RemoteH5FileX; resolvedUrl?: string; openMs?: number; status: "idle" | "opening" | "ready" | "error"; error?: string; }; // Opens the remote NWB file using one of the two strategies: // - "direct": resolve the DANDI redirect, then read the raw HDF5 lazily via // the h5wasm worker (HTTP range requests). // - "lindi": locate the precomputed LINDI JSON index and read metadata from // it, range-reading only chunk data from the original HDF5. export const useBackend = ( downloadUrl: string, dandisetId: string, mode: BackendMode, ): BackendState => { const [state, setState] = useState({ status: "idle" }); useEffect(() => { let canceled = false; const open = async () => { setState({ status: "opening" }); const t0 = performance.now(); try { let file: RemoteH5FileX; let resolvedUrl: string; if (mode === "direct") { resolvedUrl = await resolveDandiDownloadUrl(downloadUrl); file = new RemoteH5File(resolvedUrl, {}); } else { const assetId = extractAssetId(downloadUrl); if (!assetId) throw new Error("Could not extract asset id from URL"); resolvedUrl = lindiUrlForAsset(dandisetId, assetId); if (!(await lindiIndexExists(resolvedUrl))) { throw new Error( "No LINDI index is available for this asset. neurosift would " + "fall back to direct HDF5 reading in this case.", ); } file = await RemoteH5FileLindi.create(resolvedUrl); } // Touch the root group so "ready" means metadata is actually reachable. await file.getGroup("/"); if (canceled) return; setState({ file, resolvedUrl, openMs: performance.now() - t0, status: "ready", }); } catch (err: unknown) { if (canceled) return; setState({ status: "error", error: err instanceof Error ? err.message : String(err), }); } }; open(); return () => { canceled = true; }; }, [downloadUrl, dandisetId, mode]); return state; };