mrkeyoor.com_
Mon 09 Nov 22:31 UTC
npmAI / MLupdated 09 Nov 2026

adm-zip review

Opening a ZIP by filename with adm-zip reads the whole archive into a buffer. That's a useful trade for a bounded configuration bundle you need to inspect, change and save, but a costly one for an upload of unknown size. adm-zip 0.6.1 is a Node.js ZIP reader and writer with entry lookup, content replacement and extraction methods. Its synchronous API suits scripts and controlled background jobs. Choose it around a known working set, rather than assuming a filename means streamed input.

Verdict

Use adm-zip 0.6.1 for bounded ZIP inspection and editing in Node jobs where synchronous reads and buffered output fit your budget. Before accepting user uploads, test resource limits and failure cleanup in your own service.

Answers from our run

adm-zip or jszip: which should you use?

jszip: Choose JSZip for creating, reading and editing ZIPs with JavaScript, especially when a browser Blob is the output you need. Its pinned README demonstrates generateAsync with type blob; this guide did not test browser compatibility. Use adm-zip 0.6.1 for bounded ZIP inspection and editing in Node jobs where synchronous reads and buffered output fit your budget.

When should you not use adm-zip?

You must keep archive input off the JavaScript thread. The filename constructor calls readFileSync, even if you later use an asynchronous method.

API stability3/5The 0.6.1 manifest identifies a pre-1.0 version, so this score makes no promise about future compatibility. The pinned implementation exposes direct methods for reading, editing and writing, but callers must handle details such as updateFile ignoring a missing entry and writeZip falling back to the opened filename. Explicit checks and a pinned dependency reduce surprises; no cross-version test was run.
Docs3/5The version-matched implementation includes method comments describing buffer returns, extraction arguments and persistence after updates. Those comments help explain a small editing job. Reading the method bodies is still necessary to see the synchronous filename read and the missing-entry behavior of updateFile. This is a source-based assessment of the documented contracts, not a claim that every example has been executed.
Maintenance3/5The 0.6.1 release notes record specific fixes for malformed DEFLATE crashes, folder symlink traversal, extraction permissions, duplicate entries and asynchronous error handling. That is concrete evidence of repair work in this version. It does not establish future response time, a release cadence or the absence of other defects, so the score stays at the middle of the stated rubric.
Ecosystem3/5The published manifest supplies a CommonJS entry point, a Node engine declaration and a TypeScript declaration path. Those are useful integration signals for Node projects, supported by the package metadata itself. This score does not infer adoption, browser support or compatibility with every declared Node version. No TypeScript compilation or framework integration was run for this guide.

Use it if

  • You need to replace a known file inside a ZIP and save a separate result, with enough memory for the archive and its contents.
  • A local script must inspect entry names or read a small manifest without extracting everything to disk.
  • Your build job collects a bounded set of local files and generated text, and synchronous filesystem calls are acceptable.
  • You want Node.js ZIP reading and writing through one object, and can enforce limits outside the library.
Skip it if

Setup reality

Install the version discussed here with npm install adm-zip@0.6.1, then load it in a CommonJS file with const AdmZip = require('adm-zip'). The published manifest declares Node >=14.0, points main to adm-zip.js and includes types.d.ts. That is a package declaration, not a recommendation to deploy an old Node release. No installation, benchmark, browser build or snippet execution was performed for this guide. The examples are illustrations checked against the version-matched implementation.

Budget for the input archive, decoded entry data and generated output. Opening a filename uses readFileSync, readFile returns entry data as a Buffer, and writeZip calls compressToBuffer before writing. An asynchronous write does not undo the constructor's synchronous read. There is no measured memory ceiling here. Keep these operations out of a latency-sensitive request handler unless your own workload checks justify them.

Treat edits as changes to the archive object until you serialize it. updateFile silently does nothing for a missing entry, so check getEntry before replacing content. readAsText returns an empty string when an entry is absent, which can hide a missing manifest. writeZip without a new path can overwrite the archive you opened. Pass an explicit result path and retain the original until you have validated the result.

Extraction has filesystem consequences. extractAllTo defaults overwrite and keepOriginalPermission to false. Use a fresh destination and handle errors, since an exception can leave files already written. For untrusted input, enforce upload limits, resource isolation and a cleanup policy outside these snippets. The 0.6.1 release notes report fixes for malformed DEFLATE data, symlink handling, duplicate entry names and decompression size-cap enforcement. Those fixes don't establish a security guarantee for your service.

Scores below are editorial source assessments on a 1-5 scale: 1 means poor fit or thin evidence for that dimension, 3 means useful evidence with material limits, and 5 requires unusually complete support. API stability considers the declared version and method contracts. Documentation quality considers how clearly those contracts expose pitfalls. Maintenance considers the release's recorded fixes, while ecosystem considers documented integration paths. They are not test scores or adoption measurements.

