import {
  deepFreeze,
  sleep
} from "./chunk-M3J4MINX.js";
import {
  ISOFORM_EXPRESSION,
  SINGLECELL_CELLTYPE,
  SINGLECELL_GENE_EXPRESSION,
  TermTypes,
  isNumericTerm
} from "./chunk-NOEAT6CX.js";
import {
  dtcnv,
  dtfusionrna,
  dtitd,
  dtsnvindel,
  dtsv,
  mclass,
  mclassdeletion,
  mclassinsertion,
  mclassitd,
  mclassmnv,
  mclassnonstandard,
  mclasssnv,
  morigingermline,
  morigingermlinenonpathogenic,
  morigingermlinepathogenic,
  moriginrelapse,
  moriginsomatic,
  vepinfo
} from "./chunk-4UWS5Y3N.js";
import {
  isNumeric
} from "./chunk-JNITUVXP.js";
import {
  select_default
} from "./chunk-I6Y4O3RR.js";

// ../shared/utils/dist/src/bulk.js
function init_bulk_flag(genome) {
  if (!genome) {
    return null;
  }
  const mclasslabel2key2 = {};
  for (const n in mclass) {
    mclasslabel2key2[mclass[n].label.toUpperCase()] = n;
  }
  return {
    genome,
    mclasslabel2key: mclasslabel2key2,
    data: {},
    sample2disease: {},
    // (proof) k: sample, v: disease
    // will only record this when origin is used
    patient2st: {},
    // k: patient, v: { k: sampletype, v: sample }
    // new sample names always override old
    good: 0,
    geneToUpper: true,
    // option to not force uppercase on gene names
    snv: {
      loaded: false,
      header: null,
      badlines: [],
      // jinghui: based on missense/silent ratio of entire dataset to decide whether to include silent when importing...
      // hard-coded class codes
      missense: 0,
      silent: 0
    },
    svjson: {
      loaded: false,
      header: null,
      badlines: []
    },
    fusion: {
      loaded: false,
      header: null,
      badlines: [],
      original: []
    },
    sv: {
      loaded: false,
      header: null,
      badlines: [],
      original: []
    },
    cnv: {
      loaded: false,
      header: null,
      badlines: []
    },
    itd: {
      loaded: false,
      header: null,
      badlines: []
    },
    del: {
      loaded: false,
      header: null,
      badlines: []
    },
    truncation: {
      loaded: false,
      header: null,
      badlines: []
    }
  };
}
function parsesample(m, flag, i, lst) {
  let variantorigin = moriginsomatic;
  if (m.sampletype) {
    const s = m.sampletype.toLowerCase();
    switch (s) {
      case "relapse":
        variantorigin = moriginrelapse;
        break;
      case "germline":
        variantorigin = morigingermline;
        break;
      case "somatic":
      case "diagnosis":
        break;
    }
    if (m.sample) {
      if (m.patient) {
      } else {
        m.patient = m.sample + " " + m.sampletype;
      }
    } else {
      if (m.patient) {
        m.sample = m.patient + " " + m.sampletype;
      } else {
      }
    }
  } else {
    if (m.patient) {
      if (m.sample) {
        m.sampletype = m.sample;
      } else {
        m.sample = m.sampletype = m.patient;
      }
    } else {
      if (m.sample) {
        m.sampletype = m.sample;
      } else {
      }
    }
  }
  if (m.origin) {
    const s = m.origin.toLowerCase();
    switch (s) {
      case "r":
      case "relapse":
        variantorigin = moriginrelapse;
        m.isrim2 = true;
        break;
      case "g":
      case "germline":
        variantorigin = morigingermline;
        m.isrim1 = true;
        break;
      case "gp":
      case "germline pathogenic":
        variantorigin = morigingermlinepathogenic;
        m.isrim1 = true;
        break;
      case "gnp":
      case "germline nonpathogenic":
      case "germline non-pathogenic":
        variantorigin = morigingermlinenonpathogenic;
        m.isrim1 = true;
        break;
      case "s":
      case "somatic":
      case "diagnosis":
        variantorigin = moriginsomatic;
        break;
    }
  }
  m.origin = variantorigin;
  if (!m.sample && !m.patient) {
    return;
  }
  const nopatientname = "no patient/individual name";
  if (m.patient) {
    if (!flag.patient2st[m.patient]) {
      flag.patient2st[m.patient] = {};
    }
    flag.patient2st[m.patient][m.sampletype] = m.sample;
  } else {
    if (!flag.patient2st[nopatientname]) {
      flag.patient2st[nopatientname] = {};
    }
    flag.patient2st[nopatientname][m.sampletype] = m.sample;
  }
  if (m.sample) {
    if (m.disease) {
      if (m.sample in flag.sample2disease) {
        if (m.disease != flag.sample2disease[m.sample]) {
          flag.snv.badlines.push([
            i,
            'conflict of disease types for sample "' + m.sample + '": ' + m.disease + ", " + flag.sample2disease[m.sample],
            lst
          ]);
          return true;
        }
      } else {
        flag.sample2disease[m.sample] = m.disease;
      }
    }
  }
  return false;
}

// ../shared/utils/dist/src/clustering.js
var clusterMethodLst = [
  {
    label: "Average",
    value: "average",
    title: `Cluster by average value`
  },
  {
    label: `Complete`,
    value: "complete",
    title: `Use the complete clustering method`
  },
  {
    label: `Single`,
    value: "single",
    title: `Use the single clustering method`
  },
  {
    label: `Ward.D`,
    value: "ward.D",
    title: `Use the ward.D clustering method`
  },
  {
    label: `Ward.D2`,
    value: "ward.D2",
    title: `Use the ward.D2 clustering method`
  },
  {
    label: `Mcquitty`,
    value: "mcquitty",
    title: `Use the Mcquity clustering method`
  }
  /* These methods are currently disabled because the dendrogram lines tend to cross one another.
  {
  	label: `Centroid`,
  	value: 'centroid',
  	title: `Use the centroid clustering method`
  },
     	{
  	label: `Median`,
  	value: 'median',
  	title: `Use the median clustering method`
  }
         */
];
var distanceMethodLst = [
  {
    label: "Euclidean",
    value: "euclidean",
    title: `Calculate distance using euclidean method`
  },
  {
    label: "Maximum",
    value: "maximum",
    title: `Maximum distance between two components of x and y`
  },
  {
    label: "Manhattan",
    value: "manhattan",
    title: `Calculate distance using the absolute distance between the two vectors`
  },
  {
    label: "Canberra",
    value: "canberra",
    title: `Calculate distance using Canberra method`
  }
];

// ../shared/utils/dist/src/compute.percentile.js
function computePercentile(values, percentile, sorted = false) {
  if (!sorted) values.sort((a, b) => a - b);
  const index = Math.abs(percentile / 100 * values.length - 1);
  const value = Number.isInteger(index) ? (values[index] + values[index + 1]) / 2 : values[Math.ceil(index)];
  return value;
}

// ../shared/utils/dist/src/hash.js
var encoder = new TextEncoder();
async function hash(message) {
  const msgUint8 = encoder.encode(message);
  const hashBuffer = await crypto.subtle.digest("SHA-1", msgUint8);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
  return hexToBase64(hashHex).replace("=", "-");
}
function hexToBase64(hexStr) {
  return btoa(
    [...hexStr].reduce(
      (acc, _, i) => acc += !(i - 1 & 1) ? String.fromCharCode(parseInt(hexStr.substring(i - 1, i + 1), 16)) : "",
      ""
    )
  );
}

