Reference

API

JSZipp's public surface is intentionally small and stream-native. There is no mutable archive object: you write with ZipWriter (or ZipTransformStream) and read with openZip (or readZipStream). Everything else is an option or a returned entry.

Which API should I use?

Pick the entry point by what you are doing and what shape of output or iteration you want. The two writers share the same encoder options; the two readers share the same ZipReadOptions.

NeedUseWhy
Create a ZIP Blobnew ZipWriter({ outputAs: "blob" })Easiest path for downloads and uploads.
Create a ZIP HTTP Responsenew ZipWriter({ outputAs: "response" })Returns a native Response with Content-Type: application/zip.
Create a byte streamnew ZipWriter()Default output is ReadableStream<Uint8Array>.
Create raw bytes synchronouslywriter.writeSync() / closeSync()In-memory inputs only; no await.
Plug into a Web Streams pipelinenew ZipTransformStream()TransformStream of entries in, bytes out.
Open a user-supplied ZIPopenZip(source, options)Random-access reader for Blob, File, Uint8Array, or ArrayBuffer.
Iterate archive order oncereadZipStream(stream, options)Async iterator with single-use entry payloads.

Importing

Every runtime value is a named export. A default JSZipp namespace bundles the runtime API for callers who prefer one object.

import JSZipp, {
  ZipWriter,
  ZipTransformStream,
  openZip,
  readZipStream,
  TimestampMode
} from "web-jszipp";

// Named imports and the namespace are equivalent:
const a = new ZipWriter();
const b = new JSZipp.ZipWriter();

new ZipWriter(options?)

The primary way to build an archive. Append entries with add() and finish with close(); the value close() resolves to is determined by outputAs. For in-memory inputs that do not need await, use the synchronous writeSync() / closeSync() pair instead.

Returns ZipWriter<T> Since v0.1.0
const writer = new ZipWriter({
  level: 6,            // 0–9, default 6
  zip64: "auto",       // "auto" | "force" | "off"
  outputAs: "blob",    // "stream" | "blob" | "response" | "uint8array" | "arraybuffer"
  pathMode: "strict",  // "unsafe" (default) | "strict" | "sanitize" | "strict-package"
  timestamps: TimestampMode.Dos | TimestampMode.Unix, // default; OR in TimestampMode.Ntfs for NTFS
  comment: "built with jszipp",
  onProgress(p) { console.log(p.phase, p.loaded); }
});

await writer.add({ path: "hello.txt", data: "Hello World\n" });
await writer.add({ path: "nested/data.json", data: JSON.stringify({ ok: true }) });

const zipBlob = await writer.close(); // Blob, because outputAs === "blob"

Constructor options

ZipWriterOptions extends the shared ZipEncoderOptions with two output-only fields. All options are optional. Every option that affects the ZIP file specification itself (level, zip64, comment, timestamps, pathMode, explicitDirectoryEntries) lives on ZipEncoderOptions, so ZipWriter and ZipTransformStream share it; only outputAs and mimeType are writer-specific.

OptionTypeDefaultDescription
outputAs"stream" | "blob" | "response" | "uint8array" | "arraybuffer""stream"Shape returned by close() / closeSync().
mimeTypestring"application/zip"Content-Type used by outputAs: "response".
levelnumber6DEFLATE level. Integer 0–9.
zip64"auto" | "force" | "off""auto"When to emit ZIP64 records.
commentstring""Archive-level (EOCD) comment.
timestampsnumber (bitmask of TimestampMode)Dos | UnixWhich modification-time fields to write.
pathMode"unsafe" | "strict" | "sanitize" | "strict-package""unsafe"Write-side path policy. See path modes.
explicitDirectoryEntriesbooleanfalseMaterializes parent directory entries.
signalAbortSignalCancels between stream reads and structure steps.
onProgress(p: ZipProgress) => voidCoarse progress callback. See progress.
outputAs — choosing the output shape

