Skip to content

Commit

Permalink
Async iteration [feat]
Browse files Browse the repository at this point in the history
Closes #7, #8, #9.
  • Loading branch information
overlookmotel committed Apr 30, 2023
1 parent 0866e6e commit 9458ee3
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 1 deletion.
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@ Promisified version of [yauzl](https://www.npmjs.com/package/yauzl) for unzippin
npm install yauzl-promise
```

### Simple usage

```js
const {pipeline} = require('stream/promises');
const zipFile = await yauzl.open('/path/to/file.zip');
try {
for await (const entry of zipFile) {
if (entry.fileName.endsWith('/')) continue;
const readStream = await entry.openReadStream();
await pipeline(readStream, writeStream);
}
} finally {
await zipfile.close();
}
```

### Methods

#### `open()` / `fromFd()` / `fromBuffer()` / `fromRandomAccessReader()`
Expand Down Expand Up @@ -62,7 +78,7 @@ entries.forEach(console.log);

If `numEntries` is `0`, `null` or `undefined`, reading will continue until all entries are read.

WARNING: This is dangerous. If ZIP contains a large number of files, could lead to crash due to out of memory. Use `.walkEntries()` instead.
WARNING: This is dangerous. If ZIP contains a large number of files, could lead to crash due to out of memory. Use `.walkEntries()` or async iteration instead.

#### `zipFile.walkEntries( callback [, numEntries] )`

Expand All @@ -81,6 +97,19 @@ console.log('Done');

If `numEntries` is `0`, `null` or `undefined`, reading will continue until all entries are read.

#### Async iteration

`ZipFile`s can be used as async iterators, iterating over entries.

```js
const zipFile = await yauzl.open('/path/to/file.zip');

const entries = [];
for await (const entry of zipFile) {
entries.push(entry);
}
```

#### `zipFile.openReadStream( entry [, options] )`

Same as original method but returns promise of a stream.
Expand Down
16 changes: 16 additions & 0 deletions lib/promisify.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ module.exports = (yauzl, Promise) => {
ZipFile.prototype.readEntries = readEntries;
addWalkEntriesMethod(ZipFile, Promise);

// Add async iterator
addAsyncIterator(ZipFile);

// Promisify ZipFile `openReadStream` method
promisifyOpenReadStream(ZipFile, Promise);

Expand Down Expand Up @@ -285,6 +288,19 @@ function walkNextEntry(zipFile, fn, numEntries, count, cb) {
.catch(cb);
}

/**
* Add async iterator to iterate over ZIP file's entries.
* @param {Object} ZipFile - `ZipFile` class
* @returns {undefined}
*/
function addAsyncIterator(ZipFile) {
ZipFile.prototype[Symbol.asyncIterator] = function() {
return {
next: () => this.readEntry().then(entry => ({value: entry, done: entry === null}))
};
};
}

/*
* Promisify ZipFile `openReadStream` method
*/
Expand Down
10 changes: 10 additions & 0 deletions test/all.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,16 @@ function runMainTests(methodName, method, getYauzl, Promise) {
return expect(p).rejects.toBe(err);
});
});

describe('async iterator', () => {
it('iterates entries', async () => {
const filenames = [];
for await (const entry of zipFile) {
filenames.push(entry.fileName);
}
expect(filenames).toEqual(FILES);
});
});
});

describe('stream methods', () => {
Expand Down

0 comments on commit 9458ee3

Please sign in to comment.