loom-browser 0.0.14 → 0.0.15

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.
@@ -9877,15 +9877,49 @@ function createGenomeSync(config) {
9877
9877
  return new GenomeImpl(id, config.chromSizes, { name, sequence, cytobands: config.cytobands, nameSet: config.nameSet });
9878
9878
  }
9879
9879
  // ─── Sequence resolution ────��─────────────────────────────────���──────────────
9880
+ /**
9881
+ * Wrap a primary SequenceProvider with a fallback.
9882
+ *
9883
+ * On each request, tries `primary` first. If it throws (and the signal was
9884
+ * not aborted), tries `fallback`. If both fail, the primary error is thrown
9885
+ * so the caller sees the error from their configured source.
9886
+ *
9887
+ * The caching layer (createCachedSequence) wraps the combined provider,
9888
+ * so successful fallback results are cached normally — subsequent requests
9889
+ * for the same region won't re-attempt the primary.
9890
+ */
9891
+ function createFallbackProvider(primary, fallback) {
9892
+ return async (locus, signal) => {
9893
+ try {
9894
+ return await primary(locus, signal);
9895
+ }
9896
+ catch (primaryErr) {
9897
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted)
9898
+ throw primaryErr;
9899
+ console.warn('[loom] Primary sequence source failed, trying fallback:', primaryErr.message);
9900
+ try {
9901
+ return await fallback(locus, signal);
9902
+ }
9903
+ catch (_a) {
9904
+ // Both failed — throw the primary error (more relevant to the user's config)
9905
+ throw primaryErr;
9906
+ }
9907
+ }
9908
+ };
9909
+ }
9880
9910
  /**
9881
9911
  * Resolve a sequence provider from config.
9882
9912
  *
9883
9913
  * Exactly one sequence source must be set. Throws if multiple are provided.
9884
9914
  * Sources: sequenceProvider, twoBitURL, fastaURL, ucscGenome.
9885
9915
  * When none is set, falls back to UCSC API via `id` if available.
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.
9886
9920
  */
9887
9921
  function resolveSequenceProvider(config) {
9888
- var _a;
9922
+ var _a, _b;
9889
9923
  const sources = [
9890
9924
  config.sequenceProvider && 'sequenceProvider',
9891
9925
  config.twoBitURL && 'twoBitURL',
@@ -9900,13 +9934,20 @@ function resolveSequenceProvider(config) {
9900
9934
  return config.sequenceProvider;
9901
9935
  }
9902
9936
  if (config.twoBitURL) {
9903
- return createCachedSequence(createTwoBitSequenceProvider(config.twoBitURL, config.fetchImpl));
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);
9904
9945
  }
9905
9946
  if (config.fastaURL) {
9906
9947
  return createCachedSequence(createFastaSequenceProvider(config.fastaURL, config.indexURL, config.compressedIndexURL, config.fetchImpl));
9907
9948
  }
9908
9949
  // UCSC API — explicit ucscGenome, or implicit via id
9909
- const ucscGenome = (_a = config.ucscGenome) !== null && _a !== void 0 ? _a : config.id;
9950
+ const ucscGenome = (_b = config.ucscGenome) !== null && _b !== void 0 ? _b : config.id;
9910
9951
  if (ucscGenome) {
9911
9952
  return createCachedSequence((locus, signal) => fetchSequence(locus, { genome: ucscGenome }, signal));
9912
9953
  }
@@ -9914,13 +9955,15 @@ function resolveSequenceProvider(config) {
9914
9955
  }
9915
9956
  // ─── Pre-built singletons ��─────────��─────────────────────────────────────────
9916
9957
  /**
9917
- * Pre-built hg38 genome with UCSC sequence API.
9958
+ * Pre-built hg38 genome with 2-bit sequence (UCSC API fallback).
9918
9959
  *
9919
9960
  * This is the default genome used by HeadlessGenomeBrowser when no genome
9920
- * is specified. Equivalent to igv.js's default behavior of loading hg38.
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.
9921
9963
  */
9922
9964
  const hg38Genome = createGenomeSync({
9923
9965
  id: 'hg38',
9966
+ twoBitURL: 'https://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/hg38.2bit',
9924
9967
  chromSizes: hg38ChromSizes,
9925
9968
  });
9926
9969
 
@@ -22102,10 +22145,12 @@ function isZoomAware(track) {
22102
22145
  * tracks point to the same URL/region.
22103
22146
  */
22104
22147
  function dataSourceCacheKey(config) {
22105
- var _a, _b, _c, _d, _e;
22148
+ var _a, _b, _c, _d, _e, _f;
22106
22149
  switch (config.type) {
22107
22150
  case 'bigwig':
22108
22151
  return `bigwig:${config.url}:${(_a = config.windowFunction) !== null && _a !== void 0 ? _a : 'mean'}`;
22152
+ case 'bigbed':
22153
+ return `bigbed:${config.url}`;
22109
22154
  case 'gtx':
22110
22155
  return `gtx:${config.url}:${config.experimentId}`;
22111
22156
  case 'ucsc':
@@ -22113,13 +22158,9 @@ function dataSourceCacheKey(config) {
22113
22158
  case 'text':
22114
22159
  return `text:${config.url}:${(_d = config.format) !== null && _d !== void 0 ? _d : ''}:${(_e = config.indexURL) !== null && _e !== void 0 ? _e : ''}`;
22115
22160
  case 'memory':
22116
- // Each memory data source is unique — no deduplication.
22117
22161
  return `memory:${Math.random()}`;
22118
- default: {
22119
- // Unknown type resolve via URL inference, then compute key from resolved config
22120
- const resolved = resolveDataSourceConfig(config);
22121
- return dataSourceCacheKey(resolved);
22122
- }
22162
+ default:
22163
+ return `unknown:${config.type}:${(_f = config.url) !== null && _f !== void 0 ? _f : Math.random()}`;
22123
22164
  }
22124
22165
  }
22125
22166