The default output is a byte stream. The other modes are conveniences built on top of it: close() drives the same encoder and then wraps the result. The return type is inferred from the type argument, so TypeScript knows that new ZipWriter({ outputAs: "blob" }) resolves close() to a Blob.

"stream" (default)
ReadableStream<Uint8Array>. close() resolves immediately; bytes are pulled as the consumer reads.
"blob"
Blob. Ideal for object-URL downloads and FormData uploads.
"response"
A native Response whose body is the stream, tagged with mimeType.
"uint8array"
A single Uint8Array with the whole archive.
"arraybuffer"
The backing ArrayBuffer of that byte array.
// Stream straight into an upload without buffering the whole archive first.
const writer = new ZipWriter(); // default "stream"
const upload = fetch("/upload", { method: "POST", body: writer.output });
await writer.add({ path: "log.txt", data: bigLogBlob });
await writer.close();
await upload;
level & per-entry method — compression control

level sets the default DEFLATE effort for the writer; an individual entry may override it with its own level. The value must be an integer from 0 to 9, or a RangeError is thrown.

  • level: 0, directory entries, and method: "store" are written uncompressed (ZIP method 0x0000).
  • With no explicit method, JSZipp attempts DEFLATE but stores the entry instead when the compressed payload would be no smaller than the source.
  • An explicit method: "deflate" always writes a DEFLATE entry (method 0x0008), even if that is slightly larger.

The ZIP compression-method field is per entry. A DEFLATE entry may still contain internal stored blocks for incompressible runs; that does not change the entry method from 0x0008 to 0x0000. ZIP metadata does not record the DEFLATE level, so a reader cannot report the level an archive was written with.

const writer = new ZipWriter({ level: 6 });

await writer.add({ path: "report.txt", data: text });               // DEFLATE or store fallback
await writer.add({ path: "already.png", data: png, method: "store" }); // never recompress
await writer.add({ path: "huge.log", data: log, level: 9 });        // override the writer level
zip64 — large-archive framing

ZIP64 records remove the classic 4 GiB / 65 535-entry ceilings. JSZipp implements ZIP64 framing itself rather than delegating to a ZIP dependency.

"auto" (default)
Emit ZIP64 records only when entry sizes, the entry count, or Central Directory placement exceed standard limits.
"force"
Always emit ZIP64 records.
"off"
Never emit ZIP64. If the archive would need it, close() throws a RangeError.

When ZIP64 is emitted, only the saturated 32-bit slots are carried in the extra field: the local header holds the uncompressed and compressed sizes (16 data bytes); the Central Directory header additionally carries the local-header offset (24 data bytes). 64-bit values beyond Number.MAX_SAFE_INTEGER are rejected.

timestamps & reproducible output

Each entry's modifiedAt is written to the legacy DOS date/time fields as local wall-clock time. When timestamps includes TimestampMode.Unix (the default), the UTC mtime is also written to the Extended Timestamp extra field (0x5455) so timezone is preserved. Readers prefer 0x5455 and fall back to the DOS fields.

Pass a bitmask that ORs TimestampMode.Dos (1), TimestampMode.Unix (2), and TimestampMode.Ntfs (4). Values outside 0–7 are rejected.

Every ZIP entry already has a local file header before the file data and a Central Directory header near the end of the archive. The timestamp byte counts below are additional extra-field bytes written into those existing per-entry metadata locations; they do not include the base headers, filename bytes, comments, ZIP64 records, EOCD records, or compressed file data. In many-small-file archives this can make JSZipp's total larger than libraries that omit UTC timestamp extras, even when the compressed payloads are comparable.

timestamps Extra timestamp bytes/entry mtime precision createdAt / lastAccess unixPermissions dosAttributes
Dos02 s, localnot storedrejectedallowed
Dos | Unix (default)+181 s, UTCnot storedallowedrejected
Dos | Ntfs+72100 ns, UTCstored; defaults to mtimerejectedallowed
Dos | Unix | Ntfs+90100 ns, UTCstored; defaults to mtimeallowedallowed

