npm package: @qezor/livearchive
Description: Low-memory archive packing, listing, extraction, and stream compression for constrained runtimes.
Author: Abdul Ahad
Latest version: 1.0.1

# @qezor/livearchive

Low-memory archive packing, listing, extraction, and stream compression for constrained runtimes.

`@qezor/livearchive` is built on `@qezor/chunkysys` and range-capable `@qezor/objsys` so we can handle classic archive formats without pretending the whole file has to live in memory.

## What v1 supports

Archives:
- `zip`
- `tar`
- `tgz` / `tar.gz`

Single-stream compression:
- `gzip`
- `deflate`
- `brotli`

## What v1 does not support yet

- `rar`
- `7z`
- `zip64`
- encrypted zip entries
- multi-disk zip archives
- advanced tar variants beyond standard ustar-style records

## Safety and honesty

- archive entry paths are normalized and unsafe traversal-like pack paths are rejected
- `zip64`, encrypted zip entries, and multi-disk zip archives fail explicitly instead of pretending support
- archive listing and extraction only accept archive formats: `zip`, `tar`, `tgz`
- single-stream compression helpers stay separate from archive extraction so `.gz` is not misread as a full archive

## Install

```bash
npm install @qezor/livearchive
```

## Basic usage

```js
const { createLiveArchive } = require("@qezor/livearchive")

const archive = createLiveArchive()

const items = await archive.list("catalogue.zip")
await archive.extract("catalogue.zip", "unpacked")
```

## Pack a zip

```js
const archive = createLiveArchive()

await archive.pack([
  {
    sourcePath: "docs/quote.txt",
    archivePath: "quote.txt",
    compression: "deflate",
  },
  {
    data: "hello world\n",
    archivePath: "notes/hello.txt",
    compression: "store",
  },
], "bundle.zip")
```

## Pack a tar or tgz

```js
await archive.pack([
  {
    sourcePath: "src/app.js",
    archivePath: "app.js",
  },
], "bundle.tar")

await archive.pack([
  {
    sourcePath: "src/app.js",
    archivePath: "app.js",
  },
], "bundle.tgz")
```

## Compress and decompress a single file stream

```js
await archive.compress("report.json", "report.json.gz")
await archive.decompress("report.json.gz", "report.json")
```

## API

### `createLiveArchive(options?)`
Creates a `LiveArchive` instance.

### `createLiveArchiveFromEnv(options?)`
Creates a `LiveArchive` backed by `@qezor/objsys.createObjectSystemFromEnv()` and `@qezor/chunkysys.createChunkySystem()`.

### `archive.entries(path, options?)`
Async iterator over archive entries.

### `archive.list(path, options?)`
Collects archive entries into an array.

### `archive.extract(sourcePath, destinationPath, options?)`
Extracts an archive into the destination prefix/path.

### `archive.pack(entries, destinationPath, options?)`
Creates a `zip`, `tar`, or `tgz` archive.

Supported pack entry fields:
- `archivePath`
- `sourcePath`
- `data`
- `type`
- `size`
- `mode`
- `mtime`
- `compression`

### `archive.compress(sourcePath, destinationPath, options?)`
Compresses a single input stream into `gzip`, `deflate`, or `brotli`.

### `archive.decompress(sourcePath, destinationPath, options?)`
Decompresses a single compressed stream.

## Notes

- ZIP support uses range reads for the central directory and entry payloads.
- TAR support stays sequential and low-memory.
- TAR packing needs a known entry size. If you use `sourcePath`, `fs.head()` should be available.
- `stripComponents` works during extraction for both ZIP and TAR-family inputs.