node-liblzma 2.2.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +446 -766
- package/lib/cli/nxz.js +410 -85
- package/lib/cli/nxz.js.map +1 -1
- package/lib/lzma.browser.d.ts +24 -0
- package/lib/lzma.browser.d.ts.map +1 -0
- package/lib/lzma.browser.js +30 -0
- package/lib/lzma.browser.js.map +1 -0
- package/lib/lzma.d.ts.map +1 -1
- package/lib/lzma.inline.d.ts +30 -0
- package/lib/lzma.inline.d.ts.map +1 -0
- package/lib/lzma.inline.js +68 -0
- package/lib/lzma.inline.js.map +1 -0
- package/lib/lzma.js +20 -13
- package/lib/lzma.js.map +1 -1
- package/lib/pool.d.ts.map +1 -1
- package/lib/pool.js +2 -1
- package/lib/pool.js.map +1 -1
- package/lib/wasm/bindings.d.ts +109 -0
- package/lib/wasm/bindings.d.ts.map +1 -0
- package/lib/wasm/bindings.js +320 -0
- package/lib/wasm/bindings.js.map +1 -0
- package/lib/wasm/compress.d.ts +32 -0
- package/lib/wasm/compress.d.ts.map +1 -0
- package/lib/wasm/compress.js +47 -0
- package/lib/wasm/compress.js.map +1 -0
- package/lib/wasm/decompress.d.ts +32 -0
- package/lib/wasm/decompress.d.ts.map +1 -0
- package/lib/wasm/decompress.js +45 -0
- package/lib/wasm/decompress.js.map +1 -0
- package/lib/wasm/index.d.ts +14 -0
- package/lib/wasm/index.d.ts.map +1 -0
- package/lib/wasm/index.js +18 -0
- package/lib/wasm/index.js.map +1 -0
- package/lib/wasm/liblzma.inline.d.ts +10 -0
- package/lib/wasm/liblzma.inline.d.ts.map +1 -0
- package/lib/wasm/liblzma.inline.js +10 -0
- package/lib/wasm/liblzma.inline.js.map +1 -0
- package/lib/wasm/memory.d.ts +57 -0
- package/lib/wasm/memory.d.ts.map +1 -0
- package/lib/wasm/memory.js +110 -0
- package/lib/wasm/memory.js.map +1 -0
- package/lib/wasm/stream.d.ts +35 -0
- package/lib/wasm/stream.d.ts.map +1 -0
- package/lib/wasm/stream.js +168 -0
- package/lib/wasm/stream.js.map +1 -0
- package/lib/wasm/types.d.ts +77 -0
- package/lib/wasm/types.d.ts.map +1 -0
- package/lib/wasm/types.js +55 -0
- package/lib/wasm/types.js.map +1 -0
- package/lib/wasm/utils.d.ts +62 -0
- package/lib/wasm/utils.d.ts.map +1 -0
- package/lib/wasm/utils.js +164 -0
- package/lib/wasm/utils.js.map +1 -0
- package/package.json +31 -8
package/README.md
CHANGED
|
@@ -9,32 +9,49 @@ Node-liblzma
|
|
|
9
9
|
[](https://nodejs.org)
|
|
10
10
|
[](https://www.typescriptlang.org/)
|
|
11
11
|
[](https://docs.npmjs.com/generating-provenance-statements)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
12
|
+
[](https://codecov.io/gh/oorabona/node-liblzma)
|
|
13
|
+
[](https://biomejs.dev)
|
|
14
|
+
|
|
15
|
+
Native Node.js bindings for liblzma — XZ/LZMA2 compression with **browser support via WebAssembly**.
|
|
16
|
+
|
|
17
|
+
## Table of Contents
|
|
18
|
+
|
|
19
|
+
- [Quick Start](#quick-start)
|
|
20
|
+
- [What's New](#whats-new)
|
|
21
|
+
- [v3.0.0 — Browser & WASM Support](#v300--browser--wasm-support)
|
|
22
|
+
- [v2.0.0 — TypeScript Modernization](#v200--typescript-modernization)
|
|
23
|
+
- [Browser Usage](#browser-usage)
|
|
24
|
+
- [CLI Tool (nxz)](#cli-tool-nxz)
|
|
25
|
+
- [Ecosystem Packages](#ecosystem-packages)
|
|
26
|
+
- [tar-xz — tar.xz archives](#tar-xz--tarxz-archives)
|
|
27
|
+
- [nxz — standalone CLI](#nxz--standalone-cli)
|
|
28
|
+
- [API Reference](#api-reference)
|
|
29
|
+
- [API Comparison with Zlib](#api-comparison-with-zlib)
|
|
30
|
+
- [Options](#options)
|
|
31
|
+
- [Advanced Configuration](#advanced-configuration)
|
|
32
|
+
- [Thread Support](#thread-support)
|
|
33
|
+
- [Progress Monitoring](#progress-monitoring)
|
|
34
|
+
- [Concurrency Control (LZMAPool)](#concurrency-control-with-lzmapool)
|
|
35
|
+
- [File Compression Helpers](#file-compression-helpers)
|
|
36
|
+
- [Error Handling](#error-handling)
|
|
37
|
+
- [Benchmark](#benchmark)
|
|
38
|
+
- [Installation](#installation)
|
|
39
|
+
- [Testing](#testing)
|
|
40
|
+
- [Migration Guide (v1 → v2)](#migration-guide)
|
|
41
|
+
- [Contributing](#contributing)
|
|
42
|
+
- [Troubleshooting](#troubleshooting)
|
|
43
|
+
- [Bugs](#bugs)
|
|
44
|
+
- [Acknowledgements](#acknowledgements)
|
|
45
|
+
- [License](#license)
|
|
46
|
+
|
|
47
|
+
## What is liblzma/XZ?
|
|
48
|
+
|
|
49
|
+
[XZ](https://tukaani.org/xz/xz-file-format.txt) is a container for compressed archives. It offers one of the best compression ratios available, with a good balance between compression time and decompression speed/memory.
|
|
33
50
|
|
|
34
51
|
> Only LZMA2 is supported for compression output.
|
|
35
|
-
But the library can open and read any LZMA1 or LZMA2 compressed file.
|
|
52
|
+
> But the library can open and read any LZMA1 or LZMA2 compressed file.
|
|
36
53
|
|
|
37
|
-
|
|
54
|
+
## Quick Start
|
|
38
55
|
|
|
39
56
|
```bash
|
|
40
57
|
npm install node-liblzma
|
|
@@ -61,7 +78,8 @@ compressor.on('progress', ({ bytesRead, bytesWritten }) => {
|
|
|
61
78
|
});
|
|
62
79
|
```
|
|
63
80
|
|
|
64
|
-
|
|
81
|
+
<details>
|
|
82
|
+
<summary><strong>Promise style (with .then())</strong></summary>
|
|
65
83
|
|
|
66
84
|
```typescript
|
|
67
85
|
import { xzAsync, unxzAsync } from 'node-liblzma';
|
|
@@ -79,7 +97,10 @@ xzAsync(Buffer.from('Hello, World!'))
|
|
|
79
97
|
});
|
|
80
98
|
```
|
|
81
99
|
|
|
82
|
-
|
|
100
|
+
</details>
|
|
101
|
+
|
|
102
|
+
<details>
|
|
103
|
+
<summary><strong>Callback style (Node.js traditional)</strong></summary>
|
|
83
104
|
|
|
84
105
|
```typescript
|
|
85
106
|
import { xz, unxz } from 'node-liblzma';
|
|
@@ -93,25 +114,144 @@ xz(Buffer.from('Hello, World!'), (err, compressed) => {
|
|
|
93
114
|
});
|
|
94
115
|
```
|
|
95
116
|
|
|
117
|
+
</details>
|
|
118
|
+
|
|
96
119
|
📖 **Full API documentation**: [oorabona.github.io/node-liblzma](https://oorabona.github.io/node-liblzma/)
|
|
97
120
|
|
|
98
|
-
|
|
121
|
+
## What's New
|
|
122
|
+
|
|
123
|
+
### v3.0.0 — Browser & WASM Support
|
|
124
|
+
|
|
125
|
+
> **[Live Demo](https://oorabona.github.io/node-liblzma/demo/)** — Try XZ compression in your browser.
|
|
126
|
+
|
|
127
|
+
- **Browser/WASM support**: Full XZ compression and decompression via WebAssembly
|
|
128
|
+
- Same API as Node.js (`xzAsync`, `unxzAsync`, `createXz`, `createUnxz`)
|
|
129
|
+
- WASM binary: ~52KB gzipped (under 100KB budget)
|
|
130
|
+
- Web Streams API for streaming compression/decompression
|
|
131
|
+
- Zero-config inline mode: `import from 'node-liblzma/inline'`
|
|
132
|
+
- **CLI tool (nxz)**: Portable xz-like command line tool
|
|
133
|
+
- Full xz compatibility: `-z`, `-d`, `-l`, `-k`, `-f`, `-c`, `-o`, `-v`, `-q`
|
|
134
|
+
- Compression presets 0-9 with extreme mode (`-e`)
|
|
135
|
+
- tar.xz archive support: create, list, extract (compatible with system `tar`)
|
|
136
|
+
- Progress display, stdin/stdout piping, benchmarking (`-B`)
|
|
137
|
+
- **tar-xz package**: Create/extract `.tar.xz` archives — Node.js streaming + browser WASM
|
|
138
|
+
- **Progress events**: Monitor compression/decompression in real-time
|
|
139
|
+
- **XZ Utils 5.8.x**: Updated to latest stable version
|
|
140
|
+
- **519 tests**: Comprehensive test suite with 100% code coverage
|
|
141
|
+
|
|
142
|
+
### v2.0.0 — TypeScript Modernization
|
|
143
|
+
|
|
144
|
+
- **Full TypeScript migration**: Complete rewrite from CoffeeScript
|
|
145
|
+
- **Promise-based APIs**: `xzAsync()` and `unxzAsync()`
|
|
146
|
+
- **Modern tooling**: Vitest, Biome, pnpm, pre-commit hooks
|
|
147
|
+
- **Node.js >= 16** required (updated from >= 12)
|
|
148
|
+
|
|
149
|
+
<details>
|
|
150
|
+
<summary><strong>Legacy (N-API migration)</strong></summary>
|
|
151
|
+
|
|
152
|
+
In previous versions, [N-API](https://nodejs.org/api/n-api.html) replaced [nan](https://github.com/nodejs/nan) as the stable ABI for native modules.
|
|
153
|
+
|
|
154
|
+
Tested on: Linux x64, macOS (x64/arm64), Raspberry Pi 2/3/4, Windows.
|
|
155
|
+
|
|
156
|
+
**Prebuilt binaries** are bundled for: Windows x64, Linux x64, macOS x64/arm64.
|
|
157
|
+
|
|
158
|
+
| Flag | Description | Default | Values |
|
|
159
|
+
|------|-------------|---------|--------|
|
|
160
|
+
| `USE_GLOBAL` | Use system liblzma library | `yes` (`no` on Windows) | `yes`, `no` |
|
|
161
|
+
| `RUNTIME_LINK` | Static or shared linking | `shared` | `static`, `shared` |
|
|
162
|
+
| `ENABLE_THREAD_SUPPORT` | Enable thread support | `yes` | `yes`, `no` |
|
|
163
|
+
|
|
164
|
+
If no prebuilt binary matches your platform, `node-gyp` will compile from source automatically.
|
|
165
|
+
|
|
166
|
+
</details>
|
|
167
|
+
|
|
168
|
+
## Browser Usage
|
|
169
|
+
|
|
170
|
+
> **[Live Demo](https://oorabona.github.io/node-liblzma/demo/)** — Try XZ compression in your browser right now.
|
|
171
|
+
|
|
172
|
+
node-liblzma v3.0.0+ supports XZ compression in the browser via WebAssembly. The same API works in both Node.js and browsers — bundlers (Vite, Webpack, esbuild) automatically resolve the WASM-backed implementation.
|
|
173
|
+
|
|
174
|
+
### Basic Usage
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
// Bundlers auto-resolve to WASM in browser, native in Node.js
|
|
178
|
+
import { xzAsync, unxzAsync, isXZ } from 'node-liblzma';
|
|
179
|
+
|
|
180
|
+
// Compress
|
|
181
|
+
const compressed = await xzAsync('Hello, browser!');
|
|
182
|
+
|
|
183
|
+
// Decompress
|
|
184
|
+
const original = await unxzAsync(compressed);
|
|
185
|
+
|
|
186
|
+
// Check if data is XZ-compressed
|
|
187
|
+
if (isXZ(someBuffer)) {
|
|
188
|
+
const data = await unxzAsync(someBuffer);
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Streaming with Web Streams API
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
import { createXz, createUnxz } from 'node-liblzma';
|
|
196
|
+
|
|
197
|
+
// Compress a fetch response
|
|
198
|
+
const response = await fetch('/large-file.bin');
|
|
199
|
+
const compressed = response.body.pipeThrough(createXz({ preset: 6 }));
|
|
200
|
+
|
|
201
|
+
// Decompress
|
|
202
|
+
const decompressed = compressedStream.pipeThrough(createUnxz());
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Import Modes
|
|
206
|
+
|
|
207
|
+
| Import | When to use |
|
|
208
|
+
|--------|-------------|
|
|
209
|
+
| `node-liblzma` | Standard — bundler resolves to WASM (browser) or native (Node.js) |
|
|
210
|
+
| `node-liblzma/wasm` | Explicit WASM usage in Node.js (no native addon needed) |
|
|
211
|
+
| `node-liblzma/inline` | Zero-config — WASM embedded as base64 (no external file to serve) |
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
// Explicit WASM (works in Node.js too, no native build required)
|
|
215
|
+
import { xzAsync } from 'node-liblzma/wasm';
|
|
216
|
+
|
|
217
|
+
// Inline mode (larger bundle, but no WASM file to configure)
|
|
218
|
+
import { ensureInlineInit, xzAsync } from 'node-liblzma/inline';
|
|
219
|
+
await ensureInlineInit(); // Decodes embedded base64 WASM
|
|
220
|
+
const compressed = await xzAsync(data);
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Browser Limitations
|
|
224
|
+
|
|
225
|
+
- **No sync APIs**: `xzSync()` / `unxzSync()` throw `LZMAError` in browsers
|
|
226
|
+
- **Presets 0-6 only**: Presets 7-9 require more memory than WASM's 256MB limit
|
|
227
|
+
- **No filesystem**: `xzFile()` / `unxzFile()` are not available
|
|
228
|
+
- **No Node Streams**: Use `createXz()` / `createUnxz()` (Web TransformStream) instead of `Xz` / `Unxz` classes
|
|
229
|
+
|
|
230
|
+
### Bundle Size
|
|
231
|
+
|
|
232
|
+
| Component | Raw | Gzipped |
|
|
233
|
+
|-----------|-----|---------|
|
|
234
|
+
| liblzma.wasm | ~107KB | ~52KB |
|
|
235
|
+
| Glue code (liblzma.js) | ~6KB | ~2KB |
|
|
236
|
+
| **Total** | **~113KB** | **~54KB** |
|
|
237
|
+
|
|
238
|
+
For detailed browser setup instructions, see [docs/BROWSER.md](docs/BROWSER.md).
|
|
239
|
+
|
|
240
|
+
## CLI Tool (nxz)
|
|
99
241
|
|
|
100
242
|
This package includes `nxz`, a portable xz-like CLI tool that works on any platform with Node.js.
|
|
101
243
|
|
|
102
|
-
|
|
244
|
+
### Installation
|
|
103
245
|
|
|
104
246
|
```bash
|
|
105
247
|
# Global installation (recommended for CLI usage)
|
|
106
248
|
npm install -g node-liblzma
|
|
107
|
-
# or
|
|
108
|
-
pnpm add -g node-liblzma
|
|
109
249
|
|
|
110
250
|
# Then use directly
|
|
111
251
|
nxz --help
|
|
112
252
|
```
|
|
113
253
|
|
|
114
|
-
|
|
254
|
+
### Quick Examples
|
|
115
255
|
|
|
116
256
|
```bash
|
|
117
257
|
# Compress a file (creates file.txt.xz, deletes original)
|
|
@@ -123,64 +263,76 @@ nxz file.txt.xz
|
|
|
123
263
|
# Keep original file (-k)
|
|
124
264
|
nxz -k file.txt
|
|
125
265
|
|
|
126
|
-
# Decompress explicitly (-d)
|
|
127
|
-
nxz -d archive.xz
|
|
128
|
-
|
|
129
266
|
# Maximum compression (-9) with extreme mode (-e)
|
|
130
267
|
nxz -9e large-file.bin
|
|
131
268
|
|
|
132
269
|
# Compress to stdout (-c) for piping
|
|
133
270
|
nxz -c file.txt > file.txt.xz
|
|
134
271
|
|
|
135
|
-
#
|
|
136
|
-
nxz -
|
|
272
|
+
# List archive info (-l / -lv for verbose)
|
|
273
|
+
nxz -l file.txt.xz
|
|
274
|
+
|
|
275
|
+
# Benchmark native vs WASM performance (-B)
|
|
276
|
+
nxz -B file.txt
|
|
277
|
+
```
|
|
137
278
|
|
|
138
|
-
|
|
139
|
-
nxz -d archive.xz -o /tmp/output.bin
|
|
279
|
+
### tar.xz Archives
|
|
140
280
|
|
|
141
|
-
|
|
142
|
-
nxz -l file.txt.xz
|
|
281
|
+
nxz can create, list, and extract `.tar.xz` archives — auto-detected from file extension:
|
|
143
282
|
|
|
144
|
-
|
|
145
|
-
|
|
283
|
+
```bash
|
|
284
|
+
# Create a tar.xz archive from files/directories
|
|
285
|
+
nxz -T src/ lib/ README.md -o project.tar.xz
|
|
146
286
|
|
|
147
|
-
#
|
|
148
|
-
|
|
287
|
+
# List archive contents
|
|
288
|
+
nxz -Tl project.tar.xz
|
|
149
289
|
|
|
150
|
-
#
|
|
151
|
-
nxz -
|
|
290
|
+
# Extract archive to a directory
|
|
291
|
+
nxz -Td project.tar.xz -o output/
|
|
292
|
+
|
|
293
|
+
# Extract with path stripping (like tar --strip-components)
|
|
294
|
+
nxz -Td project.tar.xz --strip=1 -o output/
|
|
152
295
|
```
|
|
153
296
|
|
|
154
|
-
|
|
297
|
+
Archives created by nxz are fully compatible with system `tar -xJf`.
|
|
298
|
+
|
|
299
|
+
### All Options
|
|
155
300
|
|
|
156
301
|
| Option | Long | Description |
|
|
157
302
|
|--------|------|-------------|
|
|
158
303
|
| `-z` | `--compress` | Force compression mode |
|
|
159
304
|
| `-d` | `--decompress` | Force decompression mode |
|
|
160
305
|
| `-l` | `--list` | List archive information |
|
|
306
|
+
| `-T` | `--tar` | Treat file as tar.xz archive (auto-detected for .tar.xz/.txz) |
|
|
307
|
+
| `-B` | `--benchmark` | Benchmark native vs WASM performance |
|
|
161
308
|
| `-k` | `--keep` | Keep original file (don't delete) |
|
|
162
309
|
| `-f` | `--force` | Overwrite existing output file |
|
|
163
310
|
| `-c` | `--stdout` | Write to stdout, keep original file |
|
|
164
|
-
| `-o` | `--output=FILE` | Write output to specified file |
|
|
311
|
+
| `-o` | `--output=FILE` | Write output to specified file (or directory for tar extract) |
|
|
165
312
|
| `-v` | `--verbose` | Show progress for large files |
|
|
166
313
|
| `-q` | `--quiet` | Suppress warning messages |
|
|
167
314
|
| `-0`..`-9` | | Compression level (default: 6) |
|
|
168
315
|
| `-e` | `--extreme` | Extreme compression (slower) |
|
|
316
|
+
| | `--strip=N` | Strip N leading path components on tar extract |
|
|
169
317
|
| `-h` | `--help` | Show help |
|
|
170
318
|
| `-V` | `--version` | Show version |
|
|
171
319
|
|
|
172
|
-
|
|
320
|
+
<details>
|
|
321
|
+
<summary><strong>One-shot usage (without global install)</strong></summary>
|
|
173
322
|
|
|
174
323
|
```bash
|
|
175
|
-
#
|
|
176
|
-
npx
|
|
177
|
-
|
|
324
|
+
# Standalone nxz package (recommended — smaller, faster install)
|
|
325
|
+
npx nxz --help
|
|
326
|
+
pnpm dlx nxz --help
|
|
178
327
|
|
|
179
|
-
#
|
|
328
|
+
# Or via the full node-liblzma package
|
|
329
|
+
npx --package node-liblzma nxz --help
|
|
180
330
|
pnpm dlx --package node-liblzma nxz --help
|
|
181
331
|
```
|
|
182
332
|
|
|
183
|
-
|
|
333
|
+
</details>
|
|
334
|
+
|
|
335
|
+
### Exit Codes
|
|
184
336
|
|
|
185
337
|
| Code | Meaning |
|
|
186
338
|
|------|---------|
|
|
@@ -188,92 +340,57 @@ pnpm dlx --package node-liblzma nxz --help
|
|
|
188
340
|
| 1 | Error (file not found, format error, etc.) |
|
|
189
341
|
| 130 | Interrupted (SIGINT/Ctrl+C) |
|
|
190
342
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
## Latest Updates (2026)
|
|
194
|
-
|
|
195
|
-
* **CLI Tool (nxz)**: Portable xz-like command line tool included in the package
|
|
196
|
-
- Full xz compatibility: `-z`, `-d`, `-l`, `-k`, `-f`, `-c`, `-o`, `-v`, `-q`
|
|
197
|
-
- Compression presets 0-9 with extreme mode (`-e`)
|
|
198
|
-
- Progress display for large files, stdin/stdout piping
|
|
199
|
-
- Works on any platform with Node.js
|
|
200
|
-
- See [Command Line Interface](#command-line-interface-nxz) section
|
|
201
|
-
* **Progress Events**: Monitor compression/decompression progress with real-time events
|
|
202
|
-
```typescript
|
|
203
|
-
const compressor = createXz();
|
|
204
|
-
compressor.on('progress', ({ bytesRead, bytesWritten }) => {
|
|
205
|
-
console.log(`Read: ${bytesRead}, Written: ${bytesWritten}`);
|
|
206
|
-
});
|
|
207
|
-
```
|
|
208
|
-
* **API Documentation**: Full TypeDoc documentation with Material theme at [oorabona.github.io/node-liblzma](https://oorabona.github.io/node-liblzma/)
|
|
209
|
-
* **XZ Utils 5.8.2**: Updated to latest stable version
|
|
210
|
-
|
|
211
|
-
## Version 2.0 (2025) - Complete Modernization
|
|
343
|
+
## Ecosystem Packages
|
|
212
344
|
|
|
213
|
-
|
|
345
|
+
node-liblzma powers a family of focused packages:
|
|
214
346
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
- Pre-commit hooks with nano-staged and simple-git-hooks
|
|
221
|
-
- pnpm as package manager for better dependency management
|
|
222
|
-
* **Updated Node.js support**: Requires Node.js >= 16 (updated from >= 12)
|
|
347
|
+
| Package | Description | Install |
|
|
348
|
+
|---------|-------------|---------|
|
|
349
|
+
| [`node-liblzma`](https://www.npmjs.com/package/node-liblzma) | Core XZ library — Node.js native + browser WASM | `npm i node-liblzma` |
|
|
350
|
+
| [`tar-xz`](https://www.npmjs.com/package/tar-xz) | Create/extract .tar.xz archives — Node.js + browser | `npm i tar-xz` |
|
|
351
|
+
| [`nxz`](https://www.npmjs.com/package/nxz) | Standalone CLI — `npx nxz file.txt` | `npx nxz` |
|
|
223
352
|
|
|
224
|
-
|
|
353
|
+
### tar-xz — tar.xz archives
|
|
225
354
|
|
|
226
|
-
|
|
355
|
+
> **[Live Demo](https://oorabona.github.io/node-liblzma/tar-xz/)** — Create and extract tar.xz archives in your browser.
|
|
227
356
|
|
|
228
|
-
|
|
357
|
+
A library for working with `.tar.xz` archives, with dual Node.js (streaming) and browser (buffer-based) APIs. This fills the gap left by [node-tar](https://github.com/isaacs/node-tar) which does not support `.tar.xz`.
|
|
229
358
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
* Windows (`windows-2019` and `windows-2022` are part of GitHub CI)
|
|
234
|
-
|
|
235
|
-
> Notes:
|
|
236
|
-
>
|
|
237
|
-
> * For [Windows](https://github.com/oorabona/node-liblzma/actions/workflows/ci-windows.yml)
|
|
238
|
-
> There is no "global" installation of the LZMA library on the Windows machine provisionned by GitHub, so it is pointless to build with this config
|
|
239
|
-
>
|
|
240
|
-
* For [Linux](https://github.com/oorabona/node-liblzma/actions/workflows/ci-linux.yml)
|
|
241
|
-
|
|
242
|
-
* For [MacOS](https://github.com/oorabona/node-liblzma/actions/workflows/ci-macos.yml)
|
|
243
|
-
|
|
244
|
-
## Prebuilt images
|
|
359
|
+
```typescript
|
|
360
|
+
// Node.js — streaming API
|
|
361
|
+
import { create, extract, list } from 'tar-xz';
|
|
245
362
|
|
|
246
|
-
|
|
363
|
+
await create({ file: 'archive.tar.xz', cwd: './src', files: ['index.ts', 'utils.ts'] });
|
|
364
|
+
const entries = await list({ file: 'archive.tar.xz' });
|
|
365
|
+
await extract({ file: 'archive.tar.xz', cwd: './output' });
|
|
247
366
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
* MacOS x86_64 / Arm64
|
|
367
|
+
// Browser — buffer-based API
|
|
368
|
+
import { createTarXz, extractTarXz, listTarXz } from 'tar-xz';
|
|
251
369
|
|
|
252
|
-
|
|
370
|
+
const archive = await createTarXz({ files: [{ name: 'hello.txt', content: data }] });
|
|
371
|
+
const files = await extractTarXz(archive);
|
|
372
|
+
const entries = await listTarXz(archive);
|
|
373
|
+
```
|
|
253
374
|
|
|
254
|
-
|
|
255
|
-
|------|-------------|---------|--------|
|
|
256
|
-
| `USE_GLOBAL` | Use system liblzma library | `yes` (`no` on Windows) | `yes`, `no` |
|
|
257
|
-
| `RUNTIME_LINK` | Static or shared linking | `shared` | `static`, `shared` |
|
|
258
|
-
| `ENABLE_THREAD_SUPPORT` | Enable thread support | `yes` | `yes`, `no` |
|
|
375
|
+
### nxz — standalone CLI
|
|
259
376
|
|
|
260
|
-
|
|
377
|
+
A lightweight wrapper package for running `nxz` without installing the full `node-liblzma`:
|
|
261
378
|
|
|
262
|
-
|
|
379
|
+
```bash
|
|
380
|
+
# No install needed
|
|
381
|
+
npx nxz file.txt # compress
|
|
382
|
+
npx nxz -d file.txt.xz # decompress
|
|
383
|
+
npx nxz -T src/ -o app.tar.xz # create tar.xz archive
|
|
263
384
|
|
|
264
|
-
#
|
|
385
|
+
# Or install globally
|
|
386
|
+
npm install -g nxz
|
|
387
|
+
```
|
|
265
388
|
|
|
266
|
-
|
|
389
|
+
## API Reference
|
|
267
390
|
|
|
268
|
-
|
|
269
|
-
A pure JavaScript implementation of the algorithm
|
|
270
|
-
* [node-xz](https://github.com/robey/node-xz)
|
|
271
|
-
Node binding of XZ library
|
|
272
|
-
* [lzma-native](https://github.com/addaleax/lzma-native)
|
|
273
|
-
A very complete implementation of XZ library bindings
|
|
274
|
-
* Others are also available but they fork "xz" process in the background.
|
|
391
|
+
### API Comparison with Zlib
|
|
275
392
|
|
|
276
|
-
|
|
393
|
+
The API mirrors Node.js Zlib for easy adoption:
|
|
277
394
|
|
|
278
395
|
```js
|
|
279
396
|
// CommonJS
|
|
@@ -296,9 +413,7 @@ import * as lzma from 'node-liblzma';
|
|
|
296
413
|
| - | `xzFile` | `(input, output, [options])` → `Promise<void>` |
|
|
297
414
|
| - | `unxzFile` | `(input, output, [options])` → `Promise<void>` |
|
|
298
415
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
The `options` object accepts the following attributes:
|
|
416
|
+
### Options
|
|
302
417
|
|
|
303
418
|
| Attribute | Type | Description | Values |
|
|
304
419
|
|-----------|------|-------------|--------|
|
|
@@ -309,15 +424,13 @@ The `options` object accepts the following attributes:
|
|
|
309
424
|
| `filters` | array | Filter chain | `filter.LZMA2`, `filter.X86`, `filter.ARM`, etc. |
|
|
310
425
|
| `chunkSize` | number | Processing chunk size | Default: 64KB |
|
|
311
426
|
|
|
312
|
-
For further information
|
|
427
|
+
For further information, see the [XZ SDK documentation](http://7-zip.org/sdk.html).
|
|
313
428
|
|
|
314
429
|
## Advanced Configuration
|
|
315
430
|
|
|
316
431
|
### Thread Support
|
|
317
432
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
**Thread values:**
|
|
433
|
+
Multi-threaded compression is available when built with `ENABLE_THREAD_SUPPORT=yes` (default).
|
|
321
434
|
|
|
322
435
|
| Value | Behavior |
|
|
323
436
|
|-------|----------|
|
|
@@ -325,26 +438,15 @@ The library supports multi-threaded compression when built with `ENABLE_THREAD_S
|
|
|
325
438
|
| `1` | Single-threaded (default) |
|
|
326
439
|
| `N` | Use exactly N threads |
|
|
327
440
|
|
|
328
|
-
**Example:**
|
|
329
|
-
|
|
330
441
|
```typescript
|
|
331
442
|
import { createXz, hasThreads } from 'node-liblzma';
|
|
332
443
|
|
|
333
|
-
// Check if threading is available
|
|
334
444
|
if (hasThreads()) {
|
|
335
|
-
|
|
336
|
-
const compressor = createXz({ threads: 0 });
|
|
337
|
-
|
|
338
|
-
// Or specify exact thread count
|
|
339
|
-
const compressor4 = createXz({ threads: 4 });
|
|
445
|
+
const compressor = createXz({ threads: 0 }); // auto-detect
|
|
340
446
|
}
|
|
341
447
|
```
|
|
342
448
|
|
|
343
|
-
**
|
|
344
|
-
- Thread support only applies to **compression**, not decompression
|
|
345
|
-
- Requires LZMA library built with pthread support (`ENABLE_THREAD_SUPPORT=yes`)
|
|
346
|
-
- Default is `threads: 1` (single-threaded) for predictable behavior
|
|
347
|
-
- Check availability: `hasThreads()` returns `true` if multi-threading is supported
|
|
449
|
+
> **Note**: Threads only apply to compression, not decompression.
|
|
348
450
|
|
|
349
451
|
### Progress Monitoring
|
|
350
452
|
|
|
@@ -357,65 +459,52 @@ const compressor = createXz({ preset: 6 });
|
|
|
357
459
|
|
|
358
460
|
compressor.on('progress', ({ bytesRead, bytesWritten }) => {
|
|
359
461
|
const ratio = bytesWritten / bytesRead;
|
|
360
|
-
console.log(`Progress: ${bytesRead}
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
// Works with both compression and decompression
|
|
364
|
-
const decompressor = createUnxz();
|
|
365
|
-
decompressor.on('progress', ({ bytesRead, bytesWritten }) => {
|
|
366
|
-
console.log(`Decompressing: ${bytesRead} → ${bytesWritten} bytes`);
|
|
462
|
+
console.log(`Progress: ${bytesRead} in, ${bytesWritten} out (ratio: ${ratio.toFixed(2)})`);
|
|
367
463
|
});
|
|
368
464
|
|
|
369
465
|
inputStream.pipe(compressor).pipe(outputStream);
|
|
370
466
|
```
|
|
371
467
|
|
|
372
|
-
|
|
373
|
-
- Progress events fire after each chunk is processed
|
|
374
|
-
- `bytesRead`: Total input bytes processed so far
|
|
375
|
-
- `bytesWritten`: Total output bytes produced so far
|
|
376
|
-
- Works with streams, not buffer APIs (`xz`/`unxz`)
|
|
468
|
+
Progress events fire after each chunk is processed. Works with streams, not buffer APIs.
|
|
377
469
|
|
|
378
|
-
###
|
|
470
|
+
### Concurrency Control with LZMAPool
|
|
379
471
|
|
|
380
|
-
For
|
|
472
|
+
For production environments with high concurrency needs:
|
|
381
473
|
|
|
382
474
|
```typescript
|
|
383
|
-
|
|
384
|
-
preset: lzma.preset.DEFAULT,
|
|
385
|
-
chunkSize: 256 * 1024 // 256KB chunks (default: 64KB)
|
|
386
|
-
});
|
|
387
|
-
```
|
|
475
|
+
import { LZMAPool } from 'node-liblzma';
|
|
388
476
|
|
|
389
|
-
|
|
390
|
-
- **Small files (< 1MB)**: Use default 64KB chunks
|
|
391
|
-
- **Medium files (1-10MB)**: Use 128-256KB chunks
|
|
392
|
-
- **Large files (> 10MB)**: Use 512KB-1MB chunks
|
|
393
|
-
- **Maximum buffer size**: 512MB per operation (security limit)
|
|
477
|
+
const pool = new LZMAPool(10); // Max 10 concurrent operations
|
|
394
478
|
|
|
395
|
-
|
|
479
|
+
pool.on('metrics', (metrics) => {
|
|
480
|
+
console.log(`Active: ${metrics.active}, Queued: ${metrics.queued}`);
|
|
481
|
+
});
|
|
396
482
|
|
|
397
|
-
|
|
483
|
+
const compressed = await pool.compress(buffer);
|
|
484
|
+
const decompressed = await pool.decompress(compressed);
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
### File Compression Helpers
|
|
398
488
|
|
|
399
489
|
```typescript
|
|
400
|
-
import {
|
|
401
|
-
import { createXz } from 'node-liblzma';
|
|
490
|
+
import { xzFile, unxzFile } from 'node-liblzma';
|
|
402
491
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
492
|
+
await xzFile('input.txt', 'output.txt.xz');
|
|
493
|
+
await unxzFile('output.txt.xz', 'restored.txt');
|
|
494
|
+
|
|
495
|
+
// With options
|
|
496
|
+
await xzFile('large-file.bin', 'compressed.xz', { preset: 9, threads: 4 });
|
|
406
497
|
```
|
|
407
498
|
|
|
499
|
+
Handles files > 512MB automatically via streams with lower memory footprint.
|
|
500
|
+
|
|
408
501
|
### Error Handling
|
|
409
502
|
|
|
410
|
-
|
|
503
|
+
Typed error classes for precise error handling:
|
|
411
504
|
|
|
412
505
|
```typescript
|
|
413
506
|
import {
|
|
414
|
-
xzAsync,
|
|
415
|
-
LZMAError,
|
|
416
|
-
LZMAMemoryError,
|
|
417
|
-
LZMADataError,
|
|
418
|
-
LZMAFormatError
|
|
507
|
+
xzAsync, LZMAError, LZMAMemoryError, LZMADataError, LZMAFormatError
|
|
419
508
|
} from 'node-liblzma';
|
|
420
509
|
|
|
421
510
|
try {
|
|
@@ -427,339 +516,106 @@ try {
|
|
|
427
516
|
console.error('Corrupt data:', error.message);
|
|
428
517
|
} else if (error instanceof LZMAFormatError) {
|
|
429
518
|
console.error('Invalid format:', error.message);
|
|
430
|
-
} else {
|
|
431
|
-
console.error('Unknown error:', error);
|
|
432
519
|
}
|
|
433
520
|
}
|
|
434
521
|
```
|
|
435
522
|
|
|
436
|
-
**Available error classes
|
|
437
|
-
- `LZMAError` - Base error class
|
|
438
|
-
- `LZMAMemoryError` - Memory allocation failed
|
|
439
|
-
- `LZMAMemoryLimitError` - Memory limit exceeded
|
|
440
|
-
- `LZMAFormatError` - Unrecognized file format
|
|
441
|
-
- `LZMAOptionsError` - Invalid compression options
|
|
442
|
-
- `LZMADataError` - Corrupt compressed data
|
|
443
|
-
- `LZMABufferError` - Buffer size issues
|
|
444
|
-
- `LZMAProgrammingError` - Internal errors
|
|
445
|
-
|
|
446
|
-
### Error Recovery
|
|
447
|
-
|
|
448
|
-
Streams automatically handle recoverable errors and provide state transition hooks:
|
|
449
|
-
|
|
450
|
-
```typescript
|
|
451
|
-
const decompressor = createUnxz();
|
|
452
|
-
|
|
453
|
-
decompressor.on('error', (error) => {
|
|
454
|
-
console.error('Decompression error:', error.errno, error.message);
|
|
455
|
-
// Stream will emit 'close' event after error
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
decompressor.on('close', () => {
|
|
459
|
-
console.log('Stream closed, safe to cleanup');
|
|
460
|
-
});
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
### Concurrency Control with LZMAPool
|
|
464
|
-
|
|
465
|
-
For production environments with high concurrency needs, use `LZMAPool` to limit simultaneous operations:
|
|
466
|
-
|
|
467
|
-
```typescript
|
|
468
|
-
import { LZMAPool } from 'node-liblzma';
|
|
469
|
-
|
|
470
|
-
const pool = new LZMAPool(10); // Max 10 concurrent operations
|
|
471
|
-
|
|
472
|
-
// Monitor pool metrics
|
|
473
|
-
pool.on('metrics', (metrics) => {
|
|
474
|
-
console.log(`Active: ${metrics.active}, Queued: ${metrics.queued}`);
|
|
475
|
-
console.log(`Completed: ${metrics.completed}, Failed: ${metrics.failed}`);
|
|
476
|
-
});
|
|
477
|
-
|
|
478
|
-
// Compress with automatic queuing
|
|
479
|
-
const compressed = await pool.compress(buffer);
|
|
480
|
-
const decompressed = await pool.decompress(compressed);
|
|
481
|
-
|
|
482
|
-
// Get current metrics
|
|
483
|
-
const status = pool.getMetrics();
|
|
484
|
-
```
|
|
485
|
-
|
|
486
|
-
**Pool Events:**
|
|
487
|
-
- `queue` - Task added to queue
|
|
488
|
-
- `start` - Task started processing
|
|
489
|
-
- `complete` - Task completed successfully
|
|
490
|
-
- `error-task` - Task failed
|
|
491
|
-
- `metrics` - Metrics updated (after each state change)
|
|
492
|
-
|
|
493
|
-
**Benefits:**
|
|
494
|
-
- ✅ Automatic backpressure
|
|
495
|
-
- ✅ Prevents resource exhaustion
|
|
496
|
-
- ✅ Production-ready monitoring
|
|
497
|
-
- ✅ Zero breaking changes (opt-in)
|
|
498
|
-
|
|
499
|
-
### File Compression Helpers
|
|
523
|
+
**Available error classes**: `LZMAError` (base), `LZMAMemoryError`, `LZMAMemoryLimitError`, `LZMAFormatError`, `LZMAOptionsError`, `LZMADataError`, `LZMABufferError`, `LZMAProgrammingError`.
|
|
500
524
|
|
|
501
|
-
|
|
525
|
+
### Buffer Size Optimization
|
|
502
526
|
|
|
503
527
|
```typescript
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
//
|
|
507
|
-
await xzFile('input.txt', 'output.txt.xz');
|
|
508
|
-
|
|
509
|
-
// Decompress a file
|
|
510
|
-
await unxzFile('output.txt.xz', 'restored.txt');
|
|
511
|
-
|
|
512
|
-
// With options
|
|
513
|
-
await xzFile('large-file.bin', 'compressed.xz', {
|
|
514
|
-
preset: 9,
|
|
515
|
-
threads: 4
|
|
528
|
+
const stream = createXz({
|
|
529
|
+
preset: lzma.preset.DEFAULT,
|
|
530
|
+
chunkSize: 256 * 1024 // 256KB chunks (default: 64KB)
|
|
516
531
|
});
|
|
517
532
|
```
|
|
518
533
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
## Async callback contract (errno-based)
|
|
526
|
-
|
|
527
|
-
The low-level native callback used internally by streams follows an errno-style contract to match liblzma behavior and to avoid mixing exception channels:
|
|
528
|
-
|
|
529
|
-
- Signature: `(errno: number, availInAfter: number, availOutAfter: number)`
|
|
530
|
-
- Success: `errno` is either `LZMA_OK` or `LZMA_STREAM_END`.
|
|
531
|
-
- Recoverable/other conditions: any other `errno` value (for example, `LZMA_BUF_ERROR`, `LZMA_DATA_ERROR`, `LZMA_PROG_ERROR`) indicates an error state.
|
|
532
|
-
- Streams emit `onerror` with the numeric `errno` when `errno !== LZMA_OK && errno !== LZMA_STREAM_END`.
|
|
534
|
+
| File Size | Recommended chunkSize |
|
|
535
|
+
|-----------|-----------------------|
|
|
536
|
+
| < 1MB | 64KB (default) |
|
|
537
|
+
| 1-10MB | 128-256KB |
|
|
538
|
+
| > 10MB | 512KB-1MB |
|
|
533
539
|
|
|
534
|
-
|
|
540
|
+
Maximum buffer size: 512MB per operation (security limit). For larger files, use streaming APIs.
|
|
535
541
|
|
|
536
|
-
|
|
537
|
-
- This avoids throwing across async worker boundaries and keeps cleanup deterministic.
|
|
542
|
+
### Async Callback Contract (errno-based)
|
|
538
543
|
|
|
539
|
-
|
|
544
|
+
The low-level native callback follows an errno-style contract matching liblzma behavior:
|
|
540
545
|
|
|
541
|
-
-
|
|
542
|
-
-
|
|
546
|
+
- **Signature**: `(errno: number, availInAfter: number, availOutAfter: number)`
|
|
547
|
+
- **Success**: `errno` is `LZMA_OK` or `LZMA_STREAM_END`
|
|
548
|
+
- **Error**: any other `errno` value
|
|
543
549
|
|
|
544
|
-
|
|
550
|
+
High-level APIs remain ergonomic — Promise functions resolve to `Buffer` or reject with `Error`, stream users listen to `error` events.
|
|
545
551
|
|
|
546
|
-
|
|
552
|
+
## Benchmark
|
|
547
553
|
|
|
548
|
-
|
|
554
|
+
### Performance Hierarchy
|
|
549
555
|
|
|
550
|
-
|
|
551
|
-
npm i node-liblzma --save
|
|
552
|
-
```
|
|
553
|
-
|
|
554
|
-
--OR--
|
|
555
|
-
|
|
556
|
-
```sh
|
|
557
|
-
yarn add node-liblzma
|
|
558
|
-
```
|
|
559
|
-
|
|
560
|
-
--OR-- (recommended for development)
|
|
556
|
+
All three backends use the same liblzma library and produce **identical compression ratios**:
|
|
561
557
|
|
|
562
|
-
```sh
|
|
563
|
-
pnpm add node-liblzma
|
|
564
558
|
```
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
``` bash
|
|
569
|
-
ENABLE_THREAD_SUPPORT=no npm install node-liblzma --build-from-source
|
|
559
|
+
System xz > nxz native (C++ addon) > nxz WASM (Emscripten)
|
|
560
|
+
fastest ~1-2x slower ~2-5x slower (decompress)
|
|
561
|
+
~1x (compress, large files)
|
|
570
562
|
```
|
|
571
563
|
|
|
572
|
-
|
|
573
|
-
Enabling thread support in the library will __NOT__ work if the LZMA library itself has been built without such support.
|
|
564
|
+
### Full Comparison (246 KB source code, preset 6)
|
|
574
565
|
|
|
575
|
-
|
|
566
|
+
| Backend | Compress | Decompress | Size | Environment |
|
|
567
|
+
|---------|----------|------------|------|-------------|
|
|
568
|
+
| **System `xz` 5.8** | 81 ms | 4 ms | 76.7 KB | C binary |
|
|
569
|
+
| **nxz native** | 90 ms | 3.4 ms | 76.7 KB | Node.js + C++ addon |
|
|
570
|
+
| **nxz WASM** | 86 ms | 7.9 ms | 76.7 KB | Node.js + Emscripten |
|
|
576
571
|
|
|
577
|
-
|
|
578
|
-
2. Ask the build system to download `xz` and build it
|
|
579
|
-
3. Compile `xz` yourself, outside `node-liblzma`, and have it use it after
|
|
572
|
+
### Native vs WASM (nxz -B, preset 6)
|
|
580
573
|
|
|
581
|
-
|
|
574
|
+
| Data | Compress | Decompress | Notes |
|
|
575
|
+
|------|----------|------------|-------|
|
|
576
|
+
| 1 KB text | WASM 2.8x slower | WASM 4.9x slower | Startup overhead dominates |
|
|
577
|
+
| 135 KB binary | ~1:1 | WASM 2x slower | Compression near-parity |
|
|
578
|
+
| 246 KB source | ~1:1 | WASM 2.3x slower | Realistic workload |
|
|
579
|
+
| 1 MB random | ~1:1 | WASM 1.6x slower | Gap narrows with size |
|
|
582
580
|
|
|
583
|
-
|
|
581
|
+
<details>
|
|
582
|
+
<summary><strong>Running benchmarks</strong></summary>
|
|
584
583
|
|
|
585
|
-
```
|
|
586
|
-
#
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
If you do not plan on having a local install, you can ask for automatic download and build of whatever version of `xz` you want.
|
|
592
|
-
|
|
593
|
-
Just do:
|
|
594
|
-
|
|
595
|
-
```sh
|
|
596
|
-
npm install node-liblzma --build-from-source
|
|
597
|
-
```
|
|
598
|
-
|
|
599
|
-
When no option is given in the commandline arguments, it will build with default values.
|
|
600
|
-
|
|
601
|
-
## Local install of `xz` sources (outside `node-liblzma`)
|
|
602
|
-
|
|
603
|
-
So you did install `xz` somewhere outside the module and want the module to use it.
|
|
604
|
-
|
|
605
|
-
For that, you need to set the include directory and library directory search paths as GCC [environment variables](https://gcc.gnu.org/onlinedocs/gcc/Environment-Variables.html).
|
|
584
|
+
```bash
|
|
585
|
+
# Compare nxz (native) vs system xz across file sizes
|
|
586
|
+
./scripts/benchmark.sh
|
|
587
|
+
./scripts/benchmark.sh -s 1,50,200 -p 6,9 # custom sizes/presets
|
|
588
|
+
./scripts/benchmark.sh -o csv > results.csv # export as CSV/JSON
|
|
606
589
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
export LD_LIBRARY_PATH=$HOME/path/to/lib:$LD_LIBRARY_PATH
|
|
590
|
+
# Compare native addon vs WASM backend
|
|
591
|
+
nxz --benchmark file.txt
|
|
592
|
+
nxz -B -3 large-file.bin # with preset 3
|
|
611
593
|
```
|
|
612
594
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
Once done, this should suffice:
|
|
616
|
-
|
|
617
|
-
```sh
|
|
618
|
-
npm install
|
|
619
|
-
```
|
|
595
|
+
</details>
|
|
620
596
|
|
|
621
|
-
|
|
597
|
+
### When to Use What
|
|
622
598
|
|
|
623
|
-
|
|
599
|
+
| Scenario | Recommended |
|
|
600
|
+
|----------|-------------|
|
|
601
|
+
| Browser | WASM (only option) |
|
|
602
|
+
| Node.js, performance-critical | Native addon |
|
|
603
|
+
| Node.js, no C++ toolchain available | WASM (`node-liblzma/wasm`) |
|
|
604
|
+
| Cross-platform scripts | nxz CLI |
|
|
605
|
+
| Batch processing many files | System xz |
|
|
606
|
+
| CI/CD with Node.js already installed | nxz CLI |
|
|
624
607
|
|
|
625
|
-
|
|
608
|
+
## Installation
|
|
626
609
|
|
|
627
|
-
```
|
|
628
|
-
npm
|
|
610
|
+
```bash
|
|
611
|
+
npm install node-liblzma
|
|
629
612
|
# or
|
|
630
|
-
pnpm
|
|
631
|
-
```
|
|
632
|
-
|
|
633
|
-
It will build and launch the test suite (325+ tests) with [Vitest](https://vitest.dev/) with TypeScript support and coverage reporting.
|
|
634
|
-
|
|
635
|
-
Additional testing commands:
|
|
636
|
-
|
|
637
|
-
```sh
|
|
638
|
-
# Watch mode for development
|
|
639
|
-
pnpm test:watch
|
|
640
|
-
|
|
641
|
-
# Coverage report
|
|
642
|
-
pnpm test:coverage
|
|
643
|
-
|
|
644
|
-
# Type checking
|
|
645
|
-
pnpm type-check
|
|
646
|
-
```
|
|
647
|
-
|
|
648
|
-
# Usage
|
|
649
|
-
|
|
650
|
-
As the API is very close to NodeJS Zlib, you will probably find a good reference
|
|
651
|
-
[there](http://www.nodejs.org/api/zlib.html).
|
|
652
|
-
|
|
653
|
-
Otherwise examples can be found as part of the test suite, so feel free to use them!
|
|
654
|
-
They are written in TypeScript with full type definitions.
|
|
655
|
-
|
|
656
|
-
# Migration Guide
|
|
657
|
-
|
|
658
|
-
## Migrating from v1.x to v2.0
|
|
659
|
-
|
|
660
|
-
Version 2.0 introduces several breaking changes along with powerful new features.
|
|
661
|
-
|
|
662
|
-
### Breaking Changes
|
|
663
|
-
|
|
664
|
-
1. **Node.js Version Requirement**
|
|
665
|
-
```diff
|
|
666
|
-
- Requires Node.js >= 12
|
|
667
|
-
+ Requires Node.js >= 16
|
|
668
|
-
```
|
|
669
|
-
|
|
670
|
-
2. **ESM Module Format**
|
|
671
|
-
```diff
|
|
672
|
-
- CommonJS: var lzma = require('node-liblzma');
|
|
673
|
-
+ ESM: import * as lzma from 'node-liblzma';
|
|
674
|
-
+ CommonJS still works via dynamic import
|
|
675
|
-
```
|
|
676
|
-
|
|
677
|
-
3. **TypeScript Migration**
|
|
678
|
-
- Source code migrated from CoffeeScript to TypeScript
|
|
679
|
-
- Full type definitions included
|
|
680
|
-
- Better IDE autocomplete and type safety
|
|
681
|
-
|
|
682
|
-
### New Features You Should Adopt
|
|
683
|
-
|
|
684
|
-
1. **Promise-based APIs** (Recommended for new code)
|
|
685
|
-
```typescript
|
|
686
|
-
// Old callback style (still works)
|
|
687
|
-
xz(buffer, (err, compressed) => {
|
|
688
|
-
if (err) throw err;
|
|
689
|
-
// use compressed
|
|
690
|
-
});
|
|
691
|
-
|
|
692
|
-
// New Promise style
|
|
693
|
-
try {
|
|
694
|
-
const compressed = await xzAsync(buffer);
|
|
695
|
-
// use compressed
|
|
696
|
-
} catch (err) {
|
|
697
|
-
// handle error
|
|
698
|
-
}
|
|
699
|
-
```
|
|
700
|
-
|
|
701
|
-
2. **Typed Error Classes** (Better error handling)
|
|
702
|
-
```typescript
|
|
703
|
-
import { LZMAMemoryError, LZMADataError } from 'node-liblzma';
|
|
704
|
-
|
|
705
|
-
try {
|
|
706
|
-
await unxzAsync(corruptData);
|
|
707
|
-
} catch (error) {
|
|
708
|
-
if (error instanceof LZMADataError) {
|
|
709
|
-
console.error('Corrupt compressed data');
|
|
710
|
-
} else if (error instanceof LZMAMemoryError) {
|
|
711
|
-
console.error('Out of memory');
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
```
|
|
715
|
-
|
|
716
|
-
3. **Concurrency Control** (For high-throughput applications)
|
|
717
|
-
```typescript
|
|
718
|
-
import { LZMAPool } from 'node-liblzma';
|
|
719
|
-
|
|
720
|
-
const pool = new LZMAPool(10); // Max 10 concurrent operations
|
|
721
|
-
|
|
722
|
-
// Automatic queuing and backpressure
|
|
723
|
-
const results = await Promise.all(
|
|
724
|
-
files.map(file => pool.compress(file))
|
|
725
|
-
);
|
|
726
|
-
```
|
|
727
|
-
|
|
728
|
-
4. **File Helpers** (Simpler file compression)
|
|
729
|
-
```typescript
|
|
730
|
-
import { xzFile, unxzFile } from 'node-liblzma';
|
|
731
|
-
|
|
732
|
-
// Compress a file (handles streaming automatically)
|
|
733
|
-
await xzFile('input.txt', 'output.txt.xz');
|
|
734
|
-
|
|
735
|
-
// Decompress a file
|
|
736
|
-
await unxzFile('output.txt.xz', 'restored.txt');
|
|
737
|
-
```
|
|
738
|
-
|
|
739
|
-
### Testing Framework Change
|
|
740
|
-
|
|
741
|
-
If you maintain tests for code using node-liblzma:
|
|
742
|
-
|
|
743
|
-
```diff
|
|
744
|
-
- Mocha test framework
|
|
745
|
-
+ Vitest test framework (faster, better TypeScript support)
|
|
613
|
+
pnpm add node-liblzma
|
|
746
614
|
```
|
|
747
615
|
|
|
748
|
-
###
|
|
749
|
-
|
|
750
|
-
Development tooling has been modernized:
|
|
751
|
-
|
|
752
|
-
- **Linter**: Biome (replaces ESLint + Prettier)
|
|
753
|
-
- **Package Manager**: pnpm recommended (npm/yarn still work)
|
|
754
|
-
- **Pre-commit Hooks**: nano-staged + simple-git-hooks
|
|
616
|
+
### System Libraries
|
|
755
617
|
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
## Common Build Issues
|
|
759
|
-
|
|
760
|
-
### Issue: "Cannot find liblzma library"
|
|
761
|
-
|
|
762
|
-
**Solution**: Install system development package or let node-gyp download it:
|
|
618
|
+
If prebuilt binaries don't match your platform, install system development libraries:
|
|
763
619
|
|
|
764
620
|
```bash
|
|
765
621
|
# Debian/Ubuntu
|
|
@@ -768,374 +624,198 @@ sudo apt-get install liblzma-dev
|
|
|
768
624
|
# macOS
|
|
769
625
|
brew install xz
|
|
770
626
|
|
|
771
|
-
# Windows (
|
|
627
|
+
# Windows (automatic download and build)
|
|
772
628
|
npm install node-liblzma --build-from-source
|
|
773
629
|
```
|
|
774
630
|
|
|
775
|
-
###
|
|
776
|
-
|
|
777
|
-
**Symptoms**: Build fails with C++ compilation errors
|
|
778
|
-
|
|
779
|
-
**Solutions**:
|
|
780
|
-
1. Install build tools:
|
|
781
|
-
```bash
|
|
782
|
-
# Ubuntu/Debian
|
|
783
|
-
sudo apt-get install build-essential python3
|
|
784
|
-
|
|
785
|
-
# macOS (install Xcode Command Line Tools)
|
|
786
|
-
xcode-select --install
|
|
787
|
-
|
|
788
|
-
# Windows
|
|
789
|
-
npm install --global windows-build-tools
|
|
790
|
-
```
|
|
791
|
-
|
|
792
|
-
2. Clear build cache and retry:
|
|
793
|
-
```bash
|
|
794
|
-
rm -rf build node_modules
|
|
795
|
-
npm install
|
|
796
|
-
```
|
|
797
|
-
|
|
798
|
-
### Issue: "Prebuilt binary not found"
|
|
799
|
-
|
|
800
|
-
**Solution**: Your platform might not have prebuilt binaries. Build from source:
|
|
631
|
+
### Build from Source
|
|
801
632
|
|
|
802
633
|
```bash
|
|
634
|
+
# Force rebuild with default options
|
|
803
635
|
npm install node-liblzma --build-from-source
|
|
804
|
-
```
|
|
805
|
-
|
|
806
|
-
## Runtime Issues
|
|
807
|
-
|
|
808
|
-
### Issue: "Memory allocation failed" (LZMAMemoryError)
|
|
809
|
-
|
|
810
|
-
**Causes**:
|
|
811
|
-
- Input buffer exceeds 512MB limit (security protection)
|
|
812
|
-
- System out of memory
|
|
813
|
-
- Trying to decompress extremely large archive
|
|
814
|
-
|
|
815
|
-
**Solutions**:
|
|
816
|
-
1. For files > 512MB, use streaming APIs:
|
|
817
|
-
```typescript
|
|
818
|
-
import { createReadStream, createWriteStream } from 'fs';
|
|
819
|
-
import { createXz } from 'node-liblzma';
|
|
820
|
-
|
|
821
|
-
createReadStream('large-file.bin')
|
|
822
|
-
.pipe(createXz())
|
|
823
|
-
.pipe(createWriteStream('large-file.xz'));
|
|
824
|
-
```
|
|
825
|
-
|
|
826
|
-
2. Or use file helpers (automatically handle large files):
|
|
827
|
-
```typescript
|
|
828
|
-
await xzFile('large-file.bin', 'large-file.xz');
|
|
829
|
-
```
|
|
830
|
-
|
|
831
|
-
### Issue: "Corrupt compressed data" (LZMADataError)
|
|
832
|
-
|
|
833
|
-
**Symptoms**: Decompression fails with `LZMADataError`
|
|
834
|
-
|
|
835
|
-
**Causes**:
|
|
836
|
-
- File is not actually XZ/LZMA compressed
|
|
837
|
-
- File is corrupted or incomplete
|
|
838
|
-
- Wrong file format (LZMA1 vs LZMA2)
|
|
839
636
|
|
|
840
|
-
|
|
841
|
-
1. Verify file format:
|
|
842
|
-
```bash
|
|
843
|
-
file compressed.xz
|
|
844
|
-
# Should show: "XZ compressed data"
|
|
845
|
-
```
|
|
846
|
-
|
|
847
|
-
2. Check file integrity:
|
|
848
|
-
```bash
|
|
849
|
-
xz -t compressed.xz
|
|
850
|
-
```
|
|
851
|
-
|
|
852
|
-
3. Handle errors gracefully:
|
|
853
|
-
```typescript
|
|
854
|
-
try {
|
|
855
|
-
const data = await unxzAsync(buffer);
|
|
856
|
-
} catch (error) {
|
|
857
|
-
if (error instanceof LZMADataError) {
|
|
858
|
-
console.error('Invalid or corrupt XZ file');
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
```
|
|
862
|
-
|
|
863
|
-
### Issue: Thread support warnings during compilation
|
|
864
|
-
|
|
865
|
-
**Symptoms**: Compiler warnings about `-Wmissing-field-initializers`
|
|
866
|
-
|
|
867
|
-
**Status**: This is normal and does not affect functionality. Thread support still works correctly.
|
|
868
|
-
|
|
869
|
-
**Disable thread support** (if warnings are problematic):
|
|
870
|
-
```bash
|
|
637
|
+
# Disable thread support
|
|
871
638
|
ENABLE_THREAD_SUPPORT=no npm install node-liblzma --build-from-source
|
|
872
639
|
```
|
|
873
640
|
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
### Issue: Compression is slow on multi-core systems
|
|
641
|
+
<details>
|
|
642
|
+
<summary><strong>Custom XZ installation</strong></summary>
|
|
877
643
|
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
```typescript
|
|
881
|
-
import { xz } from 'node-liblzma';
|
|
644
|
+
If you compiled XZ outside of node-liblzma:
|
|
882
645
|
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
646
|
+
```bash
|
|
647
|
+
export CPATH=$HOME/path/to/headers
|
|
648
|
+
export LIBRARY_PATH=$HOME/path/to/lib
|
|
649
|
+
export LD_LIBRARY_PATH=$HOME/path/to/lib:$LD_LIBRARY_PATH
|
|
650
|
+
npm install
|
|
886
651
|
```
|
|
887
652
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
### Issue: High memory usage with concurrent operations
|
|
653
|
+
</details>
|
|
891
654
|
|
|
892
|
-
|
|
655
|
+
## Testing
|
|
893
656
|
|
|
894
|
-
```
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
// Pool automatically queues excess operations
|
|
900
|
-
const results = await Promise.all(
|
|
901
|
-
largeArray.map(item => pool.compress(item))
|
|
902
|
-
);
|
|
657
|
+
```bash
|
|
658
|
+
pnpm test # Run all 519 tests
|
|
659
|
+
pnpm test:watch # Watch mode
|
|
660
|
+
pnpm test:coverage # Coverage report
|
|
661
|
+
pnpm type-check # TypeScript type checking
|
|
903
662
|
```
|
|
904
663
|
|
|
905
|
-
|
|
664
|
+
Tests use [Vitest](https://vitest.dev/) with 100% code coverage across statements, branches, functions, and lines.
|
|
906
665
|
|
|
907
|
-
|
|
666
|
+
## Migration Guide
|
|
908
667
|
|
|
909
|
-
|
|
910
|
-
1. Install Visual Studio Build Tools:
|
|
911
|
-
```powershell
|
|
912
|
-
npm install --global windows-build-tools
|
|
913
|
-
```
|
|
668
|
+
### v1.x → v2.0
|
|
914
669
|
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
npm config set python python3
|
|
918
|
-
```
|
|
670
|
+
<details>
|
|
671
|
+
<summary><strong>Breaking changes and new features</strong></summary>
|
|
919
672
|
|
|
920
|
-
|
|
921
|
-
```powershell
|
|
922
|
-
npm install node-liblzma --build-from-source
|
|
923
|
-
```
|
|
673
|
+
#### Breaking Changes
|
|
924
674
|
|
|
925
|
-
|
|
675
|
+
1. **Node.js >= 16** required (was >= 12)
|
|
676
|
+
2. **ESM module format** (`import` instead of `require`)
|
|
677
|
+
3. **TypeScript source** (CoffeeScript removed)
|
|
926
678
|
|
|
927
|
-
|
|
679
|
+
#### New Features
|
|
928
680
|
|
|
929
|
-
**Solution**: Use forward slashes or `path.join()`:
|
|
930
681
|
```typescript
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
```
|
|
682
|
+
// Promise-based APIs (recommended)
|
|
683
|
+
const compressed = await xzAsync(buffer);
|
|
934
684
|
|
|
935
|
-
|
|
685
|
+
// Typed error classes
|
|
686
|
+
import { LZMAMemoryError, LZMADataError } from 'node-liblzma';
|
|
936
687
|
|
|
937
|
-
|
|
688
|
+
// Concurrency control
|
|
689
|
+
const pool = new LZMAPool(10);
|
|
690
|
+
const results = await Promise.all(files.map(f => pool.compress(f)));
|
|
938
691
|
|
|
939
|
-
|
|
692
|
+
// File helpers
|
|
693
|
+
await xzFile('input.txt', 'output.txt.xz');
|
|
694
|
+
```
|
|
940
695
|
|
|
941
|
-
|
|
942
|
-
```bash
|
|
943
|
-
git clone https://github.com/oorabona/node-liblzma.git
|
|
944
|
-
cd node-liblzma
|
|
945
|
-
```
|
|
696
|
+
#### Tooling Changes
|
|
946
697
|
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
# or
|
|
951
|
-
npm install
|
|
952
|
-
```
|
|
698
|
+
- **Linter**: Biome (replaces ESLint + Prettier)
|
|
699
|
+
- **Tests**: Vitest (replaces Mocha)
|
|
700
|
+
- **Package Manager**: pnpm recommended
|
|
953
701
|
|
|
954
|
-
|
|
955
|
-
```bash
|
|
956
|
-
pnpm build
|
|
957
|
-
```
|
|
702
|
+
</details>
|
|
958
703
|
|
|
959
|
-
|
|
960
|
-
```bash
|
|
961
|
-
pnpm test
|
|
962
|
-
```
|
|
704
|
+
## Contributing
|
|
963
705
|
|
|
964
|
-
|
|
706
|
+
We welcome contributions! See the full [contributing guidelines](#development-workflow) below.
|
|
965
707
|
|
|
966
|
-
###
|
|
708
|
+
### Development Setup
|
|
967
709
|
|
|
968
710
|
```bash
|
|
969
|
-
|
|
711
|
+
git clone https://github.com/oorabona/node-liblzma.git
|
|
712
|
+
cd node-liblzma
|
|
713
|
+
pnpm install
|
|
714
|
+
pnpm build
|
|
970
715
|
pnpm test
|
|
971
|
-
|
|
972
|
-
# Watch mode (re-run on changes)
|
|
973
|
-
pnpm test:watch
|
|
974
|
-
|
|
975
|
-
# Coverage report
|
|
976
|
-
pnpm test:coverage
|
|
977
|
-
|
|
978
|
-
# Interactive UI
|
|
979
|
-
pnpm test:ui
|
|
980
716
|
```
|
|
981
717
|
|
|
982
|
-
###
|
|
983
|
-
|
|
984
|
-
We use [Biome](https://biomejs.dev/) for linting and formatting:
|
|
718
|
+
### Development Workflow
|
|
985
719
|
|
|
986
720
|
```bash
|
|
987
|
-
#
|
|
988
|
-
pnpm
|
|
989
|
-
|
|
990
|
-
#
|
|
991
|
-
pnpm check:write
|
|
992
|
-
|
|
993
|
-
# Lint only
|
|
994
|
-
pnpm lint
|
|
995
|
-
|
|
996
|
-
# Format only
|
|
997
|
-
pnpm format:write
|
|
721
|
+
pnpm test # Run tests
|
|
722
|
+
pnpm test:watch # Watch mode
|
|
723
|
+
pnpm test:coverage # Coverage report
|
|
724
|
+
pnpm check # Lint + format check (Biome)
|
|
725
|
+
pnpm check:write # Auto-fix lint/format
|
|
726
|
+
pnpm type-check # TypeScript types
|
|
998
727
|
```
|
|
999
728
|
|
|
1000
|
-
|
|
729
|
+
We follow [Conventional Commits](https://www.conventionalcommits.org/):
|
|
1001
730
|
|
|
1002
|
-
```
|
|
1003
|
-
|
|
731
|
+
```
|
|
732
|
+
feat: add LZMAPool for concurrency control
|
|
733
|
+
fix: resolve memory leak in FunctionReference
|
|
734
|
+
docs: add migration guide for v2.0
|
|
1004
735
|
```
|
|
1005
736
|
|
|
1006
|
-
|
|
737
|
+
### Pull Request Process
|
|
1007
738
|
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
739
|
+
1. Fork and create a feature branch (`feat/`, `fix/`, `refactor/`, `docs/`)
|
|
740
|
+
2. Add tests for new functionality (100% coverage required)
|
|
741
|
+
3. Run `pnpm check:write && pnpm type-check && pnpm test`
|
|
742
|
+
4. Commit with conventional commits and push
|
|
743
|
+
5. CI checks run automatically on PR
|
|
1012
744
|
|
|
1013
|
-
##
|
|
745
|
+
## Troubleshooting
|
|
1014
746
|
|
|
1015
|
-
|
|
747
|
+
<details>
|
|
748
|
+
<summary><strong>Build issues</strong></summary>
|
|
1016
749
|
|
|
750
|
+
**"Cannot find liblzma library"** — Install system dev package:
|
|
751
|
+
```bash
|
|
752
|
+
sudo apt-get install liblzma-dev # Debian/Ubuntu
|
|
753
|
+
brew install xz # macOS
|
|
1017
754
|
```
|
|
1018
|
-
<type>(<scope>): <description>
|
|
1019
755
|
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
756
|
+
**"node-gyp rebuild failed"** — Install build tools:
|
|
757
|
+
```bash
|
|
758
|
+
sudo apt-get install build-essential python3 # Linux
|
|
759
|
+
xcode-select --install # macOS
|
|
760
|
+
npm install --global windows-build-tools # Windows
|
|
1023
761
|
```
|
|
1024
762
|
|
|
1025
|
-
**
|
|
1026
|
-
- `feat`: New feature
|
|
1027
|
-
- `fix`: Bug fix
|
|
1028
|
-
- `docs`: Documentation changes
|
|
1029
|
-
- `refactor`: Code refactoring
|
|
1030
|
-
- `test`: Test changes
|
|
1031
|
-
- `chore`: Build/tooling changes
|
|
1032
|
-
- `perf`: Performance improvements
|
|
1033
|
-
|
|
1034
|
-
**Examples**:
|
|
763
|
+
**"Prebuilt binary not found"** — Build from source:
|
|
1035
764
|
```bash
|
|
1036
|
-
|
|
1037
|
-
git commit -m "fix: resolve memory leak in FunctionReference"
|
|
1038
|
-
git commit -m "docs: add migration guide for v2.0"
|
|
765
|
+
npm install node-liblzma --build-from-source
|
|
1039
766
|
```
|
|
1040
767
|
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
1. **Fork the repository** and create a feature branch:
|
|
1044
|
-
```bash
|
|
1045
|
-
git checkout -b feat/my-new-feature
|
|
1046
|
-
```
|
|
1047
|
-
|
|
1048
|
-
2. **Make your changes** following code style guidelines
|
|
1049
|
-
|
|
1050
|
-
3. **Add tests** for new functionality:
|
|
1051
|
-
- All new code must have 100% test coverage
|
|
1052
|
-
- Tests go in `test/` directory
|
|
1053
|
-
- Use Vitest testing framework
|
|
1054
|
-
|
|
1055
|
-
4. **Ensure all checks pass**:
|
|
1056
|
-
```bash
|
|
1057
|
-
pnpm check:write # Fix code style
|
|
1058
|
-
pnpm type-check # Verify TypeScript types
|
|
1059
|
-
pnpm test # Run test suite
|
|
1060
|
-
```
|
|
1061
|
-
|
|
1062
|
-
5. **Commit with conventional commits**:
|
|
1063
|
-
```bash
|
|
1064
|
-
git add .
|
|
1065
|
-
git commit -m "feat: add new feature"
|
|
1066
|
-
```
|
|
1067
|
-
|
|
1068
|
-
6. **Push and create Pull Request**:
|
|
1069
|
-
```bash
|
|
1070
|
-
git push origin feat/my-new-feature
|
|
1071
|
-
```
|
|
768
|
+
</details>
|
|
1072
769
|
|
|
1073
|
-
|
|
770
|
+
<details>
|
|
771
|
+
<summary><strong>Runtime issues</strong></summary>
|
|
1074
772
|
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
- **Coverage**: Maintain 100% code coverage (statements, branches, functions, lines)
|
|
1078
|
-
- **Test files**: Name tests `*.test.ts` in `test/` directory
|
|
1079
|
-
- **Structure**: Use `describe` and `it` blocks with clear descriptions
|
|
1080
|
-
- **Assertions**: Use Vitest's `expect()` API
|
|
1081
|
-
|
|
1082
|
-
**Example test**:
|
|
773
|
+
**LZMAMemoryError** — Input too large for buffer API. Use streaming:
|
|
1083
774
|
```typescript
|
|
1084
|
-
|
|
1085
|
-
import { xzAsync, unxzAsync } from '../src/lzma.js';
|
|
1086
|
-
|
|
1087
|
-
describe('Compression', () => {
|
|
1088
|
-
it('should compress and decompress data', async () => {
|
|
1089
|
-
const original = Buffer.from('test data');
|
|
1090
|
-
const compressed = await xzAsync(original);
|
|
1091
|
-
const decompressed = await unxzAsync(compressed);
|
|
1092
|
-
|
|
1093
|
-
expect(decompressed.equals(original)).toBe(true);
|
|
1094
|
-
});
|
|
1095
|
-
});
|
|
775
|
+
createReadStream('large.bin').pipe(createXz()).pipe(createWriteStream('large.xz'));
|
|
1096
776
|
```
|
|
1097
777
|
|
|
1098
|
-
|
|
778
|
+
**LZMADataError** — File is not XZ-compressed or is corrupted. Verify with `file compressed.xz` or `xz -t compressed.xz`.
|
|
1099
779
|
|
|
1100
|
-
|
|
780
|
+
**Slow on multi-core** — Enable threads: `createXz({ threads: 0 })` (auto-detect cores).
|
|
1101
781
|
|
|
1102
|
-
|
|
1103
|
-
# Standard release (patch/minor/major based on commits)
|
|
1104
|
-
pnpm release
|
|
782
|
+
**High memory with concurrency** — Use `LZMAPool` to limit simultaneous operations.
|
|
1105
783
|
|
|
1106
|
-
|
|
1107
|
-
pnpm release:manual
|
|
784
|
+
</details>
|
|
1108
785
|
|
|
1109
|
-
|
|
1110
|
-
|
|
786
|
+
<details>
|
|
787
|
+
<summary><strong>Windows-specific</strong></summary>
|
|
1111
788
|
|
|
1112
|
-
|
|
1113
|
-
|
|
789
|
+
**Build fails** — Install Visual Studio Build Tools and set Python:
|
|
790
|
+
```powershell
|
|
791
|
+
npm install --global windows-build-tools
|
|
792
|
+
npm config set python python3
|
|
1114
793
|
```
|
|
1115
794
|
|
|
1116
|
-
**
|
|
795
|
+
**Path issues** — Use `path.join()` instead of hardcoded separators.
|
|
1117
796
|
|
|
1118
|
-
|
|
797
|
+
</details>
|
|
1119
798
|
|
|
1120
|
-
|
|
1121
|
-
- **Bugs**: Open an [Issue](https://github.com/oorabona/node-liblzma/issues)
|
|
1122
|
-
- **Security**: Email security@example.com (do not open public issues)
|
|
799
|
+
## Related Projects
|
|
1123
800
|
|
|
1124
|
-
|
|
801
|
+
- [tar-xz](https://www.npmjs.com/package/tar-xz) — Create/extract tar.xz archives (powered by node-liblzma)
|
|
802
|
+
- [nxz](https://www.npmjs.com/package/nxz) — Standalone CLI for XZ compression
|
|
803
|
+
- [lzma-purejs](https://github.com/cscott/lzma-purejs) — Pure JavaScript LZMA implementation
|
|
804
|
+
- [node-xz](https://github.com/robey/node-xz) — Node binding of XZ library
|
|
805
|
+
- [lzma-native](https://github.com/addaleax/lzma-native) — Complete XZ library bindings
|
|
1125
806
|
|
|
1126
|
-
|
|
807
|
+
## Bugs
|
|
1127
808
|
|
|
1128
|
-
|
|
809
|
+
If you find one, feel free to contribute and post a new [issue](https://github.com/oorabona/node-liblzma/issues)!
|
|
810
|
+
PRs are accepted as well :)
|
|
1129
811
|
|
|
1130
|
-
If you
|
|
1131
|
-
|
|
812
|
+
If you compile with threads, you may see warnings about `-Wmissing-field-initializers`.
|
|
813
|
+
This is normal and does not prevent threading from being active and working.
|
|
1132
814
|
|
|
1133
|
-
|
|
815
|
+
## Acknowledgements
|
|
1134
816
|
|
|
1135
|
-
|
|
1136
|
-
This is _normal_ and does not prevent threading from being active and working.
|
|
1137
|
-
I did not yet figure how to fix this except by masking the warning..
|
|
817
|
+
Kudos to [addaleax](https://github.com/addaleax) for helping out with C++ stuff!
|
|
1138
818
|
|
|
1139
|
-
|
|
819
|
+
## License
|
|
1140
820
|
|
|
1141
|
-
This software is released under [
|
|
821
|
+
This software is released under [LGPL-3.0+](LICENSE).
|