mrkeyoor.com_
Wed 21 Oct 00:07 UTC
npmCLI & Toolingupdated 20 Oct 2026

@electron-internal/extract-zip review

@electron-internal/extract-zip 1.0.5 extracts ZIP files for Electron's own tooling, using a Rust core behind a small Node API. Its publisher explicitly does not support use from non-Electron packages. The only supported option is dir, an absolute destination directory; extraction overwrites existing files and omits the older onEntry, defaultDirMode and defaultFileMode options. If you found it in an app's dependency tree, check that support boundary before adding it to your own project.

Verdict

Use @electron-internal/extract-zip within Electron's supported tooling context when its fixed extraction behavior fits. For a new general-purpose dependency, start with the publisher-recommended extract-zip and check its options against your requirements.

Answers from our run

@electron-internal/extract-zip or extract-zip: which should you use?

extract-zip: Choose extract-zip for a general-purpose, pure-JavaScript extractor with a documented CLI and onEntry callback. Its README also documents default directory and file modes; those are defaults for entries without archive permissions, not overrides for every entry. Use @electron-internal/extract-zip within Electron's supported tooling context when its fixed extraction behavior fits.

When should you not use @electron-internal/extract-zip?

You need a supported general-purpose dependency for a non-Electron package. The publisher says that use is unsupported and may close outside-use bug reports or feature requests without action.

API stability2/5The published 1.0.5 manifest exposes an ESM entry point and types, and its JavaScript wrapper has a small, explicit absolute-dir contract. That simplicity does not establish a compatibility commitment: the version-matched README says the API may change to suit Electron and outside use is unsupported. For direct adoption beyond Electron, that is a substantial limitation even though the call itself is easy to follow.
Docs4/5The version-matched README explains the import, absolute destination requirement, overwrite behavior, metadata handling, missing legacy options and native distribution approach. It also puts the outside-use warning at the top and excludes untrusted or unverified archives from scope. Those details make the adoption decision unusually clear for a small API. The score rewards that clarity, without treating the publisher's benchmark or containment claims as our test results.
Maintenance3/5The v1.0.5 release note names a fix for verification through a pre-existing on-disk symlink at the final target component. That is a traceable patch tied to the published version, rather than a maintenance judgment based on repository stars. The README also says outside-use reports may be closed without action. The evidence supports a specific maintained Electron use case, but gives an outside adopter no support commitment or response-time guarantee.
Ecosystem2/5The documented integrations center on Electron's own tooling. The package exposes ESM imports, includes declarations and describes native binaries for several desktop platforms, so there is a practical distribution story. Its deliberate lack of the older entry and mode options narrows migration from extract-zip. This score assesses that supported integration breadth; download totals would not establish supported third-party use, and no platform matrix was executed here.

Use it if

  • You maintain Electron's own tooling and need the extraction behavior its maintainers document for their distribution archives.
  • Your extraction job can accept the fixed overwrite and metadata behavior without an entry callback or default permission settings.
  • You already validate and trust the archive before extraction, and your Node deployment can load the supplied native binary.
Skip it if

Setup reality

Version 1.0.5 declares Node >=22.12.0. Install that version explicitly with npm install --save-exact @electron-internal/extract-zip@1.0.5, and save the JavaScript examples as .mjs unless a pattern says otherwise. The package declares ESM and ships TypeScript declarations. Its default export and named extract export lead to the same JavaScript wrapper. A CommonJS application can use dynamic import as illustrated below; that is source-based guidance, not a compatibility test.

The wrapper checks that opts.dir is a string and an absolute path. A relative destination is an error, so decide whether paths should resolve from the command's working directory or from the script's location. Those are different choices. The first example uses the working directory, while the module-relative example keeps its paths beside the script. Each recipe is independent.

The README calls the package a replacement for extract-zip, but lists meaningful differences immediately below the usage example. Existing files are overwritten. Archive mode bits and modification times are preserved, and symlinks are created, with a documented Windows privilege exception. You cannot restore the older entry callback or permission defaults by adding extra option keys. Check those requirements before changing an import in an existing application.

Treat archive verification as a separate step. The README describes trusted Electron distribution archives and excludes untrusted or unverified archives from scope. The checksum recipe only compares bytes with a digest you already trust; obtaining a digest from the same untrusted upload does not establish trust. A fresh output directory makes it easier to inspect a result without mixing it with existing application files. Do not treat a rejected promise as a rollback guarantee. The cleanup shown below belongs to the wrapper you write.

The publisher distributes native binaries in one package and describes automatic selection at load time. Its README also gives source-build prerequisites: Rust and cmake. We did not install the library, load a native addon, execute these recipes, audit dependencies or reproduce the publisher's speed benchmarks. The examples are unexecuted illustrations checked against the 1.0.5 documentation and JavaScript wrapper. Start with an already-verified archive in a disposable directory on your actual deployment platform.

If your task is selective reads or incoming ZIP streams, the existing unzipper guide covers that different decision. For turning an Electron app into installers and release artifacts, use the electron-builder guide.

Ratings use a documentation-based 1-5 rubric for direct adoption: 1 means a documented obstacle to the job, 2 substantial limits, 3 usable with caveats, 4 clear documented coverage of the dimension, and 5 would require broader verification than this source review provides. API stability considers the promised interface and change policy; documentation considers how clearly behavior and limits are explained; maintenance considers the traceable release fix and support scope; ecosystem considers supported integration breadth. These are editorial judgments, not measured compatibility, adoption or performance.