// ../shared/utils/dist/src/urljson.js
var reserved = ["false", "true", "null", "undefined"];
var delimiters = ['"', "{", "["];
function encode(rawObject) {
  const params = [];
  for (const [key, value] of Object.entries(rawObject)) {
    if (typeof value == "string" && !isNumeric(value) && !reserved.includes(value) && !delimiters.includes(value[0])) {
      params.push(`${key}=${encodeURIComponent(value)}`);
    } else if (value !== void 0) {
      params.push(`${key}=${encodeURIComponent(JSON.stringify(value))}`);
    }
  }
  return params.join("&");
}

// ../shared/utils/dist/src/fetch-helpers.js
async function processResponse(r) {
  const ct = r.headers.get("content-type");
  if (!ct) throw `missing response.header['content-type']`;
  if (ct.includes("/json")) {
    const payload = await r.json();
    return payload;
  }
  if (ct.includes("/text") || ct.includes("text/")) {
    return r.text();
  }
  if (ct.includes("multipart")) {
    if (ct.startsWith("multipart/form-data")) return processFormData(r);
    else throw `cannot handle response content-type: '${ct}'`;
  }
  if (ct == "application/x-ndjson-nestedkey") {
    return processNDJSON_nestedKey(r);
  }
  return r.blob();
}
async function processFormData(res) {
  const data = {};
  const form = await res.formData();
  for (const [key, value] of form.entries()) {
    if (value.type) {
      data[key] = { headers: { "content-type": value.type }, body: value };
    } else {
      const body = !value ? [] : value.trim().split("\n").map(JSON.parse);
      data[key] = { headers: { "content-type": "application/json" }, body };
    }
  }
  return data;
}
async function processNDJSON_nestedKey(r) {
  const stream = r.body.pipeThrough(new TextDecoderStream());
  const reader = stream.getReader();
  let rootObj = {};
  let buffer = "";
  let done = false;
  while (!done) {
    const readResult = await reader.read();
    done = readResult.done;
    if (done) break;
    const value = readResult.value;
    buffer += value;
    const parts = buffer.split("\n");
    buffer = parts.pop() ?? "";
    for (const line of parts) {
      if (line.trim()) {
        const [keys, data] = JSON.parse(line);
        if (!keys.length) rootObj = data;
        else {
          const lastKey = keys.pop();
          let target = rootObj;
          for (const k of keys) target = target[k];
          target[lastKey] = data;
        }
      }
    }
  }
  return rootObj;
}
var cacheLifetime = 1e3 * 60 * 5;
async function getDataName(url, init) {
  const dataName = url + " | " + init.method + " | " + init.body + " | " + JSON.stringify(init.headers);
  return await hash(dataName);
}

// ../shared/utils/dist/src/fileSize.js
function fileSize(v) {
  if (v > 1e9) return (v / 1e9).toFixed(2) + " GB";
  if (v > 1e6) return (v / 1e6).toFixed(2) + " MB";
  if (v > 1e3) return (v / 1e3).toFixed(2) + " KB";
  return v + " Bytes";
}

// ../shared/utils/dist/src/mds3tk.js
var ssmIdFieldsSeparator = "__";
function summarize_mclass(mlst) {
  const m2c = /* @__PURE__ */ new Map();
  const cnvs = [];
  for (const m of mlst) {
    if (m.dt == dtcnv) {
      cnvs.push(m);
      continue;
    }
    const key = m.class || m.dt;
    m2c.set(key, 1 + (m2c.get(key) || 0));
  }
  if (cnvs.length) {
    if (Number.isFinite(cnvs[0].value)) {
      m2c.set(dtcnv, cnvs.length);
    } else {
      for (const c of cnvs) {
        if (!c.class) continue;
        m2c.set(c.class, 1 + (m2c.get(c.class) || 0));
      }
    }
  }
  return [...m2c].sort((i, j) => j[1] - i[1]);
}
function guessSsmid(ssmid) {
  const l = ssmid.split(ssmIdFieldsSeparator);
  if (l.length == 4) {
    const [chr, tmp, ref, alt] = l;
    const pos = Number(tmp);
    if (Number.isNaN(pos)) throw "ssmid snvindel pos not integer";
    return { dt: dtsnvindel, l: [chr, pos, ref, alt] };
  }
  if (l.length == 5) {
    const [chr, _start, _stop, _class, _value] = l;
    const start = Number(_start), stop = Number(_stop);
    if (Number.isNaN(start) || Number.isNaN(stop)) throw new Error("ssmid cnv start/stop not integer");
    const value = _value == "" ? null : Number(_value);
    if (_class == mclassitd) {
      return { dt: dtitd, l: [chr, start, stop, _class, value] };
    }
    return { dt: dtcnv, l: [chr, start, stop, _class, value] };
  }
  if (l.length == 6) {
    if (l[3] == "+" || l[3] == "-") {
      const [_dt, chr2, _pos, strand, _pi, _mname] = l;
      const mname = decodeURIComponent(_mname);
      const dt = Number(_dt);
      if (dt != dtsv && dt != dtfusionrna) throw "ssmid dt not sv/fusion";
      const pos = Number(_pos);
      if (Number.isNaN(pos)) throw "ssmid svfusion position not integer";
      const pairlstIdx = Number(_pi);
      if (Number.isNaN(pairlstIdx)) throw "ssmid pairlstIdx not integer";
      return { dt, l: [dt, chr2, pos, strand, pairlstIdx, mname] };
    }
    const [chr, _start, _stop, _class, _value, sample] = l;
    const start = Number(_start), stop = Number(_stop);
    if (Number.isNaN(start) || Number.isNaN(stop)) throw new Error("ssmid cnv start/stop not integer");
    if (_class == mclassitd) {
      return { dt: dtitd, l: [chr, start, stop, _class, _value, sample] };
    }
    const value = _value == "" ? null : Number(_value);
    return { dt: dtcnv, l: [chr, start, stop, _class, value, sample] };
  }
  throw new Error("unknown ssmid");
}

// ../shared/utils/dist/src/scatter.js
var xAxisOffSet = 80;
var yAxisOffSet = 30;
function getCoordinate(val, min, max) {
  if (min != null && val < min) return min;
  if (max != null && val > max) return max;
  return val;
}
function calculatePadding(minScale, maxScale, min, max) {
  return minScale != null || maxScale != null ? 0 : (max - min) * 0.01;
}

