Extracting archives made easy

Overview

decompress Build Status

Extracting archives made easy

See decompress-cli for the command-line version.

Install

$ npm install decompress

Usage

const decompress = require('decompress');

decompress('unicorn.zip', 'dist').then(files => {
	console.log('done!');
});

API

decompress(input, [output], [options])

Returns a Promise for an array of files in the following format:

{
	data: Buffer,
	mode: Number,
	mtime: String,
	path: String,
	type: String
}

input

Type: string Buffer

File to decompress.

output

Type: string

Output directory.

options

filter

Type: Function

Filter out files before extracting. E.g:

decompress('unicorn.zip', 'dist', {
	filter: file => path.extname(file.path) !== '.exe'
}).then(files => {
	console.log('done!');
});

Note that in the current implementation, filter is only applied after fully reading all files from the archive in memory. Do not rely on this option to limit the amount of memory used by decompress to the size of the files included by filter. decompress will read the entire compressed file into memory regardless.

map

Type: Function

Map files before extracting: E.g:

decompress('unicorn.zip', 'dist', {
	map: file => {
		file.path = `unicorn-${file.path}`;
		return file;
	}
}).then(files => {
	console.log('done!');
});
plugins

Type: Array
Default: [decompressTar(), decompressTarbz2(), decompressTargz(), decompressUnzip()]

Array of plugins to use.

strip

Type: number
Default: 0

Remove leading directory components from extracted files.

License

MIT © Kevin Mårtensson

