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

@mattduffy/unpacker

v1.6.1

Published

A simple object oriented wrapper for unpacking zip, gzip or tar archives.

Downloads

18

Readme

Unpack Files From a Compressed Archive

This package for Node.js provides an object-oriented interface for working with archive files. Archive in this case refers to either gzip or zip compressed files and rar or tar files. This package is compatible with POSIX systems; it will not work on a Windows machine as-is. This package will not run in a browser.

Using Unpacker

The goal of this package is to simplify the process of unpacking several different formats of file archives, most likely uploaded to a website, for further processing or integration. This package abstracts away the need to know the mime type of the archive, and the commands necessary to unpack and move the archive contents to the desired target destination. The Unpacker class instantiates with a simple interface and is able to determine the location and version of tar, unrar, gzip and zip binaries.

npm install --save @mattduffy/unpacker
import { Unpacker } from '@mattduffy/unpacker'
let unpacker = new Unpacker()
unpacker = await unpacker.setPath('path/to/archive.tar.gz')
const extracted = await unpacker.unpack('final/path/to/exracted/files')

// OR a bit more concise
let unpacker = await new Unpacker().setPath('path/to/archive.tar.gz')
const extracted = await unpacker.unpack('final/path/to/extracted/files')

The Unpacker constructor does a litle bit of instance setup, but the important stuff currently happens the first time the setPath() method is called. This is when checks for the locally installed versions of tar, unrar, gzip and zip are performed. Their respective file system paths and version numbers are stored as instance properties. This happens here rather than the constructor method because it happens asynchronously. This is an Async/Await method.

let unpacker = new Unpacker()
// a relative path to archive file
await unpacker.setPath('relative/path/to/archive.zip')

// an absolute path to archive file
await unpacker.setPath('/absolute/path/to/archive.tar.gz')

The setPath() method requires a single parameter specifying the location of an archive file. The method will accept either a relative path or an absolute path to the archive. The relative path is resolved from the current working directory of the module that included the Unpacker package. If the path provided to the method does not succesfully resolve to a file, with a mime type of application/x-tar, application/x-rar, application/zip or application/gzip, it will throw an error.

After the setPath() method has been called, there are some useful helper methods to provide information about the archive file. The mime type of the archive is available with the getMimetype() method. The basename of the file is available with getFileBasename() and the extension from getExtension(). These two can be especially helpful for compressed tar files that use the extension .tar.gz rather that the more simple .tgz extension. The getPath() method returns the fully qualified path to the archive file.

const unpacker = new Unpacker()
await unpacker.setPath('uploads/photos.tar.gz')
const mime = unpacker.getMimetype()
console.log(mime)
// 'application/x-tar'
console.log(unpacker.getFileBasename())
// 'photos'
console.log(unpacker.getExtension())
// '.tar.gz'
console.log(unpacker.getPath())
// '/absolute/path/to/uploads/photos.tar.gz'

If you would like to see the path to binaries used for unpacking, and their respective version numbers, the checkCommands() method will provide that. This is an Async/Await method.

const unpacker = new Unpacker()
const binaries = await unpacker.checkCommands()
console.log(binaries)
// {
//   tar: { path: '/usr/bin/tar', version: '1.30' },
//   unrar: { path: '/usr/bin/unrar', version: '5.61' }, 
//   gzip: { path: '/usr/bin/gzip', version: '1.10' },
//   unzip: { path: '/usr/bin/unzip', version: '6.00' }
// }

After the the path to an archive file has been set, the unpack() method will complete the task. The method requires a single parameter specifying the target location for the unpacked files. The method will accept either a relative path or an absolute path. The relative path is resolved from the current working directory of the module that included the Unpacker package. This is an Async/Await method.

const unpacker = new Unpacker()
await unpacker.setPath('uploads/myPhotos.tar.gz')
const result = await unpacker.unpack('static/albums')
console.log(result)
// {
//   stdout: '',
//   stderr: '',
//   unpacked: true,
//   cwd: '/www/app/uploads/myPhotos',
//   destination: '/www/app/static/albums/'
// }

The unpack() method also accepts two additional optional parameters. The first optional parameter is for controlling how the underlying mv command works. The default behavior is to tell the mv command to force a move, and automatically create a backup of an existing directory. If you don't mind overwritting an existing directory, you can set the property backup: ''. The second optional parameter lets you change the destination directory name after it has been moved.

// default mv command options { force: true, backup: 'numbered'}
const unpacker = new Unpacker()
await unpacker.setPath('uploads/myPhotos.tar.gz')
const result = await unpacker.unpack('static/albums', {force: true, backup: ''}, {rename: true, newName: 'The_Latest_Photos'})
console.log(result)
// {
//   stdout: '',
//   stderr: '',
//   unpacked: true,
//   cwd: '/www/app/uploads/myPhotos',
//   destination: '/www/app/static/albums/'
// }

Unpacker provides a way to peek inside the archive file without having to extract the contents to the file system using the list() method. After the setPath() method has been called, setting the location of the archive file, this method will return an object containing an array of file names and the native command of the archive binary used. This is an Async/Await method.

const unpacker = new Unpacker()
await unpacker.setPath('uploads/files.tar.gz')
const { list } = await unpacker.list()
console.log(list)
// {
//  cmd: 'tar --exclude=__MACOSX --exclude=._* --exclude=.svn --exclude=.git* --list -z -f /www/site/uploads/files.tar.gz',
//  list: [
//    'files/',
//    'files/file-2.txt',
//    'files/file-1.txt',
//    'files/file-3.txt'
//  ]
// }

Sometimes it is desireable to extract an archive into a directory, one level deep, but the archive contains nested directories. Unpacker can flatten out the resulting files with the flatten({Boolean}) method. Calling this method with a argument of true enables directory flattening mode. Calling it with false disables directory flattening mode. Alternatively, an object literal can be passed to the constructor method to set flatten mode.

// config object passed to the constructor
const unpacker = new Unpacker({flatten: true})
await unpacker.setPath('uploads/multi-level-dir.tar.gz')
// OR
const unpacker = new Unpacker()
unpacker.flatten(true)
await unpacker.setPath('uploads/multi-level-dir.rar')

If there are problems with the unpacking process, the method will throw an error. Upon successful unpacking and moving files to the target destination, the Unpacker instance will make an effort to clean up the weird artifacts that may have been created (like "dot" hidden resource folders .myPhotos or __MACOSX ).

On POSIX platforms that include a version of the mv command that supports the --backup=[option] argument, a backup is automatically created if there is already a file or directory at the target destination with the same name. For example, if /www/app/static/albums/myPhotos/ already exists when myPhotos.tar.gz is unpacked with unpacker.unpack('/www/app/static/albums') then the original directory will be renamed /www/app/static/albums/myPhotos.~n~ where n is an auto-incrementing integer, starting at 1.