TimestampMode.Unix writes a 9-byte 0x5455 record in both the local and central headers. TimestampMode.Ntfs writes a 36-byte 0x000a record in both headers for modification, access, and creation FILETIMEs. dosAttributes is rejected for Dos | Unix because a Unix-host archive carrying DOS attribute bits would confuse Unix-oriented tools.

For byte-identical (reproducible) archives, supply an explicit modifiedAt for every entry. When omitted it defaults to new Date() at write time, which is not reproducible.

const epoch = new Date("2020-01-01T00:00:00Z");
const writer = new ZipWriter({ outputAs: "uint8array" });
await writer.add({ path: "a.txt", data: "A", meta: { modifiedAt: epoch } });
await writer.add({ path: "b.txt", data: "B", meta: { modifiedAt: epoch } });
const bytes = await writer.close(); // byte-identical across runs
explicitDirectoryEntries — parent directory entries

When true, each parent directory implied by an entry's path is written as a standalone entry. For example, a/b/c.txt also emits a/ and a/b/.

The default keeps the historical behavior: only caller-added directory entries are written. JSZipp never scans for empty directories; add those explicitly.

Methods & properties

MemberSignatureDescription
add(entry: ZipInputEntry) => Promise<void>Append one entry. Accepts string, bytes, Blob, or stream data.
close() => Promise<ZipWriterCloseResult<T>>Finish the archive and resolve to the outputAs shape.
writeSync(entry: ZipSyncInputEntry) => voidSynchronous add() for in-memory data only.
closeSync() => ZipWriterCloseResult<T>Synchronous close(); returns the same shape without awaiting.
outputReadableStream<Uint8Array>The live byte stream, available before close().
Async mode vs sync mode (and why mixing throws)

A writer runs in exactly one mode. add() / close() form the async mode and accept any supported data, including Blob and ReadableStream. writeSync() / closeSync() form the sync mode and accept only string, Uint8Array, and ArrayBuffer — values that can be read without awaiting.

Mixing the two would route some chunks to the stream and others to the sync buffer, silently dropping entries, so the second mode throws an InvalidStateError (DOMException). Re-using a closed writer also throws InvalidStateError.

// Sync path — no awaits, returns immediately.
const writer = new ZipWriter({ outputAs: "uint8array" });
writer.writeSync({ path: "a.txt", data: "A" });
writer.writeSync({ path: "b.txt", data: "B" });
const bytes = writer.closeSync(); // Uint8Array

// writer.add(...) here would throw InvalidStateError: modes cannot mix.
Path normalization & duplicate rejection

Before pathMode runs, writer paths are normalized: backslashes become /, leading / characters are stripped, and a path ending in / is treated as a directory entry. After normalization, writing the same normalized path twice is rejected with a SecurityError in every path mode.

await writer.add({ path: "docs\\guide.md", data: md }); // stored as docs/guide.md
await writer.add({ path: "/photos/", data: "" });       // directory entry "photos/"
// await writer.add({ path: "photos/" }) again -> SecurityError (duplicate)

Examples

// Downloadable archive.
const writer = new ZipWriter({ outputAs: "blob" });
await writer.add({ path: "hello.txt", data: "Hello from JSZipp\n" });
const blob = await writer.close();

const url = URL.createObjectURL(blob);
Object.assign(document.createElement("a"), { href: url, download: "hello.zip" }).click();
URL.revokeObjectURL(url);
// HTTP response (e.g. inside a service worker or server handler).
const writer = new ZipWriter({ outputAs: "response", mimeType: "application/zip" });
await writer.add({ path: "data.csv", data: csvText });
return writer.close(); // a native Response, streamed to the client

new ZipTransformStream(options?)

A TransformStream whose writable side accepts ZipInputEntry objects and whose readable side produces archive bytes. Use it when a Web Streams pipeline is more natural than ZipWriter. It takes the same ZipEncoderOptions as the writer (no outputAs / mimeType).

