tar-xz 5.0.1 → 6.0.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.
Files changed (62) hide show
  1. package/README.md +323 -115
  2. package/lib/browser/create.d.ts +10 -17
  3. package/lib/browser/create.d.ts.map +1 -1
  4. package/lib/browser/create.js +76 -84
  5. package/lib/browser/create.js.map +1 -1
  6. package/lib/browser/extract.d.ts +12 -13
  7. package/lib/browser/extract.d.ts.map +1 -1
  8. package/lib/browser/extract.js +50 -25
  9. package/lib/browser/extract.js.map +1 -1
  10. package/lib/browser/index.d.ts +4 -4
  11. package/lib/browser/index.d.ts.map +1 -1
  12. package/lib/browser/index.js +4 -4
  13. package/lib/browser/index.js.map +1 -1
  14. package/lib/browser/list.d.ts +7 -11
  15. package/lib/browser/list.d.ts.map +1 -1
  16. package/lib/browser/list.js +23 -15
  17. package/lib/browser/list.js.map +1 -1
  18. package/lib/index.browser.d.ts +5 -4
  19. package/lib/index.browser.d.ts.map +1 -1
  20. package/lib/index.browser.js +4 -3
  21. package/lib/index.browser.js.map +1 -1
  22. package/lib/index.d.ts +6 -4
  23. package/lib/index.d.ts.map +1 -1
  24. package/lib/index.js +4 -3
  25. package/lib/index.js.map +1 -1
  26. package/lib/internal/to-async-iterable.browser.d.ts +18 -0
  27. package/lib/internal/to-async-iterable.browser.d.ts.map +1 -0
  28. package/lib/internal/to-async-iterable.browser.js +66 -0
  29. package/lib/internal/to-async-iterable.browser.js.map +1 -0
  30. package/lib/internal/to-async-iterable.d.ts +19 -0
  31. package/lib/internal/to-async-iterable.d.ts.map +1 -0
  32. package/lib/internal/to-async-iterable.js +73 -0
  33. package/lib/internal/to-async-iterable.js.map +1 -0
  34. package/lib/node/create.d.ts +10 -12
  35. package/lib/node/create.d.ts.map +1 -1
  36. package/lib/node/create.js +109 -124
  37. package/lib/node/create.js.map +1 -1
  38. package/lib/node/extract.d.ts +14 -17
  39. package/lib/node/extract.d.ts.map +1 -1
  40. package/lib/node/extract.js +44 -111
  41. package/lib/node/extract.js.map +1 -1
  42. package/lib/node/file.d.ts +61 -0
  43. package/lib/node/file.d.ts.map +1 -0
  44. package/lib/node/file.js +337 -0
  45. package/lib/node/file.js.map +1 -0
  46. package/lib/node/index.d.ts +3 -2
  47. package/lib/node/index.d.ts.map +1 -1
  48. package/lib/node/index.js +2 -2
  49. package/lib/node/index.js.map +1 -1
  50. package/lib/node/list.d.ts +8 -8
  51. package/lib/node/list.d.ts.map +1 -1
  52. package/lib/node/list.js +13 -15
  53. package/lib/node/list.js.map +1 -1
  54. package/lib/node/xz-helpers.d.ts +15 -0
  55. package/lib/node/xz-helpers.d.ts.map +1 -0
  56. package/lib/node/xz-helpers.js +65 -0
  57. package/lib/node/xz-helpers.js.map +1 -0
  58. package/lib/types.d.ts +55 -66
  59. package/lib/types.d.ts.map +1 -1
  60. package/lib/types.js +7 -0
  61. package/lib/types.js.map +1 -1
  62. package/package.json +7 -1
package/README.md CHANGED
@@ -1,180 +1,332 @@
1
1
  # tar-xz
2
2
 
