compressing
Advanced tools
Comparing version 1.0.0 to 1.1.0
1.1.0 / 2017-02-14 | ||
================== | ||
* feat: uncompress (#2) | ||
1.0.0 / 2016-12-24 | ||
@@ -3,0 +8,0 @@ ================== |
@@ -5,4 +5,7 @@ 'use strict'; | ||
const GzipFileStream = require('./file_stream'); | ||
const GzipUncompressStream = require('./uncompress_stream'); | ||
exports.FileStream = GzipFileStream; | ||
exports.compressFile = utils.makeCompressFileFunc(GzipFileStream); | ||
exports.UncompressStream = GzipUncompressStream; | ||
exports.compressFile = utils.makeFileProcessFn(GzipFileStream); | ||
exports.uncompress = utils.makeFileProcessFn(GzipUncompressStream); |
@@ -6,6 +6,9 @@ 'use strict'; | ||
const TarFileStream = require('./file_stream'); | ||
const TarUncompressStream = require('./uncompress_stream'); | ||
exports.Stream = TarStream; | ||
exports.FileStream = TarFileStream; | ||
exports.compressDir = utils.makeCompressDirFunc(TarStream); | ||
exports.compressFile = utils.makeCompressFileFunc(TarFileStream); | ||
exports.UncompressStream = TarUncompressStream; | ||
exports.compressDir = utils.makeCompressDirFn(TarStream); | ||
exports.compressFile = utils.makeFileProcessFn(TarFileStream); | ||
exports.uncompress = utils.makeUncompressFn(TarUncompressStream); |
@@ -6,6 +6,9 @@ 'use strict'; | ||
const TgzFileStream = require('./file_stream'); | ||
const TgzUncompressStream = require('./uncompress_stream'); | ||
exports.Stream = TgzStream; | ||
exports.FileStream = TgzFileStream; | ||
exports.compressDir = utils.makeCompressDirFunc(TgzStream); | ||
exports.compressFile = utils.makeCompressFileFunc(TgzFileStream); | ||
exports.UncompressStream = TgzUncompressStream; | ||
exports.compressDir = utils.makeCompressDirFn(TgzStream); | ||
exports.compressFile = utils.makeFileProcessFn(TgzFileStream); | ||
exports.uncompress = utils.makeUncompressFn(TgzUncompressStream); |
'use strict'; | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const mkdirp = require('mkdirp'); | ||
const pipe = require('multipipe'); | ||
@@ -21,3 +23,3 @@ | ||
exports.destType = dest => { | ||
function destType(dest) { | ||
if (typeof dest._write === 'function' || typeof dest._transform === 'function') return 'stream'; | ||
@@ -29,5 +31,7 @@ if (typeof dest !== 'string') { | ||
} | ||
return 'file'; | ||
}; | ||
return 'path'; | ||
} | ||
exports.destType = destType; | ||
const illigalEntryError = new Error('Type is not supported, must be a file path, directory path, file buffer, or a readable stream'); | ||
@@ -56,7 +60,7 @@ illigalEntryError.name = 'IlligalEntryError'; | ||
exports.makeCompressFileFunc = StreamClass => { | ||
exports.makeFileProcessFn = StreamClass => { | ||
return (source, dest, opts) => { | ||
opts = opts || {}; | ||
opts.source = source; | ||
const destStream = exports.destType(dest) === 'file' ? fs.createWriteStream(dest) : dest; | ||
const destStream = destType(dest) === 'path' ? fs.createWriteStream(dest) : dest; | ||
const compressStream = new StreamClass(opts); | ||
@@ -67,5 +71,5 @@ return safePipe([ compressStream, destStream ]); | ||
exports.makeCompressDirFunc = StreamClass => { | ||
exports.makeCompressDirFn = StreamClass => { | ||
return (dir, dest, opts) => { | ||
const destStream = exports.destType(dest) === 'file' ? fs.createWriteStream(dest) : dest; | ||
const destStream = destType(dest) === 'path' ? fs.createWriteStream(dest) : dest; | ||
const compressStream = new StreamClass(); | ||
@@ -77,2 +81,54 @@ compressStream.addEntry(dir, opts); | ||
exports.makeUncompressFn = StreamClass => { | ||
return (source, destDir, opts) => { | ||
opts = opts || {}; | ||
opts.source = source; | ||
if (destType(destDir) !== 'path') { | ||
const error = new Error('uncompress destination must be a directory'); | ||
error.name = 'IlligalDestError'; | ||
throw error; | ||
} | ||
return new Promise((resolve, reject) => { | ||
mkdirp(destDir, err => { | ||
if (err) return reject(err); | ||
new StreamClass(opts) | ||
.on('finish', resolve) | ||
.on('error', reject) | ||
.on('entry', (header, stream, next) => { | ||
stream.on('end', next); | ||
if (header.type === 'file') { | ||
const fullpath = path.join(destDir, header.name); | ||
mkdirp(path.dirname(fullpath), err => { | ||
if (err) return reject(err); | ||
stream.pipe(fs.createWriteStream(fullpath)); | ||
}); | ||
} else { // directory | ||
mkdirp(path.join(destDir, header.name), err => { | ||
if (err) return reject(err); | ||
stream.resume(); | ||
}); | ||
} | ||
}); | ||
}); | ||
}); | ||
}; | ||
}; | ||
exports.streamToBuffer = stream => { | ||
return new Promise((resolve, reject) => { | ||
const chunks = []; | ||
stream | ||
.on('readable', () => { | ||
let chunk; | ||
while ((chunk = stream.read())) chunks.push(chunk); | ||
}) | ||
.on('end', () => resolve(Buffer.concat(chunks))) | ||
.on('error', err => reject(err)); | ||
}); | ||
}; | ||
function safePipe(streams) { | ||
@@ -87,1 +143,2 @@ return new Promise((resolve, reject) => { | ||
exports.safePipe = safePipe; |
@@ -6,6 +6,9 @@ 'use strict'; | ||
const ZipFileStream = require('./file_stream'); | ||
const ZipUncompressStream = require('./uncompress_stream'); | ||
exports.Stream = ZipStream; | ||
exports.FileStream = ZipFileStream; | ||
exports.compressDir = utils.makeCompressDirFunc(ZipStream); | ||
exports.compressFile = utils.makeCompressFileFunc(ZipFileStream); | ||
exports.UncompressStream = ZipUncompressStream; | ||
exports.compressDir = utils.makeCompressDirFn(ZipStream); | ||
exports.compressFile = utils.makeFileProcessFn(ZipFileStream); | ||
exports.uncompress = utils.makeUncompressFn(ZipUncompressStream); |
{ | ||
"name": "compressing", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "Everything you need for compressing and uncompressing", | ||
@@ -37,3 +37,5 @@ "main": "index.js", | ||
"dependencies": { | ||
"flushwritable": "^1.0.0", | ||
"get-ready": "^1.0.0", | ||
"mkdirp": "^0.5.1", | ||
"multipipe": "^1.0.2", | ||
@@ -46,2 +48,3 @@ "streamifier": "^0.1.1", | ||
"devDependencies": { | ||
"dir-compare": "^1.3.0", | ||
"egg-bin": "^1.9.1", | ||
@@ -48,0 +51,0 @@ "eslint": "^3.10.2", |
166
README.md
@@ -23,6 +23,4 @@ # compressing | ||
The missing compress and uncompress lib for node. | ||
The missing compressing and uncompressing lib for node. | ||
__Currently uncompressing has not been supported yet.__ | ||
Currently supported: | ||
@@ -74,13 +72,13 @@ | ||
new compressing.gzip.FileStream({ source: 'file/path/to/compress' }) | ||
.on('error', handleError) | ||
.pipe(fs.createWriteStream('path/to/destination.gz')) | ||
.on('error', handleError); | ||
.on('error', handleError) | ||
.pipe(fs.createWriteStream('path/to/destination.gz')) | ||
.on('error', handleError); | ||
// It's a transform stream, so you can pipe to it | ||
fs.createReadStream('file/path/to/compress') | ||
.on('error', handleError) | ||
.pipe(new compressing.gzip.FileStream()) | ||
.on('error', handleError) | ||
.pipe(fs.createWriteStream('path/to/destination.gz')) | ||
.on('error', handleError); | ||
.on('error', handleError) | ||
.pipe(new compressing.gzip.FileStream()) | ||
.on('error', handleError) | ||
.pipe(fs.createWriteStream('path/to/destination.gz')) | ||
.on('error', handleError); | ||
@@ -92,3 +90,3 @@ // You should take care of stream errors in caution, use multipipe to handle error in one place | ||
const destStream = fs.createWriteStream('path/to/destination.gz'); | ||
pipe(sourceStream, gzipStream, destStream, err => handleError); | ||
pipe(sourceStream, gzipStream, destStream, handleError); | ||
``` | ||
@@ -121,5 +119,5 @@ | ||
tarStream | ||
.on('error', handleError) | ||
.pipe(fs.createWriteStream('path/to/destination.tar')) | ||
.on('error', handleError); | ||
.on('error', handleError) | ||
.pipe(fs.createWriteStream('path/to/destination.tar')) | ||
.on('error', handleError); | ||
@@ -153,2 +151,91 @@ // You should take care of stream errors in caution, use multipipe to handle error in one place | ||
### Uncompress a file | ||
__promise style__ | ||
```js | ||
const compressing = require('compressing'); | ||
// uncompress a file | ||
compressing.tgz.uncompress('file/path/to/uncompress.tgz', 'path/to/destination/dir') | ||
.then(uncompressDone) | ||
.catch(handleError); | ||
// uncompress a file buffer | ||
compressing.tgz.uncompress(buffer, 'path/to/destination/dir') | ||
.then(uncompressDone) | ||
.catch(handleError); | ||
// uncompress a stream | ||
compressing.tgz.uncompress(stream, 'path/to/destination/dir') | ||
.then(uncompressDone) | ||
.catch(handleError); | ||
``` | ||
**Note: tar, tgz and zip have the same uncompressing API as above: destination should be a path of a directory, while that of gzip is slightly different: destination must be a file or filestream.** | ||
And working with urllib is super easy. Let's download a tgz file and uncompress to a directory: | ||
```js | ||
const urllib = require('urllib'); | ||
const targetDir = require('os').tmpdir(); | ||
const compressing = require('compressing'); | ||
urllib.request('http://registry.npmjs.org/pedding/-/pedding-1.1.0.tgz', { | ||
streaming: true, | ||
followRedirect: true, | ||
}) | ||
.then(result => compressing.tgz.uncompress(result.res, targetDir)) | ||
.then(() => console.log('uncompress done')) | ||
.catch(console.error); | ||
``` | ||
__stream style__ | ||
```js | ||
const compressing = require('compressing'); | ||
const mkdirp = require('mkdirp'); | ||
function onEntry(header, stream, next) => { | ||
stream.on('end', next); | ||
// header.type => file | directory | ||
// header.name => path name | ||
if (header.type === 'file') { | ||
stream.pipe(fs.createWriteStream(path.join(destDir, header.name))); | ||
} else { // directory | ||
mkdirp(path.join(destDir, header.name), err => { | ||
if (err) return handleError(err); | ||
stream.resume(); | ||
}); | ||
} | ||
} | ||
new compressing.tgz.UncompressStream({ source: 'file/path/to/uncompress.tgz' }) | ||
.on('error', handleError) | ||
.on('finish', handleFinish) // uncompressing is done | ||
.on('entry', onEntry); | ||
// It's a writable stream, so you can pipe to it | ||
fs.createReadStream('file/path/to/uncompress') | ||
.on('error', handleError) | ||
.pipe(new compressing.tgz.UncompressStream()) | ||
.on('error', handleError) | ||
.on('finish', handleFinish) // uncompressing is done | ||
.on('entry', onEntry); | ||
``` | ||
**Note: tar, tgz and zip have the same uncompressing streaming API as above: it's a writable stream, and entries will be emitted while uncompressing one after one another, while that of gzip is slightly different: gzip.UncompressStream is a transform stream, so no `entry` event will be emitted and you can just pipe to another stream** | ||
This constrants is brought by Gzip algorithm itself, it only support compressing one file and uncompress one file. | ||
```js | ||
new compressing.gzip.UncompressStream({ source: 'file/path/to/uncompress.gz' }) | ||
.on('error', handleError) | ||
.pipe(fs.createWriteStream('path/to/dest/file')) | ||
.on('error', handleError); | ||
``` | ||
## API | ||
@@ -179,12 +266,27 @@ | ||
- tar.compressDir(dir, dest, opts) | ||
- tgz.compressDir(dir, dest, opts) | ||
- zip.compressDir(dir, dest, opts) | ||
- tar.compressDir(source, dest, opts) | ||
- tgz.compressDir(source, dest, opts) | ||
- zip.compressDir(source, dest, opts) | ||
Params | ||
- dir {String|Buffer|Stream} - dir path to be compressed | ||
- source {String|Buffer|Stream} - source to be compressed | ||
- dest {String|Stream} - compressing destination, could be a file path(eg. `/path/to/xx.tgz`), or a writable stream. | ||
- opts {Object} - usually you don't need it | ||
### uncompress | ||
Use this API to uncompress a file. This is a convenient method, which wraps UncompressStream API below, but you can handle error in one place. RECOMMANDED. | ||
- tar.uncompress(source, dest, opts) | ||
- tgz.uncompress(source, dest, opts) | ||
- zip.uncompress(source, dest, opts) | ||
- gzip.uncompress(source, dest, opts) | ||
Params | ||
- source {String|Buffer|Stream} - source to be uncompressed | ||
- dest {String|Stream} - uncompressing destination. When uncompressing tar, tgz and zip, it should be a directory path (eg. `/path/to/xx`). **When uncompressing gzip, it should be a file path or a writable stream.** | ||
- opts {Object} - usually you don't need it | ||
### FileStream | ||
@@ -250,4 +352,30 @@ | ||
### UncompressStream | ||
The writable stream to uncompress anything as you need. | ||
__Note: If you are not very familiar with streams, just use `uncompress()` API, error can be handled in one place.__ | ||
__Gzip only support compressing and uncompressing one single file. So gzip.UncompressStream is a transform stream which is different from others.__ | ||
__Constructor__ | ||
- new gzip.UncompressStream(opts) | ||
- new tar.UncompressStream(opts) | ||
- new tgz.UncompressStream(opts) | ||
- new zip.UncompressStream(opts) | ||
Common params: | ||
- opts.source {String|Buffer|Stream} - source to be uncompressed, could be a file path, buffer, or a readable stream. | ||
__CAUTION for zip.UncompressStream__ | ||
Due to the design of the .zip file format, it's impossible to interpret a .zip file without loading all data into memory. | ||
Although the API is streaming style(try to keep it handy), it still loads all data into memory. | ||
https://github.com/thejoshwolfe/yauzl#no-streaming-unzip-api | ||
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
39180
21
709
375
8
7
7
+ Addedflushwritable@^1.0.0
+ Addedmkdirp@^0.5.1
+ Addedflushwritable@1.0.0(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedmkdirp@0.5.6(transitive)