Returns TransformStream<ZipInputEntry, Uint8Array> Since v0.1.0
const zipper = new ZipTransformStream({ level: 6 });
const writer = zipper.writable.getWriter();

const upload = fetch("/upload", {
  method: "POST",
  body: zipper.readable,
  headers: { "Content-Type": "application/zip" }
});

await writer.write({ path: "hello.txt", data: "Hello from a stream\n" });
await writer.close();
await upload;
Note: the output is stream-shaped, but each entry's payload and its compressed bytes are still materialized in memory before that entry's records are emitted.

openZip(source, options?)

Reads a complete archive and returns a random-access reader. The source is materialized as bytes, the End of Central Directory is located by content, and the Central Directory is used as the source of truth. Entries can then be listed, looked up by path, and read repeatedly.

Returns Promise<ZipRandomAccessReader> Since v0.1.0
const zip = await openZip(file, {
  pathMode: "strict-package",        // strict + cross-entry checks for untrusted input
  maxArchiveSize: 50 * 1024 * 1024,  // reject archives larger than 50 MiB
  maxEntrySize: 10 * 1024 * 1024     // cap each decompressed entry at 10 MiB
});

console.log(zip.entries.map((e) => e.path));
const text = await zip.get("README.md")?.text();
await zip.close();

Arguments

NameTypeDescription
sourceBlob | File | Uint8Array | ArrayBufferThe archive to read. Materialized as bytes before parsing.
optionsZipReadOptionsReader options, shared with readZipStream.

ZipReadOptions

OptionTypeDefaultDescription
pathMode"strict" | "sanitize" | "unsafe" | "strict-package""strict"Read-side path policy. See path modes.
filenameEncoding"cp437" | charset label | TextDecoder-like"utf-8"Fallback decoder for legacy (non-UTF-8-flagged) names.
maxArchiveSizenumberMaximum input archive byte length. Exceeding it throws RangeError.
maxEntrySizenumberMaximum decompressed size per entry, enforced during inflate. Exceeding it throws RangeError.
signalAbortSignalCancellation between structure steps.
onProgress(p: ZipProgress) => voidCoarse progress callback.
filenameEncoding — decoding legacy filenames

JSZipp follows ZIP metadata first: if a valid Info-ZIP Unicode Path extra field (0x7075) is present and its embedded CRC-32 matches the header name bytes, its UTF-8 name is used; otherwise, if the ZIP UTF-8 flag is set, names decode as UTF-8. filenameEncoding only applies when the UTF-8 flag is absent, and the default fallback is "utf-8". It affects entry paths, entry comments, and the archive comment — never file contents.

It accepts "cp437", any charset label the runtime's TextDecoder supports, or a custom TextDecoder-shaped object:

// A built-in label:
const a = await openZip(file, { filenameEncoding: "shift_jis" });

// A custom decoder-shaped object:
const b = await openZip(file, {
  filenameEncoding: {
    encoding: "cp866",
    fatal: false,
    ignoreBOM: true,
    decode: (bytes) => iconv.decode(bytes, "cp866")
  }
});
maxArchiveSize / maxEntrySize — zip-bomb caps

These caps are for untrusted input. maxArchiveSize bounds the input byte length. maxEntrySize bounds each entry's decompressed size and is enforced during inflate (bounded reading), so a header that misreports its uncompressed size cannot expand past the cap. Breaching either throws a RangeError.

try {
  const zip = await openZip(untrusted, {
    maxArchiveSize: 20 * 1024 * 1024,
    maxEntrySize: 5 * 1024 * 1024
  });
} catch (err) {
  if (err instanceof RangeError) {
    // archive or an entry exceeded the configured limit
  }
}
Integrity & tamper checks strict by default

openZip requires the Central Directory to be internally consistent: the number of records must equal the EOCD (or ZIP64 EOCD) entry count and must consume exactly the declared directory size, or parsing throws. The EOCD is chosen by content, so an EOCD-like sequence hidden in the archive comment, or a fake EOCD appended after a complete archive, cannot mask the real entries.

