0
# Tar Packing
1
2
Streaming tar archive generator that creates tar data from entries without hitting the file system. The pack stream allows adding files, directories, and other entry types to create complete tar archives.
3
4
## Capabilities
5
6
### Pack Factory Function
7
8
Creates a new tar packing stream.
9
10
```javascript { .api }
11
/**
12
* Creates a new tar packing stream
13
* @param {PackOptions} [opts] - Optional configuration
14
* @returns {Pack} Pack stream instance
15
*/
16
function pack(opts?: PackOptions): Pack;
17
18
interface PackOptions {
19
// No specific options currently defined
20
}
21
```
22
23
### Pack Stream
24
25
Readable stream that generates tar data from added entries.
26
27
```javascript { .api }
28
class Pack extends Readable {
29
/**
30
* Add an entry to the tar archive
31
* @param {Header} header - Entry metadata
32
* @param {Buffer|string} [buffer] - Entry content (for files)
33
* @param {Function} [callback] - Called when entry is added
34
* @returns {EntryWritableStream} Stream for writing entry content
35
*/
36
entry(header: Header, buffer?: Buffer | string, callback?: (err?: Error) => void): EntryWritableStream;
37
38
/**
39
* Finalize the tar archive - must be called when done adding entries
40
*/
41
finalize(): void;
42
}
43
```
44
45
### Entry Writable Stream
46
47
Writable stream for adding content to a tar entry.
48
49
```javascript { .api }
50
class EntryWritableStream extends Writable {
51
/** Number of bytes written to this entry */
52
written: number;
53
/** Header for this entry */
54
header: Header;
55
}
56
```
57
58
## Usage Examples
59
60
### Basic Packing
61
62
```javascript
63
const tar = require('tar-stream');
64
const fs = require('fs');
65
66
const pack = tar.pack();
67
68
// Add a simple text file
69
pack.entry({ name: 'hello.txt' }, 'Hello World!');
70
71
// Add a file with metadata
72
pack.entry({
73
name: 'readme.md',
74
size: 13,
75
mode: 0o644,
76
mtime: new Date(),
77
type: 'file'
78
}, 'Hello README!');
79
80
// Finalize the archive
81
pack.finalize();
82
83
// Save to file
84
pack.pipe(fs.createWriteStream('archive.tar'));
85
```
86
87
### Streaming Entry Content
88
89
```javascript
90
const tar = require('tar-stream');
91
92
const pack = tar.pack();
93
94
// Add a file with streaming content
95
const entry = pack.entry({
96
name: 'large-file.txt',
97
size: 11 // must specify size for streaming
98
}, function(err) {
99
if (err) throw err;
100
console.log('Entry added');
101
pack.finalize();
102
});
103
104
// Write content to the entry stream
105
entry.write('Hello ');
106
entry.write('World!');
107
entry.end();
108
109
pack.pipe(process.stdout);
110
```
111
112
### Directory Entries
113
114
```javascript
115
const tar = require('tar-stream');
116
117
const pack = tar.pack();
118
119
// Add a directory
120
pack.entry({
121
name: 'my-directory/',
122
type: 'directory',
123
mode: 0o755
124
});
125
126
// Add files within the directory
127
pack.entry({
128
name: 'my-directory/file1.txt'
129
}, 'File 1 content');
130
131
pack.entry({
132
name: 'my-directory/file2.txt'
133
}, 'File 2 content');
134
135
pack.finalize();
136
```
137
138
### Symbolic Links
139
140
```javascript
141
const tar = require('tar-stream');
142
143
const pack = tar.pack();
144
145
// Add a symlink
146
pack.entry({
147
name: 'link-to-file.txt',
148
type: 'symlink',
149
linkname: 'original-file.txt'
150
});
151
152
// Add the target file
153
pack.entry({
154
name: 'original-file.txt'
155
}, 'This is the original file');
156
157
pack.finalize();
158
```
159
160
### Complex Metadata
161
162
```javascript
163
const tar = require('tar-stream');
164
165
const pack = tar.pack();
166
167
pack.entry({
168
name: 'important-file.txt',
169
size: 0,
170
mode: 0o600, // read-write for owner only
171
uid: 1000,
172
gid: 1000,
173
uname: 'user',
174
gname: 'group',
175
mtime: new Date('2023-01-01'),
176
type: 'file'
177
}, 'Sensitive content');
178
179
pack.finalize();
180
```
181
182
### Modifying Existing Archives
183
184
```javascript
185
const tar = require('tar-stream');
186
const fs = require('fs');
187
188
const extract = tar.extract();
189
const pack = tar.pack();
190
191
extract.on('entry', function(header, stream, callback) {
192
// Modify the path - add 'backup/' prefix
193
header.name = 'backup/' + header.name;
194
195
// Pipe the entry to the new archive
196
stream.pipe(pack.entry(header, callback));
197
});
198
199
extract.on('finish', function() {
200
pack.finalize();
201
});
202
203
// Pipe old archive through extractor to new packer
204
fs.createReadStream('old.tar').pipe(extract);
205
pack.pipe(fs.createWriteStream('new.tar'));
206
```
207
208
### Error Handling
209
210
```javascript
211
const tar = require('tar-stream');
212
213
const pack = tar.pack();
214
215
pack.on('error', function(err) {
216
console.error('Pack error:', err.message);
217
});
218
219
// Add entry with error handling
220
const entry = pack.entry({
221
name: 'test.txt',
222
size: 5 // size must match actual content
223
}, function(err) {
224
if (err) {
225
console.error('Entry error:', err.message);
226
return;
227
}
228
console.log('Entry added successfully');
229
pack.finalize();
230
});
231
232
entry.on('error', function(err) {
233
console.error('Entry stream error:', err.message);
234
});
235
236
entry.write('Hello'); // exactly 5 bytes as specified
237
entry.end();
238
```
239
240
## Important Notes
241
242
- **Size Specification**: When streaming content to entries, you must specify the exact size in the header
243
- **Finalization**: Always call `finalize()` when done adding entries to properly close the archive
244
- **Sequential Processing**: Entries are processed sequentially - wait for the callback before adding the next entry
245
- **Content Matching**: The actual content size must match the size specified in the header, or an error will occur
246
- **Entry Types**: Support for all standard tar entry types including files, directories, symlinks, and device files
247
- **Header Auto-completion**: Missing header fields are automatically filled with sensible defaults