0
# Zip Dir
1
2
Zip Dir is a Node.js library that recursively zips directories into buffers while preserving directory structure. It provides both synchronous and asynchronous operation modes through callbacks and promises, with support for custom file filtering, progress tracking, and flexible output options.
3
4
## Package Information
5
6
- **Package Name**: zip-dir
7
- **Package Type**: npm
8
- **Language**: JavaScript
9
- **Installation**: `npm install zip-dir`
10
11
## Core Imports
12
13
```javascript
14
const zipdir = require('zip-dir');
15
```
16
17
ES6 modules:
18
19
```javascript
20
import zipdir from 'zip-dir';
21
```
22
23
## Basic Usage
24
25
```javascript
26
const zipdir = require('zip-dir');
27
28
// Promise-based usage
29
const buffer = await zipdir('/path/to/directory');
30
31
// Callback-based usage
32
zipdir('/path/to/directory', function(err, buffer) {
33
if (err) throw err;
34
console.log('Zip created successfully!');
35
});
36
37
// Save directly to disk
38
zipdir('/path/to/directory', { saveTo: './output.zip' }, function(err, buffer) {
39
if (err) throw err;
40
console.log('Zip saved to disk!');
41
});
42
```
43
44
## Architecture
45
46
Zip Dir is built around several key components that work together to provide efficient and reliable directory compression:
47
48
- **Dual API Design**: Supports both Promise-based and callback-based operations (mutually exclusive)
49
- **JSZip Integration**: Uses the JSZip library internally for cross-platform zip file creation with DEFLATE compression
50
- **Async Queue Management**: Implements concurrency control with a maximum of 500 concurrent file reads to prevent resource exhaustion
51
- **Recursive Directory Traversal**: Depth-first traversal that preserves directory structure in the zip archive
52
- **Stream Processing**: Files are read and processed individually to handle large directories efficiently
53
- **Error Propagation**: Comprehensive error handling that stops processing on first error and properly propagates through callback/promise chains
54
55
## Capabilities
56
57
### Directory Compression
58
59
Creates a compressed zip archive from a directory, recursively including all files and subdirectories while preserving the directory structure.
60
61
```javascript { .api }
62
/**
63
* Zips up a directory recursively preserving directory structure
64
* @param {string} rootDir - Path to directory to be zipped (resolved internally)
65
* @param {ZipOptions|function} [options] - Configuration options or callback function
66
* @param {function} [callback] - Callback function with signature (error, buffer)
67
* @returns {Promise<Buffer>|undefined} Promise resolving to zip buffer when no callback provided, undefined when callback used
68
*/
69
function zipdir(rootDir, options, callback);
70
```
71
72
**Parameter Handling:**
73
- If second parameter is a function, it's treated as the callback
74
- Promise and callback APIs are mutually exclusive - providing a callback prevents promise return
75
- When `options.saveTo` is provided, the callback/promise waits for both zip creation and file write completion
76
- All paths are resolved internally to handle trailing slashes and relative paths
77
78
**Options:**
79
80
```javascript { .api }
81
interface ZipOptions {
82
/** Path to save the zip file to disk (uses binary encoding) */
83
saveTo?: string;
84
/**
85
* Function to filter files/directories during traversal
86
* @param fullPath - Absolute path to the file or directory
87
* @param stats - Node.js fs.Stats object with file metadata
88
* @returns true to include item in zip, false to exclude
89
* @note Must return true for directories to allow traversal into subdirectories
90
*/
91
filter?(fullPath: string, stats: fs.Stats): boolean;
92
/**
93
* Function called for each item added to the zip
94
* @param path - For files: path relative to root directory (e.g., "subdir/file.txt")
95
* - For directories: full absolute path of the directory
96
*/
97
each?(path: string): void;
98
}
99
```
100
101
**Usage Examples:**
102
103
```javascript
104
const zipdir = require('zip-dir');
105
106
// Filter out temporary files and keep only JSON files
107
zipdir('/path/to/directory', {
108
filter: (path, stat) => {
109
// Allow directories to be traversed
110
if (stat.isDirectory()) return true;
111
// Only include JSON files
112
return path.endsWith('.json');
113
}
114
}, function(err, buffer) {
115
console.log('Filtered zip created');
116
});
117
118
// Track progress with each callback
119
zipdir('/path/to/directory', {
120
each: (path) => console.log('Added:', path),
121
saveTo: './archive.zip'
122
}, function(err, buffer) {
123
console.log('Archive created with progress tracking');
124
});
125
126
// Promise-based with options
127
try {
128
const buffer = await zipdir('/path/to/directory', {
129
filter: (path, stat) => !path.includes('.git'),
130
each: (path) => console.log('Processing:', path)
131
});
132
console.log('Zip buffer size:', buffer.length);
133
} catch (error) {
134
console.error('Error creating zip:', error);
135
}
136
```
137
138
### Error Handling
139
140
The function handles various error conditions and follows Node.js error-first callback conventions. Errors stop processing immediately and are propagated through the callback/promise chain.
141
142
**Common Error Scenarios:**
143
- **ENOENT**: Directory does not exist or path is invalid
144
- **ENOTDIR**: Path points to a file instead of directory
145
- **EACCES**: File system permission errors during directory traversal or file reading
146
- **EMFILE**: Too many open files (mitigated by 500 file concurrency limit)
147
- **ENOSPC**: Disk space issues when using `saveTo` option
148
- **JSZip Errors**: Zip generation failures (e.g., file too large, memory constraints)
149
150
**Error Handling Examples:**
151
152
```javascript
153
// Callback error handling
154
zipdir('/nonexistent/path', function(err, buffer) {
155
if (err) {
156
console.error('Failed to create zip:', err.message);
157
return;
158
}
159
console.log('Success!');
160
});
161
162
// Promise error handling
163
try {
164
const buffer = await zipdir('/path/to/directory');
165
} catch (error) {
166
console.error('Zip creation failed:', error.message);
167
}
168
```
169
170
## Types
171
172
```javascript { .api }
173
/**
174
* Node.js fs.Stats object containing file/directory metadata
175
*/
176
interface fs.Stats {
177
isFile(): boolean;
178
isDirectory(): boolean;
179
size: number;
180
mtime: Date;
181
// ... other fs.Stats properties
182
}
183
```
184
185
## Implementation Notes
186
187
- **Zip Library**: Uses JSZip library internally for cross-platform zip file creation
188
- **Compression**: Supports DEFLATE compression method with `type: 'nodebuffer'` output
189
- **Concurrency Control**: Implements async queue with maximum 500 concurrent file reads to prevent resource exhaustion and avoid EMFILE errors
190
- **Buffer Output**: Returns zip data as Node.js Buffer objects suitable for writing to disk or network transmission
191
- **Directory Structure**: Preserves original directory structure in the zip archive with files stored using relative paths from the root directory
192
- **Path Resolution**: All input paths are resolved using `path.resolve()` to handle relative paths and trailing slashes consistently
193
- **File System**: Uses `fs.readdir()`, `fs.stat()`, and `fs.readFile()` for directory traversal and file reading
194
- **Error Handling**: Stops processing on first error and propagates through callback/promise chains
195
- **Filter Behavior**: Filter function must return `true` for directories to allow traversal into subdirectories
196
- **Progress Tracking**:
197
- For files: `each` callback receives path relative to root directory (e.g., "subdir/file.txt")
198
- For directories: `each` callback receives full absolute path of the directory being processed
199
- **File Writing**: When `saveTo` option is used, writes with `{ encoding: 'binary' }` to preserve zip file integrity