Each entry is also cross-checked against its local file header. A local/central filename mismatch, a disagreement in the security-relevant flag bits (encryption, data descriptor), and two central entries reusing the same local-header offset all throw. These checks do not affect archives whose local and central metadata agree.

Duplicate paths are preserved in append order; the default reader does not reject them. Encrypted entries and unsupported compression methods throw NotSupportedError.

ZipRandomAccessReader

The object openZip resolves to.

MemberType / SignatureDescription
entriesreadonly ZipRandomAccessEntry[]All entries in archive (append) order, duplicates preserved.
commentstring | undefinedThe archive-level EOCD comment, when present.
get(path: string) => ZipRandomAccessEntry | undefinedThe most recently appended matching entry; also tries the writer-style normalized form of the path.
close() => Promise<void>Marks the reader closed and clears lookup state; later payload access throws InvalidStateError.

readZipStream(stream, options?)

An async iterator over archive entries in order. It accepts the same ZipReadOptions as openZip. Each yielded entry's payload methods are single-use: read it, or call skip(), before moving on.

Returns AsyncIterable<ZipStreamEntry> Since v0.1.0
const response = await fetch("/archives/content.zip");

for await (const entry of readZipStream(response.body, { maxEntrySize: 5 * 1024 * 1024 })) {
  if (entry.isDirectory) continue;

  if (entry.path.endsWith(".txt")) {
    console.log(entry.path, await entry.text());
  } else {
    await entry.skip(); // consume the payload you do not need
  }
}
Note: the current implementation collects the source stream and parses the Central Directory before iterating, to avoid ambiguous local-header parsing while the lower-level streaming decoder is hardened. The iterator contract is forward-only.

ZipInputEntry

The object passed to ZipWriter.add() and written to a ZipTransformStream.

FieldTypeDescription
pathstringEntry name. Normalized, then checked against pathMode.
datastring | Uint8Array | ArrayBuffer | Blob | ReadableStream<Uint8Array>Entry contents. Strings are encoded as UTF-8.
method"store" | "deflate"Optional per-entry compression method override.
levelnumberOptional per-entry DEFLATE level (0–9), overriding the writer's.
metaZipEntryMetaOptional comment, timestamp, and attribute metadata.

ZipSyncInputEntry (used by writeSync()) is identical except that data is limited to string | Uint8Array | ArrayBuffer — the values that can be read without awaiting.

ZipEntryMeta

Optional metadata supplied on write and exposed on read.

FieldTypeDescription
commentstringPer-entry comment (informational; does not affect extraction).
modifiedAtDateModification time.
createdAtDateCreation time.
lastAccessDateLast-access time.
extraFieldUint8ArrayAdvanced, unchecked extra-field override.
unixPermissionsnumberUnix store permission bits.
dosAttributesnumberMS-DOS attribute byte.
externalAttributesnumberEscape-hatch external attributes override.
modifiedAt, createdAt, lastAccess — timestamp validation

modifiedAt, createdAt, and lastAccess must be valid Date values on or after the Unix epoch. modifiedAt defaults to write time when omitted.

When createdAt is supplied, neither modifiedAt nor lastAccess may be earlier than it; an inconsistent entry throws RangeError. When timestamps includes TimestampMode.Ntfs, omitted createdAt and lastAccess values each default to modifiedAt.

unixPermissions & dosAttributes — permission metadata

To set permissions, prefer unixPermissions over externalAttributes. Use three octal digits 0o0000o777 (e.g. 0o644 or 0o755); file-type bits are added automatically. Out-of-range or non-integer values are rejected.

unixPermissions is accepted only when the timestamps mode includes TimestampMode.Unix (the default does); setting it without that flag throws RangeError. When an entry records a Unix store permission — via unixPermissions, a written Unix Extended Timestamp, or raw externalAttributes bits — its Central Directory header advertises the Unix host OS (3) in "version made by" so external tools apply those permissions; otherwise the DOS host (0) is used.

