{"id":22281462,"url":"https://github.com/mostafa-samir/zip-local","last_synced_at":"2025-10-08T09:39:44.006Z","repository":{"id":39821990,"uuid":"41834715","full_name":"Mostafa-Samir/zip-local","owner":"Mostafa-Samir","description":"very simple zipping/uzipping of local files and directories in node.js","archived":false,"fork":false,"pushed_at":"2023-04-27T10:13:54.000Z","size":56,"stargazers_count":117,"open_issues_count":12,"forks_count":12,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-04-28T02:31:46.206Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Mostafa-Samir.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-09-03T00:32:38.000Z","updated_at":"2024-06-18T13:43:41.640Z","dependencies_parsed_at":"2024-06-18T13:43:33.700Z","dependency_job_id":null,"html_url":"https://github.com/Mostafa-Samir/zip-local","commit_stats":{"total_commits":71,"total_committers":2,"mean_commits":35.5,"dds":"0.014084507042253502","last_synced_commit":"d8d216b93f78cc026370399e93efc68f42ef5a86"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mostafa-Samir%2Fzip-local","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mostafa-Samir%2Fzip-local/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mostafa-Samir%2Fzip-local/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mostafa-Samir%2Fzip-local/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Mostafa-Samir","download_url":"https://codeload.github.com/Mostafa-Samir/zip-local/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247242681,"owners_count":20907134,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-03T16:18:26.338Z","updated_at":"2025-10-08T09:39:38.962Z","avatar_url":"https://github.com/Mostafa-Samir.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# zip-local\n\n## Why another one?!\n\nI 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:\n* not being asynchronous\n* not being developer-friendly\n* having odd behaviors (like zipping the whole path to root along with the directory)\n\nSo I wrote this to provide something free of the three problems!\n\n## Installation\n\nusing npm:\n```\nnpm install zip-local\n```\n\n## Usage\n\nThe API comes in two versions: an asynchrnous version and a synchronous one. This gives you the choice to use whichever suitable for your application.\n\n### Zipping\n\nZipping is done through \u003ccode\u003eZipLocal.zip\u003c/code\u003e or its synchronous version \u003ccode\u003e ZipLocal.sync.zip\u003c/code\u003e 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 \u003ccode\u003e ZipExport\u003c/code\u003e object that contains the APIs to export the\nzipped file. In the synchronous version, the \u003ccode\u003eZipExport\u003c/code\u003e object is returned.\n\nHere's an example of asynchronous zipping,\n\n```javascript\nvar zipper = require(\"zip-local\");\n\n// zipping a file\nzipper.zip(\"./hello-world.cpp\", function(error, zipped) {\n\n    if(!error) {\n        zipped.compress(); // compress before exporting\n\n        var buff = zipped.memory(); // get the zipped file as a Buffer\n\n        // or save the zipped file to disk\n        zipped.save(\"../package.zip\", function(error) {\n            if(!error) {\n                console.log(\"saved successfully !\");\n            }\n        });\n    }\n});\n```\n\nand here's synchronous zipping,\n\n```javascript\nvar zipper = require('zip-local');\n\n// zipping a file to memory without compression\nvar buff = zipper.sync.zip(\"./hello-world.java\").memory();\n\n// zipping a directory to disk with compression\n// the directory has the following structure\n// |-- hello-world.txt\n// |-- cpp\n//     |-- hello-world.cpp\n// |-- java\n//     |--hello-world.java\nzipper.sync.zip(\"./hello/world/\").compress().save(\"pack.zip\");\n```\n\n### Unzipping\n\nSimiliarly, unzipping is done through \u003ccode\u003eZipLocal.unzip\u003c/code\u003e or the synchronous \u003ccode\u003eZipLocal.sync.unzip\u003c/code\u003e by passing the path to the zip file. Like the zipping functions, these functions also use the \u003ccode\u003eZipExport\u003c/code\u003e object for exporting your unzipped file, but in case of exporting in memory the \u003ccode\u003ememory\u003c/code\u003e function returns a \u003ccode\u003eZippedFS\u003c/code\u003e object instead of a buffer. This objects servers as a mini-filesystem for the unzipped file.\n\nAn example for asynchronous unzipping,\n\n```javascript\nvar zipper = require('zip-local');\n\nzipper.unzip(\"../package.zip\", function(error, unzipped) {\n\n    if(!error) {\n        // extract to the current working directory\n        unzipped.save(null, function() { });\n\n        var unzippedfs = unzipped.memory();\n\n        // print an array of file paths in the unzipped file\n        console.log(unzippedfs.contents()); // prints [ 'hello-world.cpp' ]\n\n        // read the file as text\n        var txt = unzippedfs.read(\"hello-world.cpp\", 'text');\n\n        // or read it as Buffer\n        var buff = unzippedfs.read(\"hello-world.cpp\", 'buffer');\n    }\n});\n```\n\nand the synchronous unzipping,\n\n```javascript\nvar zipper = require('zip-local');\n\n// extract to an existing directory\nzipper.sync.unzip(\"pack.zip\").save(\"../../hello\");\n\n// export in memory\nvar unzippedfs = zipper.sync.unzip(\"pack.zip\").memory();\n\n// logs ['hello-world.txt', 'cpp/hello-world.cpp', 'java/hello-world.java']\nconsole.log(unzippedfs.contents());\n\n// read file in buffer\nvar buff = unzippedfs.read(\"cpp/hello-world.cpp\", \"buffer\");\n```\n\n### Zipping/Unzipping directly from memory\n\nImagine 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.\n\nTo 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 \u003ccode\u003eZippedFS\u003c/code\u003e object from a previously unzipped file. This could be done simply by passing the bufferto the zip/unzip methods or the \u003ccode\u003eZippedFS\u003c/code\u003e 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.\n\nHere's an example implementing the above scenario that utilizes the ability to zip buffers :\n\n```javascript\nvar zipper = require('zip-local');\nvar net = require('net');\n\nvar server = net.createServer(function (socket) {\n\n    socket.on('data', function(data) {\n\n        zipper.zip(data, \"remote_file\", function(error, zipped) {\n\n            if(error) {\n                console.log(\"ERROR: %s\", error.message);\n                return;\n            }\n\n            // cache a copy of the zipped file on the server\n            zipped.save(\"zipped_from\" + socket.remoteAddress + \".zip\", function(error) {\n                if(error) {\n                    console.log(\"ERROR: %s\", error.message);\n                    return;\n                }\n            });\n\n            // send the zipped file back to the client\n            socket.write(zipped.memory());\n        });\n    });\n});\n\nserver.listen(3000);\n```\n\n### Low Level Operations\n\nWhile 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 \u003ccode\u003eJSZip\u003c/code\u003e object and all its low level features through the method \u003ccode\u003eZipExport#lowLevel()\u003c/code\u003e. After you zip/unzip your data and acquire the \u003ccode\u003eZipExport\u003c/code\u003e object, you can call this method from it and retrieve the underlying \u003ccode\u003eJSZip\u003c/code\u003e object and play around with it.\n\nHere's an example that utilizes the low level operations to remove files and also utilizes the ability to zip \u003ccode\u003eZippedFS\u003c/code\u003e object. This code cleans zipped files from executables (namely .exe, .bat, and .sh):\n\n```javascript\nvar zipper = require('zip-local');\n\nzipper.unzip('package.zip', function(error, unzipped) {\n\n    if(error) {\n        console.log(\"ERROR: %s\", error.message);\n        return;\n    }\n\n    var unzippedFS = unzipped.memory();\n    var files = unzippedFS.contents();\n    var notExecRegExp = new RegExp(/^[^.]+$|\\.(?!(sh|exe|bat)$)([^.]+$)/);\n\n    files.forEach(function (file) {\n        if(!notExecRegExp.test(file))\n            unzipped.lowLevel().remove(file);\n    });\n\n    var cleanUnzippedFS = unzipped.memory();\n\n    // re-zip the clean ZippedFS\n    zipper.zip(cleanUnzippedFS, function(zipped) {\n\n        zipped.save(\"package.zip\", function(error) {\n            if(error) {\n                console.log(\"ERROR: %s\", error.message);\n            }\n            else {\n                console.log(\"The file is scanned and cleaned of executables\");\n            }\n        });\n    });\n});\n```\nread the [API documentations](https://github.com/Mostafa-Samir/zip-local/wiki/API-Documentation) for furthur details.\n\n## License\n\n### MIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmostafa-samir%2Fzip-local","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmostafa-samir%2Fzip-local","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmostafa-samir%2Fzip-local/lists"}