Stuk/jszip
Create, read and edit .zip files with Javascript
Stale — last commit 1y ago
non-standard license (Other); last commit was 1y ago
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
last commit was 1y ago; Scorecard "Branch-Protection" is 0/10
- ⚠Stale — last commit 1y ago
- ⚠Single-maintainer risk — top contributor 81% of recent commits
- ⚠Non-standard license (Other) — review terms
- ⚠Scorecard: marked unmaintained (0/10)
- ⚠Scorecard: default branch unprotected (0/10)
- ✓14 active contributors
- ✓Other licensed
- ✓CI configured
- ✓Tests present
What would improve this?
- →Use as dependency Concerns → Mixed if: clarify license terms
- →Deploy as-is Mixed → Healthy if: 1 commit in the last 180 days
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests + OpenSSF Scorecard
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/stuk/jszip)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card
This card auto-renders when someone shares https://repopilot.app/r/stuk/jszip on X, Slack, or LinkedIn.
Ask AI about stuk/jszip
Grounded in the actual source code. Pick a starter question or write your own.
Onboarding doc
Onboarding: Stuk/jszip
Generated by RepoPilot · 2026-06-21 · Source
🎯Verdict
WAIT — Stale — last commit 1y ago
- 14 active contributors
- Other licensed
- CI configured
- Tests present
- ⚠ Stale — last commit 1y ago
- ⚠ Single-maintainer risk — top contributor 81% of recent commits
- ⚠ Non-standard license (Other) — review terms
- ⚠ Scorecard: marked unmaintained (0/10)
- ⚠ Scorecard: default branch unprotected (0/10)
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests + OpenSSF Scorecard</sub>
⚡TL;DR
JSZip is a pure JavaScript library that creates, reads, and edits .zip files entirely in the browser and Node.js without native dependencies. It uses pako for deflate/inflate compression, handles ZIP file format parsing per APPNOTE.TXT spec, and exposes a fluent API for adding files/folders, generating zip blobs asynchronously, and loading existing archives. Modular single-library structure: lib/index is the main entry point (Node.js), dist/jszip.min.js is the browserified build, documentation/ holds Jekyll-based API docs organized by JSZip class, ZipObject class, and StreamHelper class. Test suite in test/asserts/ (Node via qunit) and browser tests via test/run.js. Grunt handles build pipeline (browserify, uglify).
👥Who it's for
Web developers building file export features (e.g., bulk download tools, report generators), Electron/Node.js developers needing cross-platform zip manipulation, and full-stack engineers who want to avoid server-side zip libraries for client-side archive generation.
🌱Maturity & risk
Production-ready and actively maintained: version 3.10.1 with dual MIT/GPLv3 licensing, comprehensive test suites (test-node and test-browser in package.json), GitHub Actions CI/CD (benchmark.yml, main.yml workflows), TypeScript type definitions (index.d.ts), and multiple long-term contributors listed. Last visible activity shows active benchmarking and testing infrastructure.
Low risk: minimal dependency footprint (lie, pako, readable-stream, setimmediate only), well-established compression library (pako ~1.0.2), dual licensing provides legal flexibility. Single-maintainer concern (Stuk as primary), but stable API and comprehensive test coverage reduce breaking-change risk. No indication of unresolved critical issues in visible structure.
Active areas of work
Active maintenance with CI workflows (main.yml runs tests, benchmark.yml tracks performance), TypeScript type checking integrated into test suite (tsc step), and Playwright-based browser testing infrastructure in place. Appears focused on stability and performance profiling rather than major feature additions.
🚀Get running
git clone https://github.com/Stuk/jszip.git
cd jszip
npm install
npm test
For browser dev: npm run test-browser (requires grunt build). For Node.js only: npm run test-node.
Daily commands:
Node.js: npm run test-node runs QUnit tests. Browser: npm run test-browser (builds via Grunt, runs via Playwright). Development: npx grunt build watches and builds dist/. Linting: npm run lint (ESLint). Benchmarks: npm run benchmark-node or npm run benchmark-browser.
🗺️Map of the codebase
lib/index.js— Main entry point exporting the JSZip class; every contributor must understand the public API surface and initialization flow.lib/object.js— Core ZipObject implementation defining file/folder manipulation methods; foundational for all zip content operations.lib/load.js— Handles parsing and loading existing zip files from various input formats; critical for deserialization logic.lib/generate/index.js— Orchestrates zip file generation and serialization; essential for understanding output pipeline and async flows.lib/compressions.js— Manages compression algorithms (deflate, store) and decompression integration; impacts data integrity and performance.lib/crc32.js— CRC32 checksum calculation for zip file integrity; used across load/generate paths for validation.index.d.ts— TypeScript definitions defining the public API contract; essential for understanding method signatures and type contracts.
🛠️How to make changes
Add Support for a New Compression Algorithm
- Define the new compression algorithm entry in lib/compressions.js, mapping a compression ID to compress/decompress functions (
lib/compressions.js) - Implement or import the compress/decompress functions (e.g., create lib/my-algorithm.js following the pattern of lib/flate.js) (
lib/flate.js) - Update lib/defaults.js to include the new algorithm in supported compression methods if it should be used by default (
lib/defaults.js) - Update index.d.ts TypeScript definitions to expose the new compression option in method signatures (
index.d.ts)
Add a New Input Format (e.g., custom binary format)
- Create a new reader class extending lib/reader/DataReader.js with format-specific parsing logic (
lib/reader/DataReader.js) - Update lib/load.js loadAsync() to detect and route to the new reader based on input type detection (
lib/load.js) - Export the new reader from lib/index.js and document via index.d.ts (
lib/index.js)
Extend ZipObject with a New File Manipulation Method
- Add the new method to the ZipObject class in lib/object.js, following naming conventions (e.g., fileWithEncryption, folderWithMetadata) (
lib/object.js) - Update lib/generate/ZipFileWorker.js if the method changes how metadata or file entries are serialized (
lib/generate/ZipFileWorker.js) - Add TypeScript signature to index.d.ts under the ZipObject interface (
index.d.ts) - Add unit tests in test/asserts/ directory following existing test patterns (
test/asserts/)
Optimize or Replace a Core Algorithm
- Locate the current implementation (e.g., lib/crc32.js, lib/compressions.js, or lib/generate/ZipFileWorker.js) (
lib/crc32.js) - Add benchmark tests in test/benchmark/node.js and test/run.js to measure before/after performance (
test/benchmark/node.js) - Replace or refactor the implementation, maintaining the same function signature (
lib/crc32.js) - Run npm run test and npm run benchmark to validate correctness and measure improvement (
package.json)
🔧Why these technologies
- JavaScript/TypeScript — Universal browser and Node.js compatibility; enables client-side and server-side zip manipulation without external binaries.
- DEFLATE compression (via pako/flate.js) — Standard zip compression format; ensures compatibility with all zip readers across platforms.
- Async/await and Promises — Prevents blocking on large zip operations; critical for browser responsiveness and Node.js stream integration.
- Stream adapters (Node.js & browser polyfill) — Enables efficient memory usage for large files by processing data in chunks rather than loading entire zip into RAM.
- CRC32 checksums — Data integrity verification; detects corruption during read/write cycles as per ZIP specification.
⚖️Trade-offs already made
-
Pure JavaScript instead of native/WASM compression
- Why: Simplicity, zero dependencies, browser compatibility out-of-the-box
- Consequence: Slower compression/decompression than native implementations; users can inject faster algorithms via lib/external.js
-
Reader abstraction layer (DataReader, ArrayReader, NodeBufferReader)
- Why: Decouple input parsing from specific data types; support browsers, Node.js, and future platforms uniformly
- Consequence: Slight performance overhead from abstraction; enables universal compatibility
-
Synchronous streaming (not true streaming reads during load)
- Why: Simpler API; ZIP format requires random access to central directory at end of file
- Consequence: Must load entire zip into memory before parsing; better streaming approach would require pre-computed offsets
-
Optional external library injection (lib/external.js)
- Why: Minimal core dependencies while allowing power users to customize compression/streams
- Consequence: Increased code paths to test; users must manage compatibility of injected libraries
🚫Non-goals (don't propose these)
- Encryption/decryption of password-protected zips (no encryption support documented)
- Sparse file handling or special permissions preservation
- Real-time streaming reads during zip parsing (entire file must load first)
- Zip64 extensions for files >4GB (standard 32-bit zip limits)
- Support for legacy or non-standard zip formats (ZIP spec compliant only)
🪤Traps & gotchas
No exotic traps, but note: (1) Dual-build output — lib/ is CommonJS/Node.js, dist/ is Browserified; ensure changes to lib/ are built before releasing. (2) Pako version pinned to ~1.0.2; upgrading may require testing compression edge cases. (3) readable-stream shim in lib/readable-stream-browser.js used for browser builds; modifications to stream handling need browser-specific testing. (4) Test suite requires Playwright for browser tests; Node.js must be >=v12ish to run full suite.
🏗️Architecture
💡Concepts to learn
- DEFLATE compression (RFC 1951) — JSZip uses pako to implement DEFLATE, the standard compression algorithm in ZIP format; understanding stream-based compression/decompression is critical for debugging file corruption or size issues.
- ZIP file structure (Central Directory + Local File Headers) — JSZip must parse and generate valid ZIP metadata per APPNOTE.TXT (in docs/); file ordering, CRC checksums, and offset calculations are non-obvious.
- Promise-based async/await patterns — generateAsync() and loadAsync() are Promise-based; the library's lie dependency polyfills Promise for older browsers, core to the API contract.
- Node.js Readable streams (readable-stream polyfill) — generateNodeStream() and internalStream() expose streaming APIs for efficient memory usage on large files; readable-stream maintains cross-version compatibility.
- Base64 encoding for binary-safe transport — JSZip supports {base64: true} option in file() method; encoding/decoding binary data to/from Base64 is essential for embedded assets and cross-environment compatibility.
- Browserify module bundling and the browser field in package.json — JSZip uses package.json 'browser' field to swap lib/index with dist/jszip.min.js; understanding this is key for debugging why Node.js vs browser code paths differ.
- CRC32 checksums for file integrity — ZIP format requires CRC32 checksums in local and central directory headers; JSZip must compute and validate these to detect corruption.
🔗Related repos
nodeca/pako— Direct hard dependency for deflate/inflate compression; understanding pako's streaming API helps with JSZip's compression pipeline.substack/browserify— Build tool used by JSZip's Gruntfile.js to create dist/jszip.min.js; essential for understanding the browser distribution pipeline.mafintosh/tar-stream— Comparable archive format library for Node.js; similar async streaming API patterns useful for understanding JSZip's design philosophy.Stuk/jszip-utils— Companion utilities library for JSZip (listed in devDependencies); provides AJAX helpers for loading remote files into zip operations.FileSaver/blob-polyfill— Often paired with JSZip in browser code; the README example uses saveAs() which requires this polyfill on older browsers.
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for streaming API (generate_node_stream.md and internal_stream.md)
The documentation covers generate_node_stream and generate_internal_stream features, but test/asserts/ directory lacks dedicated test files for these streaming APIs. Given that jszip supports multiple output formats (blob, stream, arraybuffer), the streaming paths need robust coverage to prevent regressions, especially for Node.js environments where readable-stream is a critical dependency.
- [ ] Create test/asserts/stream-generation.js for node stream generation tests
- [ ] Create test/asserts/internal-stream.js for internal stream API tests
- [ ] Add tests for error handling in streaming scenarios (corrupted data, aborted streams)
- [ ] Test streaming with large files to ensure memory efficiency
- [ ] Ensure coverage for both Node.js (readable-stream) and browser (internal-stream) paths
- [ ] Run 'npm run test-node' and 'npm run test-browser' to validate
Add TypeScript definition tests and fix type coverage gaps in index.d.ts
The package.json declares 'types': './index.d.ts' and test script includes 'tsc', but there's no dedicated test file validating TypeScript definitions match implementation. With support for multiple async patterns (generateAsync, loadAsync, streamhelper API), type definitions may have gaps or diverge from actual behavior, breaking TypeScript consumers.
- [ ] Create test/asserts/types.test.ts to validate type definitions compile correctly
- [ ] Add tests for StreamHelper API return types (accumulate, on, pause, resume methods)
- [ ] Verify generic types for file() and folder() methods handle edge cases
- [ ] Test type inference for generateAsync() with different type options ('blob', 'arraybuffer', 'nodebuffer')
- [ ] Add test for external() method typing if undocumented
- [ ] Run 'npm run test' to ensure 'tsc' passes with new type tests
Add integration tests for edge cases in ZIP spec compliance (APPNOTE.TXT coverage)
The repo includes docs/APPNOTE.TXT and docs/ZIP spec.txt but test/asserts/ lacks integration tests verifying compliance with ZIP format specifications. Edge cases like zip64, unicode filenames, different compression methods, and special file attributes (permissions, timestamps) need explicit test coverage to catch spec deviations.
- [ ] Create test/asserts/zip-spec-compliance.js for ZIP format edge cases
- [ ] Add tests for Unicode filename handling in entry and extraction
- [ ] Add tests for zip64 format (files >4GB or archives >4GB limits)
- [ ] Test various compression methods beyond deflate (if supported)
- [ ] Test file attributes: Unix permissions, DOS attributes, modification timestamps
- [ ] Test malformed/edge-case ZIP structures (empty entries, nested empty folders, etc.)
- [ ] Run 'npm run test-node' to validate against actual ZIP spec requirements
🌿Good first issues
- Add integration tests for chained folder().file() operations to verify path resolution and relative folder nesting (test/asserts/ lacks coverage for complex folder hierarchies); see documentation/api_jszip/folder_name.md for expected behavior.
- Expand TypeScript definitions in index.d.ts to include overload signatures for the file() method supporting different input types (Uint8Array, base64 strings, Blob) with proper type narrowing; currently definitions may be incomplete.
- Document the StreamHelper API in documentation/api_streamhelper/ with runnable examples showing accumulate(), on(), pause(), resume() usage, as those markdown files exist but may lack concrete Node.js stream integration examples.
⭐Top contributors
Click to expand
Top contributors
- @Stuk — 81 commits
- [@Kyle Jones](https://github.com/Kyle Jones) — 3 commits
- @jonkoops — 2 commits
- @stevennyman — 2 commits
- @zakarynichols — 2 commits
📝Recent commits
Click to expand
Recent commits
643714a— Move all continuous integration to GitHub Actions (#942) (jonkoops)418c11f— Upgrade Playwright to the latest version (#940) (jonkoops)2ceb998— Create FUNDING.yml (Stuk)0f2f1e4— 3.10.1 (Stuk)cae5510— Updates for v3.10.1 (Stuk)179c9a0— Update changelog for 3.10.1 (Stuk)61e1df5— Add Jekyll files to gitignore (Stuk)f299cce— Merge pull request #852 from Stuk/metadata-ts (Stuk)852887a— Consolidate metadata types and expose OnUpdateCallback (Stuk)5be00df— Add sponsorship files (Stuk)
🔒Security observations
The JSZip codebase has moderate security concerns, primarily centered on outdated and unmaintained dependencies. The major risks include outdated build tools (browserify, grunt) from 2015 and legacy polyfills (readable-stream 2.x) that may contain unpatched vulnerabilities. The core compression library (pako) and Promise polyfill (lie) are relatively stable but could benefit from updates. No evidence of hardcoded secrets, injection vulnerabilities, or infrastructure misconfigurations was found. Immediate action should focus on upgrading build tools and evaluating the necessity of legacy polyfills for modern environments. The project would benefit from integrated security scanning in CI/CD pipelines.
- High · Outdated Browserify Dependency —
package.json - devDependencies. browserify ~13.0.0 is significantly outdated (released in 2015). This version may contain known security vulnerabilities in its transitive dependencies and lack modern security patches. Fix: Update browserify to the latest stable version (v17.0.0 or higher) to receive security patches and improvements. - High · Outdated Grunt and Build Tools —
package.json - devDependencies. grunt ~0.4.1 and grunt-browserify ~5.0.0 are significantly outdated. These legacy build tools may have unpatched security vulnerabilities and lack modern security features. Fix: Update to modern versions of grunt (latest 1.x) and grunt-browserify (latest 5.x or consider alternative modern bundlers like webpack or esbuild). - Medium · Potentially Vulnerable Transitive Dependencies —
package.json - dependencies. readable-stream ~2.3.6 is outdated (last update ~2018). While not directly exploitable, it may contain transitive vulnerabilities in its dependencies. Fix: Review and update readable-stream to version 3.x or evaluate if this polyfill is still necessary for modern environments. - Medium · Outdated Pako Compression Library —
package.json - dependencies. pako ~1.0.2 is an older version of the zlib compression library. While generally stable, newer versions include bug fixes and potential security improvements. Fix: Update pako to the latest version (1.0.11+) to ensure all security patches are applied. - Low · Missing Security Configuration —
package.json. The project lacks explicit security configuration in package.json such as engines specification, which could lead to execution on unsupported or vulnerable Node.js versions. Fix: Add 'engines' field specifying minimum Node.js version (e.g., '>=12.0.0') to prevent installation on vulnerable Node.js versions. - Low · No npm Audit Configuration —
Repository root. The project lacks an explicit .npmrc or npm audit policy configuration, which means developers may not be automatically alerted to security vulnerabilities in dependencies. Fix: Add '.npmrc' with audit settings and integrate 'npm audit' into CI/CD pipeline via GitHub Actions. - Low · Dual License with GPL-3.0 —
LICENSE.markdown, package.json. The GPL-3.0 license clause requires derivative works to be open-sourced, which may be a concern for proprietary users. This is a compliance risk rather than a code security issue. Fix: Ensure users are aware of the GPL-3.0 licensing implications when using this library in proprietary projects, or consider a more permissive license alternative.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/Stuk/jszip shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live Stuk/jszip
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/Stuk/jszip.
What it runs against: a local clone of Stuk/jszip — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in Stuk/jszip | Confirms the artifact applies here, not a fork |
| 2 | License is still Other | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 437 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of Stuk/jszip. If you don't
# have one yet, run these first:
#
# git clone https://github.com/Stuk/jszip.git
# cd jszip
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of Stuk/jszip and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "Stuk/jszip(\\.git)?\\b" \\
&& ok "origin remote is Stuk/jszip" \\
|| miss "origin remote is not Stuk/jszip (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Other)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Other\"" package.json 2>/dev/null) \\
&& ok "license is Other" \\
|| miss "license drift — was Other at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "lib/index.js" \\
&& ok "lib/index.js" \\
|| miss "missing critical file: lib/index.js"
test -f "lib/object.js" \\
&& ok "lib/object.js" \\
|| miss "missing critical file: lib/object.js"
test -f "lib/load.js" \\
&& ok "lib/load.js" \\
|| miss "missing critical file: lib/load.js"
test -f "lib/generate/index.js" \\
&& ok "lib/generate/index.js" \\
|| miss "missing critical file: lib/generate/index.js"
test -f "lib/compressions.js" \\
&& ok "lib/compressions.js" \\
|| miss "missing critical file: lib/compressions.js"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 437 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~407d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/Stuk/jszip"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.
Similar JavaScript repos
Other mixed-signal JavaScript repos by stars.
Embed this chat in your README →
Drop this iframe anywhere — the widget runs against the same live analysis cache as the main app.
<iframe src="https://repopilot.app/embed/stuk/jszip" width="100%" height="500" style="border:1px solid #d0d7de; border-radius:8px;" allow="microphone" loading="lazy" ></iframe>