dosAttributes is the DOS-attribute counterpart: the MS-DOS attribute byte (0x000xff) written into the low 8 bits of the external attributes. The directory bit 0x10 encodes the file/folder distinction and must match the entry kind; a mismatch throws RangeError.

DOS attributes suit a DOS or NTFS host but would confuse Unix tools, so they are accepted for the Dos, Dos | Ntfs, and Dos | Unix | Ntfs modes and rejected when the Unix flag is set without the NTFS flag (Dos | Unix). With both Unix and Ntfs set, the external attributes carry the Unix mode (high 16 bits) and the DOS attributes (low byte) together. dosAttributes does not affect "version made by".

extraField & externalAttributes — unchecked overrides

Caution: extraField and externalAttributes are unchecked manual overrides. JSZipp writes them as supplied and cannot detect every conflict with the entry kind or with the metadata it generates, so an inconsistent value can corrupt the archive.

extraField must contain raw, well-formed ZIP extra-field bytes (id(2)+size(2)+payload records). JSZipp writes those raw records before its own generated extras such as ZIP64, Extended Timestamp, and NTFS. It will not add a generated timestamp extra whose id already appears in the supplied bytes, so callers are responsible for emitting well-formed, non-conflicting records.

externalAttributes writes raw 32-bit external attributes verbatim (high 16 bits = Unix mode, low 8 bits = DOS attribute flags). It overrides unixPermissions and dosAttributes and is not reconciled with the entry's directory bit. Use it only to round-trip an exact value read from another archive.

On read, JSZipp exposes only the raw externalAttributes; derive the Unix mode with externalAttributes >>> 16 and the MS-DOS attribute byte with externalAttributes & 0xff.

Reader entries

Reading yields entries with metadata plus four payload helpers: stream(), text(), bytes(), and arrayBuffer(). Both entry types extend ZipEntryMeta.

ZipRandomAccessEntry (from openZip)

Payload helpers are reusable — read the same entry as many times as you like until the reader is closed.

MemberType / SignatureDescription
pathstringDecoded entry name.
sizenumberUncompressed size in bytes.
compressedSizenumberStored (compressed) size in bytes.
crc32numberCRC-32 of the uncompressed data.
isDirectorybooleanWhether the entry is a directory.
stream() => ReadableStream<Uint8Array>A fresh byte stream of the decompressed contents.
text() => Promise<string>Decode the contents as UTF-8 text.
bytes() => Promise<Uint8Array>The decompressed bytes.
arrayBuffer() => Promise<ArrayBuffer>The decompressed bytes as an ArrayBuffer.

ZipStreamEntry (from readZipStream)

The same shape, with two differences: size, compressedSize, and crc32 may be null when unknown up front, and the payload helpers are single-use. After any of stream(), text(), bytes(), arrayBuffer(), or skip() is called, calling another throws InvalidStateError.

MemberType / SignatureDescription
sizenumber | nullUncompressed size, when known.
compressedSizenumber | nullCompressed size, when known.
crc32number | nullCRC-32, when known.
isDirectorybooleanWhether the entry is a directory.
skip() => Promise<void>Discard this entry's payload so iteration can advance.
stream() · text() · bytes() · arrayBuffer()As above, but each entry's payload may be read only once.

Path modes

pathMode governs how unsafe entry names are handled. It runs on both the writer (after path normalization) and the reader. The defaults differ on purpose: writing defaults to "unsafe" to preserve legacy behavior, while reading defaults to "strict" so that untrusted archives are safe out of the box.

ModeBehavior
"strict"Reject unsafe paths with SecurityError.
"sanitize"Strip the unsafe components instead of rejecting; a path that sanitizes to empty is rejected.
"unsafe"Opt out of path rejection. The writer still applies normalization; the reader exposes raw archive names.
"strict-package""strict" plus package-level checks.
"strict" / "sanitize" — unsafe path handling

