npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

zip-local

v0.3.5

Published

very simple zipping/uzipping of local files and directories in node.js

Downloads

84,270

Readme

zip-local

Why another one?!

I was working on a project and I needed something to zip and unzip local directories, so I went and searched on npm. I got quite a lot of results and all of them worked perfectly with files, but it when it came to directories each of them suffered from at least one of these three problems:

  • not being asynchronous
  • not being developer-friendly
  • having odd behaviors (like zipping the whole path to root along with the directory)

So I wrote this to provide something free of the three problems!

Installation

using npm:

npm install zip-local

Usage

The API comes in two versions: an asynchrnous version and a synchronous one. This gives you the choice to use whichever suitable for your application.

Zipping

Zipping is done through ZipLocal.zip or its synchronous version ZipLocal.sync.zip by passing the path to the file or directory that needs to be zipped. In the asynchrnous version, the callback is passed an instance of ZipExport object that contains the APIs to export the zipped file. In the synchronous version, the ZipExport object is returned.

Here's an example of asynchronous zipping,

var zipper = require("zip-local");

// zipping a file
zipper.zip("./hello-world.cpp", function(error, zipped) {

    if(!error) {
        zipped.compress(); // compress before exporting

        var buff = zipped.memory(); // get the zipped file as a Buffer

        // or save the zipped file to disk
        zipped.save("../package.zip", function(error) {
            if(!error) {
                console.log("saved successfully !");
            }
        });
    }
});

and here's synchronous zipping,

var zipper = require('zip-local');

// zipping a file to memory without compression
var buff = zipper.sync.zip("./hello-world.java").memory();

// zipping a directory to disk with compression
// the directory has the following structure
// |-- hello-world.txt
// |-- cpp
//     |-- hello-world.cpp
// |-- java
//     |--hello-world.java
zipper.sync.zip("./hello/world/").compress().save("pack.zip");

Unzipping

Similiarly, unzipping is done through ZipLocal.unzip or the synchronous ZipLocal.sync.unzip by passing the path to the zip file. Like the zipping functions, these functions also use the ZipExport object for exporting your unzipped file, but in case of exporting in memory the memory function returns a ZippedFS object instead of a buffer. This objects servers as a mini-filesystem for the unzipped file.

An example for asynchronous unzipping,

var zipper = require('zip-local');

zipper.unzip("../package.zip", function(error, unzipped) {

    if(!error) {
        // extract to the current working directory
        unzipped.save(null, function() { });

        var unzippedfs = unzipped.memory();

        // print an array of file paths in the unzipped file
        console.log(unzippedfs.contents()); // prints [ 'hello-world.cpp' ]

        // read the file as text
        var txt = unzippedfs.read("hello-world.cpp", 'text');

        // or read it as Buffer
        var buff = unzippedfs.read("hello-world.cpp", 'buffer');
    }
});

and the synchronous unzipping,

var zipper = require('zip-local');

// extract to an existing directory
zipper.sync.unzip("pack.zip").save("../../hello");

// export in memory
var unzippedfs = zipper.sync.unzip("pack.zip").memory();

// logs ['hello-world.txt', 'cpp/hello-world.cpp', 'java/hello-world.java']
console.log(unzippedfs.contents());

// read file in buffer
var buff = unzippedfs.read("cpp/hello-world.cpp", "buffer");

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 ZippedFS object from a previously unzipped file. This could be done simply by passing the bufferto the zip/unzip methods or the ZippedFS 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 :

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(error, zipped) {

            if(error) {
                console.log("ERROR: %s", error.message);
                return;
            }

            // cache a copy of the zipped file on the server
            zipped.save("zipped_from" + socket.remoteAddress + ".zip", function(error) {
                if(error) {
                    console.log("ERROR: %s", error.message);
                    return;
                }
            });

            // 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 data 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 JSZip object and all its low level features through the method ZipExport#lowLevel(). After you zip/unzip your data and acquire the ZipExport object, you can call this method from it and retrieve the underlying JSZip 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 ZippedFS object. This code cleans zipped files from executables (namely .exe, .bat, and .sh):

var zipper = require('zip-local');

zipper.unzip('package.zip', function(error, unzipped) {

    if(error) {
        console.log("ERROR: %s", error.message);
        return;
    }

    var unzippedFS = unzipped.memory();
    var files = unzippedFS.contents();
    var notExecRegExp = new RegExp(/^[^.]+$|\.(?!(sh|exe|bat)$)([^.]+$)/);

    files.forEach(function (file) {
        if(!notExecRegExp.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(error) {
            if(error) {
                console.log("ERROR: %s", error.message);
            }
            else {
                console.log("The file is scanned and cleaned of executables");
            }
        });
    });
});

read the API documentations for furthur details.

License

MIT