loom-browser 0.0.15 → 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9910,60 +9910,62 @@ function createFallbackProvider(primary, fallback) {
9910
9910
  /**
9911
9911
  * Resolve a sequence provider from config.
9912
9912
  *
9913
- * Exactly one sequence source must be set. Throws if multiple are provided.
9914
- * Sources: sequenceProvider, twoBitURL, fastaURL, ucscGenome.
9915
- * When none is set, falls back to UCSC API via `id` if available.
9913
+ * If a custom `sequenceProvider` is set, it is used directly. Otherwise,
9914
+ * all available sources (twoBitURL, fastaURL, ucscGenome/id) are chained
9915
+ * as a prioritized fallback list:
9916
9916
  *
9917
- * When twoBitURL is used and a genome ID is available, the UCSC REST API is
9918
- * automatically added as a fallback if the 2-bit server is unreachable,
9919
- * the API is tried instead.
9917
+ * 1. twoBitURL most efficient (binary range requests)
9918
+ * 2. fastaURL — reliable CDN fallback (igv.org hosts FASTA for common genomes)
9919
+ * 3. UCSC API last resort (api.genome.ucsc.edu REST endpoint)
9920
+ *
9921
+ * This mirrors igv.js genomes3.json which provides both twoBitURL and fastaURL
9922
+ * for common genomes. On networks where one server is unreachable (e.g.,
9923
+ * hgdownload.soe.ucsc.edu blocked but igv.org reachable), the chain
9924
+ * automatically falls through to the next available source.
9920
9925
  */
9921
9926
  function resolveSequenceProvider(config) {
9922
- var _a, _b;
9923
- const sources = [
9924
- config.sequenceProvider && 'sequenceProvider',
9925
- config.twoBitURL && 'twoBitURL',
9926
- config.fastaURL && 'fastaURL',
9927
- config.ucscGenome && 'ucscGenome',
9928
- ].filter(Boolean);
9929
- if (sources.length > 1) {
9930
- throw new Error(`GenomeConfig has multiple sequence sources: ${sources.join(', ')}. ` +
9931
- 'Set exactly one of: sequenceProvider, twoBitURL, fastaURL, or ucscGenome.');
9932
- }
9927
+ var _a;
9928
+ // Custom provider — use directly, no chaining
9933
9929
  if (config.sequenceProvider) {
9934
9930
  return config.sequenceProvider;
9935
9931
  }
9932
+ // Build prioritized provider list from available config fields
9933
+ const providers = [];
9936
9934
  if (config.twoBitURL) {
9937
- const primary = createTwoBitSequenceProvider(config.twoBitURL, config.fetchImpl);
9938
- // Add UCSC REST API fallback when a genome ID is known
9939
- const genomeId = (_a = config.ucscGenome) !== null && _a !== void 0 ? _a : config.id;
9940
- if (genomeId) {
9941
- const fallback = (locus, signal) => fetchSequence(locus, { genome: genomeId }, signal);
9942
- return createCachedSequence(createFallbackProvider(primary, fallback));
9943
- }
9944
- return createCachedSequence(primary);
9935
+ providers.push(createTwoBitSequenceProvider(config.twoBitURL, config.fetchImpl));
9945
9936
  }
9946
9937
  if (config.fastaURL) {
9947
- return createCachedSequence(createFastaSequenceProvider(config.fastaURL, config.indexURL, config.compressedIndexURL, config.fetchImpl));
9938
+ providers.push(createFastaSequenceProvider(config.fastaURL, config.indexURL, config.compressedIndexURL, config.fetchImpl));
9948
9939
  }
9949
- // UCSC API explicit ucscGenome, or implicit via id
9950
- const ucscGenome = (_b = config.ucscGenome) !== null && _b !== void 0 ? _b : config.id;
9940
+ const ucscGenome = (_a = config.ucscGenome) !== null && _a !== void 0 ? _a : config.id;
9951
9941
  if (ucscGenome) {
9952
- return createCachedSequence((locus, signal) => fetchSequence(locus, { genome: ucscGenome }, signal));
9942
+ providers.push((locus, signal) => fetchSequence(locus, { genome: ucscGenome }, signal));
9953
9943
  }
9954
- return undefined;
9944
+ if (providers.length === 0)
9945
+ return undefined;
9946
+ if (providers.length === 1)
9947
+ return createCachedSequence(providers[0]);
9948
+ // Chain all providers: try each in order, fall back on failure
9949
+ const chained = providers.reduceRight((fallback, primary) => createFallbackProvider(primary, fallback));
9950
+ return createCachedSequence(chained);
9955
9951
  }
9956
9952
  // ─── Pre-built singletons ��─────────��─────────────────────────────────────────
9957
9953
  /**
9958
- * Pre-built hg38 genome with 2-bit sequence (UCSC API fallback).
9954
+ * Pre-built hg38 genome with triple-fallback sequence chain.
9959
9955
  *
9960
9956
  * This is the default genome used by HeadlessGenomeBrowser when no genome
9961
- * is specified. Matches igv.js's default behavior: 2-bit file as primary
9962
- * sequence source, with UCSC REST API as automatic fallback for resilience.
9957
+ * is specified. Sequence sources are tried in order:
9958
+ * 1. 2-bit from hgdownload.soe.ucsc.edu (most efficient, binary range requests)
9959
+ * 2. Indexed FASTA from igv.org (reliable CDN, reachable on restricted networks)
9960
+ * 3. UCSC REST API from api.genome.ucsc.edu (last resort)
9961
+ *
9962
+ * URLs match igv.js genomes3.json configuration for hg38.
9963
9963
  */
9964
9964
  const hg38Genome = createGenomeSync({
9965
9965
  id: 'hg38',
9966
9966
  twoBitURL: 'https://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/hg38.2bit',
9967
+ fastaURL: 'https://igv.org/genomes/data/hg38/hg38.fa',
9968
+ indexURL: 'https://igv.org/genomes/data/hg38/hg38.fa.fai',
9967
9969
  chromSizes: hg38ChromSizes,
9968
9970
  });
9969
9971