Unsafe paths include .. segments, absolute paths, drive-letter paths (including drive-relative names like C:name), backslash-separated paths on read, and any path containing a NUL byte.

"strict" rejects these paths with SecurityError. "sanitize" strips unsafe components instead, but rejects the path if the result is empty.

What "strict-package" adds uploads · packages · CI

This is an opt-in profile for archives crossing a trust boundary. Beyond strict per-path safety, it adds two cross-entry checks the default deliberately omits to preserve documented behavior:

  • Local/central size cross-check. With general-purpose bit 3 clear, the local and central sizes must agree. Data-descriptor entries (bit 3 set) are exempt.
  • Collision rejection. Entry paths that collide after Unicode (NFC) and case normalization are rejected — exact duplicates, case-only twins like Readme.txt / README.TXT, and NFC/NFD twins.

The default reader still preserves duplicate paths and defers size integrity to read time; only "strict-package" rejects them.

Progress & cancellation

All four entry points accept a signal (AbortSignal) and a coarse onProgress callback. Cancellation is checked between stream reads and ZIP structure steps, not inside synchronous DEFLATE work, so it is best-effort rather than instantaneous.

ZipProgress

FieldTypeDescription
phase"read" | "compress" | "write" | "parse"Which stage produced the update.
loadednumberBytes processed so far in this phase.
totalnumber | undefinedExpected total, when known.
entriesnumber | undefinedEntries processed so far, when applicable.
pathstring | undefinedThe entry path being processed, when applicable.
const controller = new AbortController();
const writer = new ZipWriter({
  signal: controller.signal,
  onProgress: ({ phase, loaded, total }) => {
    if (total) console.log(`${phase}: ${Math.round((loaded / total) * 100)}%`);
  }
});
// controller.abort() rejects the in-flight add()/close() with an AbortError.

Errors & diagnostics

JSZipp keeps the category of an exception stable across builds, even though the human-readable message differs between development and production. Branch on the exception type and the DOMException name — never on exact message text.

ConditionThrows
Unsafe or duplicate entry pathDOMException name "SecurityError"
Encrypted entry or unsupported compression methodDOMException name "NotSupportedError"
Runtime missing deflate-raw supportDOMException name "NotSupportedError"
Re-using a closed writer/reader, or mixing writer modes, or re-reading a single-use stream entryDOMException name "InvalidStateError"
maxArchiveSize / maxEntrySize breach, ZIP64 disabled but required, or a 64-bit value beyond safe-integer rangeRangeError
Invalid level (not an integer 0–9)RangeError
Corrupt structure, inconsistent Central Directory, or inflated-size mismatchError (corrupt-stream / structure error)

In production builds, error.message is shortened to stable codes such as E_PATH, E_LIMIT, E_STRUCTURE, E_ZIP64, and E_UNSUPPORTED to keep the bundle small. Development builds keep the detailed messages used by the tests. Because the message text is build-dependent, robust handling looks at the type and name:

try {
  const zip = await openZip(file, { maxEntrySize: 5 * 1024 * 1024 });
} catch (err) {
  if (err instanceof DOMException && err.name === "SecurityError") {
    // unsafe path under the active pathMode
  } else if (err instanceof DOMException && err.name === "NotSupportedError") {
    // encrypted or unsupported method
  } else if (err instanceof RangeError) {
    // exceeded a configured limit
  } else {
    // corrupt or invalid archive
  }
}

Default namespace

The default export is a JSZipp object bundling the runtime API values, for callers who prefer a single namespace over named imports.

import JSZipp from "web-jszipp";

JSZipp.ZipWriter;          // class
JSZipp.ZipTransformStream; // class
JSZipp.openZip;            // function
JSZipp.readZipStream;      // function
JSZipp.TimestampMode;      // timestamp bit flags

ZipSyncInputEntry is exported as a named type for the synchronous writer path but is not part of the default namespace object because TypeScript types do not exist at runtime.

See also: How to / examples for end-to-end recipes, and Performances / limitations for memory and streaming boundaries.