Patterns

Extract to an absolute destination extract-from-working-directory

import extract from '@electron-internal/extract-zip';
import { resolve } from 'node:path';

await extract(resolve('verified-release.zip'), {
  dir: resolve('release-output'),
});

Save as extract.mjs and use an archive you already trust and have verified. Both paths resolve from process.cwd(). Existing output files can be overwritten. The JavaScript wrapper rejects relative destination paths. This and the following recipes are unexecuted illustrations.

Use the named extract export use-named-export

import { extract } from '@electron-internal/extract-zip';
import { resolve } from 'node:path';

await extract(resolve('verified-release.zip'), {
  dir: resolve('named-output'),
});

The version-pinned index.js exports extract by name and as the default. These are two import styles for the same wrapper, with the same dir-only options. Choose one style for an entry point.

Keep archive paths beside the script resolve-beside-module

import extract from '@electron-internal/extract-zip';
import { fileURLToPath } from 'node:url';

const source = fileURLToPath(new URL('./verified-release.zip', import.meta.url));
const dir = fileURLToPath(new URL('./module-output/', import.meta.url));
await extract(source, { dir });

Save as a .mjs file. fileURLToPath produces filesystem path strings, while import.meta.url anchors them beside this module. Changing the shell working directory will not select a different archive.

Load it from a CommonJS entry point call-from-commonjs

// Save as extract.cjs.
const { resolve } = require('node:path');

async function main() {
  const { default: extract } = await import('@electron-internal/extract-zip');
  await extract(resolve('verified-release.zip'), { dir: resolve('cjs-output') });
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

Use dynamic import for the ESM package and keep the Node >=22.12.0 requirement. The surrounding entry point is CommonJS; this example makes no claim that a direct require call was tested.

Add explicit arguments and failure reporting build-small-cli

import extract from '@electron-internal/extract-zip';
import { resolve } from 'node:path';

const [source, destination] = process.argv.slice(2);
if (!source || !destination) {
  console.error('Usage: node extract.mjs VERIFIED_ARCHIVE OUTPUT_DIR');
  process.exitCode = 1;
} else {
  try {
    await extract(resolve(source), { dir: resolve(destination) });
    console.log('Extraction completed');
  } catch (error) {
    console.error(error);
    process.exitCode = 1;
  }
}

This is your Node CLI wrapper around the library, not an invocation of a package-supplied executable. Resolve paths intentionally and check the selected destination before running it. An extraction error does not establish that the destination is untouched.

Keep a successful result in a fresh directory create-fresh-output

import extract from '@electron-internal/extract-zip';
import { mkdtemp, rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join, resolve } from 'node:path';

const dir = await mkdtemp(join(tmpdir(), 'electron-zip-'));
try {
  await extract(resolve('verified-release.zip'), { dir });
  console.log(dir);
} catch (error) {
  await rm(dir, { recursive: true, force: true });
  throw error;
}

The wrapper removes its newly created output directory after an extraction failure and retains it after success. Cleanup itself can fail. Inspect the successful result and remove it when finished; a fresh directory does not expand the publisher's trusted-archive scope.

Compare a trusted digest before extraction compare-trusted-checksum

import extract from '@electron-internal/extract-zip';
import { createHash } from 'node:crypto';
import { createReadStream } from 'node:fs';
import { mkdtemp } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join, resolve } from 'node:path';

const [archive, expected] = process.argv.slice(2);
if (!archive || !/^[a-f0-9]{64}$/i.test(expected ?? '')) {
  throw new Error('Provide an archive path and a trusted SHA-256 digest');
}
const source = resolve(archive);
const hash = createHash('sha256');
for await (const chunk of createReadStream(source)) hash.update(chunk);
if (hash.digest('hex') !== expected.toLowerCase()) {
  throw new Error('Archive checksum mismatch');
}
const dir = await mkdtemp(join(tmpdir(), 'verified-zip-'));
await extract(source, { dir });
console.log(dir);

The archive must remain under your control between hashing and extraction because the library reopens its path. Obtain the expected digest from a trusted release source. This wrapper does not authenticate the digest, prevent file replacement or make arbitrary uploads in scope. Remove the temporary directory after inspection or failure.

Give each archive its own output directory separate-batch-results

import extract from '@electron-internal/extract-zip';
import { mkdtemp, rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join, resolve } from 'node:path';

for (const archive of ['verified-a.zip', 'verified-b.zip']) {
  const dir = await mkdtemp(join(tmpdir(), 'release-item-'));
  try {
    await extract(resolve(archive), { dir });
    console.log({ archive, dir });
  } catch (error) {
    await rm(dir, { recursive: true, force: true });
    throw error;
  }
}

The application awaits each call and gives it a distinct destination, avoiding accidental merging of these two results. A failure stops this loop; earlier successful directories remain. This recipe makes no assertion about running concurrent extractions into shared output.

Alternatives

PackageRegistryPick it when
extract-zipnpmChoose extract-zip for a general-purpose, pure-JavaScript extractor with a documented CLI and onEntry callback. Its README also documents default directory and file modes; those are defaults for entries without archive permissions, not overrides for every entry.
yauzlnpmChoose yauzl when you need to read individual ZIP entries as streams and can write the output-handling code yourself. Its lazy-entry API gives you control of entry flow; it is a lower-level reader rather than the same extract-to-directory call.

More cli & tooling guides

commander · chalk · click · typescript · esbuild · yargs · 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.