Skip to content

Commit afe01ba

Browse files
committed
Update all the stuff
* switch to ESM, require Node.js 12 * switch to GitHub Actions * add coverage with c8 * update all packages to the latest version
1 parent 84a8c10 commit afe01ba

File tree

7 files changed

+175
-143
lines changed

7 files changed

+175
-143
lines changed

.github/workflows/ci.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
pull_request:
6+
workflow_dispatch:
7+
8+
env:
9+
FORCE_COLOR: 2
10+
11+
jobs:
12+
test:
13+
name: Node ${{ matrix.node }} on ${{ matrix.os }}
14+
runs-on: ${{ matrix.os }}
15+
16+
strategy:
17+
fail-fast: false
18+
matrix:
19+
node: [12, 14, 16, 18]
20+
os: [ubuntu-latest, windows-latest]
21+
22+
steps:
23+
- name: Clone repository
24+
uses: actions/checkout@v3
25+
26+
- name: Set up Node.js
27+
uses: actions/setup-node@v3
28+
with:
29+
node-version: ${{ matrix.node }}
30+
31+
- name: Install npm dependencies
32+
run: npm install
33+
34+
- name: Run tests
35+
run: npm run test-ci

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
node_modules
22
yarn.lock
3+
/coverage

.travis.yml

Lines changed: 0 additions & 5 deletions
This file was deleted.

index.js

Lines changed: 73 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,71 @@
1-
'use strict';
2-
const path = require('path');
3-
const fs = require('graceful-fs');
4-
const decompressTar = require('decompress-tar');
5-
const decompressTarbz2 = require('decompress-tarbz2');
6-
const decompressTargz = require('decompress-targz');
7-
const decompressUnzip = require('decompress-unzip');
8-
const makeDir = require('make-dir');
9-
const pify = require('pify');
10-
const stripDirs = require('strip-dirs');
1+
import {Buffer} from 'node:buffer';
2+
import path from 'node:path';
3+
import process from 'node:process';
4+
import decompressTar from 'decompress-tar';
5+
import decompressTarbz2 from 'decompress-tarbz2';
6+
import decompressTargz from 'decompress-targz';
7+
import decompressUnzip from 'decompress-unzip';
8+
import fs from 'graceful-fs';
9+
import makeDir from 'make-dir';
10+
import pify from 'pify';
11+
import stripDirs from 'strip-dirs';
1112

1213
const fsP = pify(fs);
1314

