{"_id":"@emn178/lzma-wasm","name":"@emn178/lzma-wasm","dist-tags":{"latest":"1.1.0"},"versions":{"1.1.0":{"name":"@emn178/lzma-wasm","version":"1.1.0","author":{"name":"emn178"},"contributors":[{"name":"Aluria"}],"description":"High-performance universal LZMA/XZ/LZIP compressor & decompressor in WebAssembly (Rust bindings)","keywords":["lzma","xz","lzip","wasm","webassembly","compress","decompress","archive","rust","zero-allocation","performance","browser","node"],"homepage":"https://github.com/emn178/lzma-wasm#readme","bugs":{"url":"https://github.com/emn178/lzma-wasm/issues"},"repository":{"type":"git","url":"git+https://github.com/emn178/lzma-wasm.git"},"publishConfig":{"access":"public"},"license":"(MIT OR Apache-2.0)","sideEffects":false,"engines":{"node":">=16.0.0"},"type":"module","main":"./dist/cjs/index.cjs","module":"./dist/esm/index.js","types":"./dist/index.d.ts","unpkg":"./dist/iife/index.js","jsdelivr":"./dist/iife/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.cjs","default":"./dist/esm/index.js"},"./external":{"types":"./dist/external.d.ts","browser":{"types":"./dist/external.d.ts","default":"./dist/esm/external.js"},"node":{"types":"./dist/external-node.d.ts","import":"./dist/esm/external-node.js","require":"./dist/cjs/external-node.cjs","default":"./dist/esm/external-node.js"},"import":"./dist/esm/external.js","require":"./dist/cjs/external-node.cjs","default":"./dist/esm/external.js"},"./lzma_wasm_bg.wasm":"./dist/wasm/lzma_wasm_bg.wasm"},"scripts":{"build":"node ./scripts/build.mjs","tsc":"tsc","prepublishOnly":"pnpm run build","test":"vitest run"},"devDependencies":{"@types/node":"^25.6.0","esbuild":"^0.28.0","playwright":"^1.54.1","typescript":"^6.0.3","vitest":"^4.1.5"},"_id":"@emn178/lzma-wasm@1.1.0","gitHead":"1f2c7b6f7b25bbb1e5773879fa73769d99a0d81a","_nodeVersion":"22.14.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-fp8lr/7I1gdtmLVXKkVDllBe4Ku3s++k8SuAUefnePDNVHWKI0P/CwgoFnYaF6kqkai9jgpfMsI+rBQ1ClltrA==","shasum":"14ada7b3f7defb82f02cb7a03019b0bcd57a01e1","tarball":"https://registry.npmjs.org/@emn178/lzma-wasm/-/lzma-wasm-1.1.0.tgz","fileCount":18,"unpackedSize":1434063,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIA9jpkAm7lbbw6RCzde1q3xFTxFByCxndPJ2RNnSC7QAAiEAqmU482eQ5gWH1WY5yWNkHfXclAruFLD5HlLfznEf8QI="}]},"_npmUser":{"name":"emn178","email":"emn178@gmail.com"},"directories":{},"maintainers":[{"name":"emn178","email":"emn178@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/lzma-wasm_1.1.0_1784684136220_0.023588707386569707"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-22T01:35:36.131Z","1.1.0":"2026-07-22T01:35:36.354Z","modified":"2026-07-22T01:35:36.505Z"},"maintainers":[{"name":"emn178","email":"emn178@gmail.com"}],"description":"High-performance universal LZMA/XZ/LZIP compressor & decompressor in WebAssembly (Rust bindings)","homepage":"https://github.com/emn178/lzma-wasm#readme","keywords":["lzma","xz","lzip","wasm","webassembly","compress","decompress","archive","rust","zero-allocation","performance","browser","node"],"repository":{"type":"git","url":"git+https://github.com/emn178/lzma-wasm.git"},"contributors":[{"name":"Aluria"}],"author":{"name":"emn178"},"bugs":{"url":"https://github.com/emn178/lzma-wasm/issues"},"license":"(MIT OR Apache-2.0)","readme":"# @emn178/lzma-wasm\n\n[![npm version](https://img.shields.io/npm/v/@emn178/lzma-wasm.svg)](https://www.npmjs.com/package/@emn178/lzma-wasm)\n[![License](https://img.shields.io/badge/License-MIT%20OR%20Apache--2.0-blue.svg)](#license)\n\n**[View on GitHub](https://github.com/emn178/lzma-wasm)** | **[View on npm](https://www.npmjs.com/package/@emn178/lzma-wasm)**\n\nThis package is maintained as a fork of the original [`lzma-wasm`](https://github.com/Wu-Yijun/lzma-wasm) project.\n\nA high-performance, universal WebAssembly binding for the [`lzma-rust2`](https://github.com/hasenbanck/lzma-rust2) crate (currently **0.16.5**). It brings near-native LZMA, XZ, and LZIP compression and decompression to Node.js, modern browsers, and bundlers.\n\n## Features\n\n* **Near-Native Performance:** Powered by Rust and WebAssembly, heavily optimized for execution in V8/modern JS engines.\n* **Universal & Zero-Config:** The Wasm binary is base64-inlined. **No `wasm-loader`, no static asset serving, and no Webpack/Vite configuration required.** Just import and use it anywhere.\n* **External Wasm Support:** An optional external-Wasm entry is available for Workers and bundlers that prefer a separately cached `.wasm` asset.\n* **Multi-Format Support:** Seamlessly supports `.xz` (modern, recommended), `.lzma` (legacy), and `.lz` (lzip) formats.\n* **Streaming codec API:** Incremental XZ encode/decode; incremental LZIP and LZMA-Alone encode.\n* **Zero-Allocation Decompression:** Expert APIs are available to decompress directly into pre-allocated memory and reduce JavaScript Garbage Collection (GC) overhead.\n* **Safe & Robust:** Output-size limits help protect applications from unexpectedly large decompressed data. LZMA-Alone also supports a separate decoder-memory limit.\n\nStreaming support matrix:\n\n| Format | Streaming encode | Streaming decode |\n|--------|------------------|------------------|\n| XZ | yes | yes |\n| LZIP | yes | not yet (upstream resumable LZMA1 required) |\n| LZMA-Alone | yes | not yet (upstream resumable LZMA1 required) |\n\nOne-shot compress/decompress remains available for all three formats.\n\n## 📦 Installation\n\n```bash\nnpm install @emn178/lzma-wasm\n# or\nyarn add @emn178/lzma-wasm\npnpm add @emn178/lzma-wasm\n```\n\nGit checkouts do **not** include built `dist/` or Wasm files because they are build outputs. Use a published npm package, or run `pnpm run build` and consume a packed `.tgz` after building.\n\n## Import Methods\n\nThis library ships with ES Modules, CommonJS, and IIFE builds, making it compatible with any environment.\n\n**1. ES Modules (Vite, Rollup, Deno, Node.js ESM)**\n```javascript\nimport { initWasm, compress, decompress } from '@emn178/lzma-wasm';\n```\n\n**2. CommonJS (Node.js)**\n```javascript\nconst { initWasm, compress, decompress } = require('@emn178/lzma-wasm');\n```\n\n**3. Browser / CDN (Raw HTML)**\n```html\n<script src=\"https://cdn.jsdelivr.net/npm/@emn178/lzma-wasm/dist/iife/index.js\"></script>\n<script>\n  // Exposed globally as `lzma_wasm`\n  const { initWasm, compress, decompress } = window.lzma_wasm;\n</script>\n```\n\n## 🚀 Quick Start\n\n**⚠️ Important:** You must call and await `initWasm()` once before using any compression or decompression methods.\n\nThe asynchronous `initWasm` can be replaced by the synchronous function `initWasmSync`.\n\n```javascript\nimport { initWasm, compress, decompress } from '@emn178/lzma-wasm';\n\nasync function run() {\n    // 1. Initialize the Wasm module\n    await initWasm();\n\n    const text = \"WebAssembly is awesome! \".repeat(100);\n    const rawData = new TextEncoder().encode(text);\n\n    // 2. Compress (Default is 'xz' format, level 6)\n    const compressed = compress(rawData, { format: 'xz', level: 6 });\n    console.log(`Compressed size: ${compressed.length} bytes`);\n\n    // 3. Decompress\n    const decompressed = decompress(compressed);\n    const decodedText = new TextDecoder().decode(decompressed);\n\n    console.log(decodedText.substring(0, 23)); // \"WebAssembly is awesome!\"\n}\n\nrun();\n```\n\n## Embedded Wasm Entry (Default)\n\nWASM bytes are Base64-inlined. No asset serving is required.\n\n```js\nimport { initWasm, compress, decompress } from \"@emn178/lzma-wasm\";\n\nawait initWasm();\nconst compressed = compress(data, { format: \"xz\", level: 6 });\nconst out = decompress(compressed);\n```\n\n`initWasm()` shares an in-flight Promise across concurrent callers. After a failure, a later\ncall can retry. `initWasmSync()` throws if asynchronous initialization is already in progress.\n\n## External Wasm Entry\n\n```js\nimport { initWasm, compress, decompress } from \"@emn178/lzma-wasm/external\";\n\n// Browser/Worker: zero-arg uses the shipped `.wasm` URL next to this module.\nawait initWasm();\n\n// Explicit URL for a custom asset layout:\n// await initWasm(new URL(\"/assets/lzma_wasm_bg.wasm\", location.href));\n```\n\nPackage paths:\n\n- JS: `@emn178/lzma-wasm/external`\n- WASM: `@emn178/lzma-wasm/lzma_wasm_bg.wasm` → `dist/wasm/lzma_wasm_bg.wasm`\n\nThe external JS bundle does **not** embed a Base64 copy of the WASM.\n\nExport conditions for `@emn178/lzma-wasm/external`:\n\n| Condition | Entry | Notes |\n|-----------|-------|-------|\n| `browser` / default `import` | `dist/esm/external.js` | No `node:` imports — safe for Vite/esbuild |\n| `node` `import` | `dist/esm/external-node.js` | Zero-arg reads `.wasm` from disk |\n| `node` / default `require` | `dist/cjs/external-node.cjs` | Same for CommonJS |\n\nSync init still requires bytes or a `WebAssembly.Module` (it cannot fetch a URL).\n\n## ⚡ Advanced: Zero-Allocation Decompression\n\nFor extreme performance scenarios (e.g., high-frequency decompression, large files), you can avoid dynamic memory allocation and GC pressure by providing `expectedSize`. The Wasm module writes into a pre-allocated buffer with that capacity.\n\n```javascript\n// If you know the maximum size of the uncompressed data beforehand:\nconst uncompressedCapacity = 2400;\n\nconst result = decompress(compressed, {\n    expectedSize: uncompressedCapacity\n});\n// 'result' is a Uint8Array view containing the bytes actually written.\n// Decompression fails if the output is larger than the supplied capacity.\n```\n\nYou can also call `decompressToBuffer` to decompress data directly into a pre-allocated JavaScript `Uint8Array`.\n\n```javascript\n// You must ensure enough space in your buffer:\nconst buffer = new Uint8Array(2400);\n\n// The data will be written directly into the buffer you provided.\nconst length = decompressToBuffer(compressed, buffer);\n```\n\n## Decompression Options\n\n```ts\ninterface DecompressOptions {\n  /** Destination capacity. May be larger than the actual output. */\n  expectedSize?: number;\n  /** Max decompressed output bytes (all formats). */\n  maxOutputSize?: number;\n  /** LZMA-Alone decoder memory limit only. @default 256 MiB */\n  lzmaMemoryLimit?: number;\n  /** @deprecated Use lzmaMemoryLimit. */\n  memLimit?: number;\n}\n```\n\nRules:\n\n- if both `expectedSize` and `maxOutputSize` are set, require `expectedSize <= maxOutputSize`\n  or throw before allocating;\n- `maxOutputSize` is **not** a WASM-heap / dictionary-memory limit;\n- `lzmaMemoryLimit` does **not** protect XZ or LZIP;\n- `lzmaMemoryLimit` / `memLimit` are expressed in **bytes**. The value is converted to KiB once\n  at the `lzma-rust2` boundary (`floor(bytes / 1024)`). This is a correctness fix: earlier\n  builds accidentally treated the byte value as KiB, so the documented 256 MiB default behaved\n  like 256 GiB.\n\n```ts\ndecompressToBuffer(\n  compressed,\n  outBuffer,\n  options?: { lzmaMemoryLimit?: number; memLimit?: number } | number,\n): number;\n```\n\n`outBuffer.byteLength` is the hard output ceiling. Undersized buffers throw.\n\n## Incremental XZ Decompression\n\n```js\nimport { createDecoder, initWasm } from \"@emn178/lzma-wasm/external\";\n\nawait initWasm();\nconst decoder = createDecoder({\n  format: \"xz\",\n  maxOutputSize: 512 * 1024 * 1024,\n});\n\nfor await (const inputChunk of compressedInput) {\n  const outputChunk = decoder.write(inputChunk);\n  if (outputChunk.byteLength) consume(outputChunk);\n}\n\nconst finalChunk = decoder.finish();\nif (finalChunk.byteLength) consume(finalChunk);\n```\n\n`write()` accepts arbitrary input boundaries and may return an empty chunk while an XZ or LZMA2\nstructure is incomplete. `finish()` validates the complete stream, including block checksums,\nIndex and footer; truncated input throws. Concatenated XZ streams are supported. Call `close()`\nto release the decoder early after cancellation.\n\n## Incremental Compression\n\n```js\nimport { createEncoder, initWasm } from \"@emn178/lzma-wasm/external\";\n\nawait initWasm();\nconst encoder = createEncoder({\n  format: \"xz\", // or \"lzip\" / \"lzma\"\n  level: 6,\n  // XZ-only optional tuning; defaults to 1 MiB / 4 MiB:\n  // dictionarySize: 1024 * 1024,\n  // blockSize: 4 * 1024 * 1024,\n});\n\nfor await (const inputChunk of uncompressedInput) {\n  const outputChunk = encoder.write(inputChunk);\n  if (outputChunk.byteLength) consume(outputChunk);\n}\n\nconst finalChunk = encoder.finish();\nif (finalChunk.byteLength) consume(finalChunk);\n```\n\nAll `write()` calls share one encoder instance and codec state. A call may return an empty\nchunk while the encoder buffers data. `finish()` emits the remaining compressed bytes and\nformat trailer. Call `close()` to release the encoder without finalizing it after cancellation.\n\nFor XZ, `dictionarySize` defaults to 1 MiB. A smaller dictionary reduces memory use and\nmatch-search work at the cost of compression ratio. `blockSize` creates multiple independently\ncompressed blocks inside one XZ stream and must be at least as large as the effective\ndictionary. It defaults to 4 MiB, or the dictionary size when a larger custom dictionary is\nselected. Both values are expressed in bytes and are rejected for LZIP/LZMA-Alone streaming.\n\nStreaming LZMA-Alone uses an unknown-size `.lzma` header plus an end marker because the total\ninput length is not known when the encoder is constructed. Byte-for-byte output may therefore\ndiffer from one-shot `compress(..., { format: \"lzma\" })`, which writes the known uncompressed\nsize.\n\n## Compression Options\n\n```ts\ncompress(data, { format?: \"xz\" | \"lzma\" | \"lzip\"; level?: 0..9 });\n```\n\nUnknown `format` values throw. Non-integer / out-of-range `level` values throw.\nDefault when omitted: `format: \"xz\"`, `level: 6`.\n\n## Formats\n\n| Format | Compress | Decompress detection |\n|--------|----------|----------------------|\n| XZ | yes | 6-byte magic `FD 37 7A 58 5A 00` |\n| LZIP | yes | 4-byte magic `LZIP` (version + dictionary bytes validated) |\n| LZMA-Alone | yes | fallback when neither magic matches |\n\n## 📊 Performance Benchmarks\n\nUsing a non-rigorous test, we briefly evaluated the compression and decompression performance of various algorithms and compression levels within our test environment. *(Note: The observed speeds may appear extraordinarily high because highly repetitive JSON text data was used as the test sample, rather than dense binary executables.)*\n\nThe following table is retained from the original project README at commit `dbe085ddcc58863bc87025520f7467cd8dc8a364`. It has not yet been rerun against the current release, so treat it as historical reference data rather than a current performance guarantee.\n\n| (index) | Env      | Platform  | Format | Level | RawSize KB | Compression Rate | Enc MB/s | Dec MB/s  | DecToBuf MB/s |\n| :---:   |  :---:   |  :---:    |  :---: | :---: |  ---:     |  ---:        |  ---:   |  ---:    |  ---:         |\n| 0       | 'ESM'    | 'Nodejs'  | 'XZ'   | 1     | 8426.02   | 1.1273       | 140.598 | 358.707  | 368.754       |\n| 1       | 'ESM'    | 'Nodejs'  | 'XZ'   | 6     | 8426.02   | 1.1247       | 13.753  | 353.292  | 372.668       |\n| 2       | 'ESM'    | 'Nodejs'  | 'XZ'   | 9     | 8426.02   | 1.1247       | 13.177  | 300.286  | 322.342       |\n| 3       | 'ESM'    | 'Nodejs'  | 'LZMA' | 1     | 8426.02   | 1.1262       | 206.875 | 1343.863 | 1501.964      |\n| 4       | 'ESM'    | 'Nodejs'  | 'LZMA' | 6     | 8426.02   | 1.1236       | 14.485  | 1224.712 | 1445.286      |\n| 5       | 'ESM'    | 'Nodejs'  | 'LZMA' | 9     | 8426.02   | 1.1236       | 13.545  | 1242.776 | 1409.033      |\n| 6       | 'ESM'    | 'Nodejs'  | 'LZIP' | 1     | 8426.02   | 1.1265       | 156.559 | 379.209  | 394.477       |\n| 7       | 'ESM'    | 'Nodejs'  | 'LZIP' | 6     | 8426.02   | 1.1238       | 13.907  | 366.508  | 390.274       |\n| 8       | 'ESM'    | 'Nodejs'  | 'LZIP' | 9     | 8426.02   | 1.1238       | 13.127  | 318.203  | 339.759       |\n| 9       | 'CJS'    | 'Nodejs'  | 'XZ'   | 1     | 8392.24   | 1.1305       | 149.621 | 360.957  | 374.654       |\n| 10      | 'CJS'    | 'Nodejs'  | 'XZ'   | 6     | 8392.24   | 1.1219       | 13.839  | 355.453  | 370.518       |\n| 11      | 'CJS'    | 'Nodejs'  | 'XZ'   | 9     | 8392.24   | 1.1219       | 13.242  | 304.177  | 316.927       |\n| 12      | 'CJS'    | 'Nodejs'  | 'LZMA' | 1     | 8392.24   | 1.1294       | 205.239 | 1344.910 | 1554.119      |\n| 13      | 'CJS'    | 'Nodejs'  | 'LZMA' | 6     | 8392.24   | 1.1208       | 14.569  | 1277.358 | 1482.728      |\n| 14      | 'CJS'    | 'Nodejs'  | 'LZMA' | 9     | 8392.24   | 1.1208       | 13.633  | 1299.108 | 1487.986      |\n| 15      | 'CJS'    | 'Nodejs'  | 'LZIP' | 1     | 8392.24   | 1.1296       | 152.282 | 393.079  | 405.422       |\n| 16      | 'CJS'    | 'Nodejs'  | 'LZIP' | 6     | 8392.24   | 1.1211       | 14.054  | 374.654  | 379.739       |\n| 17      | 'CJS'    | 'Nodejs'  | 'LZIP' | 9     | 8392.24   | 1.1211       | 13.405  | 328.078  | 345.076       |\n| 18      | 'IMPORT' | 'Browser' | 'XZ'   | 1     | 8387.91   | 1.1413       | 96.992  | 340.972  | 302.922       |\n| 19      | 'IMPORT' | 'Browser' | 'XZ'   | 6     | 8387.91   | 1.1228       | 5.685   | 330.233  | 230.627       |\n| 20      | 'IMPORT' | 'Browser' | 'XZ'   | 9     | 8387.91   | 1.1228       | 5.939   | 295.349  | 315.691       |\n| 21      | 'IMPORT' | 'Browser' | 'LZMA' | 1     | 8387.91   | 1.1402       | 117.117 | 933.027  | 1011.811      |\n| 22      | 'IMPORT' | 'Browser' | 'LZMA' | 6     | 8387.91   | 1.1217       | 5.341   | 788.337  | 1009.375      |\n| 23      | 'IMPORT' | 'Browser' | 'LZMA' | 9     | 8387.91   | 1.1217       | 5.784   | 878.315  | 1011.811      |\n| 24      | 'IMPORT' | 'Browser' | 'LZIP' | 1     | 8387.91   | 1.1405       | 96.479  | 322.736  | 344.049       |\n| 25      | 'IMPORT' | 'Browser' | 'LZIP' | 6     | 8387.91   | 1.1219       | 5.785   | 321.007  | 338.495       |\n| 26      | 'IMPORT' | 'Browser' | 'LZIP' | 9     | 8387.91   | 1.1219       | 5.670   | 280.814  | 289.738       |\n| 27      | 'CDN'    | 'Browser' | 'XZ'   | 1     | 8417.64   | 1.1330       | 94.136  | 290.464  | 349.425       |\n| 28      | 'CDN'    | 'Browser' | 'XZ'   | 6     | 8417.64   | 1.1302       | 6.052   | 283.422  | 345.836       |\n| 29      | 'CDN'    | 'Browser' | 'XZ'   | 9     | 8417.64   | 1.1302       | 5.882   | 255.312  | 307.438       |\n| 30      | 'CDN'    | 'Browser' | 'LZMA' | 1     | 8417.64   | 1.1319       | 115.563 | 953.300  | 1017.852      |\n| 31      | 'CDN'    | 'Browser' | 'LZMA' | 6     | 8417.64   | 1.1291       | 5.996   | 911.000  | 1008.101      |\n| 32      | 'CDN'    | 'Browser' | 'LZMA' | 9     | 8417.64   | 1.1291       | 5.843   | 926.033  | 1029.051      |\n| 33      | 'CDN'    | 'Browser' | 'LZIP' | 1     | 8417.64   | 1.1322       | 99.288  | 318.007  | 340.933       |\n| 34      | 'CDN'    | 'Browser' | 'LZIP' | 6     | 8417.64   | 1.1293       | 5.939   | 329.716  | 340.519       |\n| 35      | 'CDN'    | 'Browser' | 'LZIP' | 9     | 8417.64   | 1.1293       | 5.706   | 282.756  | 290.263       |\n\n> **Takeaway:** LZMA provides blisteringly fast decompression speeds, while XZ provides a robust modern container format. Using the Zero-Allocation strategy (`DecToBuf`) consistently boosts decompression throughput by eliminating internal memory reallocations.\n\n## Build / Test\n\n```sh\npnpm install --frozen-lockfile\npnpm run build\npnpm run test\ncargo test\npnpm pack --dry-run\n```\n\nNative interop tests require `xz` (`xz-utils`) and `lzip`. Browser tests require Playwright Chromium.\n\n## 📄 License\n\nThis project is dual-licensed under either the [MIT License](LICENSE-MIT) or the [Apache License, Version 2.0](LICENSE-APACHE), at your option.\n\nThe underlying Rust compression logic is powered by [lzma-rust2](https://github.com/hasenbanck/lzma-rust2) (Apache-2.0 / MIT).\n","readmeFilename":"README.md","_rev":"1-ed5945aeaf0b2ade1a3e4b756fca0635"}