Comments
  • Vulnerable to zip slip

    Vulnerable to zip slip

    It appears as decompress is vulnerable to archives containing files that hold path-traversal names such as ../../outside.txt.

    As a PoC I have attached a .tar.gz-archive(slip.tar.gz) that will, when extracted, create a file in /tmp/slipped.txt. Use the example code to extract:

    const decompress = require('decompress');
    
    decompress('slip.tar.gz', 'dist').then(files => {
    	console.log('done!');
    });
    

    Note that this will not work out-of-the-box with .zip-archives since yauzl will throw an exception if the entry's filename contains "..".

    However, since this package also supports symlinks we can use that instead to bypass this limitation. But just adding a symlink to our desired target location won't do the trick - since the archive's files are being extracted asynchronous (index.js#44-73) we will end up in a race condition between extracting the symlink and the file referencing it.

    By creating a directory and within that create a symlink to its' parent directory. Continue with creating a symlink to / and a file with a name using a looped structure of all symlinks to the target. We end up with something like;

    mkdir generic_dir
    ln -s ../ generic_dir/symlink_to_parent_dir
    ln -s / symlink_to_root
    touch generic_dir/symlink_to_parent_dir/generic_dir/symlink_to_parent_dir/[...]/symlink_to_root/tmp/slipped_zip.txt
    

    Adding this to an archive allows us to always win the race! Here's a PoC (slip.zip), that when extracted will create a file in /tmp/slipped_zip.txt. Demonstrating how this also works for zip-archives using symlinks.

    opened by magicOz 35
  • Prevent directory traversal

    Prevent directory traversal

    This fixes #71 by throwing, rather than allowing paths outside the output directory to be extracted.

    I believe this loud failure to be the correct one, as it behaves similarly to tar -zxvf in protecting against directory traversal:

    $ tar -zxvf fixtures/slipping.tar.gz
    x ../../../decompress-traversal.txt: Path contains '..'
    tar: Error exit delayed from previous errors.
    

    But since this package seems to be fairly widely used, I want to call out explicitly that I don't know all the use cases and who this loudly-failing implementation might end up breaking.

    The fixture I swapped in contains a single file, pathed at ../../../decompress-traversal.txt (containing the text "DIRECTORY TRAVERSAL"). Prior to this fix, that file got created by the included unit test, and afterwards it does not get created.

    Update: There are several other test cases added as well (see the comments below), involving symlinks, directories, and other situations.

    I also needed to update some setup and testing things to get the tests passing since the linting/testing tools are at version "*", but tried to keep the commits separate in case you'd prefer cherry-picking.

    opened by trptcolin 34
  • Ubuntu - Decompressed folder is left without any permissions 0000

    Ubuntu - Decompressed folder is left without any permissions 0000

    When I run my server in Ubuntu (Ubuntu 14.04 LTS) the decompressed destination folder is left without any permissions.

    var decompress = new Decompress({mode: '755'}); decompress.src(file).dest(destFolder).use(Decompress.zip).run(function (err) { if (err) throw err; });

    I get a Error: EACCES, open

    When I check destFolder I find it was created without any permissions (octal: 0000).

    This forces me to run as sudo which really isn't ideal. Please help.

    opened by roeeyud 17
  • Files are not extracted and no error is thrown.

    Files are not extracted and no error is thrown.

    When I am trying to unzip a file, the callback is executed but there are no extracted files in the destination directory and no error is thrown. The file to unzip exists (checked in Finder and with fs.existsSync(file).

    Environment

    Decompress version: 3.0.0 Node.js version : 0.12.0 OS X El Capitan

    Code:

    var Decompress = require("decompress");
    
    var file = "/Users/Username/Desktop/App/node_cache/0.12.0/package.zip";
    var dest = "/Users/Username/Desktop/App/node_cache/0.12.0/";
    
    new Decompress()
      .src(file)
      .dest(dest)
      .use(Decompress.zip({ stripe: 1 })
      .run(function(error) {
        if (error) {
          console.log(error);
        } else {
          console.log("ok");
        }
      });
    
    opened by Bartozzz 9
  • mopt is a hell heavy dependency

    mopt is a hell heavy dependency

    I tracked down this dependency from yeoman-generator and it takes about 150ms to require. Can we replace this lines with generic functions? It will speedup yo like twice.

    P.s. here is my track path: yo - yeoman-generator - fetch - download - decompress and some numbers:

      decompress requires begin +0ms
      decompress required AdmZip +38ms
      decompress required fs +0ms
      decompress required mkdirp +2ms
      decompress required mout +135ms
      decompress required path +0ms
      decompress required stream-combiner +2ms
      decompress required rimraf +1ms
      decompress required tar +49ms
      decompress required temp +3ms
      decompress required zlib +0ms
    
    opened by floatdrop 7
  • Support .xz format

    Support .xz format

    As pointed at https://github.com/kevva/download/issues/55, .xz format being used as standard by GNU packages is not supported, There are several libraries can be used:

    https://www.npmjs.com/package/xz https://www.npmjs.com/package/node-liblzma https://www.npmjs.com/package/lzma-native

    Also some of them in pure Javascript:

    https://github.com/cscott/lzma-purejs https://github.com/nmrugg/LZMA-JS

    opened by piranna 6
  • Use graceful-fs to prevent EMFILE issues

    Use graceful-fs to prevent EMFILE issues

    I'm using this for a Go command wrapper which download's and unpack's the latest Go release, and finding that in Windows EMFILE errors are common when unpacking via decompress.

    Using graceful-fs takes care of that.

    opened by doesdev 4
  • Incorrectly decompressing through multiple streams

    Incorrectly decompressing through multiple streams

    When attempting to extract a tar.gz archive of WordPress, Decompress correctly used Decompress.targz to extract everything, but then continued to pass those files through the other decompression plugins. Eventually, it encountered a .xap file, which it attempted to unzip, resulting in an error due to the files being Windows files.

    Obviously this is not the desired behavior. I can see addressing this in a few ways:

    1. Decompress.zip should not attempt to decompress .xap files. Perhaps isZip() should return false, or there should be some other short circuit here. While it technically is a zip file, it is not meant to be decompressed; I'm sure there are a lot of file extensions that fall into this category. Maybe there should be a blacklist for these types of extensions?
    2. Some better handling of the decompression plugins. Perhaps you could use the decompression plugins based on extension, or skip the remaining plugins once the first succeeds? I realize that this is not a issue that's going to be hit often: for example, changing the order of these plugins would also fix my problem (but that's definitely not a long-term solution).

    If this 'multiple decompressions' behavior is desired, I would either make that an option that has to be enabled, or at least document that behavior explicitly.

    FYI I originally hit this while using yeoman/generator's extract function.

    opened by rylnd 4
  • endsWith error on zip file

    endsWith error on zip file

    OK in 1.6 version but KO on 1.9 et 2.x version

    TypeError: Object function (obj, val) { var ret = find(Object.keys(obj), function (ret) { return endsWith(val, ret); });

    return ret ? obj[ret] : null;
    

    } has no method 'endsWith' at Decompress._getExtractor (/Users/lcalvy/Documents/Boulot/Sources/coorpacademy/node_modules/decompress/index.js:89:19) at new Decompress (/Users/lcalvy/Documents/Boulot/Sources/coorpacademy/node_modules/decompress/index.js:40:27) at module.exports (/Users/lcalvy/Documents/Boulot/Sources/coorpacademy/node_modules/decompress/index.js:168:22)

    opened by lcalvy 4
  • Emit errors on streams

    Emit errors on streams

    I've only tested this with the .zip files, but when an error occurs, I don't think it's passed up properly.

    I have a fix for the .zip which could be applied to the others. I'll try to get a PR in if you'd like.

    opened by doowb 4
  • Decouple builtin plugins?

    Decouple builtin plugins?

    Currently i just uses decompress-unzip, but it needs some more workarounds it because of the dest. I don't need the others. Yea they are pretty small deps, but... would be better. :)

    opened by tunnckoCore 3
  • Error: EISDIR illegal operation on a directory, open '{path to a dir in the zip file}'

    Error: EISDIR illegal operation on a directory, open '{path to a dir in the zip file}'

    Hi Folks,

    I am facing this issue of illegal operation when I am trying to unzip a zip file which has multiple directories in it using decompress module.

    Is it something related to the permissions of the particular zip file?

    Sample Code:

    var unzipFiles = async function (dirPath, dcmfolder) { const files = fs.readdirSync(dirPath); await Promise.all( files.map(async (file) => { const fullFilePath = path.join(dirPath, "/", file); if (file.endsWith(".zip")) { console.log("Inside unzip if condition"); await decompress(fullFilePath, dcmfolder); } }) ); };

    opened by Somesh-bsai 0
  • Obsolete (pre 0.9.5) bzip format not supported.

    Obsolete (pre 0.9.5) bzip format not supported.

    Would be nice to address this issue: Obsolete (pre 0.9.5) bzip format not supported. either by clarifying it in the README.md or by adding support for older bzip formats.

    opened by Meekohi 0
  • Vulnerable to Infinite Loop via malformed MKV file through `file-type` package

    Vulnerable to Infinite Loop via malformed MKV file through `file-type` package

    The following report is provided by NPM audit when using the latest version of decompress package (v4.2.1):

    file-type  <16.5.4
    Severity: moderate
    file-type vulnerable to Infinite Loop via malformed MKV file - https://github.com/advisories/GHSA-mhxj-85r3-2x55
    
    node_modules/decompress-tar/node_modules/file-type
    node_modules/decompress-tarbz2/node_modules/file-type
    node_modules/decompress-targz/node_modules/file-type
    node_modules/decompress-unzip/node_modules/file-type
      decompress-tar  >=4.0.0
    
      Depends on vulnerable versions of file-type
      node_modules/decompress-tar
      decompress-tarbz2  >=4.0.0
    
      Depends on vulnerable versions of file-type
      node_modules/decompress-tarbz2
        decompress  >=4.0.0
        Depends on vulnerable versions of decompress-tarbz2
        node_modules/decompress
    
      decompress-targz  >=4.0.0
      Depends on vulnerable versions of file-type
      node_modules/decompress-targz
      
      decompress-unzip  >=4.0.1
      Depends on vulnerable versions of file-type
      node_modules/decompress-unzip
    

    More description about the problem is provided here: https://github.com/advisories/GHSA-mhxj-85r3-2x55

    The fix was implemented in file-type v16.5.4, so probably file-type should just be bumped in sub-packages: decompress-tar, decompress-tarbz2, decompress-targz, decompress-unzip.

    opened by qooban 4
  • decompress function is stucked when i pass the buffer array into it

    decompress function is stucked when i pass the buffer array into it

    I've got a problem with decompression library. I use it for unarchive file. I haven't had problems with it before but recently i've got a bug. I get this archive as base64 string, then a transform it into Buffer and finally pass this Buffer into decompression function and it's just stucked. There are no info or error messages, my server is stucked too. I guess there must be infinity loop or something like this.

    Error Result:

    const value = 'UEsDBBQACAAIAONFuVQAAAAAAAAAAAAAAAAWAAAAZmlsZV9kZXRlY3RfYnlfTUQ1LmlvY4VSwY7bIBS8V+o/IO4EjMFAZGdVdVVppaaX7qG3iIWXDWqMI0Oa9O9LnGyyaQ+9WPjNm3lvBtqHY79Fv2BMYYgdrmYMI4hu8CG+dnifiE0uBPyw+PihDYNDpTum+TGFDm9y3s0pPRwOs0M9G8ZXyhmr6I/l1+9uA70lIaZsowN8Zfn/szAKpUtLZRsnKqIEByI0M8RC0xAttQbOrJemwWhrUyZ92XUdoJA44xVhNWHyuVJzrueMXUZfx6ZpRpr1NvpgY565oS8LVIwWc7iYRKhNm2HMKw/JjWGXSyyLL2ELq+WjbOm/2ESx+1wA8CtvMyz+2qOZi6al9y0Taxviz4To+cfDOsRwlSyVp7Kis3kY0bCD8XTo8Kdvj+eAxAuohnNDfG0NEVZZYurKlw8w2bi1WCuDL0rvtZ4y9JMAr+rSWluinJBEKKuIFlYSy2sD2r/UTiiM3FCIeXoaId30iuLnIWY4ZuQHt+8h5g6fUjrJY5TAjm5zq9Cll2lfgPx7Bx3uw4gvtt+LxfyGe4kXojHagjFKKvB1pYxmunKyBs29WAvb0gvpZpLeuXyL8VY9B03vkm5PF7/4A1BLBwgAAAAAuQEAAAAAAABQSwECLQMUAAgACADjRblUAAAAALkBAAAAAAAAFgAAAAAAAAAAACAApIEAAAAAZmlsZV9kZXRlY3RfYnlfTUQ1LmlvY1BLBQYAAAAAAQABAEQAAAD9AQAAAAA='

    const buffered = Buffer.from(value, "base64"); const data = await decompress(buffered); // my program stuck here

    it's a proof that my base64 right - https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9%2B/%3D',true)Unzip('',false)&input=VUVzREJCUUFDQUFJQU9ORnVWUUFBQUFBQUFBQUFBQUFBQUFXQUFBQVptbHNaVjlrWlhSbFkzUmZZbmxmVFVRMUxtbHZZNFZTd1k3YklCUzhWK28vSU80RWpNRkFaR2RWZFZWcHBhYVg3cUczaUlXWERXcU1JME9hOU85TG5HeXlhUSs5V1BqTm0zbHZCdHFIWTc5RnYyQk1ZWWdkcm1ZTUk0aHU4Q0crZG5pZmlFMHVCUHl3K1BpaERZTkRwVHVtK1RHRkRtOXkzczBwUFJ3T3MwTTlHOFpYeWhtcjZJL2wxKzl1QTcwbElhWnNvd044WmZuL3N6QUtwVXRMWlJzbktxSUVCeUkwTThSQzB4QXR0UWJPckplbXdXaHJVeVo5MlhVZG9KQTQ0eFZoTldIeXVWSnpydWVNWFVaZng2WnBScHIxTnZwZ1k1NjVvUzhMVkl3V2M3aVlSS2hObTJITUt3L0pqV0dYU3l5TEwyRUxxK1dqYk9tLzJFU3grMXdBOEN0dk15eisycU9aaTZhbDl5MFRheHZpejRUbytjZkRPc1J3bFN5VnA3S2lzM2tZMGJDRDhYVG84S2R2aitlQXhBdW9obk5EZkcwTkVWWlpZdXJLbHc4dzJiaTFXQ3VETDBydnRaNHk5Sk1BcityU1dsdWluSkJFS0t1SUZsWVN5MnNEMnIvVVRpaU0zRkNJZVhvYUlkMzBpdUxuSVdZNFp1UUh0KzhoNWc2ZlVqckpZNVRBam01enE5Q2xsMmxmZ1B4N0J4M3V3NGd2dHQrTHhmeUdlNGtYb2pIYWdqRktLdkIxcFl4bXVuS3lCczI5V0F2YjBndnBacExldVh5TDhWWTlCMDN2a201UEY3LzRBMUJMQndnQUFBQUF1UUVBQUFBQUFBQlFTd0VDTFFNVUFBZ0FDQURqUmJsVUFBQUFBTGtCQUFBQUFBQUFGZ0FBQUFBQUFBQUFBQ0FBcElFQUFBQUFabWxzWlY5a1pYUmxZM1JmWW5sZlRVUTFMbWx2WTFCTEJRWUFBQUFBQVFBQkFFUUFBQUQ5QVFBQUFBQT0

    Access result:

    const value2 = 'UEsDBBQACAAIADJtwlQAAAAAAAAAAAAAAAAWAAAAZmlsZV9kZXRlY3RfYnlfTUQ1LmlvY4VSwY7bIBS8V+o/IO4EjMFAZGdVdVVppaaX7qG3iIWXDWqMI0Oa9O9LnGyyaQ+9WPjNm3lvBtqHY79Fv2BMYYgdrmYMI4hu8CG+dnifiE0uBPyw+PihDYNDpTum+TGFDm9y3s0pPRwOs0M9G8ZXyhmr6I/l1+9uA70lIaZsowN8Zfn/szAKpUtLZRsnKqIEByI0M8RC0xAttQbOrJemwWhrUyZ92XUdoJA44xVhNWHyuVJzrueMXUZfx6ZpRpr1NvpgY565oS8LVIwWc7iYRKhNm2HMKw/JjWGXSyyLL2ELq+WjbOm/2ESx+1wA8CtvMyz+2qOZi6al9y0Taxviz4To+cfDOsRwlSyVp7Kis3kY0bCD8XTo8Kdvj+eAxAuohnNDfG0NEVZZYurKlw8w2bi1WCuDL0rvtZ4y9JMAr+rSWluinJBEKKuIFlYSy2sD2r/UTiiM3FCIeXoaId30iuLnIWY4ZuQHt+8h5g6fUjrJY5TAjm5zq9Cll2lfgPx7Bx3uw4gvtt+LxfyGe4kXojHagjFKKvB1pYxmunKyBs29WAvb0gvpZpLeuXyL8VY9B03vkm5PF7/4A1BLBwhca76XuQEAAAYDAABQSwECLQMUAAgACAAybcJUXGu+l7kBAAAGAwAAFgAAAAAAAAAAACAApIEAAAAAZmlsZV9kZXRlY3RfYnlfTUQ1LmlvY1BLBQYAAAAAAQABAEQAAAD9AQAAAAA='

    const buffered = Buffer.from(value2, "base64"); const data = await decompress(buffered); // using value2 i got right object with data

    decompressing with value2 - https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9%2B/%3D',true)Unzip('',false)&input=VUVzREJCUUFDQUFJQURKdHdsUUFBQUFBQUFBQUFBQUFBQUFXQUFBQVptbHNaVjlrWlhSbFkzUmZZbmxmVFVRMUxtbHZZNFZTd1k3YklCUzhWK28vSU80RWpNRkFaR2RWZFZWcHBhYVg3cUczaUlXWERXcU1JME9hOU85TG5HeXlhUSs5V1BqTm0zbHZCdHFIWTc5RnYyQk1ZWWdkcm1ZTUk0aHU4Q0crZG5pZmlFMHVCUHl3K1BpaERZTkRwVHVtK1RHRkRtOXkzczBwUFJ3T3MwTTlHOFpYeWhtcjZJL2wxKzl1QTcwbElhWnNvd044WmZuL3N6QUtwVXRMWlJzbktxSUVCeUkwTThSQzB4QXR0UWJPckplbXdXaHJVeVo5MlhVZG9KQTQ0eFZoTldIeXVWSnpydWVNWFVaZng2WnBScHIxTnZwZ1k1NjVvUzhMVkl3V2M3aVlSS2hObTJITUt3L0pqV0dYU3l5TEwyRUxxK1dqYk9tLzJFU3grMXdBOEN0dk15eisycU9aaTZhbDl5MFRheHZpejRUbytjZkRPc1J3bFN5VnA3S2lzM2tZMGJDRDhYVG84S2R2aitlQXhBdW9obk5EZkcwTkVWWlpZdXJLbHc4dzJiaTFXQ3VETDBydnRaNHk5Sk1BcityU1dsdWluSkJFS0t1SUZsWVN5MnNEMnIvVVRpaU0zRkNJZVhvYUlkMzBpdUxuSVdZNFp1UUh0KzhoNWc2ZlVqckpZNVRBam01enE5Q2xsMmxmZ1B4N0J4M3V3NGd2dHQrTHhmeUdlNGtYb2pIYWdqRktLdkIxcFl4bXVuS3lCczI5V0F2YjBndnBacExldVh5TDhWWTlCMDN2a201UEY3LzRBMUJMQndoY2E3Nlh1UUVBQUFZREFBQlFTd0VDTFFNVUFBZ0FDQUF5YmNKVVhHdStsN2tCQUFBR0F3QUFGZ0FBQUFBQUFBQUFBQ0FBcElFQUFBQUFabWxzWlY5a1pYUmxZM1JmWW5sZlRVUTFMbWx2WTFCTEJRWUFBQUFBQVFBQkFFUUFBQUQ5QVFBQUFBQT0

    opened by TkachenkoDaniil 0
  • Unable to decrompress archive containing folders (compressed with 7zip)

    Unable to decrompress archive containing folders (compressed with 7zip)

    Hello,

    i have some troubles decrompressing a zip file that contains folders. It seems only to be a problem if the file was created using 7zip (on Windows). If I create the archive with the build in windows tool everything works fine.

    My archive looks something like that:

    archive 
    - somefolder
    - - someotherfile
    - somefile
    

    Results in:

    outputfolder
    - somefolder ---> **this is a empty file now** 
    - somefile
    

    I guess its a problem with decrompess and not with 7zip (other decrompessing tools are working fine with my example archive).

    Example: archive_from_7zip.zip

    PS: For me it is currently not a problem, I just wanted to inform you about this behaviour.

    Thanks & BG Manuel

    opened by DarphBobo 0
Releases(v4.2.1)
Owner
Kevin Mårtensson
Kevin Mårtensson
🦎 A jQuery plugin for extracting the dominant color from images and applying the color to their parent.

jquery.adaptive-backgrounds.js A simple jQuery plugin to extract the dominant color of an image and apply it to the background of its parent element.

Brian Gonzalez 6.6k Dec 21, 2022
CTF Archives: Collection of CTF Challenges.

Collection of CTF challenges. CTF Event Writeups 0CTF 2020 Quals CTFtime 2019 Quals CTFtime 2018 Finals CTFtime PersianCats 2018 Quals CTFtime Persian

Sajjad 299 Jan 4, 2023
🎨 A simple library for extracting dominant colors from images.

A dead simple, zero-dependency, promise-based javascript library for extracting the dominant color(s) from an image (in the browser). ?? Version 2 was

Brian Gonzalez 1.7k Jan 4, 2023
A JavaScript library to read, write, and merge ZIP archives in web browsers.

Armarius About Armarius is a JavaScript library to read, write, and merge ZIP archives in web browsers. This library mainly focuses on a low memory fo

Aternos 5 Nov 9, 2022
A web scraping / data mining script for extracting beginner-friendly github repos from Y Combinator's company database

A web scraping / data mining script for extracting beginner-friendly github repos from Y Combinator's company database

Oscar Mier 27 Nov 24, 2022
Experimental proxy and wrapper for safely embedding Web Archives (warc.gz, wacz) into web pages.

warc-embed-netlify ??️ Experimental proxy and wrapper for safely embedding Web Archives (.warc.gz, .wacz) into web pages. This particular implementati

Harvard Library Innovation Laboratory 6 Sep 1, 2022
Website to present projects made by me and that are part of my personal portfolio. It was made using React, HTML y Scss (CSS).

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

Portfolio Jesús Leal 0 Dec 23, 2021
Simple realtime chat application made by NodeJS, Express, Socket.io and Vanilla Javascript. This project is made to discover socket.io and understand its basic features.

LearnByChat App Simple realtime chat application made with NodeJS, Express, Socket.io and Vanilla Javascript. This project is made to discover socket.

Ayoub Saouidi 1 Dec 19, 2021
A showcase of problems once hard or impossible to solve with CSS alone, now made trivially easy with Flexbox.

Solved by Flexbox A showcase of problems once hard or impossible to solve with CSS alone, now made trivially easy with Flexbox. View Site Viewing the

Philip Walton 13k Jan 2, 2023
:necktie: :briefcase: Build fast :rocket: and easy multiple beautiful resumes and create your best CV ever! Made with Vue and LESS.

best-resume-ever ?? ?? Build fast ?? and easy multiple beautiful resumes and create your best CV ever! Made with Vue and LESS. Cool Creative Green Pur

Sara Steiert 15.8k Jan 9, 2023
Stellar.js - Parallax scrolling made easy

Stellar.js PLEASE NOTE: This project is no longer maintained. If parallax scrolling is something you care about, please apply to become a contributor

Mark Dalgleish 4.6k Dec 10, 2022
Modern native Git hooks made easy 🐶 woof!

husky Modern native Git hooks made easy Husky improves your commits and more ?? woof! Install npm install husky -D Usage Edit package.json > prepare

null 28.4k Jan 4, 2023
:fork_and_knife: Web applications made easy. Since 2011.

Brunch Web applications made easy. Since 2011. Fast front-end web app build tool with simple declarative config and seamless incremental compilation f

Brunch 6.8k Dec 25, 2022
API Services Made Easy With Node.js

Nodal API Services Made Easy with Node.js View the website at nodaljs.com. Nodal is a web server and opinionated framework for building data manipulat

Keith Horwood 4.5k Dec 26, 2022
:fork_and_knife: Web applications made easy. Since 2011.

Brunch Web applications made easy. Since 2011. Fast front-end web app build tool with simple declarative config and seamless incremental compilation f

Brunch 6.8k Jan 2, 2023
pattern matching in javascript & typescript made easy

?? matchbook pattern matching in typescript & javascript made easy matchbook is a lightweight & easy to use pattern matching library, for TypeScript a

@matchbook/ts 25 Dec 1, 2022
node.js command-line interfaces made easy

Commander.js The complete solution for node.js command-line interfaces. Read this in other languages: English | 简体中文 Commander.js Installation Declari

TJ Holowaychuk 24k Jan 8, 2023
Installing husky made easy as woof!

auto-husky Installing husky made easy as woof! ?? ?? Table of contents ?? Installation ?? Usage ?? Versioning ?? Installation You can install the pack

G.Script 24 Jun 28, 2022
⛏ Mining Infrastructure Made Easy

Carrot Pool Enterprise proof-of-work infrastructure & API for blockchain mining. Setup & Install » Demo · Report Bug · Roadmap · Updates Background Ca

HashRabbit 53 Jan 5, 2023
Config-based action debouncing made easy

Pinia Debounce Debounce any action in your pinia ?? store! This is also a very good example of how to create a pinia plugin and how to type it. Instal

Eduardo San Martin Morote 40 Dec 5, 2022