{
  "version": 3,
  "sources": ["../agent.ts", "../controller.ts", "../download.ts", "../file_handler.ts", "../error.ts", "../controlled_handler.ts", "../range_handler.ts", "../range_policy.ts", "../progress.ts"],
  "sourcesContent": ["import { Agent, interceptors, RetryHandler } from 'undici'\n\nexport function getDefaultAgent(retry?: RetryHandler.RetryOptions, defaultMaxRedirections = 5) {\n  const options: Agent.Options = {\n    connections: 16,\n  }\n  return new Agent(options).compose(\n    interceptors.retry(\n      retry || {\n        errorCodes: [\n          'UND_ERR_CONNECT_TIMEOUT',\n          'UND_ERR_HEADERS_TIMEOUT',\n          'UND_ERR_BODY_TIMEOUT',\n          'ECONNRESET',\n          'ECONNREFUSED',\n          'ENOTFOUND',\n          'ENETDOWN',\n          'ETIMEDOUT',\n          'ENETUNREACH',\n          'EHOSTDOWN',\n          'EHOSTUNREACH',\n          'EPIPE',\n          'UND_ERR_SOCKET',\n        ],\n        statusCodes: [567, 500, 502, 503, 504, 429],\n        maxRetries: 3,\n      },\n    ),\n    interceptors.redirect({ maxRedirections: defaultMaxRedirections }),\n  )\n}\n", "/**\n * A throughput observation for a single in-flight download connection.\n *\n * Emitted periodically (every `DownloadController.sampleInterval` ms)\n * while the body is streaming, so a controller can decide whether the\n * assigned host is fast enough to keep.\n */\nexport interface DownloadSample {\n  /**\n   * The origin the request was dispatched to (e.g. the BMCLAPI origin,\n   * before any redirect).\n   */\n  origin: string\n  /**\n   * The final URL after following redirects, if known. For a CDN that\n   * redirects to a mirror this is the mirror URL actually serving bytes.\n   */\n  finalUrl?: string\n  /**\n   * The final host after following redirects, if known. Use this as the\n   * reputation key for a distributed CDN.\n   */\n  host?: string\n  /**\n   * Bytes of this download (or segment) already on disk, including bytes\n   * from earlier resumed attempts. `total - received` is the remaining\n   * work, which the optimal-stop rule compares against.\n   */\n  received: number\n  /**\n   * Total expected bytes for this download (or segment), or 0 if unknown.\n   */\n  total: number\n  /**\n   * Throughput over the most recent sampling window, in bytes/second.\n   */\n  speed: number\n  /**\n   * Milliseconds elapsed since the first body byte of this connection\n   * arrived. Useful to ignore the TCP slow-start ramp.\n   */\n  elapsed: number\n}\n\nexport type DownloadDecision = 'continue' | 'abort'\n\n/**\n * The outcome reported to the controller when a single connection ends,\n * whether it completed, was aborted by the controller, or failed.\n */\nexport interface DownloadResult {\n  origin: string\n  finalUrl?: string\n  host?: string\n  /**\n   * Total bytes transferred on this connection.\n   */\n  received: number\n  /**\n   * Wall-clock duration of the connection, in milliseconds, measured\n   * from the first body byte.\n   */\n  duration: number\n  /**\n   * Average throughput in bytes/second over the connection lifetime.\n   */\n  speed: number\n  outcome: 'completed' | 'aborted' | 'failed'\n}\n\n/**\n * A pluggable strategy that observes a download's per-connection\n * throughput and may request a *managed abort* \u2014 which makes `download`\n * resume the transfer (via an HTTP `Range` request) on a fresh\n * connection instead of failing the whole download.\n *\n * This is the seam the BMCLAPI coordinator plugs into to drop slow\n * mirror assignments and re-request the signed API for a (hopefully)\n * faster host. When no controller is supplied to `download`, behaviour\n * is byte-for-byte unchanged.\n */\nexport interface DownloadController {\n  /**\n   * Minimum milliseconds between throughput samples.\n   * @default 1000\n   */\n  readonly sampleInterval?: number\n  /**\n   * Ignore the connection's throughput (never abort) until this many\n   * milliseconds have elapsed since the first byte. Guards against\n   * killing a healthy connection during TCP slow-start.\n   * @default 0\n   */\n  readonly warmup?: number\n  /**\n   * Maximum number of managed aborts before `download` stops resuming\n   * and surfaces the underlying failure. Bounds worst-case rerolls.\n   * @default 5\n   */\n  readonly maxResumes?: number\n  /**\n   * Maximum *no-progress* re-rolls (TTFB/stall, i.e. dead/stuck mirrors)\n   * to attempt on one URL before falling through to the next fallback\n   * URL (e.g. the official source). Keeps a dead CDN from blocking the\n   * download indefinitely. (Default applied by `download`: 2.)\n   */\n  readonly maxNoProgressRerolls?: number\n  /**\n   * If no body byte arrives within this many ms of starting a connection\n   * (covering connect + redirect + TTFB), trigger a managed abort so a\n   * dead/blackholed mirror is re-rolled quickly instead of waiting for\n   * the dispatcher's much longer headers/body timeout. `0` disables it.\n   * @default 0\n   */\n  readonly ttfbDeadline?: number\n  /**\n   * After the first byte, if no further byte arrives within this many ms,\n   * treat the connection as stalled and abort it (a mid-stream stuck\n   * mirror). Active even in the committed finishing phase. `0` disables.\n   * @default 0\n   */\n  readonly stallTimeout?: number\n  /**\n   * Files at least this large are split into `rangeConcurrency` byte\n   * segments fetched in parallel \u2014 each a separate request, so on a\n   * distributed CDN each segment streams from a different mirror at\n   * once. `0` disables splitting. (Default applied by `download`: 4 MiB.)\n   */\n  readonly rangeSplitThreshold?: number\n  /**\n   * Number of parallel segments to use when range-splitting a large\n   * file. (Default applied by `download`: 4.)\n   */\n  readonly rangeConcurrency?: number\n  /**\n   * Inspect a throughput sample and decide whether to keep the\n   * connection (`'continue'`) or trigger a managed abort + resume\n   * (`'abort'`).\n   */\n  onSample?(sample: DownloadSample): DownloadDecision\n  /**\n   * Decide whether a *failed* attempt (HTTP error, network error) on the\n   * given origin should be retried by re-rolling \u2014 i.e. re-requesting the\n   * same URL to be re-assigned a different mirror \u2014 rather than treated\n   * as terminal. For a distributed CDN a 403/404/5xx from one mirror\n   * often succeeds on the next assignment. Bounded by `maxResumes`.\n   */\n  shouldReroll?(origin: string, error: unknown): boolean\n  /**\n   * Whether the given origin is worth aborting (TTFB/stall) and\n   * re-rolling \u2014 i.e. a re-assignable CDN whose next request can land on\n   * a different mirror. Non-re-assignable origins (e.g. the official\n   * source) are NOT aborted on TTFB/stall: re-rolling cannot help and\n   * the slow-but-working source is the last resort. Defaults to `true`\n   * (abort everything) when not implemented.\n   */\n  isAbortable?(origin: string): boolean\n  /**\n   * Whether requests to the given origin should be skipped *entirely*\n   * right now \u2014 a circuit breaker. When a re-assignable CDN is failing\n   * hard (delivering no data), `download` skips its URLs and goes\n   * straight to a fallback (e.g. the official source) until the breaker\n   * resets. `download` never skips the last remaining URL. Defaults to\n   * never-skip when not implemented.\n   */\n  shouldSkip?(origin: string): boolean\n  /**\n   * Receive the final outcome of a single connection, for updating a\n   * reputation / speed model.\n   */\n  report?(result: DownloadResult): void\n}\n\nconst kManagedAbort = Symbol('ManagedAbort')\n\n/**\n * Why a connection was aborted by the controller/handler:\n * - `ttfb`: connected/redirected but delivered no first byte in time.\n * - `stall`: delivered a first byte then stopped making progress.\n * - `slow`: making progress, but too slow vs. the learned model.\n *\n * `ttfb` and `stall` mean *no progress* (a dead/stuck mirror) and should\n * be abandoned fast; `slow` is a tuning decision.\n */\nexport type ManagedAbortReason = 'ttfb' | 'stall' | 'slow'\n\n/**\n * Error used to signal a controller-requested abort. `download`\n * recognises it and resumes the transfer instead of failing.\n */\nexport class ManagedAbortError extends Error {\n  readonly [kManagedAbort] = true\n  readonly reason: ManagedAbortReason\n\n  constructor(reason: ManagedAbortReason = 'slow') {\n    super(`Download connection aborted by controller (${reason})`)\n    this.name = 'ManagedAbortError'\n    this.reason = reason\n  }\n}\n\nexport function isManagedAbortError(e: unknown): e is ManagedAbortError {\n  return !!e && typeof e === 'object' && (e as any)[kManagedAbort] === true\n}\n\nconst kRangeUnsupported = Symbol('RangeNotSupported')\n\n/**\n * Thrown by a segment download when a ranged request is answered with a\n * full `200` response (the mirror ignored `Range`). The orchestrator\n * catches it and falls back to a single whole-file stream so the shared\n * file is not corrupted by overlapping writes.\n */\nexport class RangeNotSupportedError extends Error {\n  readonly [kRangeUnsupported] = true\n\n  constructor() {\n    super('Server ignored the Range header and returned a full response')\n    this.name = 'RangeNotSupportedError'\n  }\n}\n\nexport function isRangeNotSupportedError(e: unknown): e is RangeNotSupportedError {\n  return !!e && typeof e === 'object' && (e as any)[kRangeUnsupported] === true\n}\n", "import { close as sclose, ftruncate as sftruncate, mkdir as smkdir, open as sopen, unlink } from 'fs'\nimport { dirname } from 'path'\nimport { Dispatcher } from 'undici'\nimport { promisify } from 'util'\nimport { getDefaultAgent } from './agent'\nimport { ControlledFileHandler } from './controlled_handler'\nimport {\n  DownloadController,\n  isManagedAbortError,\n  isRangeNotSupportedError,\n  ManagedAbortError,\n} from './controller'\nimport { ProgressTrackerMultiple, ProgressTrackerSingle } from './progress'\nimport { RangeRequestHandler } from './range_handler'\nimport { DefaultRangePolicyOptions, RangePolicy, resolveRangePolicy } from './range_policy'\nimport { decorateError, getDestinationExtension } from './error'\n\nexport interface DownloadBaseOptions {\n  rangePolicy?: RangePolicy | DefaultRangePolicyOptions\n  dispatcher?: Dispatcher\n  /**\n   * Optional adaptive strategy. When supplied, the download runs as a\n   * single resumable stream whose throughput is sampled, and the\n   * controller may request a managed abort that resumes (via HTTP\n   * `Range`) on a fresh connection instead of failing. When omitted,\n   * the classic parallel-range / multi-URL-fallback path is used and\n   * behaviour is unchanged.\n   */\n  controller?: DownloadController\n}\n\nexport function getDownloadBaseOptions(options?: DownloadBaseOptions) {\n  return {\n    dispatcher: options?.dispatcher || getDefaultAgent(),\n    rangePolicy: resolveRangePolicy(options?.rangePolicy),\n    controller: options?.controller,\n  }\n}\n\nexport interface DownloadOptions extends DownloadBaseOptions {\n  /**\n   * The url or urls (fallback) of the resource\n   */\n  url: string | string[]\n  /**\n   * The header of the request\n   */\n  headers?: Record<string, any>\n  /**\n   * Where the file will be downloaded to\n   */\n  destination: string\n  /**\n   * The progress controller. If you want to track download progress, you should use this.\n   */\n  tracker?: ProgressTrackerSingle\n  /**\n   * The user abort signal to abort the download\n   */\n  signal?: AbortSignal\n  /**\n   * The expected total size of the file.\n   */\n  expectedTotal?: number\n}\n\nexport type DownloadMultipleOption = Pick<\n  DownloadOptions,\n  'url' | 'headers' | 'destination' | 'expectedTotal'\n>\n\nexport interface DownloadMultipleOptions extends DownloadBaseOptions {\n  options: DownloadMultipleOption[]\n\n  tracker?: ProgressTrackerMultiple\n\n  signal?: AbortSignal\n}\n\nexport async function downloadMultiple(\n  options: DownloadMultipleOptions,\n): Promise<PromiseSettledResult<void>[]> {\n  const tracker = options.tracker\n\n  if (tracker) {\n    let expectedTotal = 0\n    for (const opt of options.options) {\n      if (!opt.expectedTotal) {\n        expectedTotal = 0\n        break\n      }\n      expectedTotal += opt.expectedTotal\n    }\n    if (expectedTotal) {\n      tracker.expectedTotal = expectedTotal\n    }\n  }\n\n  return Promise.allSettled(\n    options.options.map((opt) =>\n      download({\n        ...opt,\n        tracker: tracker?.subSingle(),\n        signal: options.signal,\n        ...getDownloadBaseOptions(options),\n      }),\n    ),\n  )\n}\n\nexport async function download(options: DownloadOptions): Promise<void> {\n  const urls = typeof options.url === 'string' ? [options.url] : options.url\n  const headers = options.headers || {}\n  const destination = options.destination\n  const tracker = options.tracker\n  const signal = options.signal\n  const expectedTotal = options.expectedTotal\n  const { dispatcher, rangePolicy, controller } = getDownloadBaseOptions(options)\n\n  // Check if already aborted before opening file\n  signal?.throwIfAborted()\n\n  if (tracker && expectedTotal) {\n    tracker.expectedTotal = expectedTotal\n  }\n\n  const fd = await openFd(options.destination)\n  // Move the post-open abort check inside the try/finally so an abort\n  // race here (signal fires between openFd resolving and this line)\n  // still results in fd being closed.\n  const errors = []\n\n  try {\n    signal?.throwIfAborted()\n\n    if (controller) {\n      await downloadWithController({\n        urls,\n        headers,\n        fd,\n        dispatcher,\n        controller,\n        tracker,\n        signal,\n        expectedTotal: expectedTotal ?? 0,\n      })\n      await close(fd).catch(() => {})\n      return\n    }\n\n    for (const url of urls) {\n      const parsedUrl = new URL(url)\n      const ops = {\n        path: parsedUrl.pathname + parsedUrl.search,\n        origin: parsedUrl.origin,\n        method: 'GET',\n        signal,\n        headers: {\n          ...headers,\n          ...(expectedTotal && expectedTotal > rangePolicy.rangeThreshold\n            ? {\n                Range: `bytes=0-${rangePolicy.rangeThreshold - 1}`,\n              }\n            : {}),\n        },\n      }\n      // Allow one rewind+restart per URL: when the connection dies\n      // mid-stream undici's retry interceptor sends a `Range:\n      // bytes=<consumed>-` request to resume, and throws\n      // `RequestRetryError` (\"server does not support the range header\n      // and the payload was partially consumed\" / \"content-range\n      // mismatch\") if the origin can't honour it. Treat that as a\n      // transient failure and retry this same URL from byte 0 with the\n      // file truncated. The retry deliberately removes our initial Range\n      // header so a proxy/CDN that mangles range responses gets one chance\n      // to serve a complete single stream.\n      let restartedForRangeRetry = false\n      while (true) {\n        const handler = new RangeRequestHandler(\n          ops,\n          dispatcher,\n          fd,\n          rangePolicy,\n          tracker,\n          getDestinationExtension(destination),\n        )\n        dispatcher.dispatch(ops, handler)\n        const err = await handler.wait().catch((e) => e)\n        if (!err) {\n          errors.length = 0\n          // break out of both loops by setting urls.length = 0 below\n          break\n        }\n        signal?.throwIfAborted()\n        if (!restartedForRangeRetry && isRangeRetryError(err)) {\n          restartedForRangeRetry = true\n          await ftruncateAsync(fd, 0).catch(() => {})\n          delete ops.headers.Range\n          continue\n        }\n        errors.push(err)\n        break\n      }\n      if (errors.length === 0) break\n    }\n\n    if (errors.length > 0) {\n      if (errors.length === 1) {\n        throw errors[0]\n      }\n      throw new AggregateError(errors, 'All urls failed to download')\n    }\n\n    await close(fd).catch(() => {})\n  } catch (e) {\n    decorateError(e as any, urls, headers, destination)\n    await close(fd).catch(() => {})\n    await unlinkAsync(destination).catch(() => {})\n    throw e\n  }\n}\n\ninterface ControlledDownloadParams {\n  urls: string[]\n  headers: Record<string, any>\n  fd: number\n  dispatcher: Dispatcher\n  controller: DownloadController\n  tracker?: ProgressTrackerSingle\n  signal?: AbortSignal\n  expectedTotal: number\n}\n\n/**\n * The adaptive download path used when a {@link DownloadController} is\n * supplied. Runs a single resumable stream:\n *\n * - The controller samples throughput and may request a *managed abort*.\n *   On a managed abort we keep the partial bytes on disk and re-request\n *   the *same* URL \u2014 for a distributed CDN this re-triggers the redirect\n *   and (hopefully) lands on a faster mirror, resuming via `Range`.\n * - On a *terminal* failure (HTTP/network error after undici retries)\n *   we advance to the next fallback URL, still resuming from the bytes\n *   already written (safe because callers download content-addressed\n *   resources, so any mirror serves identical bytes).\n *\n * The partial file is never truncated here; the caller's outer\n * `catch` removes it only when every attempt is exhausted.\n */\nasync function downloadWithController(params: ControlledDownloadParams): Promise<void> {\n  const { urls, headers, fd, dispatcher, controller, tracker, signal, expectedTotal } = params\n\n  try {\n    const splitThreshold = controller.rangeSplitThreshold ?? 4 * 1024 * 1024\n    const concurrency = controller.rangeConcurrency ?? 4\n\n    if (expectedTotal >= splitThreshold && concurrency > 1) {\n      try {\n        await downloadRanged(params, concurrency)\n        return\n      } catch (e) {\n        if (!isRangeNotSupportedError(e)) throw e\n        // A mirror ignored Range \u2014 abandon the split and re-download the\n        // whole file as a single stream from a clean slate.\n        await ftruncateAsync(fd, 0).catch(() => {})\n      }\n    }\n\n    await runSegment({\n      urls,\n      headers,\n      fd,\n      dispatcher,\n      controller,\n      signal,\n      expectedTotal,\n      tracker,\n    })\n  } finally {\n    if (tracker) {\n      tracker.done = true\n    }\n  }\n}\n\n/**\n * Split a large file into `concurrency` byte-range segments and fetch\n * them in parallel. Because each segment is a *separate* request to the\n * (signed CDN) origin, each is independently redirected \u2014 so the chunks\n * stream from different mirrors at once. A slow mirror only delays its\n * own chunk, which the controller can re-roll. Rejects with\n * {@link RangeNotSupportedError} if any mirror refuses Range.\n */\nasync function downloadRanged(params: ControlledDownloadParams, concurrency: number): Promise<void> {\n  const { urls, headers, fd, dispatcher, controller, tracker, signal, expectedTotal } = params\n\n  const chunkSize = Math.ceil(expectedTotal / concurrency)\n  const chunks: { start: number; end: number }[] = []\n  for (let s = 0; s < expectedTotal; s += chunkSize) {\n    chunks.push({ start: s, end: Math.min(expectedTotal - 1, s + chunkSize - 1) })\n  }\n\n  // Aggregate per-chunk progress into one shared accessor.\n  const shared: ProgressTrackerSingle['accessor'] = {\n    url: urls[0],\n    total: expectedTotal,\n    progress: 0,\n  }\n  if (tracker) tracker.setAccessor(shared)\n  const segDone = new Array(chunks.length).fill(0)\n\n  // Internal signal so one chunk's terminal failure cancels its siblings\n  // (e.g. a RangeNotSupported chunk that forces a whole-file fallback).\n  const ac = new AbortController()\n  const onOuterAbort = () => ac.abort(signal?.reason)\n  if (signal) {\n    if (signal.aborted) ac.abort(signal.reason)\n    else signal.addEventListener('abort', onOuterAbort, { once: true })\n  }\n\n  try {\n    await Promise.all(\n      chunks.map((segment, i) =>\n        runSegment({\n          urls,\n          headers,\n          fd,\n          dispatcher,\n          controller,\n          signal: ac.signal,\n          expectedTotal,\n          segment,\n          onAdvance: (pos) => {\n            segDone[i] = pos - segment.start\n            shared.progress = segDone.reduce((a, b) => a + b, 0)\n          },\n        }),\n      ),\n    )\n  } catch (e) {\n    ac.abort(e)\n    throw e\n  } finally {\n    signal?.removeEventListener('abort', onOuterAbort)\n  }\n}\n\ninterface SegmentParams {\n  urls: string[]\n  headers: Record<string, any>\n  fd: number\n  dispatcher: Dispatcher\n  controller: DownloadController\n  signal?: AbortSignal\n  expectedTotal: number\n  /**\n   * Inclusive byte range this call is responsible for. Omitted for a\n   * whole-file single stream.\n   */\n  segment?: { start: number; end: number }\n  tracker?: ProgressTrackerSingle\n  onAdvance?: (absolutePosition: number) => void\n}\n\n/**\n * Download one segment (or the whole file) over a single resumable,\n * speed-sampled connection. A managed abort re-requests the *same* URL\n * (re-roll \u2192 fresh mirror) resuming from where it stopped; a terminal\n * failure advances to the next fallback URL, still resuming. Throws\n * {@link RangeNotSupportedError} immediately if a ranged request is\n * answered with a full 200.\n */\nasync function runSegment(p: SegmentParams): Promise<void> {\n  const { urls, headers, fd, dispatcher, controller, signal, expectedTotal } = p\n  const maxResumes = controller.maxResumes ?? 5\n  const maxNoProgress = controller.maxNoProgressRerolls ?? 2\n  const isSeg = !!p.segment\n  const segStart = p.segment?.start ?? 0\n  const segEnd = p.segment?.end\n  const segTotal = isSeg ? segEnd! - segStart + 1 : 0\n\n  let resumeOffset = segStart\n  let resumes = 0\n  let noProgress = 0\n  let committed = false\n  let lastError: unknown\n  let done = false\n\n  for (let urlIndex = 0; urlIndex < urls.length; ) {\n    const parsedUrl = new URL(urls[urlIndex])\n    // Circuit breaker: when a re-assignable CDN is failing hard, skip its\n    // URLs and fall straight through to a fallback \u2014 but never skip the\n    // last remaining URL (it is the last resort).\n    if (\n      urlIndex < urls.length - 1 &&\n      controller.shouldSkip?.(parsedUrl.origin)\n    ) {\n      urlIndex++\n      continue\n    }\n    const range = isSeg\n      ? `bytes=${resumeOffset}-${segEnd}`\n      : resumeOffset > 0\n        ? `bytes=${resumeOffset}-`\n        : undefined\n    const ops = {\n      path: parsedUrl.pathname + parsedUrl.search,\n      origin: parsedUrl.origin,\n      method: 'GET',\n      signal,\n      headers: { ...headers, ...(range ? { Range: range } : {}) },\n    }\n\n    const handler = new ControlledFileHandler(ops, fd, controller, {\n      expectedTotal,\n      tracker: p.tracker,\n      segment: isSeg ? { start: segStart, total: segTotal } : undefined,\n      requireRange: isSeg,\n      requestStart: isSeg ? resumeOffset : -1,\n      noAbort: committed,\n      abortable: controller.isAbortable ? controller.isAbortable(ops.origin) : true,\n      onAdvance: p.onAdvance,\n    })\n    const startedAt = Date.now()\n    dispatcher.dispatch(ops, handler)\n    const err = await handler.wait().catch((e) => e)\n\n    const duration = Date.now() - startedAt\n    const received = handler.received\n    controller.report?.({\n      origin: ops.origin,\n      finalUrl: handler.resolvedUrl,\n      host: handler.finalHost,\n      received,\n      duration,\n      speed: duration > 0 ? (received / duration) * 1000 : 0,\n      outcome: !err ? 'completed' : isManagedAbortError(err) ? 'aborted' : 'failed',\n    })\n\n    if (!err) {\n      // Defend against a mirror that completed \"successfully\" but\n      // delivered FEWER bytes than requested (a short, otherwise-valid\n      // 206, or a whole-file stream cut short). Without this check the\n      // un-delivered tail stays as zero bytes on disk \u2014 a silent gap\n      // that corrupts the file (e.g. empty zip entries). The expected\n      // end is the segment's inclusive end + 1, or the whole-file total\n      // discovered from the response headers.\n      const target = isSeg ? segEnd! + 1 : handler.total\n      if (target > 0 && handler.offset < target) {\n        resumeOffset = Math.max(resumeOffset, handler.offset)\n        if (resumes < maxResumes) {\n          resumes++\n          continue // resume the missing tail\n        }\n        lastError = new Error(\n          `Incomplete download: received ${handler.offset} of ${target} bytes`,\n        )\n        urlIndex++\n        continue\n      }\n      done = true\n      break\n    }\n\n    signal?.throwIfAborted()\n\n    // A mirror that ignored Range cannot be safely resumed within a\n    // shared multi-segment file \u2014 bubble up to force a whole-file retry.\n    if (isRangeNotSupportedError(err)) throw err\n\n    // Carry the resume offset forward across both rerolls and URL\n    // fallbacks so we never re-download bytes already on disk.\n    resumeOffset = Math.max(resumeOffset, handler.offset)\n    lastError = err\n\n    if (isManagedAbortError(err)) {\n      const reason = (err as ManagedAbortError).reason\n      if (reason === 'slow') {\n        if (resumes < maxResumes) {\n          // Reroll: retry the same URL to be re-assigned a (hopefully)\n          // faster mirror, resuming from where we stopped.\n          resumes++\n          continue\n        }\n        // The re-roll budget is spent. A slow-but-working connection is\n        // never a hard failure \u2014 commit to finishing the next attempt\n        // with the speed abort disabled so it can complete.\n        committed = true\n        continue\n      }\n      // 'ttfb' or 'stall' \u2014 NO progress: the assigned mirror is dead or\n      // stuck. Try a couple of fresh assignments, then fall straight to\n      // the next fallback URL (e.g. the official source) instead of\n      // looping on dead mirrors and wasting the whole reroll budget.\n      if (noProgress < maxNoProgress) {\n        noProgress++\n        continue\n      }\n      noProgress = 0\n      committed = false\n      urlIndex++\n      continue\n    }\n\n    // A transient mirror failure (e.g. 403/404/5xx) on a re-assignable\n    // origin is worth re-rolling \u2014 a fresh assignment usually serves the\n    // bytes \u2014 rather than giving up on this URL.\n    if (controller.shouldReroll?.(ops.origin, err) && resumes < maxResumes) {\n      resumes++\n      continue\n    }\n\n    // Terminal failure, or the reroll budget is spent: fall through to\n    // the next fallback URL.\n    urlIndex++\n  }\n\n  if (!done) {\n    throw lastError ?? new Error('Download failed with no attempts')\n  }\n}\n\nconst unlinkAsync = promisify(unlink)\nconst ftruncateAsync = promisify(sftruncate)\nconst mkdir = promisify(smkdir)\nconst open = promisify(sopen)\nconst close = promisify(sclose)\n\n/**\n * undici's retry interceptor wraps a transient socket failure by\n * re-issuing the request with `Range: bytes=<bytesConsumed>-` to resume.\n * If the origin then replies with a fresh 200 (no Range support) or a\n * Content-Range that doesn't match what we already wrote, it throws\n * `RequestRetryError` with code `UND_ERR_REQ_RETRY` and one of these\n * messages. We use this to decide whether to truncate the partial file\n * and restart the download from scratch on the same URL.\n */\nfunction isRangeRetryError(e: any): boolean {\n  if (!e) return false\n  if (e.code === 'UND_ERR_REQ_RETRY') return true\n  const msg = typeof e.message === 'string' ? e.message : ''\n  return msg.includes('range header') || msg.includes('content-range mismatch')\n}\n\nfunction assignError(e: Error) {\n  Error.captureStackTrace(e)\n  Object.assign(e, {\n    phase: 'open',\n  })\n}\n\nasync function openFd(output: string) {\n  const fd = await open(output, 'w').catch(async (e) => {\n    if (e.code === 'ENOENT') {\n      await mkdir(dirname(output), { recursive: true })\n      return await open(output, 'w').catch((e) => {\n        assignError(e)\n        throw e\n      })\n    }\n    assignError(e)\n    throw e\n  })\n  return fd\n}\n", "import { write } from 'fs'\nimport { Dispatcher, util } from 'undici'\nimport { decorateHttpError } from './error'\n\nexport class FileHandler implements Dispatcher.DispatchHandler {\n  private abort?: (err?: Error) => void\n\n  protected context?: {\n    history?: URL[]\n  }\n  start = 0\n  position: number = 0\n  contentLength: number = 0\n  protected statusCode = 0\n  protected signal: AbortSignal | undefined\n  protected resolvers = Promise.withResolvers<void>()\n  protected terminated = false\n  protected pending = 0\n  protected writeError?: Error\n  protected listener = () => this.resolvers.reject(this.signal?.reason)\n\n  constructor(\n    signal: AbortSignal | undefined,\n    readonly fd: number,\n    private readonly requestUrl?: string,\n    protected readonly destinationExtension?: string,\n  ) {\n    this.signal = signal\n    this.resolvers.promise\n      .catch((e) => {\n        this.abort?.(e)\n      })\n      .finally(() => {\n        this.signal?.removeEventListener('abort', this.listener)\n      })\n    this.signal?.addEventListener('abort', this.listener)\n  }\n\n  onConnect(...args: any[]): void {\n    const [abort, context] = args\n    this.context = context\n    if (this.signal?.reason) {\n      abort(this.signal?.reason)\n      return\n    }\n\n    this.abort = abort\n  }\n\n  onHeaders(\n    statusCode: number,\n    rawHeaders: Buffer[],\n    resume: () => void,\n    statusText: string,\n  ): boolean {\n    const headers = util.parseHeaders(rawHeaders) as Record<string, string>\n\n    this.statusCode = statusCode\n\n    if (statusCode < 200) {\n      return false\n    }\n\n    if (statusCode >= 400) {\n      const err = new Error(`HTTP Error: ${statusCode} ${statusText}`)\n      ;(err as any).statusCode = statusCode\n      decorateHttpError(err, this.requestUrl, this.context?.history, this.destinationExtension)\n      this.resolvers.reject(err)\n      return false\n    }\n\n    // Check if server supports range requests\n    // 206 Partial Content indicates range request was accepted\n    // Accept-Ranges: bytes header indicates server supports range requests\n    const acceptRanges = headers['accept-ranges']\n    const contentRange = headers['content-range']\n    const contentLength = headers['content-length']\n\n    let acceptRangesFlag = false\n    let total = 0\n\n    if (statusCode === 206) {\n      // Server returned partial content, it supports range requests\n      acceptRangesFlag = true\n      // Defensive: a misbehaving server can return 206 without a\n      // Content-Range header. Without this guard, the next line would\n      // throw a raw TypeError (\"Cannot read property 'match' of\n      // undefined\") instead of a clean HTTP error.\n      if (!contentRange) {\n        this.resolvers.reject(\n          new Error(\n            `HTTP Error: 206 Partial Content with no Content-Range header (statusText=${statusText})`,\n          ),\n        )\n        return false\n      }\n      const match = contentRange.match(/bytes\\s+(\\d+)-(\\d+)\\/(\\d+|\\*)/)\n      if (match) {\n        this.position = parseInt(match[1], 10)\n        this.contentLength = parseInt(match[2], 10) - this.position + 1\n\n        if (match[3] !== '*') {\n          total = parseInt(match[3], 10)\n        }\n      }\n    } else if (statusCode === 200) {\n      // Full content returned\n      if (acceptRanges && acceptRanges.toLowerCase() === 'bytes') {\n        acceptRangesFlag = true\n      }\n      if (contentLength) {\n        this.contentLength = parseInt(contentLength, 10)\n        total = this.contentLength\n      }\n    }\n\n    this.start = this.position\n\n    this.onHeaderParsed(acceptRangesFlag, total)\n\n    resume()\n\n    return true\n  }\n\n  protected onHeaderParsed(acceptRanges: boolean, total: number) {}\n\n  private checkTermination() {\n    if (this.pending === 0) {\n      if (this.writeError) {\n        this.resolvers.reject(this.writeError)\n      } else {\n        this.resolvers.resolve()\n      }\n    }\n  }\n\n  onData(chunk: Buffer): boolean {\n    if (this.writeError) {\n      return false\n    }\n\n    this.pending++\n\n    write(this.fd, chunk, 0, chunk.length, this.position, (err, written) => {\n      this.pending--\n\n      if (err) {\n        Error.captureStackTrace(err)\n        this.writeError = err\n        this.resolvers.reject(err)\n        return\n      }\n\n      this.onWritten?.(written)\n\n      if (this.terminated) {\n        this.checkTermination()\n      }\n    })\n\n    this.position += chunk.length\n    return true\n  }\n\n  onWritten?(bytesWritten: number): void\n\n  onComplete(trailers: string[] | null): void {\n    this.terminated = true\n    this.checkTermination()\n  }\n\n  onError(err: Error): void {\n    this.terminated = true\n    this.resolvers.reject(err)\n  }\n\n  wait(): Promise<void> {\n    return this.resolvers.promise\n  }\n}\n", "\nfunction safeSet(err: Error, key: string, value: unknown): void {\n  try {\n    (err as any)[key] = value\n  } catch {\n    try {\n      Object.defineProperty(err, key, { value, configurable: true, writable: true, enumerable: false })\n    } catch {\n      // The target property is non-writable, non-configurable and the\n      // object is frozen. Accept it \u2014 better to surface the original\n      // error than to crash the error pipeline with a `TypeError:\n      // Cannot set property name of <obj> which has only a getter`\n      // (problemId \"TypeError at decorateError\" in telemetry).\n    }\n  }\n}\n\nfunction sanitizeUrl(raw: string): string | undefined {\n  try {\n    const url = new URL(raw)\n    return `${url.protocol}//${url.host}${url.pathname}`\n  } catch {\n    return undefined\n  }\n}\n\nexport function getDestinationExtension(path: string) {\n  const base = path.slice(Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\\\')) + 1)\n  const dot = base.lastIndexOf('.')\n  return dot > 0 ? base.slice(dot).toLowerCase() : ''\n}\n\n/**\n * Adds safe request context before an HTTP error is rejected. Unlike\n * `decorateError`, this runs at the handler boundary, before a rejected\n * promise can be observed by global exception telemetry.\n */\nexport function decorateHttpError(\n  err: Error,\n  requestUrl?: string,\n  redirects?: URL[],\n  destinationExtension?: string,\n) {\n  const sanitizedRedirects = redirects\n    ?.map((url) => sanitizeUrl(url.toString()))\n    .filter((url): url is string => !!url)\n  const responseUrl = sanitizedRedirects?.at(-1) ?? (requestUrl ? sanitizeUrl(requestUrl) : undefined)\n  if (responseUrl) {\n    safeSet(err, 'downloadUrl', responseUrl)\n    safeSet(err, 'downloadHost', new URL(responseUrl).host)\n  }\n  if (sanitizedRedirects?.length) {\n    safeSet(err, 'downloadRedirects', JSON.stringify(sanitizedRedirects))\n  }\n  if (destinationExtension) {\n    safeSet(err, 'downloadDestinationExtension', destinationExtension)\n  }\n}\n\nexport function decorateError(\n  err: Error,\n  urls: string[],\n  headers: Record<string, any>,\n  destination: string,\n) {\n  safeSet(err, 'name', 'DownloadError')\n  safeSet(err, 'urls', urls.join(' '))\n  safeSet(err, 'headers', headers)\n  safeSet(err, 'destination', destination)\n\n  // These fields are safe to forward to telemetry: query strings and local\n  // paths can contain credentials or personal data, so retain only origin,\n  // pathname, and file extension.\n  const sanitizedUrls = urls.map(sanitizeUrl).filter((url): url is string => !!url)\n  safeSet(err, 'downloadUrls', JSON.stringify(sanitizedUrls))\n  safeSet(err, 'downloadHosts', JSON.stringify([...new Set(sanitizedUrls.map((url) => new URL(url).host))]))\n  safeSet(err, 'downloadDestinationExtension', getDestinationExtension(destination))\n}", "import { Dispatcher } from 'undici'\nimport { DownloadController, ManagedAbortError, RangeNotSupportedError } from './controller'\nimport { FileHandler } from './file_handler'\nimport { ProgressTracker, ProgressTrackerSingle } from './progress'\n\nexport interface ControlledHandlerParams {\n  /**\n   * The whole-file expected size, used to seed progress before headers\n   * arrive. Ignored once the real size is known.\n   */\n  expectedTotal?: number\n  /**\n   * Single-stream progress tracker. Mutually exclusive with `onAdvance`\n   * (segment mode aggregates progress externally).\n   */\n  tracker?: ProgressTrackerSingle\n  /**\n   * When set, this connection is responsible only for `[start, start +\n   * total)` of the file (a range segment). The optimal-stop decision is\n   * then made relative to the segment, not the whole file.\n   */\n  segment?: { start: number; total: number }\n  /**\n   * Require a partial (`206`) response. If the server answers a ranged\n   * request with a full `200`, reject with {@link RangeNotSupportedError}\n   * instead of clobbering the shared file from offset 0.\n   */\n  requireRange?: boolean\n  /**\n   * The absolute byte offset this request asked the server to start at\n   * (the `Range: bytes=<start>-` value). If a `206` comes back starting\n   * somewhere else, the mirror mis-honoured the range; writing it would\n   * land bytes at the wrong offset, so the response is rejected.\n   */\n  requestStart?: number\n  /**\n   * Commit to finishing this connection: ignore the controller's\n   * speed-based abort and the TTFB deadline (a managed abort must never\n   * be the terminal failure once the re-roll budget is spent). Real\n   * network/HTTP errors still propagate.\n   */\n  noAbort?: boolean\n  /**\n   * Whether this origin may be aborted on TTFB/stall (a re-assignable\n   * CDN). When false (e.g. the official source) the connection is left\n   * to finish or hit the dispatcher's own timeout. Default true.\n   */\n  abortable?: boolean\n  /**\n   * Called after each write with the new absolute file offset, so a\n   * multi-segment orchestrator can aggregate overall progress.\n   */\n  onAdvance?: (absolutePosition: number) => void\n}\n\n/**\n * A single-connection file handler that periodically samples its own\n * throughput and asks a {@link DownloadController} whether to keep the\n * connection. When the controller returns `'abort'`, the handler\n * rejects with a {@link ManagedAbortError}, which `download` turns into\n * a resumed retry (re-roll) rather than a hard failure.\n *\n * It can fetch either the whole file (single resumable stream) or a\n * single byte-range segment of it (for range-split-across-mirrors). In\n * both cases an abort has a well-defined resume offset (`this.position`).\n */\nexport class ControlledFileHandler extends FileHandler {\n  private readonly origin: string\n  private readonly path: string\n  private totalSize = 0\n  private finalUrl?: string\n  private host?: string\n\n  private readonly segStart: number\n  private readonly segTotal: number\n  private readonly requireRange: boolean\n  private readonly requestStart: number\n  private readonly noAbort: boolean\n  private readonly abortable: boolean\n  private readonly advance?: (absolutePosition: number) => void\n\n  private firstByteAt = 0\n  private lastByteAt = 0\n  private windowStart = 0\n  private windowBytes = 0\n  private timer?: ReturnType<typeof setInterval>\n  private ttfbTimer?: ReturnType<typeof setTimeout>\n  private rangeRejected = false\n\n  private readonly progressInfo: ProgressTracker = { url: '', total: 0, progress: 0 }\n\n  constructor(\n    options: Dispatcher.DispatchOptions & { signal?: AbortSignal },\n    fd: number,\n    private readonly controller: DownloadController,\n    params: ControlledHandlerParams = {},\n  ) {\n    super(options.signal, fd, `${options.origin}${options.path}`)\n    this.origin = options.origin as string\n    this.path = options.path as string\n    this.segStart = params.segment?.start ?? 0\n    this.segTotal = params.segment?.total ?? 0\n    this.requireRange = params.requireRange ?? false\n    this.requestStart = params.requestStart ?? -1\n    this.noAbort = params.noAbort ?? false\n    this.abortable = params.abortable ?? true\n    this.advance = params.onAdvance\n\n    this.totalSize = this.segTotal || params.expectedTotal || 0\n    this.progressInfo.total = params.expectedTotal ?? this.totalSize\n    this.progressInfo.url = this.origin + this.path\n    if (params.tracker) {\n      params.tracker.setAccessor(this.progressInfo)\n    }\n    this.onWritten = () => {\n      this.progressInfo.progress = this.position\n      this.advance?.(this.position)\n    }\n    this.resolvers.promise.catch(() => {}).finally(() => this.clearTimers())\n\n    // The TTFB deadline stays active even in committed mode: a mirror\n    // that delivers no first byte is dead and must always be abandoned.\n    // Only re-assignable origins are worth abandoning, though.\n    const ttfb = controller.ttfbDeadline ?? 0\n    if (ttfb > 0 && this.abortable) {\n      this.ttfbTimer = setTimeout(() => {\n        if (this.firstByteAt === 0) {\n          // Connected (or redirected) but no bytes \u2014 re-roll fast.\n          this.clearTimers()\n          this.resolvers.reject(new ManagedAbortError('ttfb'))\n        }\n      }, ttfb)\n      this.ttfbTimer.unref?.()\n    }\n  }\n\n  protected override onHeaderParsed(_acceptRanges: boolean, total: number): void {\n    if (this.requireRange && this.statusCode === 200) {\n      // The mirror ignored Range and is about to stream the whole file\n      // from offset 0 \u2014 refuse before any byte lands on the shared fd.\n      this.rangeRejected = true\n      this.clearTimers()\n      this.resolvers.reject(new RangeNotSupportedError())\n      return\n    }\n    if (\n      this.requireRange &&\n      this.statusCode === 206 &&\n      this.requestStart >= 0 &&\n      this.start !== this.requestStart\n    ) {\n      // The mirror returned a different range than requested; writing it\n      // would place bytes at the wrong offset and gap the region we\n      // asked for. Reject so the caller re-rolls / falls back cleanly.\n      this.rangeRejected = true\n      this.clearTimers()\n      this.resolvers.reject(new RangeNotSupportedError())\n      return\n    }\n    if (!this.segTotal && total) {\n      this.totalSize = total\n      this.progressInfo.total = total\n    }\n    const history = this.context?.history\n    if (history && history.length > 0) {\n      const last = history[history.length - 1]\n      this.finalUrl = last.toString()\n      this.host = last.host\n      this.progressInfo.url = this.finalUrl\n    }\n  }\n\n  override onData(chunk: Buffer): boolean {\n    if (this.rangeRejected) {\n      return false\n    }\n    const now = Date.now()\n    this.lastByteAt = now\n    if (this.firstByteAt === 0) {\n      this.firstByteAt = now\n      this.windowStart = now\n      this.clearTtfb()\n      this.startSampling()\n    }\n    this.windowBytes += chunk.length\n    return super.onData(chunk)\n  }\n\n  override onComplete(trailers: string[] | null): void {\n    this.clearTimers()\n    super.onComplete(trailers)\n  }\n\n  override onError(err: Error): void {\n    this.clearTimers()\n    super.onError(err)\n  }\n\n  /**\n   * Absolute file offset reached so far on this connection. Used as the\n   * resume offset for the next attempt.\n   */\n  get offset(): number {\n    return this.position\n  }\n\n  /**\n   * Bytes received on this connection alone (excluding bytes already on\n   * disk from a previous resumed attempt).\n   */\n  get received(): number {\n    return this.position - this.start\n  }\n\n  get finalHost(): string | undefined {\n    return this.host\n  }\n\n  get resolvedUrl(): string | undefined {\n    return this.finalUrl\n  }\n\n  get total(): number {\n    return this.totalSize\n  }\n\n  private startSampling() {\n    const interval = this.controller.sampleInterval ?? 1000\n    this.timer = setInterval(() => this.sample(), interval)\n    // Do not keep the event loop alive solely for sampling.\n    this.timer.unref?.()\n  }\n\n  private clearTimer() {\n    if (this.timer) {\n      clearInterval(this.timer)\n      this.timer = undefined\n    }\n  }\n\n  private clearTtfb() {\n    if (this.ttfbTimer) {\n      clearTimeout(this.ttfbTimer)\n      this.ttfbTimer = undefined\n    }\n  }\n\n  private clearTimers() {\n    this.clearTimer()\n    this.clearTtfb()\n  }\n\n  private sample() {\n    const now = Date.now()\n    const windowMs = now - this.windowStart\n    const speed = windowMs > 0 ? (this.windowBytes / windowMs) * 1000 : 0\n    this.windowBytes = 0\n    this.windowStart = now\n\n    // Stall watchdog: first byte arrived, then no byte for stallTimeout.\n    // A stuck mid-stream mirror must be abandoned even in committed mode\n    // (otherwise the download hangs forever with no progress). Only for\n    // re-assignable origins \u2014 the official source is left to finish.\n    const stallTimeout = this.controller.stallTimeout ?? 0\n    if (\n      this.abortable &&\n      stallTimeout > 0 &&\n      this.lastByteAt > 0 &&\n      now - this.lastByteAt > stallTimeout\n    ) {\n      this.clearTimers()\n      this.resolvers.reject(new ManagedAbortError('stall'))\n      return\n    }\n\n    // In committed mode we still sample (so report() sees throughput) and\n    // keep the stall watchdog above, but never abort merely for slowness.\n    if (this.noAbort) {\n      return\n    }\n\n    const elapsed = now - this.firstByteAt\n    if (elapsed < (this.controller.warmup ?? 0)) {\n      return\n    }\n\n    // For a segment, the decision is made relative to the segment's own\n    // remaining bytes; for a whole-file stream, relative to the file.\n    const inSegment = this.segTotal > 0\n    const total = inSegment ? this.segTotal : this.totalSize\n    const received = inSegment ? this.position - this.segStart : this.position\n\n    const decision = this.controller.onSample?.({\n      origin: this.origin,\n      finalUrl: this.finalUrl,\n      host: this.host,\n      received,\n      total,\n      speed,\n      elapsed,\n    })\n\n    if (decision === 'abort') {\n      this.clearTimers()\n      // Rejecting the resolver triggers the undici abort wired up in the\n      // base FileHandler constructor; the partial bytes already written\n      // stay on disk for the resumed retry.\n      this.resolvers.reject(new ManagedAbortError('slow'))\n    }\n  }\n}\n", "import { Dispatcher } from 'undici'\nimport { ProgressTracker, ProgressTrackerSingle } from './progress'\nimport { FileHandler } from './file_handler'\nimport { RangePolicy } from './range_policy'\n\nexport class RangeRequestHandler extends FileHandler {\n  rangeInfo: ProgressTracker = {\n    total: 0,\n    progress: 0,\n    url: '',\n  }\n\n  private childrenResolvers = Promise.withResolvers<void>()\n  private children: FileHandler[] = []\n\n  constructor(\n    readonly options: Dispatcher.DispatchOptions & {\n      signal?: AbortSignal\n    },\n    readonly dispatcher: Dispatcher,\n    fd: number,\n    readonly rangePolicy: RangePolicy,\n    tracker?: ProgressTrackerSingle,\n    destinationExtension?: string,\n  ) {\n    super(options.signal, fd, `${options.origin}${options.path}`, destinationExtension)\n    // If the parent's response fails before `onHeaderParsed` runs\n    // (e.g. HTTP 4xx/5xx, malformed headers, network error), we will\n    // never spawn child range requests and the existing code paths\n    // would leave `childrenResolvers` pending forever \u2014 leaking the\n    // promise pair and preventing `tracker.done` from ever being set.\n    // Folding children to \"resolved\" on parent rejection is safe: if\n    // children were never spawned there is nothing to wait for, and\n    // if they were spawned the inner `Promise.all` wiring will settle\n    // them independently (subsequent calls on an already-settled\n    // resolver are no-ops).\n    this.resolvers.promise.catch(() => this.childrenResolvers.resolve())\n    if (tracker) {\n      tracker.setAccessor(this.rangeInfo)\n      this.rangeInfo.url = options.origin + options.path\n      Promise.allSettled([this.resolvers.promise, this.childrenResolvers.promise]).finally(() => {\n        tracker.done = true\n      })\n    }\n  }\n\n  protected override onHeaderParsed(acceptRanges: boolean, total: number): void {\n    const [origin, path] = [\n      this.context?.history?.[0]?.origin ?? this.options.origin,\n      this.context?.history?.[0]?.pathname ?? this.options.path,\n    ]\n    this.rangeInfo.total = total\n    this.rangeInfo.url = origin + path\n\n    if (!acceptRanges || total === this.contentLength) {\n      this.childrenResolvers.resolve()\n      return\n    }\n\n    const remainingStart = this.start + this.contentLength\n    const remainingEnd = total - 1\n\n    const ranges = this.rangePolicy.computeRangesInRange(remainingStart, remainingEnd)\n\n    const childrenPromises: Promise<void>[] = []\n\n    for (const range of ranges) {\n      const handler = new FileHandler(this.options.signal, this.fd, `${origin}${path}`, this.destinationExtension)\n      this.children.push(handler)\n      handler.onWritten = this.onWritten\n      childrenPromises.push(handler.wait())\n      this.dispatcher.dispatch(\n        {\n          ...this.options,\n          origin,\n          path,\n          headers: {\n            ...this.options.headers,\n            Range: `bytes=${range.start}-${range.end}`,\n          },\n        },\n        handler,\n      )\n    }\n\n    Promise.all(childrenPromises)\n      .then(() => this.childrenResolvers.resolve())\n      .catch((err) => this.childrenResolvers.reject(err))\n  }\n\n  onWritten = (bytesWritten: number) => {\n    this.rangeInfo.progress =\n      this.position - this.start + this.children.reduce((a, b) => a + b.position - b.start, 0)\n  }\n\n  override wait(): Promise<void> {\n    return Promise.all([super.wait(), this.childrenResolvers.promise]).then(() => {})\n  }\n}\n", "export interface Range {\n  start: number\n  end: number\n}\n\nexport interface RangePolicy {\n  rangeThreshold: number\n  /**\n   * Compute ranges for a specific portion of the file.\n   * @param start The start position (inclusive)\n   * @param end The end position (inclusive)\n   * @returns Array of ranges within the specified portion\n   */\n  computeRangesInRange(start: number, end: number): Range[]\n}\n\nexport function isRangePolicy(\n  rangeOptions?: RangePolicy | DefaultRangePolicyOptions,\n): rangeOptions is RangePolicy {\n  if (!rangeOptions) {\n    return false\n  }\n  return 'computeRangesInRange' in rangeOptions && typeof (rangeOptions as any).computeRangesInRange === 'function'\n}\n\nexport function resolveRangePolicy(rangeOptions?: RangePolicy | DefaultRangePolicyOptions) {\n  if (isRangePolicy(rangeOptions)) {\n    return rangeOptions\n  }\n  return new DefaultRangePolicy(\n    rangeOptions?.rangeThreshold ?? 1024 * 1024 * 5, // 5MB\n    4,\n  )\n}\n\nexport interface DefaultRangePolicyOptions {\n  /**\n   * The minimum bytes a range should have.\n   * @default 5MB\n   */\n  rangeThreshold?: number\n}\n\nexport class DefaultRangePolicy implements RangePolicy {\n  constructor(\n    public rangeThreshold: number,\n    public concurrency: number,\n  ) {}\n\n  computeRangesInRange(start: number, end: number): Range[] {\n    const total = end - start + 1\n    const { rangeThreshold: minChunkSize } = this\n    if (total <= minChunkSize) {\n      return [{ start, end }]\n    }\n    const partSize = Math.max(minChunkSize, Math.floor(total / this.concurrency))\n    const ranges: Range[] = []\n    for (let cur = start, chunkSize = 0; cur <= end; cur += chunkSize) {\n      const remain = end - cur + 1\n      if (remain >= partSize) {\n        chunkSize = partSize\n        ranges.push({ start: cur, end: cur + chunkSize - 1 })\n      } else {\n        const last = ranges[ranges.length - 1]\n        if (!last) {\n          ranges.push({ start, end })\n        } else {\n          last.end = end\n        }\n        break\n      }\n    }\n    return ranges\n  }\n}\n", "export interface ProgressTracker {\n  url: string\n  total: number\n  progress: number\n}\n\nexport class ProgressTrackerMultiple implements ProgressTracker {\n  trackers: ProgressTrackerSingle[] = []\n  expectedTotal: number = 0\n\n  subSingle(): ProgressTrackerSingle {\n    const single = new ProgressTrackerSingle()\n    this.trackers.push(single)\n    return single\n  }\n\n  get url() {\n    for (const t of this.trackers) {\n      if (!t.done) {\n        return t.url\n      }\n    }\n    return this.trackers[0]?.url ?? ''\n  }\n\n  get total() {\n    const total = this.trackers.reduce((a, b) => a + b.total, 0)\n    return total < this.expectedTotal ? this.expectedTotal : total\n  }\n\n  get progress() {\n    return this.trackers.reduce((a, b) => a + b.progress, 0)\n  }\n\n  toJSON() {\n    return {\n      url: this.url,\n      total: this.total,\n      progress: this.progress,\n    }\n  }\n}\n\n/**\n * Track progress of a download\n */\nexport class ProgressTrackerSingle implements ProgressTracker {\n  accessor?: ProgressTracker\n  expectedTotal: number = 0\n\n  done = false\n\n  constructor(readonly onDownload?: (accessor: ProgressTracker) => void) {}\n\n  setAccessor(accessor: ProgressTracker) {\n    this.accessor = accessor\n    try {\n      this.onDownload?.(accessor)\n    } catch (e) {\n      // Prevent callback errors from breaking the download\n      console.error('Error in progress callback:', e)\n    }\n  }\n\n  get progress() {\n    return this.accessor?.progress ?? 0\n  }\n\n  get total() {\n    return this.accessor?.total ?? this.expectedTotal\n  }\n\n  get url() {\n    return this.accessor?.url ?? ''\n  }\n\n  toJSON() {\n    return {\n      url: this.url,\n      total: this.total,\n      progress: this.progress,\n    }\n  }\n}\n"],
  "mappings": "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",
  "names": ["_a", "_a", "e"]
}