3
- Create and extract tar.xz archives with streaming support for Node.js and buffer-based API for browsers.
3
+ Universal tar.xz library stream-first, Node and Browser, same API.
4
+
5
+ [![npm](https://img.shields.io/npm/v/tar-xz)](https://www.npmjs.com/package/tar-xz)
6
+ [![License: LGPL-3.0](https://img.shields.io/badge/License-LGPL--3.0-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0)
7
+
8
+ Create and extract `.tar.xz` archives with streaming support for Node.js and
9
+ WebAssembly-powered support for browsers — using the same `create`/`extract`/`list`
10
+ function names in both environments.
4
11
 
5
12
  ## Features
6
13
 
7
- - **Node.js streaming API** - Memory-efficient processing of large archives
8
- - **Browser support** - WASM-powered XZ compression works in any browser
9
- - **Full TAR support** - POSIX ustar format with PAX extensions for long filenames
10
- - **TypeScript** - Full type definitions included
11
- - **Zero dependencies** - Only requires `node-liblzma` (workspace dependency)
14
+ - **Unified API** `create`, `extract`, `list` work identically in Node.js and browsers
15
+ - **Stream-shaped API** all functions return `AsyncIterable<…>`; stream-shaped inputs accepted. Note: current Node `extract()`/`list()` implementations buffer internally — true streaming is a planned optimization
16
+ - **Flexible input** `extract()` and `list()` accept `AsyncIterable`, `Uint8Array`,
17
+ `ArrayBuffer`, Web `ReadableStream`, or Node `ReadableStream`
18
+ - **Flexible source** `create()` accepts fs paths (Node), `Buffer`/`Uint8Array`, or
19
+ `AsyncIterable<Uint8Array>` per file
20
+ - **File helpers** — `tar-xz/file` subpath for disk I/O (Node only)
21
+ - **Full TAR support** — POSIX ustar with PAX extensions for long filenames and metadata
22
+ - **TypeScript** — full type definitions included
23
+ - **Zero runtime deps** — only requires `node-liblzma` (native in Node, WASM in browser)
12
24
 
13
25
  ## Installation
14
26
 
15
27
  ```bash
16
28
  npm install tar-xz
17
- # or
18
29
  pnpm add tar-xz
19
- # or
20
30
  yarn add tar-xz
21
31
  ```
22
32
 
23
- ## Usage
33
+ ## Quick Start
24
34
 
25
- ### Node.js
35
+ Node.js and browser use the **same import**:
26
36
 
27
37
  ```typescript
28
38
  import { create, extract, list } from 'tar-xz';
39
+ ```
40
+
41
+ Bundlers (Vite, Webpack, esbuild) resolve to the WASM implementation in browser
42
+ builds automatically via the `browser` condition in `package.json`.
43
+
44
+ ## API Usage
45
+
46
+ ### Creating an archive
29
47
 
30
- // Create an archive
31
- await create({
32
- file: 'archive.tar.xz',
33
- cwd: '/source/directory',
34
- files: ['file1.txt', 'subdir/'],
35
- preset: 6 // compression level (0-9)
48
+ `create()` returns an `AsyncIterable<Uint8Array>`. Pipe it wherever you need:
49
+
50
+ ```typescript
51
+ import { create } from 'tar-xz';
52
+
53
+ const enc = new TextEncoder();
54
+ const archiveStream = create({
55
+ files: [
56
+ { name: 'hello.txt', source: enc.encode('Hello, world!') },
57
+ { name: 'data.json', source: enc.encode(JSON.stringify({ ok: true })) },
58
+ ],
59
+ preset: 6, // XZ compression level 0–9 (default: 6)
60
+ filter: (file) => !file.name.endsWith('.tmp'), // optional
36
61
  });
37
62
 
38
- // List contents
39
- const entries = await list({ file: 'archive.tar.xz' });
40
- for (const entry of entries) {
41
- console.log(entry.name, entry.size);
63
+ // Collect to a Uint8Array (browser / in-memory use)
64
+ const chunks: Uint8Array[] = [];
65
+ for await (const chunk of archiveStream) {
66
+ chunks.push(chunk);
67
+ }
68
+ const archive = new Uint8Array(chunks.reduce((n, c) => n + c.length, 0));
69
+ let offset = 0;
70
+ for (const chunk of chunks) { archive.set(chunk, offset); offset += chunk.length; }
71
+
72
+ // Or pipe to a WritableStream (browser)
73
+ const writer = writable.getWriter();
74
+ for await (const chunk of create({ files: [...] })) {
75
+ await writer.write(chunk);
42
76
  }
77
+ await writer.close();
78
+ ```
43
79
 
44
- // Extract to disk
45
- await extract({
46
- file: 'archive.tar.xz',
47
- cwd: '/destination',
48
- strip: 1, // remove leading path component
49
- filter: (entry) => !entry.name.startsWith('.') // skip hidden files
50
- });
80
+ ### Extracting an archive
81
+
82
+ `extract()` yields `TarEntryWithData` objects. Consume `entry.data` or use the
83
+ convenience helpers `entry.text()` and `entry.bytes()`:
51
84
 
52
- // Extract to memory
53
- import { extractToMemory } from 'tar-xz';
54
- const files = await extractToMemory('archive.tar.xz');
55
- for (const file of files) {
56
- console.log(file.name, file.content.toString());
85
+ ```typescript
86
+ import { extract } from 'tar-xz';
87
+
88
+ for await (const entry of extract(archiveStream)) {
89
+ if (entry.type === '0') { // regular file — TarEntryType.FILE
90
+ const content = await entry.text();
91
+ console.log(entry.name, content);
92
+ }
93
+ }
94
+
95
+ // Or collect raw bytes
96
+ for await (const entry of extract(archive)) {
97
+ if (entry.type === '0') {
98
+ const bytes = await entry.bytes();
99
+ console.log(entry.name, bytes.byteLength, 'bytes');
100
+ }
57
101
  }
58
102
  ```
59
103
 
60
- ### Browser
104
+ > **Important:** `entry.data` is a lazy `AsyncIterable` — consume or skip each entry
105
+ > before the `for await` loop advances to the next one. Calling `entry.bytes()` or
106
+ > iterating `entry.data` fully satisfies this requirement.
107
+
108
+ ### Listing an archive
109
+
110
+ `list()` yields `TarEntry` metadata without reading file content:
111
+
112
+ ```typescript
113
+ import { list } from 'tar-xz';
114
+
115
+ for await (const entry of list(archiveStream)) {
116
+ console.log(entry.name, entry.size, entry.mtime);
117
+ }
118
+ ```
119
+
120
+ ### Inputs accepted by `extract()` and `list()`
121
+
122
+ All of the following are valid as the first argument:
123
+
124
+ ```typescript
125
+ extract(asyncIterable) // AsyncIterable<Uint8Array>
126
+ extract(syncIterable) // Iterable<Uint8Array> (e.g. [chunk1, chunk2])
127
+ extract(uint8array) // Uint8Array (in-memory archive)
128
+ extract(arrayBuffer) // ArrayBuffer
129
+ extract(webReadableStream) // ReadableStream<Uint8Array> (Web Streams)
130
+ extract(nodeReadableStream) // NodeJS.ReadableStream (Node only)
131
+ ```
132
+
133
+ ### Source types per file in `create()`
134
+
135
+ ```typescript
136
+ create({
137
+ files: [
138
+ { name: 'from-disk.txt', source: '/absolute/or/relative/path' }, // Node only
139
+ { name: 'from-buffer.bin', source: Buffer.from([0x01, 0x02]) },
140
+ { name: 'from-uint8.bin', source: new Uint8Array([0x03, 0x04]) },
141
+ { name: 'from-stream.bin', source: asyncIterableOfChunks },
142
+ ],
143
+ });
144
+ ```
145
+
146
+ `string` sources (fs paths) throw a helpful error in browser environments — there
147
+ is no filesystem access in browsers.
148
+
149
+ ## File Helpers (Node only)
150
+
151
+ `tar-xz/file` wraps the stream API with disk I/O convenience functions:
61
152
 
62
153
  ```typescript
63
- import { createTarXz, extractTarXz, listTarXz } from 'tar-xz';
154
+ import { createFile, extractFile, listFile } from 'tar-xz/file';
64
155
 
65
- // Create from files (e.g., from file input or drag & drop)
66
- const archive = await createTarXz({
156
+ // Write archive to disk
157
+ await createFile('archive.tar.xz', {
67
158
  files: [
68
- { name: 'hello.txt', content: 'Hello, World!' },
69
- { name: 'data.json', content: JSON.stringify({ foo: 'bar' }) }
159
+ { name: 'a.txt', source: '/path/to/a.txt' },
160
+ { name: 'b.txt', source: Buffer.from('hello') },
70
161
  ],
71
- preset: 3 // lower preset for browser performance
72
162
  });
73
163
 
74
- // Download the archive
75
- const blob = new Blob([archive], { type: 'application/x-xz' });
76
- const url = URL.createObjectURL(blob);
77
- // ... trigger download
164
+ // Extract archive from disk to a directory
165
+ await extractFile('archive.tar.xz', {
166
+ cwd: './output', // target directory (default: process.cwd())
167
+ strip: 1, // strip N leading path components (default: 0)
168
+ filter: (entry) => entry.name.endsWith('.ts'), // optional
169
+ });
170
+
171
+ // List archive on disk (returns TarEntry[])
172
+ const entries = await listFile('archive.tar.xz');
173
+ for (const entry of entries) {
174
+ console.log(entry.name, entry.size);
175
+ }
176
+ ```
177
+
178
+ Do not import `tar-xz/file` in browser bundles — it imports `node:fs` and will
179
+ fail at runtime. Use `create`/`extract`/`list` directly in browser code.
180
+
181
+ ## Streaming Patterns
182
+
183
+ ### Hash while creating
184
+
185
+ Compute a checksum over the compressed bytes as they are produced:
186
+
187
+ ```typescript
188
+ import { create } from 'tar-xz';
189
+ import { createHash } from 'node:crypto';
78
190
 
79
- // Extract an archive
80
- const response = await fetch('archive.tar.xz');
81
- const data = await response.arrayBuffer();
82
- const files = await extractTarXz(data);
191
+ const hasher = createHash('sha256');
192
+ const chunks: Uint8Array[] = [];
83
193
 
84
- for (const file of files) {
85
- console.log(file.name, file.data.length);
194
+ for await (const chunk of create({ files: [...] })) {
195
+ hasher.update(chunk);
196
+ chunks.push(chunk);
86
197
  }
87
198
 
88
- // List contents only (no extraction)
89
- const entries = await listTarXz(data);
199
+ const digest = hasher.digest('hex');
200
+ console.log('SHA-256:', digest);
90
201
  ```
91
202
 
92
- ## API Reference
203
+ ### HTTP upload
93
204
 
94
- ### Node.js API
205
+ Stream the archive directly to an HTTP endpoint without buffering:
95
206
 
96
- #### `create(options: CreateOptions): Promise<void>`
207
+ ```typescript
208
+ import { create } from 'tar-xz';
209
+ import { Readable } from 'node:stream';
210
+ import { pipeline } from 'node:stream/promises';
97
211
 
98
- Create a tar.xz archive from files on disk.
212
+ const archiveStream = Readable.from(create({ files: [...] }));
213
+ // Use with node:http or any streaming HTTP client
214
+ ```
99
215
 
100
- Options:
101
- - `file` - Output archive path
102
- - `cwd` - Base directory for file paths (default: `process.cwd()`)
103
- - `files` - Array of file/directory paths to include
104
- - `preset` - XZ compression preset 0-9 (default: 6)
105
- - `follow` - Follow symbolic links (default: false)
216
+ ### Extract from HTTP response (browser)
106
217
 
107
- #### `extract(options: ExtractOptions): Promise<TarEntry[]>`
218
+ ```typescript
219
+ import { extract } from 'tar-xz';
220
+
221
+ const response = await fetch('https://example.com/archive.tar.xz');
222
+ // ReadableStream<Uint8Array> is accepted directly
223
+ for await (const entry of extract(response.body!)) {
224
+ if (entry.type === '0') {
225
+ const text = await entry.text();
226
+ console.log(entry.name, text);
227
+ }
228
+ }
229
+ ```
108
230
 
109
- Extract a tar.xz archive to disk.
231
+ ### Large file extraction to IndexedDB (browser)
110
232
 
111
- Options:
112
- - `file` - Input archive path
113
- - `cwd` - Output directory (default: `process.cwd()`)
114
- - `strip` - Number of leading path components to strip (default: 0)
115
- - `filter` - Function to filter entries
116
- - `preserveOwner` - Preserve file ownership (requires root)
233
+ ```typescript
234
+ import { extract } from 'tar-xz';
235
+
236
+ const response = await fetch('large.tar.xz');
237
+ for await (const entry of extract(response.body!)) {
238
+ if (entry.type === '0') {
239
+ const bytes = await entry.bytes();
240
+ // write to IndexedDB, OPFS, etc.
241
+ await saveToStorage(entry.name, bytes);
242
+ }
243
+ }
244
+ ```
117
245
 
118
- #### `list(options: ListOptions): Promise<TarEntry[]>`
246
+ ## API Reference
119
247
 
120
- List contents of a tar.xz archive.
248
+ ### Core API (`tar-xz`)
121
249
 
122
- #### `extractToMemory(file: string, options?): Promise<Array<TarEntry & { content: Buffer }>>`
250
+ | Function | Signature | Returns |
251
+ |----------|-----------|---------|
252
+ | `create` | `(options: CreateOptions) => AsyncIterable<Uint8Array>` | Compressed archive chunks |
253
+ | `extract` | `(input: TarInput, options?: ExtractOptions) => AsyncIterable<TarEntryWithData>` | Entries with data |
254
+ | `list` | `(input: TarInput) => AsyncIterable<TarEntry>` | Metadata only |
123
255
 
124
- Extract archive to memory without writing to disk.
256
+ ### File Helpers API (`tar-xz/file`, Node only)
125
257
 
126
- ### Browser API
258
+ | Function | Signature | Returns |
259
+ |----------|-----------|---------|
260
+ | `createFile` | `(path: string, options: CreateOptions) => Promise<void>` | Writes archive to `path` |
261
+ | `extractFile` | `(archivePath: string, options?: ExtractOptions & { cwd?: string }) => Promise<void>` | Extracts to `cwd` |
262
+ | `listFile` | `(archivePath: string) => Promise<TarEntry[]>` | Collected entry array |
127
263
 
128
- #### `createTarXz(options: BrowserCreateOptions): Promise<Uint8Array>`
264
+ ### `CreateOptions`
129
265
 
130
- Create a tar.xz archive from in-memory files.
266
+ | Field | Type | Default | Description |
267
+ |-------|------|---------|-------------|
268
+ | `files` | `TarSourceFile[]` | required | Files to include |
269
+ | `preset` | `number` | `6` | XZ compression level 0–9 |
270
+ | `filter` | `(file: TarSourceFile) => boolean` | — | Return `false` to exclude |
131
271
 
132
- Options:
133
- - `files` - Array of `{ name, content, mode?, mtime? }`
134
- - `preset` - XZ compression preset 0-9 (default: 3)
272
+ ### `TarSourceFile`
135
273
 
136
- #### `extractTarXz(archive: ArrayBuffer | Uint8Array, options?): Promise<ExtractedFile[]>`
274
+ | Field | Type | Description |
275
+ |-------|------|-------------|
276
+ | `name` | `string` | Path inside the archive |
277
+ | `source` | `string \| Uint8Array \| ArrayBuffer \| AsyncIterable<Uint8Array>` | File content or fs path (Node only) |
278
+ | `mode` | `number?` | File permissions (default: `0o644`) |
279
+ | `mtime` | `Date?` | Modification time (default: now) |
137
280
 
138
- Extract a tar.xz archive to memory.
281
+ ### `ExtractOptions`
139
282
 
140
- Options:
141
- - `strip` - Number of leading path components to strip
142
- - `filter` - Function to filter entries
283
+ | Field | Type | Default | Description |
284
+ |-------|------|---------|-------------|
285
+ | `strip` | `number` | `0` | Strip N leading path components |
286
+ | `filter` | `(entry: TarEntry) => boolean` | — | Return `false` to skip entry |
143
287
 
144
- #### `listTarXz(archive: ArrayBuffer | Uint8Array): Promise<TarEntry[]>`
288
+ ### `TarEntry`
145
289
 
146
- List contents of a tar.xz archive.
290
+ Metadata yielded by `list()` and attached to each `TarEntryWithData`:
147
291
 
148
- ## Low-level API
292
+ | Field | Type | Description |
293
+ |-------|------|-------------|
294
+ | `name` | `string` | Relative file path |
295
+ | `type` | `TarEntryTypeValue` | Entry type (`'0'`=file, `'5'`=dir, `'2'`=symlink, …) |
296
+ | `size` | `number` | File size in bytes |
297
+ | `mode` | `number` | File permissions |
298
+ | `uid` / `gid` | `number` | Owner user/group IDs |
299
+ | `uname` / `gname` | `string` | Owner user/group names |
300
+ | `mtime` | `number` | Modification time (seconds since epoch) |
301
+ | `linkname` | `string` | Symlink / hardlink target |
149
302
 
150
- For advanced usage, the package also exports low-level TAR utilities:
303
+ ### `TarEntryWithData` (extends `TarEntry`)
151
304
 
152
- ```typescript
153
- import {
154
- BLOCK_SIZE,
155
- createHeader,
156
- parseHeader,
157
- calculatePadding,
158
- createEndOfArchive,
159
- needsPaxHeaders,
160
- createPaxHeaderBlocks,
161
- } from 'tar-xz';
162
- ```
305
+ | Member | Description |
306
+ |--------|-------------|
307
+ | `data` | `AsyncIterable<Uint8Array>` — lazy content stream (consume once, in order) |
308
+ | `text(encoding?)` | Collect all chunks and decode to string (default UTF-8) |
309
+ | `bytes()` | Collect all chunks into a single `Uint8Array` |
163
310
 
164
311
  ## Compression Presets
165
312
 
166
- | Preset | Memory Usage | Speed | Ratio |
167
- |--------|-------------|-------|-------|
168
- | 1 | ~10 MB | Fastest | Lowest |
169
- | 3 | ~20 MB | Fast | Good (browser default) |
170
- | 6 | ~100 MB | Medium | Very Good (Node default) |
171
- | 9 | ~700 MB | Slowest | Best |
313
+ | Preset | WASM Memory | Speed | Ratio | Recommendation |
314
+ |--------|------------|-------|-------|----------------|
315
+ | 1 | ~10 MB | Fastest | Lowest | Batch of many small files |
316
+ | 3 | ~20 MB | Fast | Good | Memory-constrained environments |
317
+ | 6 | ~100 MB | Medium | Very good | Default (Node + Browser) |
318
+ | 9 | ~700 MB | Slowest | Best | Archive longevity |
319
+
320
+ ## Browser Limitations
172
321
 
173
- For browser usage, presets 1-6 are recommended to avoid memory issues.
322
+ - **No fs path source** `source: '/path/to/file'` throws; use `Uint8Array` or `AsyncIterable` instead
323
+ - **256 MB WASM memory cap** — single-file content exceeding this limit will fail; batch large files carefully
324
+ - **No synchronous APIs** — all browser operations are async
325
+ - **Preset 1–6 recommended** — presets 7–9 approach or exceed the memory cap
174
326
 
175
327
  ## Compatibility
176
328
 
177
- Archives created with `tar-xz` are fully compatible with standard tools:
329
+ Archives produced by `tar-xz` are fully compatible with standard tooling:
178
330
 
179
331
  ```bash
180
332
  # Extract with system tar
@@ -182,20 +334,76 @@ tar -xJf archive.tar.xz
182
334
 
183
335
  # List contents
184
336
  tar -tJf archive.tar.xz
337
+ ```
338
+
339
+ ## Migration: v5 → v6
340
+
341
+ v6 unifies the Node and browser APIs under a single set of function names.
342
+
343
+ ### Renamed / removed exports
344
+
345
+ | v5 | v6 |
346
+ |----|----|
347
+ | `createTarXz(options)` | `create(options)` (browser entry point) |
348
+ | `extractTarXz(archive)` | `extract(archive)` (browser entry point) |
349
+ | `listTarXz(archive)` | `list(archive)` (browser entry point) |
350
+ | `extractToMemory(path)` | `extract(createReadStream(path))` + `entry.bytes()` |
351
+ | `BrowserCreateOptions` | `CreateOptions` |
352
+ | `BrowserExtractOptions` | `ExtractOptions` |
353
+ | `ExtractedFile` | `TarEntryWithData` |
354
+
355
+ ### Return type changes
356
+
357
+ `create()` now returns `AsyncIterable<Uint8Array>` instead of `Promise<Uint8Array>`.
358
+ Collect all chunks if you need the full buffer:
359
+
360
+ ```typescript
361
+ // v5
362
+ const archive = await createTarXz({ files: [...] });
363
+
364
+ // v6
365
+ const chunks: Uint8Array[] = [];
366
+ for await (const chunk of create({ files: [...] })) chunks.push(chunk);
367
+ const archive = Buffer.concat(chunks); // Node
368
+ // or new Blob(chunks) for a Blob in browser
369
+ ```
370
+
371
+ `extract()` now returns `AsyncIterable<TarEntryWithData>` instead of `Promise<Array<...>>`.
372
+ Iterate with `for await`:
373
+
374
+ ```typescript
375
+ // v5
376
+ const files = await extractTarXz(archive);
377
+ for (const f of files) { /* f.name, f.data */ }
378
+
379
+ // v6
380
+ for await (const entry of extract(archive)) {
381
+ if (entry.type === '0') {
382
+ const data = await entry.bytes(); // f.data equivalent
383
+ }
384
+ }
385
+ ```
386
+
387
+ ### Node-only file helpers moved to subpath
388
+
389
+ ```typescript
390
+ // v5 (mixed in main export)
391
+ import { create, extract } from 'tar-xz';
392
+ await create({ file: 'archive.tar.xz', cwd: '.', files: ['a.txt'] });
185
393
 
186
- # Create (for reference)
187
- tar -cJf archive.tar.xz files/
394
+ // v6 (dedicated subpath)
395
+ import { createFile, extractFile } from 'tar-xz/file';
396
+ await createFile('archive.tar.xz', { files: [{ name: 'a.txt', source: 'a.txt' }] });
188
397
  ```
189
398
 
190
399
  ## Why tar-xz?
191
400
 
192
- The popular `node-tar` package (226M downloads/month) does not support `.tar.xz` files.
193
- While there are open issues requesting this feature, the maintainer prefers external libraries handle it.
401
+ [node-tar](https://github.com/isaacs/node-tar) (230M+ downloads/month) does not
402
+ support `.tar.xz`. `tar-xz` fills that gap by combining:
194
403
 
195
- `tar-xz` fills this gap by combining:
196
- - **node-liblzma** for XZ compression (native + WASM)
197
- - A minimal TAR implementation (no external dependencies)
404
+ - **node-liblzma** for XZ compression (native addon in Node, WASM in browser)
405
+ - A minimal POSIX ustar TAR implementation (no external dependencies)
198
406
 
199
407
  ## License
200
408
 
201
- LGPL-3.0 - Same as node-liblzma
409
+ [LGPL-3.0](https://www.gnu.org/licenses/lgpl-3.0) same as node-liblzma.
@@ -1,27 +1,20 @@
1
1
  /**
2
- * Browser-based TAR creation with XZ compression
2
+ * Browser-based TAR creation with XZ compression — v6 AsyncIterable API
3
3
  */
4
- import { type BrowserCreateOptions } from '../types.js';
4
+ import { type CreateOptions } from '../types.js';
5
5
  /**
6
- * Create a tar.xz archive in browser
6
+ * Create a tar.xz archive (browser).
7
7
  *
8
- * @param options - Creation options
9
- * @returns Compressed archive as Uint8Array
8
+ * Returns an `AsyncIterable<Uint8Array>` of compressed chunks.
10
9
  *
11
10
  * @example
12
11
  * ```ts
13
- * const archive = await createTarXz({
14
- * files: [
15
- * { name: 'hello.txt', content: 'Hello, World!' },
16
- * { name: 'data.json', content: JSON.stringify({ foo: 'bar' }) }
17
- * ],
18
- * preset: 3
19
- * });
20
- *
21
- * // Download the archive
22
- * const blob = new Blob([archive], { type: 'application/x-xz' });
23
- * const url = URL.createObjectURL(blob);
12
+ * const chunks: Uint8Array[] = [];
13
+ * for await (const chunk of create({ files })) {
14
+ * chunks.push(chunk);
15
+ * }
16
+ * const blob = new Blob(chunks, { type: 'application/x-xz' });
24
17
  * ```
25
18
  */
26
- export declare function createTarXz(options: BrowserCreateOptions): Promise<Uint8Array>;
19
+ export declare function create(options: CreateOptions): AsyncIterable<Uint8Array>;
27
20
  //# sourceMappingURL=create.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/browser/create.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH,OAAO,EAAE,KAAK,oBAAoB,EAAgB,MAAM,aAAa,CAAC;AAsCtE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,UAAU,CAAC,CAiEpF"}
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/browser/create.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH,OAAO,EACL,KAAK,aAAa,EAInB,MAAM,aAAa,CAAC;AAqFrB;;;;;;;;;;;;;GAaG;AACH,wBAAuB,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,CAAC,UAAU,CAAC,CAY/E"}