// ../shared/utils/dist/src/termdb.initbinconfig.js
function initBinConfig(data, opts = {}) {
  if (!data.length)
    return { mode: "discrete", type: "regular-bin", startinclusive: true, bin_size: null, first_bin: { stop: null } };
  if (data.find((d) => !Number.isFinite(d))) throw new Error("non-numeric values found");
  let binConfig;
  const s = new Set(data);
  if (s.size === 1) {
    const value = [...s][0];
    binConfig = {
      type: "custom-bin",
      lst: [
        { stop: value, stopinclusive: false, startunbounded: true, label: "<" + value },
        { start: value, stop: value, startinclusive: true, stopinclusive: true, label: "=" + value },
        { start: value, startinclusive: false, stopunbounded: true, label: ">" + value }
      ]
    };
  } else {
    data.sort((a, b) => a - b);
    const l = data.length;
    const min = data[0];
    const max = data[l - 1];
    const p5idx = Math.ceil(l * 0.05) - 1;
    const p98idx = Math.ceil(l * 0.98) - 1;
    const p5 = data[p5idx];
    const p98 = data[p98idx];
    const binSize = p98 != p5 ? (p98 - p5) / 8 : (max - min) / 8;
    const firstBinStop = Math.max(min + binSize, p5);
    const [binSize_rnd, firstBinStop_rnd, lastBinStart_rnd, rounding] = roundBinVals(binSize, firstBinStop, max, min);
    binConfig = {
      type: "regular-bin",
      startinclusive: true,
      bin_size: binSize_rnd,
      first_bin: { stop: firstBinStop_rnd }
    };
    if (lastBinStart_rnd) binConfig.last_bin = { start: lastBinStart_rnd };
    if (rounding) binConfig.rounding = rounding;
  }
  if ("format" in opts) {
    if (opts.format === "string") {
      return JSON.stringify(binConfig);
    } else {
      throw "options are not in the correct format";
    }
  } else {
    return binConfig;
  }
}
function roundBinVals(binSize, firstBinStop, max, min) {
  let binSize_rnd, firstBinStop_rnd, lastBinStart_rnd, rounding;
  const log = Math.floor(Math.log10(binSize));
  if (binSize >= 0.1 && binSize <= 2) {
    binSize_rnd = Math.round(binSize / (1 * 10 ** log)) * (1 * 10 ** log);
    firstBinStop_rnd = Math.round(firstBinStop / (1 * 10 ** log)) * (1 * 10 ** log);
  } else {
    binSize_rnd = Math.round(binSize / (5 * 10 ** log)) * (5 * 10 ** log);
    firstBinStop_rnd = Math.round(firstBinStop / (5 * 10 ** log)) * (5 * 10 ** log);
    if (binSize_rnd === 0) binSize_rnd = 1 * 10 ** log;
    if (firstBinStop_rnd === 0) firstBinStop_rnd = 1 * 10 ** log;
    if (binSize_rnd === 5 * 10 ** log && firstBinStop_rnd === 1 * 10 ** log) firstBinStop_rnd = 5 * 10 ** log;
  }
  if (firstBinStop_rnd < min) firstBinStop_rnd = firstBinStop_rnd * 2;
  const eighthBinStop_rnd = firstBinStop_rnd + binSize_rnd * 7;
  if (max > eighthBinStop_rnd) {
    lastBinStart_rnd = firstBinStop_rnd + binSize_rnd * 6;
  }
  if (binSize < 1) {
    const digits = Math.abs(log);
    binSize_rnd = Number(binSize_rnd.toFixed(digits));
    firstBinStop_rnd = Number(firstBinStop_rnd.toFixed(digits));
    if (lastBinStart_rnd) lastBinStart_rnd = Number(lastBinStart_rnd.toFixed(digits));
    rounding = "." + digits + "f";
  }
  if (Object.is(firstBinStop_rnd, -0)) firstBinStop_rnd = 0;
  return [binSize_rnd, firstBinStop_rnd, lastBinStart_rnd, rounding];
}

// ../shared/utils/dist/src/termdb.usecase.js
var graphableTypes = /* @__PURE__ */ new Set([
  "categorical",
  "integer",
  "float",
  "condition",
  "survival",
  "snplst",
  "snplocus",
  "geneVariant",
  "samplelst",
  "geneExpression",
  ISOFORM_EXPRESSION,
  "dtcnv",
  "dtsnvindel",
  "dtfusion",
  "dtsv",
  "date",
  TermTypes.SSGSEA,
  TermTypes.DNA_METHYLATION,
  TermTypes.METABOLITE_INTENSITY,
  TermTypes.PROTEOME_ABUNDANCE,
  SINGLECELL_GENE_EXPRESSION,
  SINGLECELL_CELLTYPE,
  TermTypes.SNP,
  TermTypes.TERM_COLLECTION
]);
function isUsableTerm(term, _usecase, termdbConfig, ds) {
  const usecase = _usecase || {};
  if (typeof ds?.usecase?.[usecase.target] == "function") {
    return ds.usecase[usecase.target](term, usecase);
  }
  const uses = /* @__PURE__ */ new Set();
  const child_types = term.child_types || [];
  switch (usecase.target) {
    case "barchart":
    case "violin":
    case "boxplot":
    case "summary":
      if (term.type && term.type !== "survival") uses.add("plot");
      if (hasAllowedChildTypes(child_types, ["survival"])) uses.add("branch");
      return uses;
    case "summaryInput":
      if (usecase.detail === "term2" || usecase.detail == "term0") {
        if (term.type && term.type !== "survival") uses.add("plot");
        if (hasAllowedChildTypes(child_types, ["survival"])) uses.add("branch");
        return uses;
      } else {
        if (graphableTypes.has(term.type)) uses.add("plot");
        if (!term.isleaf) uses.add("branch");
        return uses;
      }
    case "matrix":
      if (term.type) uses.add("plot");
      if (!term.isleaf) uses.add("branch");
      return uses;
    case "table":
      if (usecase.detail == "term") uses.add("plot");
      if (child_types.length > 1) uses.add("branch");
      return uses;
    case "sampleScatter":
      if (usecase.detail == "numeric") {
        if (isNumericTerm(term)) {
          uses.add("plot");
        }
        if (hasNumericChild(child_types)) uses.add("branch");
      } else {
        if (graphableTypes.has(term.type)) uses.add("plot");
        if (!term.isleaf) uses.add("branch");
      }
      return uses;
    case "runChart2":
      if (usecase.detail == "date" || usecase.detail == "xtw") {
        if (term.type == "date") {
          uses.add("plot");
        }
        if (child_types.includes("date")) uses.add("branch");
      } else if (usecase.detail == "numeric") {
        if (isNumericTerm(term) && term.type != "date") {
          uses.add("plot");
        }
        if (hasNumericChild(child_types)) uses.add("branch");
      } else {
        if (graphableTypes.has(term.type)) uses.add("plot");
        if (!term.isleaf) uses.add("branch");
      }
      return uses;
    case "numericDictTermCluster":
      if (!usecase.detail?.exclude?.includes(term.id)) {
        if (isNumericTerm(term)) {
          uses.add("plot");
        }
        if (hasNumericChild(child_types)) {
          uses.add("branch");
        }
      }
      return uses;
    case "termCollections":
      if (usecase.detail?.termIds?.includes(term.id)) uses.add("plot");
      if (usecase.detail?.branchIds?.includes(term.id)) uses.add("branch");
      return uses;
    case "profileForms":
      if (!term.isleaf) {
        const ancestors = term.id.split("__").length;
        if (ancestors == 3) {
          uses.add("plot");
        } else if (ancestors < 3) uses.add("branch");
      }
      return uses;
    case "profileForms2": {
      if (term.isleaf) return uses;
      const allowed = termdbConfig?.plotConfigByCohort?.[usecase.cohort]?.profileForms2?.domains;
      if (!allowed) return uses;
      const ancestors = term.id.split("__").length;
      const subtype = usecase.subtype;
      if (ancestors == 3) {
        if (allowed.find((d) => d.id === term.id)?.plotTypes?.includes(subtype)) uses.add("plot");
      } else if (ancestors < 3) {
        const prefix = term.id + "__";
        if (allowed.some((d) => d.id.startsWith(prefix) && d.plotTypes.includes(subtype))) {
          uses.add("branch");
        }
      }
      return uses;
    }
    // case 'boxplot':
    // 	if (term.type == 'float' || term.type == 'integer') uses.add('plot')
    // 	if (usecase.detail === 'term2' && hasNumericChild(child_types)) uses.add('branch')
    // 	return uses
    case "cuminc":
      if (usecase.detail == "term") {
        if (term.type == "condition") uses.add("plot");
        if (child_types.includes("condition")) uses.add("branch");
        return uses;
      }
      if (usecase.detail === "term2" || usecase.detail == "term0") {
        if (term.type && term.type != "condition" && term.type != "survival") uses.add("plot");
        if (hasAllowedChildTypes(child_types, ["condition", "survival"])) uses.add("branch");
        return uses;
      }
      return uses;
    case "survival":
      if (usecase.detail == "term") {
        if (term.type == "survival") uses.add("plot");
        if (child_types.includes("survival")) uses.add("branch");
        return uses;
      }
      if (usecase.detail === "term2" || usecase.detail == "term0") {
        if (term.type && term.type != "survival") uses.add("plot");
        if (hasAllowedChildTypes(child_types, ["survival"])) uses.add("branch");
        return uses;
      }
      return uses;
    case "regression":
      if (usecase.detail == "outcome") {
        if (usecase.regressionType == "linear") {
          if (term.type == "float" || term.type == "integer") uses.add("plot");
          if (hasNumericChild(child_types)) uses.add("branch");
          return uses;
        }
        if (usecase.regressionType == "logistic") {
          if (term.type && term.type != "survival") uses.add("plot");
          if (hasAllowedChildTypes(child_types, ["survival"])) uses.add("branch");
          return uses;
        } else if (usecase.regressionType == "cox") {
          if (term.type == "condition" || term.type == "survival") uses.add("plot");
          if (child_types.includes("condition") || child_types.includes("survival")) uses.add("branch");
          return uses;
        }
      }
      if (usecase.detail == "independent") {
        if (term.type == "float" || term.type == "integer" || term.type == "categorical" || term.type == "samplelst")
          uses.add("plot");
        if (hasChildTypes(child_types, ["categorical", "float", "integer"])) uses.add("branch");
        return uses;
      }
      return uses;
    case "filter": {
      const exlst = termdbConfig?.excludedTermtypeByTarget?.filter;
      if (exlst) {
        if (graphableTypes.has(term.type) && !exlst.includes(term.type)) uses.add("plot");
        if (child_types.find((t) => !exlst.includes(t))) uses.add("branch");
        return uses;
      }
      if (graphableTypes.has(term.type)) uses.add("plot");
      if (!term.isleaf) uses.add("branch");
      return uses;
    }
    case "correlationVolcano":
      if (usecase.detail == "numeric") {
        if (isNumericTerm(term)) {
          uses.add("plot");
        }
        if (hasNumericChild(child_types)) uses.add("branch");
      } else {
        if (graphableTypes.has(term.type)) uses.add("plot");
        if (!term.isleaf) uses.add("branch");
      }
      return uses;
    case "proteinView":
      if (term.type == TermTypes.PROTEOME_ABUNDANCE) uses.add("plot");
      if (child_types.includes(TermTypes.PROTEOME_ABUNDANCE)) uses.add("branch");
      return uses;
    default:
      if (graphableTypes.has(term.type)) uses.add("plot");
      if (!term.isleaf) uses.add("branch");
      return uses;
  }
}
function hasAllowedChildTypes(child_types, excluded_types) {
  if (!child_types.length) {
    return false;
  }
  if (!excluded_types?.length) {
    return true;
  }
  if (child_types.some((type) => !excluded_types.includes(type))) {
    return true;
  }
}
function hasNumericChild(child_types) {
  return child_types.includes("float") || child_types.includes("integer");
}
function hasChildTypes(child_types, expected_types) {
  for (const a of expected_types) {
    if (child_types.includes(a)) return true;
  }
}