14-
const runPlugins = (input, opts) => {
15-
if (opts.plugins.length === 0) {
15+
const runPlugins = (input, options) => {
16+
if (options.plugins.length === 0) {
1617
return Promise.resolve([]);
1718
}
1819

19-
return Promise.all(opts.plugins.map(x => x(input, opts))).then(files => files.reduce((a, b) => a.concat(b)));
20+
return Promise.all(options.plugins.map(x => x(input, options)))
21+
// eslint-disable-next-line unicorn/no-array-reduce, unicorn/prefer-spread
22+
.then(files => files.reduce((a, b) => a.concat(b)));
2023
};
2124

22-
const safeMakeDir = (dir, realOutputPath) => {
23-
return fsP.realpath(dir)
24-
.catch(_ => {
25-
const parent = path.dirname(dir);
26-
return safeMakeDir(parent, realOutputPath);
27-
})
28-
.then(realParentPath => {
29-
if (realParentPath.indexOf(realOutputPath) !== 0) {
30-
throw (new Error('Refusing to create a directory outside the output path.'));
31-
}
32-
33-
return makeDir(dir).then(fsP.realpath);
34-
});
35-
};
25+
const safeMakeDir = (dir, realOutputPath) => fsP.realpath(dir)
26+
.catch(_ => {
27+
const parent = path.dirname(dir);
28+
return safeMakeDir(parent, realOutputPath);
29+
})
30+
.then(realParentPath => {
31+
if (realParentPath.indexOf(realOutputPath) !== 0) {
32+
throw new Error('Refusing to create a directory outside the output path.');
33+
}
3634

37-
const preventWritingThroughSymlink = (destination, realOutputPath) => {
38-
return fsP.readlink(destination)
39-
.catch(_ => {
40-
// Either no file exists, or it's not a symlink. In either case, this is
41-
// not an escape we need to worry about in this phase.
42-
return null;
43-
})
44-
.then(symlinkPointsTo => {
45-
if (symlinkPointsTo) {
46-
throw new Error('Refusing to write into a symlink');
47-
}
48-
49-
// No symlink exists at `destination`, so we can continue
50-
return realOutputPath;
51-
});
52-
};
35+
return makeDir(dir).then(fsP.realpath);
36+
});
37+
38+
const preventWritingThroughSymlink = (destination, realOutputPath) => fsP.readlink(destination)
39+
// Either no file exists, or it's not a symlink. In either case, this is
40+
// not an escape we need to worry about in this phase.
41+
.catch(_ => null)
42+
.then(symlinkPointsTo => {
43+
if (symlinkPointsTo) {
44+
throw new Error('Refusing to write into a symlink');
45+
}
46+
47+
// No symlink exists at `destination`, so we can continue
48+
return realOutputPath;
49+
});
5350

54-
const extractFile = (input, output, opts) => runPlugins(input, opts).then(files => {
55-
if (opts.strip > 0) {
51+
const extractFile = (input, output, options) => runPlugins(input, options).then(files => {
52+
if (options.strip > 0) {
5653
files = files
5754
.map(x => {
58-
x.path = stripDirs(x.path, opts.strip);
55+
x.path = stripDirs(x.path, options.strip);
5956
return x;
6057
})
6158
.filter(x => x.path !== '.');
6259
}
6360

64-
if (typeof opts.filter === 'function') {
65-
files = files.filter(opts.filter);
61+
if (typeof options.filter === 'function') {
62+
// eslint-disable-next-line unicorn/no-array-callback-reference
63+
files = files.filter(options.filter);
6664
}
6765

68-
if (typeof opts.map === 'function') {
69-
files = files.map(opts.map);
66+
if (typeof options.map === 'function') {
67+
// eslint-disable-next-line unicorn/no-array-callback-reference
68+
files = files.map(options.map);
7069
}
7170

7271
if (!output) {
@@ -75,7 +74,7 @@ const extractFile = (input, output, opts) => runPlugins(input, opts).then(files
7574

7675
return Promise.all(files.map(x => {
7776
const dest = path.join(output, x.path);
78-
const mode = x.mode & ~process.umask();
77+
const mode = x.mode & ~process.umask(); // eslint-disable-line no-bitwise
7978
const now = new Date();
8079

8180
if (x.type === 'directory') {
@@ -88,26 +87,23 @@ const extractFile = (input, output, opts) => runPlugins(input, opts).then(files
8887

8988
return makeDir(output)
9089
.then(outputPath => fsP.realpath(outputPath))
91-
.then(realOutputPath => {
90+
.then(realOutputPath =>
9291
// Attempt to ensure parent directory exists (failing if it's outside the output dir)
93-
return safeMakeDir(path.dirname(dest), realOutputPath)
94-
.then(() => realOutputPath);
95-
})
92+
safeMakeDir(path.dirname(dest), realOutputPath).then(() => realOutputPath),
93+
)
9694
.then(realOutputPath => {
9795
if (x.type === 'file') {
9896
return preventWritingThroughSymlink(dest, realOutputPath);
9997
}
10098

10199
return realOutputPath;
102100
})
103-
.then(realOutputPath => {
104-
return fsP.realpath(path.dirname(dest))
105-
.then(realDestinationDir => {
106-
if (realDestinationDir.indexOf(realOutputPath) !== 0) {
107-
throw (new Error('Refusing to write outside output directory: ' + realDestinationDir));
108-
}
109-
});
110-
})
101+
.then(realOutputPath => fsP.realpath(path.dirname(dest))
102+
.then(realDestinationDir => {
103+
if (realDestinationDir.indexOf(realOutputPath) !== 0) {
104+
throw new Error(`Refusing to write outside output directory: ${realDestinationDir}`);
105+
}
106+
}))
111107
.then(() => {
112108
if (x.type === 'link') {
113109
return fsP.link(x.linkname, dest);
@@ -128,24 +124,29 @@ const extractFile = (input, output, opts) => runPlugins(input, opts).then(files
128124
}));
129125
});
130126

131-
module.exports = (input, output, opts) => {
127+
const decompress = (input, output, options) => {
132128
if (typeof input !== 'string' && !Buffer.isBuffer(input)) {
133129
return Promise.reject(new TypeError('Input file required'));
134130
}
135131

136132
if (typeof output === 'object') {
137-
opts = output;
133+
options = output;
138134
output = null;
139135
}
140136

141-
opts = Object.assign({plugins: [
142-
decompressTar(),
143-
decompressTarbz2(),
144-
decompressTargz(),
145-
decompressUnzip()
146-
]}, opts);
137+
options = {
138+
plugins: [
139+
decompressTar(),
140+
decompressTarbz2(),
141+
decompressTargz(),
142+
decompressUnzip(),
143+
],
144+
...options,
145+
};
147146

148147
const read = typeof input === 'string' ? fsP.readFile(input) : Promise.resolve(input);
149148

150-
return read.then(buf => extractFile(buf, output, opts));
149+
return read.then(buf => extractFile(buf, output, options));
151150
};
151+
152+
export default decompress;

package.json

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,18 @@
1010
"url": "github.com/kevva"
1111
},
1212
"engines": {
13-
"node": ">=4"
13+
"node": "^12.20.0 || ^14.14.0 || >=16.0.0"
1414
},
1515
"scripts": {
16-
"test": "xo && ava"
16+
"ava": "ava",
17+
"xo": "xo",
18+
"test": "npm run xo && npm run ava",
19+
"test-ci": "npm run xo && c8 ava"
20+
},
21+
"main": "index.js",
22+
"type": "module",
23+
"exports": {
24+
".": "./index.js"
1725
},
1826
"files": [
1927
"index.js"
@@ -30,32 +38,21 @@
3038
"unzip"
3139
],
3240
"dependencies": {
33-
"decompress-tar": "^4.0.0",
34-
"decompress-tarbz2": "^4.0.0",
35-
"decompress-targz": "^4.0.0",
41+
"decompress-tar": "^4.1.1",
42+
"decompress-tarbz2": "^4.1.1",
43+
"decompress-targz": "^4.1.1",
3644
"decompress-unzip": "^4.0.1",
37-
"graceful-fs": "^4.1.10",
38-
"make-dir": "^1.0.0",
39-
"pify": "^2.3.0",
40-
"strip-dirs": "^2.0.0"
45+
"graceful-fs": "^4.2.10",
46+
"make-dir": "^3.1.0",
47+
"pify": "^5.0.0",
48+
"strip-dirs": "^3.0.0"
4149
},
4250
"devDependencies": {
43-
"ava": "*",
44-
"esm": "^3.2.25",
45-
"is-jpg": "^1.0.0",
46-
"path-exists": "^3.0.0",
47-
"pify": "^2.3.0",
51+
"ava": "^4.3.0",
52+
"c8": "^7.11.3",
53+
"is-jpg": "^3.0.0",
54+
"path-exists": "^5.0.0",
4855
"rimraf": "^3.0.2",
49-
"xo": "*"
50-
},
51-
"ava": {
52-
"require": [
53-
"esm"
54-
]
55-
},
56-
"xo": {
57-
"rules": {
58-
"promise/prefer-await-to-then": "off"
59-
}
56+
"xo": "^0.49.0"
6057
}
6158
}

readme.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
# decompress [![Build Status](https://travis-ci.org/kevva/decompress.svg?branch=master)](https://travis-ci.org/kevva/decompress)
1+
# decompress [![CI](https://github.com/kevva/decompress/actions/workflows/ci.yml/badge.svg)](https://github.com/kevva/decompress/actions/workflows/ci.yml)
22

33
> Extracting archives made easy
44
55
*See [decompress-cli](https://github.com/kevva/decompress-cli) for the command-line version.*
66

77
## Install
88

9-
```
10-
$ npm install decompress
9+
```sh
10+
npm install decompress
1111
```
1212

1313

1414
## Usage
1515

1616
```js
17-
const decompress = require('decompress');
17+
import decompress from 'decompress';
1818

1919
decompress('unicorn.zip', 'dist').then(files => {
2020
console.log('done!');
@@ -87,15 +87,15 @@ decompress('unicorn.zip', 'dist', {
8787

8888
##### plugins
8989

90-
Type: `Array`<br>
91-
Default: `[decompressTar(), decompressTarbz2(), decompressTargz(), decompressUnzip()]`
90+
* Type: `Array`
91+
* Default: `[decompressTar(), decompressTarbz2(), decompressTargz(), decompressUnzip()]`
9292

9393
Array of [plugins](https://www.npmjs.com/browse/keyword/decompressplugin) to use.
9494

9595
##### strip
9696

97-
Type: `number`<br>
98-
Default: `0`
97+
* Type: `number`
98+
* Default: `0`
9999

100100
Remove leading directory components from extracted files.
101101

0 commit comments

Comments
 (0)