Comparing version 0.1.3 to 0.2.0
@@ -177,2 +177,11 @@ var fs = require('fs'); | ||
/* | ||
* returns the associated JSZip object for low level operations | ||
* @returns {JSZip}: the associated JSZip object | ||
*/ | ||
ZipExport.prototype.lowLevel = function () { | ||
return this.content; | ||
} | ||
/* | ||
* sets the object so that the exported format will be compressed | ||
@@ -179,0 +188,0 @@ */ |
205
main.js
@@ -7,2 +7,3 @@ var fs = require('fs'); | ||
var ZipExport = require('./libs/ZipExport.js'); | ||
var ZippedFS = require('./libs/ZippedFS.js'); | ||
@@ -133,42 +134,76 @@ /***************************************************************************************** | ||
* zips a given file/directory asynchronously | ||
* @param _path {String}: the path to file/directory to zip | ||
* @param entity {String || Buffer || ZippedFS}: the path to file/directory to zip, the buffer containing the file or a ZippedFS object of an unzipped file | ||
* @param _callback {Function}: the function to be called when the zipping is done | ||
* @param _shiftedCallback {Function}: the callback shifted to last argument if entity is a Buffer (optional) | ||
*/ | ||
ZipLocal.zip = function (_path, _callback) { | ||
ZipLocal.zip = function (entity, _callback, _shiftedCallback) { | ||
var callback = _callback || function () { }; | ||
var normalized_path = path.normalize(_path); | ||
var zipped_obj = new JSZip(); | ||
fs.stat(normalized_path, function (err, stats) { | ||
if (typeof entity === "string") { | ||
if (err) | ||
throw err; | ||
if (stats.isDirectory()) { | ||
// the entity is a path pointing to a file or a directory | ||
// the callback is not shifted | ||
var callback = _callback || function () { }; | ||
var normalized_path = path.normalize(entity); | ||
fs.stat(normalized_path, function (err, stats) { | ||
// start zipping the directory | ||
Q.fcall(zip_dir, normalized_path, zipped_obj).then(function () { | ||
if (err) | ||
throw err; | ||
if (stats.isDirectory()) { | ||
// invoke the callback | ||
callback(new ZipExport(zipped_obj, false, true)); | ||
}).done(); | ||
} | ||
else { | ||
var parsed_path = path.parse(normalized_path); | ||
fs.readFile(normalized_path, function (err, file) { | ||
// start zipping the directory | ||
Q.fcall(zip_dir, normalized_path, zipped_obj).then(function () { | ||
// invoke the callback | ||
callback(new ZipExport(zipped_obj, false, true)); | ||
}).done(); | ||
} | ||
else { | ||
if (err) | ||
throw err; | ||
var parsed_path = path.parse(normalized_path); | ||
fs.readFile(normalized_path, function (err, file) { | ||
if (err) | ||
throw err; | ||
zipped_obj.file(parsed_path.base, file); | ||
// invoke the callback | ||
callback(new ZipExport(zipped_obj, false, true)); | ||
zipped_obj.file(parsed_path.base, file); | ||
}); | ||
} | ||
}); | ||
} | ||
else if (entity instanceof Buffer) { | ||
// the entity is a buffer containing a file | ||
// the _callback argument is now the name of the file in buffer | ||
// the callback is shifted to _shiftedCallback argument | ||
var name = _callback; | ||
var callback = _shiftedCallback || function () { }; | ||
// invoke the callback | ||
callback(new ZipExport(zipped_obj, false, true)); | ||
zipped_obj.file(name, entity); | ||
// invoke the callback | ||
callback(new ZipExport(zipped_obj, false, true)); | ||
} | ||
}); | ||
} | ||
}); | ||
else if (entity instanceof ZippedFS) { | ||
// the entity is a ZippedFS from an unzipped file | ||
var callback = _callback || function () { }; | ||
//invoke the callback | ||
callback(new ZipExport(entity.unzipped_file, false, true)); | ||
} | ||
else { | ||
throw new Error("Unsupported type: data is neither a path or a Buffer"); | ||
} | ||
} | ||
@@ -178,21 +213,38 @@ | ||
* unzips a given zip file asynchronously | ||
* @param _path {String}: the path to the zip file | ||
* @param file {String || Buffer}: the path to the zip file or the buffer containing it | ||
* @param _callback {Function}: the function to be called when the unzipping is done | ||
*/ | ||
ZipLocal.unzip = function (_path, _callback) { | ||
ZipLocal.unzip = function (file, _callback) { | ||
var callback = _callback || function () { }; | ||
var zipped_obj = new JSZip(); | ||
if (typeof file === "string") { | ||
// file is a path that points to a zip file | ||
var normalized_path = path.normalize(file); | ||
fs.readFile(normalized_path, function (err, data) { | ||
zipped_obj.load(data); | ||
//invoke the callback | ||
callback(new ZipExport(zipped_obj, true, true)) | ||
var normalized_path = path.normalize(_path); | ||
}); | ||
} | ||
else if (file instanceof Buffer) { | ||
// file is a Buffer that contains the data | ||
fs.readFile(normalized_path, function (err, data) { | ||
zipped_obj.load(file); | ||
var zipped_obj = new JSZip(); | ||
zipped_obj.load(data); | ||
//invoke the callback | ||
callback(new ZipExport(zipped_obj, true, true)) | ||
} | ||
else { | ||
throw new Error("Unsupported type: data is neither a path or a Buffer"); | ||
} | ||
}); | ||
} | ||
@@ -202,27 +254,51 @@ | ||
* zips a given file/directory synchronously | ||
* @param _path {String}: the path to the file/directory to zip | ||
* @param entity {String || Buffer || ZippedFS}: the path to the file/directory to zip, a buffer containing a file or a ZippedFS object of an unzipped file | ||
* @param buffer_name {String}: the name of the file if entity is buffer (optional) | ||
* @return {ZipExport}: the ZipExport object that contains exporting interfaces | ||
*/ | ||
ZipLocal.sync.zip = function(_path) { | ||
ZipLocal.sync.zip = function(entity, buffer_name) { | ||
var normalized_path = path.normalize(_path); | ||
var stats = fs.statSync(normalized_path); | ||
var zipped_obj = new JSZip(); | ||
if(stats.isDirectory()) { | ||
if (typeof entity === "string") { | ||
// start zipping the directory | ||
zip_dir_sync(normalized_path, zipped_obj); | ||
// the entity is a path pointing to a file or a directory | ||
return new ZipExport(zipped_obj); | ||
var normalized_path = path.normalize(entity); | ||
var stats = fs.statSync(normalized_path); | ||
if (stats.isDirectory()) { | ||
// start zipping the directory | ||
zip_dir_sync(normalized_path, zipped_obj); | ||
return new ZipExport(zipped_obj); | ||
} | ||
else { | ||
var parsed_path = path.parse(normalized_path); | ||
var file = fs.readFileSync(normalized_path); | ||
zipped_obj.file(parsed_path.base, file); | ||
} | ||
} | ||
else { | ||
else if (entity instanceof Buffer) { | ||
var parsed_path = path.parse(normalized_path); | ||
var file = fs.readFileSync(normalized_path); | ||
// the entity is a buffer containing a file | ||
zipped_obj.file(buffer_name, entity); | ||
} | ||
else if (entity instanceof ZippedFS) { | ||
zipped_obj.file(parsed_path.base, file); | ||
// the entity is a ZippedFS from an unzipped file | ||
return new ZipExport(zipped_obj); | ||
//change the zipped_obj | ||
zipped_obj = entity.unzipped_file; | ||
} | ||
else { | ||
throw new Error("Unsupported type: data is neither a path or a Buffer"); | ||
} | ||
return new ZipExport(zipped_obj); | ||
} | ||
@@ -232,13 +308,28 @@ | ||
* unzips a given zip file synchrnously | ||
* @param _path {String}: the path to the zip file | ||
* @param file {String || Buffer}: the path to the zip file or the buffer containing it | ||
* @return {ZipExport}: the ZipExport object that contains exporting interfaces | ||
*/ | ||
ZipLocal.sync.unzip = function (_path) { | ||
ZipLocal.sync.unzip = function (file) { | ||
var zipped_obj = new JSZip(); | ||
if (typeof file === "string") { | ||
// file is a path that points to a zip file | ||
var normalized_path = path.normalize(_path); | ||
var normalized_path = path.normalize(file); | ||
var data = fs.readFileSync(normalized_path); | ||
zipped_obj.load(data); | ||
} | ||
else if (file instanceof Buffer) { | ||
var data = fs.readFileSync(_path); | ||
// file is a Buffer that contains the data | ||
var zipped_obj = new JSZip(); | ||
zipped_obj.load(data); | ||
zipped_obj.load(file); | ||
} | ||
else { | ||
throw new Error("Unsupported type: data is neither a path or a Buffer"); | ||
} | ||
@@ -245,0 +336,0 @@ return new ZipExport(zipped_obj, true, false); |
{ | ||
"name": "zip-local", | ||
"version": "0.1.3", | ||
"version": "0.2.0", | ||
"description": "very simple zipping/uzipping of local files and directories in node.js", | ||
@@ -5,0 +5,0 @@ "main": "main.js", |
@@ -1,2 +0,2 @@ | ||
# zip-local | ||
# zip-local | ||
@@ -110,2 +110,63 @@ ## Why another one?! | ||
### Zipping/Unzipping directly from memory | ||
Imagine a serevr that needs to zip files it receives through its clients and send the zipped file to the client. When the file is received it resides in a buffer in memory, and to be able to zip it with the library (using the methods described so far) we must first save the file to local storage then zip it using its path so that the library would read it back to memory and zip it. This is definitely ineffcient and wasteful of the serevr's time and resources. | ||
To solve this issue, starting from v0.2.0 you can zip/unzip a file directly from the buffer containing it in memory or zip an entire <code>ZippedFS</code> object from a previously unzipped file. This could be done simply by passing the bufferto the zip/unzip methods or the <code>ZippedFS</code> object to zip method instead of the path, and it works for both asynchronous and synchronous versions. Notice that in the case of zipping a buffer you'll need to pass an extra argument after the buffer which is the name of the file that will be included in the zip. | ||
Here's an example implementing the above scenario that utilizes the ability to zip buffers : | ||
```javascript | ||
var zipper = require('zip-local'); | ||
var net = require('net'); | ||
var server = net.createServer(function (socket) { | ||
socket.on('data', function(data) { | ||
zipper.zip(data, "remote_file", function(zipped) { | ||
// cache a copy of the zipped file on the server | ||
zipped.save("zipped_from" + socket.remoteAddress + ".zip"); | ||
// send the zipped file back to the client | ||
socket.write(zipped.memory()); | ||
}); | ||
}); | ||
}); | ||
server.listen(3000); | ||
``` | ||
### Low Level Operations | ||
While the library was designed to provide a simple high-level APIs to zip/unzip local directories and files, it's sometimes needed to perform some low level operations on the before exporting it like adding new files to the zip or removing some files form an unzipped file before writing to disk. And since this library is based on JSZip which provides these low level operations, starting from v0.2.0 you can access the underlying <code>JSZip</code> object and all its low level features through the method <code>ZipExport#lowLevel()</code>. After you zip/unzip your data and acquire the <code>ZipExport</code> object, you can call this method from it and retrieve the underlying <code>JSZip</code> object and play around with it. | ||
Here's an example that utilizes the low level operations to remove files and also utilizes the ability to zip <code>ZippedFS</code> object. This code cleans zipped files from executables (namely .exe, .bat, and .sh): | ||
```javascript | ||
var zipper = require('zip-local'); | ||
zipper.unzip('package.zip', function(unzipped) { | ||
var unzippedFS = unzipped.memory(); | ||
var files = unzippedFS.contents(); | ||
var notExecutableRegExp = new RegExp(/^[^.]+$|\.(?!(sh|exe|bat)$)([^.]+$)/); | ||
files.forEach(function (file) { | ||
if(!notExecutableRegExp.test(file)) | ||
unzipped.lowLevel().remove(file); | ||
}); | ||
var cleanUnzippedFS = unzipped.memory(); | ||
// re-zip the clean ZippedFS | ||
zipper.zip(cleanUnzippedFS, function(zipped) { | ||
zipped.save("package.zip", function() { | ||
console.log("The file is scanned and cleaned of executables"); | ||
}); | ||
}); | ||
}); | ||
``` | ||
read the [API documentations](https://github.com/Mostafa-Samir/zip-local/wiki/API-Documentation) for furthur details. | ||
@@ -112,0 +173,0 @@ |
@@ -63,5 +63,24 @@ var fs = require('fs'); | ||
}); | ||
}); | ||
it("unzips a file directly from the buffer containing it", function (done) { | ||
var buff = fs.readFileSync("./tests/assets/hello.zip"); | ||
zipper.unzip(buff, function (unzipped) { | ||
localMemory.T5ZippedFS = unzipped.memory(); | ||
done(); | ||
}); | ||
}); | ||
it("checks if the ZippedFS object contains correct data", function () { | ||
expect(localMemory.T5ZippedFS.contents()).to.include("hello/says-hello") && | ||
expect(localMemory.T5ZippedFS.read("hello/says-hello", 'text')).to.equal("Hello") && | ||
expect(localMemory.T5ZippedFS.contents()).to.include("hello/world/says-world") && | ||
expect(localMemory.T5ZippedFS.read("hello/world/says-world", 'text')).to.equal("World"); | ||
}); | ||
}) |
@@ -11,3 +11,3 @@ var fs = require('fs'); | ||
it("should unzip a .zip file in memory without errors", function () { | ||
it("unzips a .zip file in memory without errors", function () { | ||
@@ -25,3 +25,3 @@ localMemory.T1ZippedFS = zipper.sync.unzip("./tests/assets/hello.zip").memory(); | ||
it("should unzip a .zip file to disk without errors", function () { | ||
it("unzips a .zip file to disk without errors", function () { | ||
@@ -32,3 +32,3 @@ fs.mkdirSync("./tests/assets/hello-sync-unzip"); | ||
it("should check if unzipped files on disk contain correct data", function (done) { | ||
it("checks if unzipped files on disk contain correct data", function (done) { | ||
@@ -52,5 +52,19 @@ fs.readFile("./tests/assets/hello-sync-unzip/hello/says-hello", 'utf8', function (err, data) { | ||
}); | ||
}); | ||
it("unzips a file directly from the buffer containing it", function () { | ||
var buff = fs.readFileSync("./tests/assets/hello.zip"); | ||
localMemory.T5ZippedFS = zipper.sync.unzip(buff).memory(); | ||
}); | ||
it("checks if the ZippedFS object contains correct data", function () { | ||
expect(localMemory.T5ZippedFS.contents()).to.include("hello/says-hello") && | ||
expect(localMemory.T5ZippedFS.read("hello/says-hello", 'text')).to.equal("Hello") && | ||
expect(localMemory.T5ZippedFS.contents()).to.include("hello/world/says-world") && | ||
expect(localMemory.T5ZippedFS.read("hello/world/says-world", 'text')).to.equal("World"); | ||
}); | ||
}) |
@@ -63,2 +63,50 @@ var fs = require('fs'); | ||
/* Test 5: zipping a file from the buffer containing it */ | ||
it("zips a file directly from the buffer containing it", function (done) { | ||
var buff = fs.readFileSync("./tests/assets/hello-world"); | ||
zipper.zip(buff, "hello-world", function (zipped) { | ||
localMemory.T5ZippedBuffer = zipped.memory(); | ||
done(); | ||
}); | ||
}); | ||
/* Test 6: making sure that the zipped buffer from Test 5 contains correct data */ | ||
it("checks if the zipped buffer contains correct data (using JSZip)", function () { | ||
var zipped = new JSZip(localMemory.T5ZippedBuffer); | ||
expect(zipped.files).to.have.property("hello-world") && | ||
expect(zipped.file("hello-world").asText()).to.equal("Hello World."); | ||
}); | ||
/* Test 7: zipping a ZippedFS from an unzipped file */ | ||
it("zips a ZippedFS form a previously unzipped files", function (done) { | ||
var unzippedfs = zipper.sync.unzip("./tests/assets/hello.zip").memory(); | ||
zipper.zip(unzippedfs, function (zipped) { | ||
localMemory.T7ZippedBuffer = zipped.memory(); | ||
done(); | ||
}); | ||
}); | ||
/* Test 8: making sure that the zipped buffer from Test 7 contains correct data */ | ||
it("checks if the zipped buffer contains correct data", function () { | ||
var T8ZippedFS = zipper.sync.unzip(localMemory.T7ZippedBuffer).memory(); | ||
expect(T8ZippedFS.contents()).to.include("hello/says-hello") && | ||
expect(T8ZippedFS.read("hello/says-hello", 'text')).to.equal("Hello") && | ||
expect(T8ZippedFS.contents()).to.include("hello/world/says-world") && | ||
expect(T8ZippedFS.read("hello/world/says-world", 'text')).to.equal("World"); | ||
}); | ||
}); |
@@ -51,2 +51,40 @@ var fs = require('fs'); | ||
/* Test 5: zipping a file from the buffer containing it */ | ||
it("zips a file directly from the buffer containing it", function () { | ||
var buff = fs.readFileSync("./tests/assets/hello-world"); | ||
localMemory.T5ZippedBuffer = zipper.sync.zip(buff, "hello-world").memory(); | ||
}); | ||
/* Test 6: making sure that the zipped buffer from Test 5 contains correct data */ | ||
it("checks if the zipped buffer contains correct data (using JSZip)", function () { | ||
var zipped = new JSZip(localMemory.T5ZippedBuffer); | ||
expect(zipped.files).to.have.property("hello-world") && | ||
expect(zipped.file("hello-world").asText()).to.equal("Hello World."); | ||
}); | ||
/* Test 7: zipping a ZippedFS from an unzipped file */ | ||
it("zips a ZippedFS form a previously unzipped files", function () { | ||
var unzippedfs = zipper.sync.unzip("./tests/assets/hello.zip").memory(); | ||
localMemory.T7ZippedBuffer = zipper.sync.zip(unzippedfs).memory(); | ||
}); | ||
/* Test 8: making sure that the zipped buffer from Test 7 contains correct data */ | ||
it("checks if the zipped buffer contains correct data", function () { | ||
var T8ZippedFS = zipper.sync.unzip(localMemory.T7ZippedBuffer).memory(); | ||
expect(T8ZippedFS.contents()).to.include("hello/says-hello") && | ||
expect(T8ZippedFS.read("hello/says-hello", 'text')).to.equal("Hello") && | ||
expect(T8ZippedFS.contents()).to.include("hello/world/says-world") && | ||
expect(T8ZippedFS.read("hello/world/says-world", 'text')).to.equal("World"); | ||
}); | ||
}); |
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
51567
19
824
176