// ../shared/utils/dist/src/time.js
function formatElapsedTime(ms, precision = 2) {
  if (typeof ms !== "number" || isNaN(ms)) {
    return typeof ms !== "number" ? "Invalid time: not a number" : "Invalid time: NaN";
  }
  if (!isFinite(ms)) {
    return ms > 0 ? "Infinite time" : "-Infinite time";
  }
  const absMs = Math.abs(ms);
  const sign = ms < 0 ? "-" : "";
  if (absMs < 1e3) {
    return `${sign}${absMs}ms`;
  }
  if (absMs < 6e4) {
    return `${sign}${(absMs / 1e3).toFixed(precision)}s`;
  }
  const minutes = Math.floor(absMs / 6e4);
  const seconds = (absMs % 6e4 / 1e3).toFixed(precision);
  return `${sign}${minutes}m ${seconds}s`;
}

// ../shared/utils/dist/src/vcf.ann.js
function parse_ANN(str, header, m) {
  if (!header) {
    return null;
  }
  for (const thisannotation of str.split(",")) {
    const lst = thisannotation.replace(/&/g, ",").split("|");
    const o = {};
    for (let i = 0; i < header.length; i++) {
      if (lst[i]) {
        o[header[i].name] = lst[i];
      }
    }
    if (!o.Allele) {
      continue;
    }
    let allele = null;
    for (const a of m.alleles) {
      if (a.allele == o.Allele) {
        allele = a;
        break;
      }
    }
    if (!allele) {
      continue;
    }
    if (!allele.ann) {
      allele.ann = [];
    }
    allele.ann.push(o);
    o._gene = o.Gene_Name;
    if (o.Feature_Type && o.Feature_Type == "transcript" && o.Feature_ID) {
      o._isoform = o.Feature_ID.split(".")[0];
    }
    if (o.Annotation) {
      const [dt, cls, rank] = vepinfo(o.Annotation);
      o._dt = dt;
      o._class = cls;
      o._csqrank = rank;
    } else {
      o._dt = dtsnvindel;
      o._class = mclassnonstandard;
    }
    if (o["HGVS.p"]) {
      o._mname = o["HGVS.p"];
    } else if (o["HGVS.c"]) {
      o._mname = o["HGVS.c"];
    }
  }
  return true;
}

// ../shared/utils/dist/src/vcf.csq.js
function parse_CSQ(str, header, m) {
  if (!header) {
    return null;
  }
  for (const thisannotation of str.split(",")) {
    const lst = thisannotation.replace(/&/g, ",").split("|");
    const o = {};
    for (let i = 0; i < header.length; i++) {
      if (lst[i]) {
        o[header[i].name] = lst[i];
      }
    }
    if (!o.Allele) {
      continue;
    }
    let allele = null;
    for (const a of m.mlst || m.alleles) {
      if (a.allele_original == o.Allele) {
        allele = a;
        break;
      }
    }
    if (!allele) {
      if (o.Allele == "-") {
        if (m.mlst) {
          if (m.mlst.length == 1) {
            allele = m.mlst[0];
          }
        } else if (m.alleles) {
          if (m.alleles.length == 1) {
            allele = m.alleles[0];
          }
        }
      } else {
        for (const a of m.mlst || m.alleles) {
          if (a.allele_original.substr(1) == o.Allele) {
            allele = a;
            break;
          }
        }
      }
      if (!allele) {
        continue;
      }
    }
    if (!allele.csq) {
      allele.csq = [];
    }
    allele.csq.push(o);
    o._gene = o.SYMBOL || o.Gene;
    if (o.Feature_type && o.Feature_type == "Transcript") {
      o._isoform = o.Feature.split(".")[0];
    } else {
      o._isoform = o._gene;
    }
    if (o.Consequence) {
      const [dt, cls, rank] = vepinfo(o.Consequence);
      o._dt = dt;
      o._class = cls;
      o._csqrank = rank;
    } else {
      o._dt = dtsnvindel;
      o._class = mclassnonstandard;
    }
    if (o.HGVSp) {
      o._mname = decodeURIComponent(o.HGVSp.substr(o.HGVSp.indexOf(":") + 1));
    } else if (o.Protein_position && o.Amino_acids) {
      o._mname = decodeURIComponent(o.Protein_position + o.Amino_acids);
    } else if (o.HGVSc) {
      o._mname = o.HGVSc.substr(o.HGVSc.indexOf(":") + 1);
    } else if (o.Existing_variation) {
      o._name = o.Existing_variation;
    }
  }
  return true;
}

