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
1213const 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 ;
0 commit comments