@nodearchive/nodearchive
v1.0.0
Published
Pack and unpack nar, zip, tar, tgz, tar.gz, and gz archives from one API and CLI for Node.js and Bun.
Downloads
31
Maintainers
Readme
nodearchive
nodearchive packs and unpacks .nar, .zip, .tar, .tgz, .tar.gz, and
.gz from one package surface for ESM, CommonJS, Bun, and the nar CLI. Use
it when a JavaScript build, release, or vendor-import flow needs one archive
tool instead of a stack of one-format packages.
Install
npm install @nodearchive/nodearchive
pnpm add @nodearchive/nodearchive
yarn add @nodearchive/nodearchive
bun add @nodearchive/nodearchiveGlobal CLI:
npm install --global @nodearchive/nodearchive
# or
bun add --global @nodearchive/nodearchiveRun once without a global install:
npx @nodearchive/nodearchive pack --help
bunx @nodearchive/nodearchive unpack --helpQuick start
CLI:
npm i -g @nodearchive/nodearchive
nar --help
nar pack ./src ./app.nar
nar unpack ./incoming.zip ./vendorCode:
import { pack, unpack } from '@nodearchive/nodearchive'
await pack({ literalPath: ['src'], destinationPath: './app.nar' })
await unpack({ path: './incoming.zip', destinationPath: './vendor' })CommonJS:
const { pack, unpack } = require('@nodearchive/nodearchive')
async function main() {
const archive = await pack({ blob: 'hello world' })
const restored = await unpack({ blob: archive })
console.log(Buffer.from(restored).toString('utf8'))
}
main()Formats and runtime support
- Writes:
.nar,.zip,.tar,.tgz,.tar.gz, and.gz - Reads:
.nar,.zip,.tar,.tgz,.tar.gz, and.gz - Runtimes: Node >= 18 and Bun
- Package entry points: ESM
importand CommonJSrequire() - CLI:
nar - Inputs: glob paths, exact paths, and in-memory bytes
- Outputs: filesystem writes or memory return values
Examples
Filesystem output
import { pack, unpack } from '@nodearchive/nodearchive'
await pack({
literalPath: ['src', 'package.json'],
destinationPath: './dist/app.nar',
force: true,
})
await unpack({
path: './dist/app.nar',
destinationPath: './out',
force: true,
})In-memory bytes
import { pack, unpack } from '@nodearchive/nodearchive'
const archive = await pack({ blob: 'hello world' })
const restored = await unpack({ blob: archive })
console.log(Buffer.from(restored).toString('utf8'))CommonJS
const { pack, unpack } = require('@nodearchive/nodearchive')
async function main() {
const archive = await pack({ literalPath: ['src'] })
const restored = await unpack({ blob: archive })
console.log(restored.entries.length)
}
main()Alternative output formats
import { pack } from '@nodearchive/nodearchive'
await pack({
literalPath: ['src'],
destinationPath: './dist/app.zip',
outFormat: 'zip',
})
await pack({
literalPath: ['src'],
destinationPath: './dist/app.tgz',
})Incoming zip or tarball
import { unpack } from '@nodearchive/nodearchive'
await unpack({
path: './vendor/release.tar.gz',
destinationPath: './vendor/release',
force: true,
})CLI
nar pack ./src ./dist/app.nar --passThru
nar pack ./src ./dist/app.zip --outFormat zip --passThru
nar unpack ./dist/app.nar ./out --force --passThru
nar unpack ./incoming.zip ./out --force
nar pack --help
npx @nodearchive/nodearchive pack --help
bunx @nodearchive/nodearchive unpack --helpBehavior
pack()writes.nar,.zip,.tar,.tgz,.tar.gz, and.gz.unpack()reads.nar,.zip,.tar,.tgz,.tar.gz, and.gz.outFormatselects the output archive type.destinationPathalso infers the format from supported extensions..gzoutput is limited to a single input.updateis limited to native.naroutput.- In-memory mode accepts strings, blobs, typed arrays,
ArrayBuffer, andSharedArrayBuffer. pathuses glob expansion throughfast-glob;literalPathstays exact.- Validation failures throw
NodearchiveErrorcodes such asARCHIVE_INPUT_REQUIRED,ARCHIVE_INVALID_FORMAT,ARCHIVE_DESTINATION_EXISTS, andARCHIVE_ENTRY_PATH_INVALID. - Unsafe extraction paths and unsupported entry types are rejected instead of being silently rewritten.
Reference
- Landing page: https://nodearchive.github.io/nodearchive/
- In-depth guide: https://nodearchive.github.io/nodearchive/in-depth/
- Coverage report: https://nodearchive.github.io/nodearchive/coverage/
Quality signals
- Suite: unit + integration (Node), E2E (Playwright), Bun smoke
- Matrix: Node 18 / 20 / 22; Chromium / Firefox / WebKit plus mobile emulation
- Coverage: c8 at 100% statements, branches, functions, and lines
- Reports:
coverage/lcov.infoandcoverage/index.html
Benchmarks
Command: npm run bench
Environment: Node v22.14.0 on win32 x64
| Benchmark | Result |
| ---------------- | ---------------------------- |
| pack blob | 3,170.28 ops/s (126.17 ms) |
| unpack blob | 3,306.20 ops/s (120.98 ms) |
| pack directory | 309.35 ops/s (387.91 ms) |
| unpack archive | 4,109.76 ops/s (29.20 ms) |
Results vary by machine.
License
Apache-2.0
