modern-tar 0.3.3 → 0.3.5

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 CHANGED
@@ -12,23 +12,9 @@ Zero-dependency, cross-platform, streaming tar archive library for every JavaScr
12
12
  - 🌐 **Cross-Platform** - Works in browsers, Node.js, Cloudflare Workers, and other JavaScript runtimes.
13
13
  - 📁 **Node.js Integration** - Additional high-level APIs for directory packing and extraction.
14
14
 
15
- ## Table of Contents
16
-
17
- - [Installation](#installation)
18
- - [Usage](#usage)
19
- - [Core Usage (Browser, Node.js, etc.)](#core-usage)
20
- - [Node.js Filesystem Usage](#nodejs-filesystem-usage)
21
- - [API Reference](#api-reference)
22
- - [Core API (`modern-tar`)](#core-api-modern-tar)
23
- - [Node.js Filesystem API (`modern-tar/fs`)](#nodejs-filesystem-api-modern-tarfs)
24
- - [Types](#types)
25
- - [Core Types](#core-types)
26
- - [Filesystem Types](#filesystem-types)
27
- - [Compatibility](#compatibility)
28
-
29
15
  ## Installation
30
16
 
31
- ```bash
17
+ ```sh
32
18
  npm install modern-tar
33
19
  ```
34
20
 
@@ -225,322 +211,26 @@ const archiveStream = packTarSources(sources);
225
211
  await pipeline(archiveStream, createWriteStream('project.tar'));
226
212
  ```
227
213
 
228
- ## API Reference
229
-
230
- ### Core API (`modern-tar`)
231
-
232
- #### `packTar(entries: TarEntry[]): Promise<Uint8Array>`
233
-
234
- Pack an array of entries into a tar archive buffer.
235
-
236
- - **`entries`**: Array of `TarEntry` objects to pack.
237
- - **Returns**: Promise resolving to a complete tar archive as a `Uint8Array`.
238
-
239
- **Example:**
240
-
241
- ```typescript
242
- const entries = [
243
- { header: { name: "file.txt", size: 5 }, body: "hello" },
244
- { header: { name: "dir/", type: "directory", size: 0 } }
245
- ];
246
- const tarBuffer = await packTar(entries);
247
- ```
248
-
249
- #### `unpackTar(archive: ArrayBuffer | Uint8Array | ReadableStream<Uint8Array>, options?: UnpackOptions): Promise<ParsedTarEntryWithData[]>`
250
-
251
- Extract all entries from a tar archive buffer with optional filtering and transformation.
252
-
253
- - **`archive`**: Complete tar archive as `ArrayBuffer` or `Uint8Array`.
254
- - **`options`**: Optional extraction configuration (see `UnpackOptions`).
255
- - **Returns**: Promise resolving to an array of entries with buffered data.
256
-
257
- **Example:**
258
-
259
- ```typescript
260
- // With filtering and path manipulation
261
- const filteredEntries = await unpackTar(tarBuffer, {
262
- strip: 1, // Remove first path component
263
- filter: (header) => header.name.endsWith('.js'),
264
- map: (header) => ({ ...header, name: header.name.toLowerCase() })
265
- });
266
- ```
267
-
268
- #### `createTarPacker(): { readable, controller }`
269
-
270
- Create a streaming tar packer for dynamic entry creation.
271
-
272
- - **Returns**: An object containing:
273
- - `readable` - `ReadableStream` outputting tar archive bytes.
274
- - `controller` - `TarPackController` for adding entries.
275
-
276
- **Example:**
277
-
278
- ```typescript
279
- const { readable, controller } = createTarPacker();
280
-
281
- // Add entries dynamically
282
- const stream1 = controller.add({ name: "file1.txt", size: 5 });
283
- const stream2 = controller.add({ name: "file2.txt", size: 4 });
284
-
285
- // Write content to streams and finalize
286
- // ...
287
- controller.finalize();
288
- ```
289
-
290
- #### `createTarDecoder(options?: DecoderOptions): TransformStream<Uint8Array, ParsedTarEntry>`
291
-
292
- Create a transform stream that parses tar bytes into entries.
293
-
294
- - **Returns**: `TransformStream` that converts tar archive bytes to `ParsedTarEntry` objects.
295
-
296
- **Example:**
297
-
298
- ```typescript
299
- const decoder = createTarDecoder();
300
- const entriesStream = tarStream.pipeThrough(decoder);
301
-
302
- for await (const entry of entriesStream) {
303
- console.log(`Entry: ${entry.header.name}`);
304
- // Process entry.body stream as needed
305
- }
306
- ```
307
-
308
- #### `createTarOptionsTransformer(options?: UnpackOptions): TransformStream<ParsedTarEntry, ParsedTarEntry>`
309
-
310
- Create a transform stream that applies unpacking options (`strip`, `filter`, `map`) to tar entries.
311
-
312
- - **`options`**: Optional unpacking configuration (see `UnpackOptions`).
313
- - **Returns**: `TransformStream` that processes `ParsedTarEntry` objects.
314
-
315
- **Example:**
316
-
317
- ```typescript
318
- import { createTarDecoder, createTarOptionsTransformer } from 'modern-tar';
319
-
320
- const transformedStream = sourceStream
321
- .pipeThrough(createTarDecoder())
322
- .pipeThrough(createTarOptionsTransformer({
323
- strip: 1,
324
- filter: (header) => header.name.endsWith('.txt'),
325
- }));
326
- ```
327
-
328
- #### `createGzipEncoder(): CompressionStream`
329
-
330
- Create a gzip compression stream for `.tar.gz` creation.
331
-
332
- **Example:**
333
-
334
- ```typescript
335
- const tarStream = /* ... */;
336
- const compressedStream = tarStream.pipeThrough(createGzipEncoder());
337
- ```
338
-
339
- #### `createGzipDecoder(): DecompressionStream`
340
-
341
- Create a gzip decompression stream for `.tar.gz` extraction.
342
-
343
- **Example:**
344
-
345
- ```typescript
346
- const gzipStream = /* ... */;
347
- const tarStream = gzipStream.pipeThrough(createGzipDecoder());
348
- ```
349
-
350
- ### Node.js Filesystem API (`modern-tar/fs`)
351
-
352
- #### `packTar(directoryPath: string, options?: PackOptionsFS): Readable`
353
-
354
- Pack a directory into a Node.js Readable stream containing tar archive bytes.
355
-
356
- - **`directoryPath`**: Path to the directory to pack.
357
- - **`options`**: Optional packing configuration (see `PackOptionsFS`).
358
- - **Returns**: Node.js `Readable` stream of tar archive bytes.
359
-
360
- **Example:**
361
-
362
- ```typescript
363
- import { packTar } from 'modern-tar/fs';
364
-
365
- const tarStream = packTar('/home/user/project', {
366
- dereference: true, // Follow symlinks
367
- filter: (path, stats) => !path.includes('tmp'),
368
- });
369
- ```
370
-
371
- #### `unpackTar(directoryPath: string, options?: UnpackOptionsFS): Writable`
372
-
373
- Extract a tar archive to a directory.
374
-
375
- - **`directoryPath`**: Path to the directory where files will be extracted.
376
- - **`options`**: Optional extraction configuration (see `UnpackOptionsFS`).
377
- - **Returns**: Node.js `Writable` stream to pipe tar archive bytes into.
378
-
379
- **Example:**
380
-
381
- ```typescript
382
- import { unpackTar } from 'modern-tar/fs';
383
- import { createReadStream } from 'node:fs';
384
- import { pipeline } from 'node:stream/promises';
385
-
386
- const tarStream = createReadStream('backup.tar');
387
- const extractStream = unpackTar('/restore/location', {
388
- strip: 1,
389
- fmode: 0o644, // Set consistent file permissions
390
- strict: true, // Enable strict validation
391
- });
392
- await pipeline(tarStream, extractStream);
393
- ```
394
-
395
- #### `packTarSources(sources: TarSource[]): Readable`
396
-
397
- Pack multiple sources (files, directories, or raw content) into a tar archive stream.
398
-
399
- - **`sources`**: Array of `TarSource` objects describing what to include in the archive.
400
- - **Returns**: Node.js `Readable` stream of tar archive bytes.
401
-
402
- **Example:**
214
+ #### Compression/Decompression (gzip)
403
215
 
404
216
  ```typescript
405
- import { packTarSources, type TarSource } from 'modern-tar/fs';
406
- import { createWriteStream } from 'node:fs';
217
+ import { packTar, unpackTar } from 'modern-tar/fs';
218
+ import { createWriteStream, createReadStream } from 'node:fs';
219
+ import { createGzip, createGunzip } from 'node:zlib';
407
220
  import { pipeline } from 'node:stream/promises';
408
221
 
409
- const sources: TarSource[] = [
410
- { type: 'file', source: './README.md', target: 'docs/readme.txt' },
411
- { type: 'directory', source: './src', target: 'app/src' },
412
- { type: 'content', content: '{"version": "1.0.0"}', target: 'app/config.json' },
413
- { type: 'content', content: Buffer.from('binary data'), target: 'data/binary.dat' }
414
- ];
415
-
416
- const archiveStream = packTarSources(sources);
417
- await pipeline(archiveStream, createWriteStream('app.tar'));
418
- ```
419
-
420
- ## Types
421
-
422
- ### Core Types
423
-
424
- ```typescript
425
- // Header information for a tar entry
426
- interface TarHeader {
427
- name: string; // File/directory name
428
- size: number; // File size in bytes
429
- mtime?: Date; // Modification time
430
- mode?: number; // File permissions (e.g., 0o644)
431
- type?: "file" | "directory" | "symlink" | "link" | "pax-header" | "pax-global-header";
432
- linkname?: string; // Target for symlinks/hardlinks
433
- uid?: number; // User ID
434
- gid?: number; // Group ID
435
- uname?: string; // User name
436
- gname?: string; // Group name
437
- pax?: Record<string, string>; // PAX extended attributes
438
- }
439
-
440
- // Input entry for packing functions
441
- interface TarEntry {
442
- header: TarHeader;
443
- body?: string | Uint8Array | ArrayBuffer | ReadableStream<Uint8Array> | Blob | null;
444
- }
445
-
446
- // Output entry from a streaming decoder
447
- interface ParsedTarEntry {
448
- header: TarHeader;
449
- body: ReadableStream<Uint8Array>;
450
- }
451
-
452
- // Output entry from a buffered unpack function
453
- interface ParsedTarEntryWithData {
454
- header: TarHeader;
455
- data: Uint8Array;
456
- }
457
-
458
- // Platform-neutral configuration for unpacking
459
- interface DecoderOptions {
460
- /** Enable strict validation (e.g., throw on invalid checksums) */
461
- strict?: boolean;
462
- }
222
+ // Pack directory and compress to .tar.gz
223
+ const tarStream = packTar('./my/project');
224
+ await pipeline(tarStream, createGzip(), createWriteStream('./project.tar.gz'));
463
225
 
464
- interface UnpackOptions extends DecoderOptions {
465
- /** Number of leading path components to strip from entry names (e.g., strip: 1 removes first directory) */
466
- strip?: number;
467
- /** Filter function to include/exclude entries (return false to skip) */
468
- filter?: (header: TarHeader) => boolean;
469
- /** Transform function to modify tar headers before extraction */
470
- map?: (header: TarHeader) => TarHeader;
471
- }
226
+ // Decompress and extract .tar.gz
227
+ const gzipStream = createReadStream('./project.tar.gz');
228
+ await pipeline(gzipStream, createGunzip(), unpackTar('./output'));
472
229
  ```
473
230
 
474
- ### Filesystem Types
475
-
476
- ```typescript
477
- interface PackOptionsFS {
478
- /** Follow symlinks instead of archiving them as symlinks (default: false) */
479
- dereference?: boolean;
480
- /** Filter function to determine which files to include (uses Node.js fs.Stats) */
481
- filter?: (path: string, stat: Stats) => boolean;
482
- /** Transform function to modify headers before packing */
483
- map?: (header: TarHeader) => TarHeader;
484
- }
485
-
486
- // Source types for packTarSources function
487
- interface FileSource {
488
- type: "file";
489
- /** Path to the source file on the local filesystem */
490
- source: string;
491
- /** Destination path inside the tar archive */
492
- target: string;
493
- }
494
-
495
- interface DirectorySource {
496
- type: "directory";
497
- /** Path to the source directory on the local filesystem */
498
- source: string;
499
- /** Destination path inside the tar archive */
500
- target: string;
501
- }
502
-
503
- interface ContentSource {
504
- type: "content";
505
- /** Raw content to add. Supports string, Uint8Array, ArrayBuffer, ReadableStream, Blob, or null. */
506
- content: TarEntryData;
507
- /** Destination path inside the tar archive */
508
- target: string;
509
- /** Optional Unix file permissions (e.g., 0o644, 0o755) */
510
- mode?: number;
511
- }
231
+ ## API Reference
512
232
 
513
- type TarSource = FileSource | DirectorySource | ContentSource;
514
-
515
- interface UnpackOptionsFS extends UnpackOptions {
516
- // Inherited from UnpackOptions (platform-neutral):
517
- /** Number of leading path components to strip from entry names */
518
- strip?: number;
519
- /** Filter function to determine which entries to extract */
520
- filter?: (header: TarHeader) => boolean;
521
- /** Transform function to modify headers before extraction */
522
- map?: (header: TarHeader) => TarHeader;
523
-
524
- // Filesystem-specific options:
525
- /** Default mode for created directories (e.g., 0o755). Overrides tar header mode */
526
- dmode?: number;
527
- /** Default mode for created files (e.g., 0o644). Overrides tar header mode */
528
- fmode?: number;
529
- /**
530
- * Prevent symlinks from pointing outside the extraction directory.
531
- * @default true
532
- */
533
- validateSymlinks?: boolean;
534
- /**
535
- * The maximum depth of paths to extract. Prevents Denial of Service (DoS) attacks
536
- * from malicious archives with deeply nested directories.
537
- *
538
- * Set to `Infinity` to disable depth checking (not recommended for untrusted archives).
539
- * @default 1024
540
- */
541
- maxDepth?: number;
542
- }
543
- ```
233
+ See the [API Reference](./REFERENCE.md).
544
234
 
545
235
  ## Compatibility
546
236