or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/npm-unzip

Streaming cross-platform unzip library for Node.js compatible with fstream and fs.ReadStream

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/unzip@0.1.x

To install, run

npx @tessl/cli install tessl/npm-unzip@0.1.0

0

# Unzip

1

2

Unzip is a streaming cross-platform unzip library for Node.js that provides simple APIs for parsing and extracting zip files. It offers compatibility with fstream and fs.ReadStream interfaces without compiled dependencies, using Node.js's built-in zlib support for inflation.

3

4

## Package Information

5

6

- **Package Name**: unzip

7

- **Package Type**: npm

8

- **Language**: JavaScript (Node.js)

9

- **Installation**: `npm install unzip`

10

11

## Core Imports

12

13

```javascript

14

const unzip = require('unzip');

15

// Or destructured

16

const { Parse, Extract } = require('unzip');

17

```

18

19

ES6 modules (if supported by your Node.js version):

20

21

```javascript

22

import unzip from 'unzip';

23

import { Parse, Extract } from 'unzip';

24

```

25

26

## Basic Usage

27

28

### Extract to Directory

29

30

```javascript

31

const fs = require('fs');

32

const unzip = require('unzip');

33

34

// Extract entire zip archive to a directory

35

fs.createReadStream('path/to/archive.zip')

36

.pipe(unzip.Extract({ path: 'output/path' }));

37

```

38

39

### Parse and Process Entries

40

41

```javascript

42

const fs = require('fs');

43

const unzip = require('unzip');

44

45

// Parse zip file and process individual entries

46

fs.createReadStream('path/to/archive.zip')

47

.pipe(unzip.Parse())

48

.on('entry', function (entry) {

49

const fileName = entry.path;

50

const type = entry.type; // 'Directory' or 'File'

51

const size = entry.size;

52

53

if (fileName === "target-file.txt") {

54

entry.pipe(fs.createWriteStream('output.txt'));

55

} else {

56

entry.autodrain(); // Important: drain unused entries

57

}

58

});

59

```

60

61

## Architecture

62

63

Unzip is built around three core components:

64

65

- **Parse**: Transform stream that parses zip archive structure and emits entry events

66

- **Extract**: Writable stream that extracts entire archives to directories using fstream

67

- **Entry**: PassThrough stream representing individual zip entries (files/directories)

68

69

The library uses a streaming approach for memory efficiency, processing zip files without loading entire contents into memory.

70

71

## Capabilities

72

73

### Zip Archive Parsing

74

75

Parse zip files and access individual entries with streaming support.

76

77

```javascript { .api }

78

/**

79

* Creates a streaming zip parser (can be called with or without 'new')

80

* @param {Object} opts - Configuration options

81

* @param {boolean} opts.verbose - Enable verbose logging (default: false)

82

* @returns {Parse} Transform stream for parsing zip archives

83

*/

84

function Parse(opts);

85

86

/**

87

* Factory method equivalent to new Parse(opts) - preferred way to create instances

88

* @param {Object} opts - Configuration options

89

* @returns {Parse} Transform stream instance

90

*/

91

Parse.create = function(opts);

92

93

/**

94

* Enhanced pipe method with fstream compatibility

95

* Automatically calls dest.add(entry) for each entry if destination has an add method

96

* @param {Object} dest - Destination stream or fstream Writer

97

* @param {Object} opts - Standard pipe options

98

* @returns {Object} The destination stream

99

*/

100

Parse.prototype.pipe = function(dest, opts);

101

102

/**

103

* Enhanced event listener registration that tracks 'entry' listeners

104

* When entry listeners are added, the parser will emit entry events and provide entry streams

105

* @param {string} type - Event type ('entry', 'error', 'close', etc.)

106

* @param {Function} listener - Event handler function

107

* @returns {Parse} This Parse instance for chaining

108

*/

109

Parse.prototype.addListener = function(type, listener);

110

Parse.prototype.on = function(type, listener); // Alias for addListener

111

```

112

113

The Parse stream emits the following events:

114

115

- **'entry'** - Emitted for each zip entry (file/directory)

116

- **'error'** - Emitted on parsing errors

117

- **'close'** - Emitted when parsing completes

118

- **'end'** - Emitted when stream ends

119

- **'finish'** - Emitted when stream finishes

120

121

### Directory Extraction

122

123

Extract entire zip archives to filesystem directories.

124

125

```javascript { .api }

126

/**

127

* Creates a writable stream for extracting zip archives to directories (can be called with or without 'new')

128

* @param {Object} opts - Configuration options

129

* @param {string} opts.path - Target extraction directory (required)

130

* @param {boolean} opts.verbose - Enable verbose logging (default: false)

131

* @returns {Extract} Writable stream for zip extraction

132

*/

133

function Extract(opts);

134

```

135

136

The Extract stream emits the following events:

137

138

- **'error'** - Emitted on extraction errors

139

- **'close'** - Emitted when extraction completes

140

- **'pipe'** - Emitted when piped to

141

- **'finish'** - Emitted when stream finishes

142

143

### Zip Entry Processing

144

145

Individual zip entries are represented as Entry streams.

146

147

```javascript { .api }

148

/**

149

* PassThrough stream representing a zip entry

150

* Note: Entry instances are created internally by Parse, not directly by users

151

* @constructor

152

*/

153

function Entry();

154

155

/**

156

* Automatically drain entry content to prevent memory issues

157

* Call this for entries you don't intend to process

158

*/

159

Entry.prototype.autodrain = function();

160

```