// ../shared/utils/dist/src/vcf.info.js
function dissect_INFO(str) {
  let findsemicolon = false;
  let findequalorsemicolon = true;
  let i = 0;
  let idx = 0;
  const k2v = {};
  let lastkey;
  while (i < str.length) {
    const c = str[i];
    if (findequalorsemicolon) {
      if (c == "=") {
        findsemicolon = true;
        findequalorsemicolon = false;
        lastkey = str.substring(idx, i);
        idx = i + 1;
      } else if (c == ";") {
        k2v[str.substring(idx, i)] = 1;
        idx = i + 1;
      }
    } else if (findsemicolon && c == ";") {
      findequalorsemicolon = true;
      findsemicolon = false;
      k2v[lastkey] = str.substring(idx, i);
      lastkey = null;
      idx = i + 1;
    }
    i++;
  }
  const remainstr = str.substr(idx, i);
  if (lastkey) {
    k2v[lastkey] = remainstr;
  } else {
    k2v[remainstr] = 1;
  }
  return k2v;
}

// ../shared/utils/dist/src/vcf.type.js
function getVariantType(ref, alt) {
  if (ref.length == 1 && alt.length == 1) {
    if (alt == ".") {
      return mclassdeletion;
    }
    return mclasssnv;
  }
  if (ref.length == alt.length) return mclassmnv;
  if (ref.length < alt.length) return mclassinsertion;
  if (ref.length > alt.length) return mclassdeletion;
  return mclassnonstandard;
}

