0
# tar-fs
1
2
tar-fs provides filesystem bindings for tar-stream, enabling developers to pack directories into tarballs and extract tarballs into directories with a simple streaming API. It offers comprehensive tar file manipulation capabilities including selective file packing/extraction, header modification, stream transformation, and permission control.
3
4
## Package Information
5
6
- **Package Name**: tar-fs
7
- **Package Type**: npm
8
- **Language**: JavaScript
9
- **Installation**: `npm install tar-fs`
10
11
## Core Imports
12
13
```javascript
14
const tar = require('tar-fs');
15
```
16
17
For ES modules:
18
19
```javascript
20
import tar from 'tar-fs';
21
```
22
23
## Basic Usage
24
25
```javascript
26
const tar = require('tar-fs');
27
const fs = require('fs');
28
29
// Pack a directory into a tarball
30
tar.pack('./my-directory').pipe(fs.createWriteStream('my-tarball.tar'));
31
32
// Extract a tarball into a directory
33
fs.createReadStream('my-other-tarball.tar').pipe(tar.extract('./my-other-directory'));
34
35
// Copy a directory (with permissions and timestamps intact)
36
tar.pack('source-directory').pipe(tar.extract('dest-directory'));
37
```
38
39
## Architecture
40
41
tar-fs is built around two core streaming functions that work with tar-stream instances:
42
43
- **Pack Function**: Creates readable streams from filesystem directories, converting files and folders into tar entries
44
- **Extract Function**: Creates writable streams that consume tar entries and recreate filesystem structures
45
- **Options System**: Extensive configuration for filtering, transforming, and controlling permissions
46
- **Stream Integration**: Direct compatibility with tar-stream instances for advanced use cases
47
- **Cross-platform Support**: Works on Windows, macOS, Linux with platform-specific handling
48
49
## Capabilities
50
51
### Directory Packing
52
53
Packs a directory into a tar stream with extensive filtering and transformation options.
54
55
```javascript { .api }
56
/**
57
* Packs a directory into a tar stream
58
* @param cwd - Directory to pack (defaults to '.')
59
* @param opts - Packing options
60
* @returns tar-stream pack instance (readable stream)
61
*/
62
function pack(cwd, opts);
63
```
64
65
**Options:**
66
67
```javascript { .api }
68
interface PackOptions {
69
/** Custom filesystem implementation */
70
fs?: object;
71
/** Function to ignore/filter files: (name) => boolean */
72
ignore?: (name: string) => boolean;
73
/** Alias for ignore */
74
filter?: (name: string) => boolean;
75
/** Function to transform file streams: (stream, header) => stream */
76
mapStream?: (stream: ReadableStream, header: object) => ReadableStream;
77
/** Dereference symlinks (pack contents instead of links) */
78
dereference?: boolean;
79
/** Array of specific entries to pack */
80
entries?: string[];
81
/** Sort entries alphabetically */
82
sort?: boolean;
83
/** Strict mode - fail on unsupported file types (default: true) */
84
strict?: boolean;
85
/** Permission umask */
86
umask?: number;
87
/** Existing pack stream to use */
88
pack?: object;
89
/** Callback function on completion */
90
finish?: (pack: object) => void;
91
/** Function to modify tar headers: (header) => header */
92
map?: (header: object) => object;
93
/** Directory mode permissions */
94
dmode?: number;
95
/** File mode permissions */
96
fmode?: number;
97
/** Number of path levels to strip */
98
strip?: number;
99
/** Make files readable (adds 444 to files, 555 to directories) */
100
readable?: boolean;
101
/** Make files writable (adds 222 to files, 333 to directories) */
102
writable?: boolean;
103
/** Finalize pack when done (default: true) */
104
finalize?: boolean;
105
}
106
```
107
108
**Usage Examples:**
109
110
```javascript
111
// Pack with file filtering
112
const pack = tar.pack('./my-directory', {
113
ignore(name) {
114
return path.extname(name) === '.bin'; // ignore .bin files
115
}
116
});
117
118
// Pack specific entries only
119
const pack = tar.pack('./my-directory', {
120
entries: ['file1.txt', 'subdir/file2.txt']
121
});
122
123
// Pack with header modification
124
const pack = tar.pack('./my-directory', {
125
map(header) {
126
header.name = 'prefixed/' + header.name;
127
return header;
128
}
129
});
130
131
// Pack with stream transformation
132
const pack = tar.pack('./my-directory', {
133
mapStream(fileStream, header) {
134
if (path.extname(header.name) === '.js') {
135
return fileStream.pipe(someTransform);
136
}
137
return fileStream;
138
}
139
});
140
141
// Pack with custom permissions
142
const pack = tar.pack('./my-directory', {
143
dmode: parseInt('755', 8), // directory permissions
144
fmode: parseInt('644', 8), // file permissions
145
readable: true,
146
writable: false
147
});
148
```
149
150
### Tar Extraction
151
152
Extracts a tar stream into a directory with extensive filtering and transformation options.
153
154
```javascript { .api }
155
/**
156
* Extracts a tar stream into a directory
157
* @param cwd - Directory to extract to (defaults to '.')
158
* @param opts - Extraction options
159
* @returns tar-stream extract instance (writable stream)
160
*/
161
function extract(cwd, opts);
162
```
163
164
**Options:**
165
166
```javascript { .api }
167
interface ExtractOptions {
168
/** Custom filesystem implementation */
169
fs?: object;
170
/** Function to ignore/filter files: (name, header) => boolean */
171
ignore?: (name: string, header?: object) => boolean;
172
/** Alias for ignore */
173
filter?: (name: string, header?: object) => boolean;
174
/** Function to transform file streams: (stream, header) => stream */
175
mapStream?: (stream: ReadableStream, header: object) => ReadableStream;
176
/** Change file ownership (default: true on Unix as root) */
177
chown?: boolean;
178
/** Existing extract stream to use */
179
extract?: object;
180
/** Function to modify tar headers: (header) => header */
181
map?: (header: object) => object;
182
/** Directory mode permissions */
183
dmode?: number;
184
/** File mode permissions */
185
fmode?: number;
186
/** Number of path levels to strip */
187
strip?: number;
188
/** Make files readable (adds 444 to files, 555 to directories) */
189
readable?: boolean;
190
/** Make files writable (adds 222 to files, 333 to directories) */
191
writable?: boolean;
192
/** Strict mode - fail on unsupported entry types (default: true) */
193
strict?: boolean;
194
/** Validate symlinks are within extraction directory (default: true) */
195
validateSymlinks?: boolean;
196
/** Set file modification times (default: true) */
197
utimes?: boolean;
198
/** Permission umask */
199
umask?: number;
200
/** Callback function on completion */
201
finish?: () => void;
202
/** Fallback hard links as file copies on permission errors */
203
hardlinkAsFilesFallback?: boolean;
204
}
205
```
206
207
**Usage Examples:**
208
209
```javascript
210
// Extract with file filtering
211
const extract = tar.extract('./my-directory', {
212
ignore(name) {
213
return path.extname(name) === '.bin'; // ignore .bin files
214
}
215
});
216
217
// Extract with type filtering using header
218
const extract = tar.extract('./my-directory', {
219
ignore(name, header) {
220
// Only extract files and directories, ignore symlinks
221
return header.type !== 'file' && header.type !== 'directory';
222
}
223
});
224
225
// Extract with header modification
226
const extract = tar.extract('./my-directory', {
227
map(header) {
228
header.name = 'another-prefix/' + header.name;
229
return header;
230
}
231
});
232
233
// Extract with stream transformation
234
const extract = tar.extract('./my-directory', {
235
mapStream(fileStream, header) {
236
if (path.extname(header.name) === '.js') {
237
return fileStream.pipe(someTransform);
238
}
239
return fileStream;
240
}
241
});
242
243
// Extract with custom permissions
244
const extract = tar.extract('./my-directory', {
245
dmode: parseInt('755', 8), // directory permissions
246
fmode: parseInt('644', 8), // file permissions
247
readable: true,
248
writable: true
249
});
250
```
251
252
### Advanced tar-stream Integration
253
254
For advanced use cases, tar-fs integrates seamlessly with tar-stream instances.
255
256
```javascript { .api }
257
// Using custom pack stream
258
const mypack = tar.pack('./my-directory', {
259
finalize: false,
260
finish(pack) {
261
// Add custom entry
262
pack.entry({name: 'generated-file.txt'}, 'Hello World');
263
// Pack another directory into same stream
264
tar.pack('./other-directory', { pack: pack });
265
}
266
});
267
268
// Using custom extract stream
269
const tarStream = require('tar-stream');
270
const extract = tarStream.extract();
271
extract.on('entry', (header, stream, next) => {
272
// Custom entry processing
273
console.log('Extracting:', header.name);
274
stream.resume();
275
next();
276
});
277
278
tar.extract('./output', { extract: extract });
279
```
280
281
## Types
282
283
```javascript { .api }
284
interface TarHeader {
285
/** File/directory name */
286
name: string;
287
/** File mode/permissions */
288
mode: number;
289
/** User ID */
290
uid: number;
291
/** Group ID */
292
gid: number;
293
/** File size in bytes */
294
size: number;
295
/** Modification time */
296
mtime: Date;
297
/** Entry type: 'file', 'directory', 'symlink', 'link' */
298
type: string;
299
/** Link target for symlinks and hard links */
300
linkname?: string;
301
}
302
```
303
304
## Platform Considerations
305
306
- **Windows**: Symlinks and hard links are skipped due to platform limitations
307
- **Unix-like systems**: Full symlink and hard link support with security validation
308
- **Bare.js**: Alternative filesystem bindings through optional dependencies (bare-fs, bare-path)
309
- **Permissions**: Automatic umask handling and cross-platform permission management
310
311
## Error Handling
312
313
Common error scenarios:
314
315
- **ENOENT**: File not found during packing (ignored for dynamically deleted files)
316
- **EPERM**: Permission denied during extraction (handled with hardlinkAsFilesFallback)
317
- **Invalid symlinks**: Prevented by validateSymlinks option (default: true)
318
- **Unsupported file types**: Controlled by strict option (default: true)
319
- **Path traversal**: Prevented by built-in path validation