161

162

Entry objects have the following properties (set by Parse during processing):

163

164

- **path** (string) - Entry file path within the zip archive

165

- **type** (string) - Entry type: 'File' or 'Directory' (determined by compressed size and path ending)

166

- **size** (number) - Entry uncompressed size (available after processing, may be undefined during parsing)

167

- **props** (object) - Additional entry properties including a copy of the path

168

169

## Types

170

171

```javascript { .api }

172

/**

173

* Parse stream class (extends Node.js Transform stream)

174

*/

175

class Parse {

176

constructor(opts);

177

178

// Enhanced pipe method with automatic fstream compatibility

179

// Calls dest.add(entry) for each entry if destination has add method

180

pipe(dest, opts);

181

182

// Enhanced event listener methods that track 'entry' listeners

183

// When entry listeners are registered, parser provides entry streams

184

addListener(type, listener);

185

on(type, listener); // Alias for addListener

186

187

// Standard Transform stream methods available

188

write(chunk, encoding, callback);

189

end();

190

// ... other Transform stream methods

191

}

192

193

/**

194

* Extract stream class (extends Node.js Writable stream)

195

*/

196

class Extract {

197

constructor(opts);

198

199

// Standard Writable stream methods available

200

write(chunk, encoding, callback);

201

end();

202

// ... other Writable stream methods

203

}

204

205

/**

206

* Entry stream class (extends Node.js PassThrough stream)

207

*/

208

class Entry {

209

constructor();

210

autodrain();

211

212

// Properties set by Parse during zip processing

213

path: string;

214

type: 'File' | 'Directory';

215

size: number;

216

props: object;

217

218

// Standard PassThrough stream methods available

219

pipe(destination, options);

220

read(size);

221

write(chunk, encoding, callback);

222

// ... other stream methods

223

}

224

225

/**

226

* Configuration options for Parse

227

*/

228

interface ParseOptions {

229

verbose?: boolean;

230

}

231

232

/**

233

* Configuration options for Extract

234

*/

235

interface ExtractOptions {

236

path: string;

237

verbose?: boolean;

238

}

239

```

240

241

## Error Handling

242

243

The library emits errors for various conditions:

244

245

- **Invalid zip signatures**: Throws errors with signature details (e.g., "invalid signature: 0x12345678")

246

- **Stream errors**: Propagated through 'error' events on Parse and Extract streams

247

- **Compression errors**: zlib inflation errors are propagated through the error event chain

248

249

```javascript

250

const parser = unzip.Parse();

251

parser.on('error', function(err) {

252

console.error('Parse error:', err.message);

253

});

254

255

const extractor = unzip.Extract({ path: './output' });

256

extractor.on('error', function(err) {

257

console.error('Extract error:', err.message);

258

});

259

```

260

261

## Advanced Usage

262

263

### Pipe to fstream Writer

264

265

```javascript

266

const fs = require('fs');

267

const fstream = require('fstream');

268

const unzip = require('unzip');

269

270

const readStream = fs.createReadStream('archive.zip');

271

const writeStream = fstream.Writer('output/path');

272

273

readStream

274

.pipe(unzip.Parse())

275

.pipe(writeStream);

276

```

277

278

### Selective File Extraction

279

280

```javascript

281

fs.createReadStream('archive.zip')

282

.pipe(unzip.Parse())

283

.on('entry', function (entry) {

284

if (entry.path.endsWith('.txt')) {

285

// Extract only text files

286

entry.pipe(fs.createWriteStream(`output/${entry.path}`));

287

} else {

288

// Skip other files

289

entry.autodrain();

290

}

291

});

292

```

293

294

### Memory Management

295

296

**Important**: Always call `entry.autodrain()` for entries you don't process to prevent memory leaks:

297

298

```javascript

299

fs.createReadStream('large-archive.zip')

300

.pipe(unzip.Parse())

301

.on('entry', function (entry) {

302

if (entry.type === 'Directory') {

303

// Skip directories

304

entry.autodrain();

305

} else if (entry.size > 1000000) {

306

// Skip large files

307

entry.autodrain();

308

} else {

309

// Process small files

310

entry.pipe(fs.createWriteStream(entry.path));

311

}

312

});

313

```

314

315

### Enhanced Parse Class Features

316

317

#### Automatic fstream Compatibility

318

319

The Parse class automatically detects when piped to fstream destinations and calls `dest.add(entry)` for each zip entry:

320

321

```javascript

322

// Enhanced pipe method detects fstream Writers and calls add() automatically

323

fs.createReadStream("archive.zip")

324

.pipe(unzip.Parse())

325

.pipe(fstream.Writer("output/path")); // Automatically calls writeStream.add(entry)

326

```

327

328

#### Entry Listener Optimization

329

330

The Parse class optimizes behavior based on whether entry listeners are registered:

331

332

```javascript

333

// Without entry listeners - entries are not processed into streams (memory efficient)

334

fs.createReadStream("archive.zip")

335

.pipe(unzip.Parse())

336

.pipe(fstream.Writer("output"));

337

338

// With entry listeners - entries become readable streams

339

fs.createReadStream("archive.zip")

340

.pipe(unzip.Parse())

341

.on("entry", function(entry) {

342

// Entry is now a readable stream with available properties

343

console.log("Processing:", entry.path, "Type:", entry.type);

344

if (entry.size) console.log("Size:", entry.size);

345

entry.autodrain(); // Important: drain if not processing

346

});

347

```

348