Luxar Viewer API Documentation - v2026.10.19
    Preparing search index...

    A unzipit Reader over HTTP, structurally typed so neither unzipit nor its types need to become a direct dependency.

    Index
    MAX_RETAINED_BYTES: number = ...

    Backstop so a pathological archive (a huge comment, a colossal directory) cannot balloon the heap. The preamble is ~141 kB at a thousand members and scales at ~70 B/member, so this holds a very large directory and still refuses to hold a whole archive.

    url: string
    lifetime?: AbortSignal

    Aborted when the owning store is disposed; cancels reads in flight.

    • Arm or disarm retention of fetched ranges.

      Armed by LuxarZipStore around the directory read and disarmed afterwards, so what survives is the archive's structure — not its data.

      Parameters

      • on: boolean

      Returns void

    • Fetch the archive tail with ONE suffix GET (bytes=-65557), taking the total length from Content-Range.

      Opening used to cost three serial round trips — HEAD for identity, a length lookup, then the fixed 65,557-byte tail — before the first member could be named. The suffix range answers all three: Content-Range carries the total, the body IS the tail unzipit reads next (and, for all but huge archives, the central directory inside it), and when the identity probe already did this GET there is nothing left to fetch at all.

      Anything but a valid tail 206 — a 416 (empty archive, or suffix ranges refused), a 200, a window that is not the tail — falls back to the getLength + explicit-offset path rather than failing, so only a host that really cannot serve ranges is reported as one, by the checks that already word that precisely. Missing/denied archives still fail here, as they would there.

      Returns Promise<void>

    • Read ONE member with a single ranged GET, then run body — the unzipit member read — against it.

      unzipit reads a member in two strictly serial requests: the 30-byte local header (to learn where the payload starts), then the payload. On a 100 ms RTT host that doubled the cost of every chunk. The caller sizes one window from the CENTRAL directory — local header, name, extra field plus slack, compressed payload — so both reads are answered from memory. A local extra field that outgrows the slack simply misses the window for the payload read, which then goes to the network as before: slower, never wrong.

      Type Parameters

      • T

      Parameters

      • offset: number
      • size: number
      • body: () => Promise<T>
      • Optionalpriority: FetchPriority | FetchPriorityCell

        Gate class for the window fetch (the member's caller knows whether a frame is waiting on it; unzipit's own reads do not).

      • Optionalsignal: AbortSignal

        The member caller's abort signal. It cancels the window fetch — queued in the gate or in flight — on top of the reader's lifetime, so a superseded view stops holding a slot. unzipit's follow-up reads are answered from the window, or go out under the lifetime alone.

      Returns Promise<T>

    • Record what a fresh HEAD already told us, so getLength does not repeat it. The identity probe and the length lookup ask the same question of the same URL; paying for it twice adds a serialised round trip to every load.

      Parameters

      • length: number

      Returns void

    • Fresh identity of the archive, bypassing every cache — ETag, else Last-Modified + Content-Length. null means "cannot tell", which is never evidence that the archive changed.

      Lives here rather than in the caller because it is a HEAD on this exact URL: doing it here lets the length it reports seed getLength.

      Parameters

      • Optionalsignal: AbortSignal
      • OptionaltimeoutMs: number

      Returns Promise<string | null>

    • Total archive size.

      Prefers HEAD, but falls back to a one-byte ranged GET when HEAD is rejected or answers without a usable Content-Length — some static hosts and signed-URL schemes allow only GET. The fallback doubles as an early probe: a host that answers it with 200 is telling us it ignores Range, and we would rather say so here than at the first chunk.

      Both requests go through fetchWithRetry like every other read here: the metadata lane of the fetch gate, the retry budget and its timeouts, cache: 'no-store', and the reader's lifetime signal. An unread body (the whole archive, from a host that ignores Range) is cancelled by it.

      Returns Promise<number>

    • Read size bytes at offset, insisting on a real partial response.

      Parameters

      • offset: number
      • size: number
      • Optionalsignal: AbortSignal

      Returns Promise<Uint8Array<ArrayBuffer>>