// ../shared/utils/dist/src/vcf.js
var getallelename = new RegExp(/<(.+)>/);
var mclasslabel2key = {};
for (const k in mclass) {
  mclasslabel2key[mclass[k].label.toUpperCase()] = k;
}
function vcfparsemeta(lines) {
  let sample = [];
  const errlst = [];
  const info = {};
  let hasinfo = false;
  const format = {};
  let hasformat = false;
  for (const line of lines) {
    if (!line.startsWith("#")) {
      continue;
    }
    if (line.startsWith("#C")) {
      sample = line.split("	").slice(9);
      continue;
    }
    if (line.startsWith("##INFO")) {
      const e = tohash(line.substring(8, line.length - 1), info);
      if (e) {
        errlst.push("INFO error: " + e);
      } else {
        hasinfo = true;
      }
      continue;
    }
    if (line.startsWith("##FORMAT")) {
      const e = tohash(line.substring(10, line.length - 1), format);
      if (e) {
        errlst.push("FORMAT error: " + e);
      } else {
        hasformat = true;
      }
    }
  }
  const sampleobjlst = [];
  for (const samplename of sample) {
    const a = { name: samplename };
    sampleobjlst.push(a);
  }
  if (info.CSQ) {
    const lst = info.CSQ.Description.split(" Format: ");
    if (lst[1]) {
      const lst2 = lst[1].split("|");
      if (lst2.length > 1) {
        info.CSQ.csqheader = [];
        for (const str of lst2) {
          const attr = { name: str };
          info.CSQ.csqheader.push(attr);
        }
      } else {
        errlst.push("unknown format for CSQ header: " + info.CSQ.Description);
      }
    } else {
      errlst.push("unknown format for CSQ header: " + info.CSQ.Description);
    }
  }
  if (info.ANN) {
    const lst = info.ANN.Description.split("'");
    if (lst[1]) {
      const lst2 = lst[1].split(" | ");
      if (lst2.length) {
        info.ANN.annheader = [];
        for (const s of lst2) {
          const attr = { name: s };
          info.ANN.annheader.push(attr);
        }
      } else {
        errlst.push('no " | " joined annotation fields for ANN (snpEff annotation): ' + info.ANN.Description);
      }
    } else {
      errlst.push("no single-quote enclosed annotation fields for ANN (snpEff annotation): " + info.ANN.Description);
    }
  }
  return [hasinfo ? info : null, hasformat ? format : null, sampleobjlst, errlst.length ? errlst : null];
}
function vcfparseline(line, vcf) {
  const lst = line.split("	");
  if (lst.length < 8) {
    return ["line has less than 8 fields", null, null];
  }
  const rawpos = Number.parseInt(lst[2 - 1]);
  if (!Number.isInteger(rawpos)) {
    return ["invalid value for genomic position", null, null];
  }
  const refallele = lst[4 - 1];
  const m = {
    vcf_ID: lst[3 - 1],
    chr: (vcf.nochr ? "chr" : "") + lst[1 - 1],
    pos: rawpos - 1,
    ref: refallele,
    //refstr:refallele, // e.g. GA>GCC, ref:A, refstr:GA, "refstr" is required for matching in FORMAT
    altstr: lst[5 - 1],
    alleles: [
      {
        /*
        ref allele only a placeholder, to be removed, this array only contains alt alleles
        this is a must
        also allows GT allele index to work
        */
        allele: refallele,
        sampledata: []
      }
    ],
    info: {},
    // locus info, do not contain allele info
    name: lst[3 - 1] == "." ? null : lst[3 - 1]
  };
  const altinvalid = [];
  for (const alt of lst[5 - 1].split(",")) {
    const a = {
      ref: m.ref,
      // may be corrected just below!
      allele: alt,
      // 5078356.TATCAGAGAA.GGGAGGA keep original allele for matching with csq which hardcodes original allele
      allele_original: alt,
      sampledata: [],
      _m: m,
      info: {}
      // allele info, do not contain locus info
    };
    m.alleles.push(a);
    if (alt[0] == "<") {
      const tmp2 = alt.match(getallelename);
      if (!tmp2) {
        altinvalid.push(alt);
        continue;
      }
      a.type = tmp2[1];
      a.allele = tmp2[1];
      a.issymbolicallele = true;
    } else {
      const [p, ref, alt2] = correctRefAlt(m.pos, m.ref, a.allele);
      a.pos = p;
      a.ref = ref;
      a.allele = alt2;
    }
  }
  if (lst[9 - 1] && lst[10 - 1]) {
    parse_FORMAT2(lst, m, vcf);
  }
  m.alleles.shift();
  const tmp = lst[8 - 1] == "." ? [] : dissect_INFO(lst[8 - 1]);
  let badinfokeys = [];
  if (vcf.info) {
    badinfokeys = parse_INFO(tmp, m, vcf);
  } else {
    m.info = tmp;
  }
  const mlst = [];
  for (const a of m.alleles) {
    const m2 = {};
    for (const k in m) {
      if (k != "alleles") {
        m2[k] = m[k];
      }
    }
    for (const k in a) {
      if (k == "allele") {
        m2.alt = a[k];
      } else if (k == "info") {
        m2.altinfo = a[k];
      } else {
        m2[k] = a[k];
      }
    }
    if (!m2.issymbolicallele && m2.alt != "NON_REF") {
      m2.type = getVariantType(m2.ref, m2.alt);
    }
    mlst.push(m2);
  }
  return [
    badinfokeys.length ? "unknown info keys: " + badinfokeys.join(",") : null,
    mlst,
    altinvalid.length > 0 ? altinvalid : null
  ];
}
function correctRefAlt(p, ref, alt) {
  while (ref.length > 1 && alt.length > 1 && ref[ref.length - 1] == alt[alt.length - 1]) {
    ref = ref.substr(0, ref.length - 1);
    alt = alt.substr(0, alt.length - 1);
  }
  while (ref.length > 1 && alt.length > 1 && ref[0] == alt[0]) {
    ref = ref.substr(1);
    alt = alt.substr(1);
    p++;
  }
  return [p, ref, alt];
}
function parse_FORMAT2(lst, m, vcf) {
  const formatfields = lst[9 - 1].split(":");
  for (let _sampleidx = 9; _sampleidx < lst.length; _sampleidx++) {
    const valuelst = lst[_sampleidx].split(":");
    {
      let none = true;
      for (const v of valuelst) {
        if (v != ".") {
          none = false;
          break;
        }
      }
      if (none) {
        continue;
      }
    }
    const sampleidx = _sampleidx - 9;
    for (let i = 1; i < m.alleles.length; i++) {
      const sobj = {};
      if (vcf.samples && vcf.samples[sampleidx]) {
        for (const k in vcf.samples[sampleidx]) {
          sobj[k] = vcf.samples[sampleidx][k];
        }
      } else {
        sobj.name = "missing_samplename_from_vcf_header";
      }
      m.alleles[i].sampledata.push({
        sampleobj: sobj
      });
    }
    for (let fi = 0; fi < formatfields.length; fi++) {
      const field = formatfields[fi];
      const value = valuelst[fi];
      if (value == ".") {
        continue;
      }
      if (field == "GT") {
        const splitter = value.indexOf("/") != -1 ? "/" : "|";
        let gtsum = 0;
        let unknowngt = false;
        const gtalleles = [];
        for (const i of value.split(splitter)) {
          if (i == ".") {
            unknowngt = true;
            continue;
          }
          const j = Number.parseInt(i);
          if (Number.isNaN(j)) {
            unknowngt = true;
            continue;
          }
          gtsum += j;
          const ale = m.alleles[j];
          if (ale) {
            gtalleles.push(ale.allele);
          }
        }
        let gtallref = false;
        if (!unknowngt) {
          gtallref = gtsum == 0;
        }
        const genotype = gtalleles.join(splitter);
        for (let i = 1; i < m.alleles.length; i++) {
          const ms = m.alleles[i].sampledata[m.alleles[i].sampledata.length - 1];
          ms.GT = value;
          ms.genotype = genotype;
          if (gtallref) {
            ms.gtallref = true;
          }
          ms.__gtalleles = gtalleles;
        }
        continue;
      }
      const formatdesc = vcf.format ? vcf.format[field] : null;
      if (!formatdesc) {
        for (let i = 1; i < m.alleles.length; i++) {
          m.alleles[i].sampledata[m.alleles[i].sampledata.length - 1][field] = value;
        }
        continue;
      }
      const isinteger = formatdesc.Type == "Integer";
      const isfloat = formatdesc.Type == "Float";
      if (formatdesc.Number && formatdesc.Number == "R" || field == "AD") {
        const fvlst = value.split(",").map((i) => {
          if (isinteger) return Number.parseInt(i);
          if (isfloat) return Number.parseFloat(i);
          return i;
        });
        for (let i = 1; i < m.alleles.length; i++) {
          if (fvlst[i] != void 0) {
            const m2 = m.alleles[i];
            const m2s = m2.sampledata[m2.sampledata.length - 1];
            m2s[field] = {};
            m2s[field][m2.ref] = fvlst[0];
            m2s[field][m2.allele] = fvlst[i];
          }
        }
        continue;
      }
      if (formatdesc.Number && formatdesc.Number == "A") {
        const fvlst = value.split(",").map((i) => {
          if (isinteger) return Number.parseInt(i);
          if (isfloat) return Number.parseFloat(i);
          return i;
        });
        for (let i = 1; i < m.alleles.length; i++) {
          if (fvlst[i - 1] != void 0) {
            const m2 = m.alleles[i];
            const m2s = m2.sampledata[m2.sampledata.length - 1];
            m2s[field] = {};
            m2s[field][m2.allele] = fvlst[i - 1];
          }
        }
        continue;
      }
      for (let i = 1; i < m.alleles.length; i++) {
        m.alleles[i].sampledata[m.alleles[i].sampledata.length - 1][field] = value;
      }
    }
  }
  for (const a of m.alleles) {
    for (const s of a.sampledata) {
      if (s.AD) {
        s.allele2readcount = {};
        for (const k in s.AD) {
          s.allele2readcount[k] = s.AD[k];
        }
      }
    }
  }
}
function tohash(s, hash2) {
  const h = {}, err = [];
  let prev = 0, prevdoublequote = false, k = null;
  for (let i = 0; i < s.length; i++) {
    if (s[i] == '"') {
      i++;
      const thisstart = i;
      while (s[i] != '"') {
        i++;
      }
      if (k) {
        h[k] = s.substring(thisstart, i);
        k = null;
      } else {
        err.push("k undefined before double quotes");
      }
      prevdoublequote = true;
      continue;
    }
    if (s[i] == "=") {
      k = s.substring(prev, i);
      prev = i + 1;
      continue;
    }
    if (s[i] == ",") {
      if (prevdoublequote) {
        prevdoublequote = false;
      } else {
        if (k) {
          h[k] = s.substring(prev, i);
          k = null;
        } else {
          err.push("k undefined");
        }
      }
      prev = i + 1;
      continue;
    }
  }
  if (k) {
    h[k] = s.substring(prev);
  }
  if (h.ID) {
    hash2[h.ID] = h;
  } else {
    return "no ID";
  }
  if (err.length) return err.join("\n");
}
function parse_INFO(tmp, m, vcf) {
  const badinfokeys = [];
  for (const key in tmp) {
    if (vcf.info[key] == void 0) {
      badinfokeys.push(key);
      continue;
    }
    const value = tmp[key];
    if (key == "CSQ") {
      const okay = parse_CSQ(value, vcf.info.CSQ.csqheader, m);
      if (!okay) {
        m.info[key] = value;
      }
      continue;
    }
    if (key == "ANN") {
      const okay = parse_ANN(value, vcf.info.ANN.annheader, m);
      if (!okay) {
        m.info[key] = value;
      }
      continue;
    }
    if (vcf.info[key].Type == "Flag") {
      m.info[key] = key;
      continue;
    }
    const __number = vcf.info[key].Number;
    const isinteger = vcf.info[key].Type == "Integer";
    const isfloat = vcf.info[key].Type == "Float";
    if (__number == "0") {
      m.info[key] = key;
      continue;
    }
    if (__number == "A") {
      const tt = value.split(",");
      for (let j = 0; j < tt.length; j++) {
        if (m.alleles[j]) {
          m.alleles[j].info[key] = isinteger ? Number.parseInt(tt[j]) : isfloat ? Number.parseFloat(tt[j]) : tt[j];
        }
      }
      continue;
    }
    if (__number == "R") {
    }
    if (__number == "1") {
      m.info[key] = isinteger ? Number.parseInt(value) : isfloat ? Number.parseFloat(value) : value;
      continue;
    }
    if (!value.split) {
      continue;
    }
    const lst = value.split(",");
    if (isinteger) {
      m.info[key] = lst.map(Number.parseInt);
    } else if (isfloat) {
      m.info[key] = lst.map(Number.parseFloat);
    } else {
      m.info[key] = lst;
    }
  }
  return badinfokeys;
}