Patterns

Build a ZIP from generated text create-buffer

const AdmZip = require('adm-zip')
const zip = new AdmZip()
zip.addFile('config.json', Buffer.from('{"enabled":true}\n'))
const result = zip.toBuffer()
require('node:fs').writeFileSync('bundle.zip', result)

Source-checked illustration, not executed. toBuffer returns the entire ZIP as a Buffer; the final filesystem write is synchronous too.

Inspect a bounded archive list-entry-names

const AdmZip = require('adm-zip')
const zip = new AdmZip('bundle.zip')
for (const entry of zip.getEntries()) {
  console.log(entry.entryName)
}

getEntries returns entry objects, including directories. Opening the filename has already read the archive synchronously; listing names is not streamed input.

Check that a manifest exists before decoding read-manifest

const AdmZip = require('adm-zip')
const zip = new AdmZip('bundle.zip')
const entry = zip.getEntry('config.json')
if (!entry || entry.isDirectory) throw new Error('Missing config file')
const config = JSON.parse(zip.readAsText(entry, 'utf8'))
console.log(config)

readAsText returns an empty string for an absent entry. The explicit lookup keeps that case separate from invalid or empty JSON; parsing can still throw.

Keep binary content as a Buffer read-binary-entry

const AdmZip = require('adm-zip')
const zip = new AdmZip('bundle.zip')
const entry = zip.getEntry('assets/icon.png')
if (!entry || entry.isDirectory) throw new Error('Missing icon file')
const bytes = zip.readFile(entry)
if (bytes === null) throw new Error('No icon data')
console.log(bytes.length)

readFile returns entry data as a Buffer or null when lookup fails. Corrupt data can throw; the null check is not comprehensive archive validation.

Replace an existing config and save a copy replace-entry

const AdmZip = require('adm-zip')
const zip = new AdmZip('bundle.zip')
const entry = zip.getEntry('config.json')
if (!entry || entry.isDirectory) throw new Error('Missing config file')
zip.updateFile(entry, Buffer.from('{"enabled":false}\n'))
zip.writeZip('bundle-edited.zip')

updateFile silently ignores a missing entry. The lookup prevents a false-success update, and an explicit output path avoids writeZip falling back to the original filename. An existing result file can still be overwritten.

Remove a file before serializing remove-entry

const AdmZip = require('adm-zip')
const zip = new AdmZip('bundle.zip')
const entry = zip.getEntry('notes.txt')
if (!entry || entry.isDirectory) throw new Error('Missing notes file')
zip.deleteFile(entry)
zip.writeZip('bundle-without-notes.zip')

deleteFile changes the archive object. You still need to serialize it. This example rejects directories because deleting a directory can also remove its nested entries.

Map a local file to an archive path add-local-file

const AdmZip = require('adm-zip')
const zip = new AdmZip()
zip.addLocalFile('config.json', 'settings', 'app.json')
zip.writeZip('settings.zip')

The arguments are local path, archive directory and optional archive filename. The entry becomes settings/app.json. addLocalFile uses synchronous stat and file reads, and throws if the source is absent.

Extract a trusted bundle without overwriting files extract-to-fresh-directory

const AdmZip = require('adm-zip')
const fs = require('node:fs')
const os = require('node:os')
const path = require('node:path')
const target = fs.mkdtempSync(path.join(os.tmpdir(), 'bundle-'))
try {
  new AdmZip('bundle.zip').extractAllTo(target, false, false)
  console.log(target)
} catch (error) {
  fs.rmSync(target, { recursive: true, force: true })
  throw error
}

The booleans disable overwrite and restoration of archived permissions. A fresh directory reduces collisions, but does not provide resource isolation for hostile archives. This illustration removes partial output on failure; the caller owns cleanup after success.

Open an archive already held in memory load-known-buffer

const AdmZip = require('adm-zip')
const fs = require('node:fs')
const input = fs.readFileSync('bundle.zip')
const zip = new AdmZip(input)
console.log(Boolean(zip.getEntry('config.json')))

Pass a Node Buffer, rather than a stream. Reading the file into a Buffer here makes the memory boundary explicit; it doesn't save memory compared with opening the filename. All examples in this guide remain unexecuted illustrations.

Alternatives

PackageRegistryPick it when
jszipnpmChoose JSZip for creating, reading and editing ZIPs with JavaScript, especially when a browser Blob is the output you need. Its pinned README demonstrates generateAsync with type blob; this guide did not test browser compatibility.
yauzlnpmChoose yauzl to read ZIP entries through asynchronous APIs when you want to avoid buffering entire files. Its documented focus is unzipping; choose a separate writer if you also need to create archives.

More ai / ml guides

@types/node · openai · @modelcontextprotocol/sdk · mcp · huggingface-hub · @anthropic-ai/sdk · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.