node-zip-stream
A streaming ZIP archive generator for Node.js that pipes archives out as they're built, without buffering the whole thing in memory.
Repository Health
Technical Analysis
zip-stream is a low-level Node.js library for generating ZIP archives as a readable stream, built on top of compress-commons’ ZipArchiveOutputStream. Rather than assembling an entire archive in memory before writing it out, it lets you append entries — strings, buffers, or streams — one at a time and pipe the result directly to a file, an HTTP response, or any other writable destination as it is produced.
It is intentionally minimal: there is no built-in queueing or glob-based directory support, so callers must wait for one entry to finish before appending the next. This makes it best suited as a building block inside higher-level tools — most notably the archiver package, which wraps zip-stream (and its sibling tar-stream) to add queue management, glob patterns, and a unified interface across archive formats.
What You Get
- A ZipStream class you can pipe() anywhere a writable stream is accepted — filesystem, HTTP response, or another stream.
- An entry() API for appending files, directories, and symlinks from strings, Buffers, or readable streams.
- Support for ZIP64 headers, configurable zlib compression levels, STORE-only (uncompressed) entries, and archive- or entry-level comments.
- Automatic path sanitization that strips drive letters and directory traversal from entry names before they are written.
Common Use Cases
- Streaming a ZIP of dynamically generated files straight to an HTTP response without writing a temp file first.
- Acting as the ZIP backend inside a higher-level archiving tool, as the archiver package does internally.
- Building backup or export bundles from data produced incrementally by another process (logs, reports, generated files).
- Packaging build artifacts into a ZIP entry-by-entry as each file finishes processing in a build pipeline.
Under The Hood
Architecture The entire package is a thin subclass: ZipStream (index.js) extends compress-commons’ ZipArchiveOutputStream, overriding the constructor to normalize options (zlib level, forceZip64, store, comment), overriding entry() to translate a plain data object into a ZipArchiveEntry before delegating to the parent class, and adding a finalize() alias for finish(). A small utils.js holds two pure helper functions (dateify, sanitizePath) used during entry normalization. There is no internal queueing, worker pool, or event bus — the module relies entirely on Node’s native stream backpressure, and the README explicitly documents that callers must serialize entry() calls themselves. Because nearly every method is a direct translation layer, the real abstraction being protected is compress-commons’ ZipArchiveOutputStream/ZipArchiveEntry contract; a breaking change there would ripple through almost all of index.js.
Tech Stack The package ships as pure ESM (“type”: “module”) targeting Node >=18. Runtime dependencies are compress-commons (the underlying ZIP writer), normalize-path (path sanitization), and readable-stream (a consistent Readable/Writable implementation across Node versions). Dev tooling covers mocha and chai for testing, prettier for formatting, and jsdoc (with archiver-jsdoc-theme/minami themes) to generate the published API docs from source comments. There is no bundler or build step — index.js and utils.js ship as-is via the package’s “files” allowlist — and a GitHub Actions workflow is present under .github/ for CI.
Code Quality Tests live under test/ (pack.js and utils.js) written with mocha and chai’s assert style, covering entry() with buffer, stream, and stream-like sources, several date edge cases including DOS date range overflow/underflow boundaries, and the two utils.js helpers directly. Error handling is Node-style: explicit Error objects are passed to err-first callbacks for invalid entry types, names, or symlink data rather than being swallowed silently. There is no TypeScript — types are documented only via JSDoc annotations — and no ESLint config was found, though prettier formatting and CI are in place. Overall this is a modest but genuine test suite focused on observable output rather than exhaustive internal coverage.
API Design The public surface is deliberately tiny: one class extending a Node stream, with entry(source, data, callback) as effectively the only method most callers need, plus finalize(). Getting started takes three lines — construct, pipe, call entry() — and the library composes naturally with anything in Node’s stream ecosystem rather than inventing its own I/O model. The tradeoff, stated plainly in the README, is that there is no queue management: callers (or wrapper libraries like archiver) must serialize entry() calls themselves. That is a legible, honest design choice rather than a novel one — the ZIP format handling itself lives in compress-commons, not here.
Used by 3 apps in this directory
Enso
Analytics · Data Engineering · Low Code Platforms
A visual and textual programming platform for data prep and analysis where the node graph and the underlying Enso code are always perfectly in sync, built by an Alteryx co-founder on a GraalVM engine.
Grist
Databases · No Code Platforms
A modern relational spreadsheet that combines Python-powered formulas, drag-and-drop dashboards, and granular access controls in a self-hostable, SQLite-backed data platform.
overleaf
Collaboration · Productivity
Open-source, real-time collaborative LaTeX editor with sandboxed compilation and full TeXLive support for self-hosted academic and research teams.