// common/auth.js
var jwtByDsRoute;
function setJwtByDsRoute() {
  if (jwtByDsRoute) return;
  const jwtByDsRouteStr = localStorage.getItem("jwtByDsRoute") || `{}`;
  jwtByDsRoute = JSON.parse(jwtByDsRouteStr);
}
function setTokenByDsRoute(dslabel, route, jwt) {
  setJwtByDsRoute();
  if (!jwtByDsRoute[dslabel]) jwtByDsRoute[dslabel] = {};
  if (jwt) jwtByDsRoute[dslabel][route] = jwt;
  else delete jwtByDsRoute[dslabel][route];
  localStorage.setItem("jwtByDsRoute", JSON.stringify(jwtByDsRoute));
}
function getSavedToken(dslabel, route) {
  setJwtByDsRoute();
  return jwtByDsRoute[dslabel]?.[route] || jwtByDsRoute[dslabel]?.["/**"];
}
function mayAddJwtToRequest(init, body, url) {
  if (init.headers.authorization) return;
  let dslabel = body?.dslabel;
  if (!dslabel) {
    const param = url.split("?")[1]?.split("&").find((kv) => kv.includes("dslabel"));
    if (!param) return;
    let value = decodeURIComponent(param.split("=")[1]);
    if (value.startsWith("{") && value.endsWith("}")) {
      value = JSON.parse(value);
      dslabel = value.dslabel || value.mass?.vocab.dslabel || value.tracks?.find((t) => t.dslabel)?.dslabel;
    } else {
      dslabel = value;
    }
  }
  setJwtByDsRoute();
  if (!dslabel || !jwtByDsRoute[dslabel]) return;
  const h = url.split("//");
  const postProtocolStr = h[1] || h[0];
  const preQuestionMarkStr = postProtocolStr.split("?")[0];
  const pathSegments = preQuestionMarkStr.split("/");
  let route = pathSegments.find((p) => p != "" && !p.includes(":") && !p.includes("."));
  const jwt = jwtByDsRoute[dslabel][route] || jwtByDsRoute[dslabel]["/**"];
  if (jwt) init.headers.authorization = "Bearer " + btoa(jwt);
}
var dsAuthOk = /* @__PURE__ */ new Set();
var dsAuth;
var authUi;
var authUiHolder;
var includeEmbedder = false;
async function setDsAuthOk(opts) {
  dsAuth = opts.dsAuth;
  authUi = opts.ui || defaultAuthUi;
  authUiHolder = opts.holder || select_default("body");
  for (const auth of dsAuth) {
    if (auth.insession) dsAuthOk.add(auth);
  }
  includeEmbedder = opts.dsAuth?.length > 0 || false;
}
function getRequiredAuth(dslabel, route) {
  if (!dsAuth || !Array.isArray(dsAuth)) return;
  for (const a of dsAuth) {
    if (a.dslabel == dslabel && (a.route == route || a.route == "*" || a.route == "/**")) return a;
  }
}
async function isInSession(dslabel, route) {
  if (!dslabel) return false;
  if (!Array.isArray(dsAuth)) return false;
  for (const a of dsAuth) {
    if (a.dslabel != dslabel || a.route != route && a.route != "/**") continue;
    if (dsAuthOk.has(a)) return true;
    if (a.checked) return false;
    const jwt = getSavedToken(dslabel, a.route);
    if (!jwt) return false;
    const { dofetch3: dofetch32 } = await import("./dofetch-RADX3AFU.js");
    const payload = decodeJwtPayload(jwt);
    if (payload.exp && Math.ceil(Date.now() / 1e3) > payload.exp) return false;
    const data = await dofetch32("/jwt-status", {
      method: "POST",
      credentials: "include",
      headers: {
        //authorization: `Bearer ${btoa(jwt)}`
        [a.headerKey]: jwt
      },
      body: {
        dslabel,
        route,
        embedder: location.hostname
      }
    });
    a.checked = true;
    if (data.ok || data.status == "ok") {
      dsAuthOk.add(a);
      a.insession = true;
      return true;
    }
  }
  return false;
}
async function mayShowAuthUi(init, path, opts = {}) {
  const ok = { status: "ok" };
  if (!dsAuth || path.endsWith("jwt-status")) return ok;
  const body = JSON.parse(init.body || `{}`);
  const params = (path.split("?")[1] || "").split("&").reduce((obj, kv) => {
    const [key, value] = kv.split("=");
    obj[key] = value;
    return obj;
  }, {});
  const q = Object.assign({}, body, params);
  const route = ((path.split("?")[0] || "").split("//")[1] || "").split("/").slice(1).join("/");
  for (const a of dsAuth) {
    if (q.dslabel == a.dslabel && (a.route == "/**" || route == a.route)) {
      if (dsAuthOk.has(a)) return ok;
      else if (a.route != "/**") return ok;
      else if (a.type == "basic") return await authUi(a.dslabel, a, opts);
      else if (a.type == "jwt") {
      } else if (a.type == "forbidden") {
        alert("Forbidden access");
      } else throw `unsupported dsAuth type='${a.type}'`;
    }
  }
  return ok;
}
async function defaultAuthUi(dslabel, auth, opts = {}) {
  const mask = authUiHolder.append("div").style("position", "fixed").style("top", 0).style("left", 0).style("height", "100%").style("width", "100%").style("margin", 0).style("padding", "20px").style("background-color", "rgb(150,150,150)");
  const form = mask.append("div").style("opacity", 1);
  form.append("div").html(`Restricted dataset '${dslabel}'`);
  form.append("span").html("Please enter password ");
  const pwd = form.append("input").attr("type", "password");
  pwd.node().focus();
  const btn = form.append("button").html("Submit");
  return new Promise((resolve, reject) => {
    function login() {
      fetch("/dslogin", {
        method: "POST",
        headers: {
          authorization: `Basic ${btoa(pwd.property("value"))}`
        },
        body: JSON.stringify({ dslabel, route: auth.route, embedder: window.location.hostname })
      }).then((res) => res.json()).then((res) => {
        if (res.error) throw res.error;
        mask.remove();
        dsAuthOk.add(auth);
        if (res.jwt) {
          setTokenByDsRoute(dslabel, res.route, res.jwt);
        }
        if (!opts.setDomRefs) window.location.reload();
        else resolve(dslabel);
      }).catch((e) => {
        alert("login error: " + e);
      });
    }
    btn.on("click", login);
    pwd.on("change", login);
    if (opts.setDomRefs)
      opts.setDomRefs({
        pwd,
        btn,
        mask,
        authUiHolder
      });
  });
}
function decodeJwtPayload(token) {
  const base64Url = token.split(".")[1];
  const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
  const paddedBase64 = base64 + "=".repeat((4 - base64.length % 4) % 4);
  const jsonPayload = decodeURIComponent(window.atob(paddedBase64).split("").map(convertAtoBresult).join(""));
  return JSON.parse(jsonPayload);
}
function convertAtoBresult(c) {
  return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
}

// common/dofetch.js
function dofetch(path, arg, opts = null) {
  if (opts && typeof opts == "object") {
    if (opts.serverData && typeof opts.serverData == "object") {
      if (!dofetch.serverData) {
        dofetch.serverData = opts.serverData;
      } else if (!opts.serverData) {
        opts.serverData = dofetch.serverData;
      }
    }
    return dofetch2(
      path,
      {
        method: "POST",
        headers: {
          "content-type": "application/json"
        },
        body: JSON.stringify(arg)
      },
      opts
    );
  } else {
    if (path[0] == "/") {
      path = path.slice(1);
    }
    const jwt = sessionStorage.getItem("jwt");
    if (jwt) {
      arg.jwt = jwt;
    }
    let url = path;
    const host = sessionStorage.getItem("hostURL") || window.testHost || "";
    if (host) {
      if (host.endsWith("/")) {
        url = host + path;
      } else {
        url = host + "/" + path;
      }
    }
    return fetch(
      new Request(url, {
        method: "POST",
        headers: {
          "content-type": "application/json"
        },
        body: JSON.stringify(arg)
      })
    ).then((r) => r.json());
  }
}
function dofetch2(path, init = {}, opts = {}) {
  if (path[0] == "/") {
    path = path.slice(1);
  }
  let url = path;
  const host = sessionStorage.getItem("hostURL") || window.testHost || "";
  if (host) {
    if (host.endsWith("/")) {
      url = host + path;
    } else {
      url = host + "/" + path;
    }
  }
  const body = init.body || {};
  url = mayAdjustRequest(url, init);
  if (!init.headers) {
    init.headers = {};
  }
  if (!init.headers["content-type"] && init.body) {
    init.headers["content-type"] = "application/json";
  }
  const jwt = sessionStorage.getItem("jwt");
  if (jwt) {
    init.headers.authorization = "Bearer " + jwt;
  }
  return mayShowAuthUi(init, url).then(async () => {
    if (!jwt) mayAddJwtToRequest(init, body, url);
    if (opts.serverData) {
      return namedFetch(url, init, opts);
    } else {
      return fetch(url, init).then(processResponse);
    }
  });
}
var optsServerDataNames = /* @__PURE__ */ new WeakMap();
async function namedFetch(url, init, opts = {}) {
  if (!opts.serverData) throw `use ezFetch() from fetch-helpers if a fetched response is not meant to be cached`;
  if (typeof opts.serverData != "object") throw `opts.serverData is not an object`;
  let result;
  const dataName = await getDataName(url, init);
  if (opts.serverData[dataName]) {
    if (init.signal) {
      await sleep(0);
      if (init.signal.aborted) throw `stale sequenceId`;
    }
    result = structuredClone(opts.serverData[dataName]);
  }
  if (!result || typeof result != "object" && !(result instanceof Promise)) {
    delete opts.serverData[dataName];
    result = void 0;
  }
  if (!result) {
    try {
      const res = await fetch(url, init);
      result = await processResponse(res);
      if (typeof result == "object" && !(result instanceof Promise)) {
        deepFreeze(result);
        opts.serverData[dataName] = result;
        result = structuredClone(result);
      }
    } catch (e) {
      delete opts.serverData[dataName];
      throw e;
    }
  }
  if (!optsServerDataNames.has(opts.serverData)) optsServerDataNames.set(opts.serverData, []);
  const keys = optsServerDataNames.get(opts.serverData);
  const i = keys.indexOf(dataName);
  if (i > 0) {
    keys.splice(i, 1);
  }
  keys.unshift(dataName);
  const maxKeys = 360;
  while (keys.length > maxKeys) {
    const oldestDataKey = keys.pop();
    delete opts.serverData[oldestDataKey];
  }
  return result;
}
var defaultServerDataCache = {};
function dofetch3(path, init = {}, opts = {}) {
  if (!init.signal && this) {
    init.signal = this.getAbortSignal?.() || this.app?.getAbortSignal?.();
  }
  opts.serverData = defaultServerDataCache;
  return dofetch2(path, init, opts);
}
function clearServerDataCache(opts = {}) {
  const cache = opts?.serverData || defaultServerDataCache;
  if (!cache) return;
  for (const k of Object.keys(cache)) {
    delete cache[k];
  }
}
var urlMaxLength = 2e3;
function mayAdjustRequest(url, init) {
  const hostname = window.location.hostname;
  const method = init.method && init.method.toUpperCase() || "GET";
  if (method == "POST") {
    if (typeof init.body == "string") init.body = JSON.parse(init.body);
    if (!init.body.embedder && includeEmbedder) init.body.embedder = hostname;
    init.body = JSON.stringify(init.body);
    return url;
  }
  if (method != "GET" && method != "DELETE" && method != "PUT") {
    throw `unsupported init.method='${method}': must be undefined or GET or POST or DELETE or PUT`;
  }
  if (init.body) {
    if (!init.body.embedder && includeEmbedder) init.body.embedder = hostname;
    const params = encode(init.body);
    if (!url.includes("?")) url += "?";
    url += params;
  }
  if (!url.includes("embedder=") && includeEmbedder) {
    const sep = url.includes("?") ? "&" : "?";
    url += `${sep}embedder=${hostname}`;
  }
  if (url.length < urlMaxLength) {
    if (init.body) delete init.body;
    return url;
  }
  init.method = "POST";
  const [hostpath, query] = url.split("?");
  if (init.body) {
    init.body = JSON.stringify(init.body);
  } else {
    const params = {};
    if (query)
      query.split("&").forEach((p) => {
        const [k, v] = p.split("=");
        const decodedVal = decodeURIComponent(v);
        try {
          params[k] = JSON.parse(decodedVal);
        } catch {
          params[k] = decodedVal;
        }
      });
    if (!params.embedder && includeEmbedder) params.embedder = hostname;
    init.body = JSON.stringify(params);
  }
  return hostpath;
}
function setAuth(opts) {
  setDsAuthOk(opts, dofetch3);
}

export {
  init_bulk_flag,
  parsesample,
  clusterMethodLst,
  distanceMethodLst,
  computePercentile,
  processFormData,
  fileSize,
  ssmIdFieldsSeparator,
  summarize_mclass,
  guessSsmid,
  xAxisOffSet,
  yAxisOffSet,
  getCoordinate,
  calculatePadding,
  initBinConfig,
  isUsableTerm,
  formatElapsedTime,
  vcfparsemeta,
  vcfparseline,
  setTokenByDsRoute,
  getSavedToken,
  mayAddJwtToRequest,
  includeEmbedder,
  setDsAuthOk,
  getRequiredAuth,
  isInSession,
  mayShowAuthUi,
  dofetch,
  dofetch2,
  namedFetch,
  dofetch3,
  clearServerDataCache,
  setAuth
};
//# sourceMappingURL=chunk-7EMWHCVW.js.map
