{"version":3,"sources":["jsdelivr-header.js","/npm/adm-zip@0.5.17/adm-zip.js"],"names":[],"mappings":"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","file":"/npm/adm-zip@0.5.17/adm-zip.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/adm-zip@0.5.17/adm-zip.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","const Utils = require(\"./util\");\nconst pth = require(\"path\");\nconst ZipEntry = require(\"./zipEntry\");\nconst ZipFile = require(\"./zipFile\");\n\nconst get_Bool = (...val) => Utils.findLast(val, (c) => typeof c === \"boolean\");\nconst get_Str = (...val) => Utils.findLast(val, (c) => typeof c === \"string\");\nconst get_Fun = (...val) => Utils.findLast(val, (c) => typeof c === \"function\");\n\nconst defaultOptions = {\n    // option \"noSort\" : if true it disables files sorting\n    noSort: false,\n    // read entries during load (initial loading may be slower)\n    readEntries: false,\n    // default method is none\n    method: Utils.Constants.NONE,\n    // file system\n    fs: null\n};\n\nmodule.exports = function (/**String*/ input, /** object */ options) {\n    let inBuffer = null;\n\n    // create object based default options, allowing them to be overwritten\n    const opts = Object.assign(Object.create(null), defaultOptions);\n\n    // test input variable\n    if (input && \"object\" === typeof input) {\n        // if value is not buffer we accept it to be object with options\n        if (!(input instanceof Uint8Array)) {\n            Object.assign(opts, input);\n            input = opts.input ? opts.input : undefined;\n            if (opts.input) delete opts.input;\n        }\n\n        // if input is buffer\n        if (Buffer.isBuffer(input)) {\n            inBuffer = input;\n            opts.method = Utils.Constants.BUFFER;\n            input = undefined;\n        }\n    }\n\n    // assign options\n    Object.assign(opts, options);\n\n    // instanciate utils filesystem\n    const filetools = new Utils(opts);\n\n    if (typeof opts.decoder !== \"object\" || typeof opts.decoder.encode !== \"function\" || typeof opts.decoder.decode !== \"function\") {\n        opts.decoder = Utils.decoder;\n    }\n\n    // if input is file name we retrieve its content\n    if (input && \"string\" === typeof input) {\n        // load zip file\n        if (filetools.fs.existsSync(input)) {\n            opts.method = Utils.Constants.FILE;\n            opts.filename = input;\n            inBuffer = filetools.fs.readFileSync(input);\n        } else {\n            throw Utils.Errors.INVALID_FILENAME();\n        }\n    }\n\n    // create variable\n    const _zip = new ZipFile(inBuffer, opts);\n\n    const { canonical, sanitize, zipnamefix } = Utils;\n\n    function getEntry(/**Object*/ entry) {\n        if (entry && _zip) {\n            var item;\n            // If entry was given as a file name\n            if (typeof entry === \"string\") item = _zip.getEntry(pth.posix.normalize(entry));\n            // if entry was given as a ZipEntry object\n            if (typeof entry === \"object\" && typeof entry.entryName !== \"undefined\" && typeof entry.header !== \"undefined\") item = _zip.getEntry(entry.entryName);\n\n            if (item) {\n                return item;\n            }\n        }\n        return null;\n    }\n\n    function fixPath(zipPath) {\n        const { join, normalize, sep } = pth.posix;\n        // convert windows file separators and normalize\n        return join(pth.isAbsolute(zipPath) ? \"/\": '.',  normalize(sep + zipPath.split(\"\\\\\").join(sep) + sep));\n    }\n\n    function filenameFilter(filterfn) {\n        if (filterfn instanceof RegExp) {\n            // if filter is RegExp wrap it\n            return (function (rx) {\n                return function (filename) {\n                    return rx.test(filename);\n                };\n            })(filterfn);\n        } else if (\"function\" !== typeof filterfn) {\n            // if filter is not function we will replace it\n            return () => true;\n        }\n        return filterfn;\n    }\n\n    // keep last character on folders\n    const relativePath = (local, entry) => {\n        let lastChar = entry.slice(-1);\n        lastChar = lastChar === filetools.sep ? filetools.sep : \"\";\n        return pth.relative(local, entry) + lastChar;\n    };\n\n    return {\n        /**\n         * Extracts the given entry from the archive and returns the content as a Buffer object\n         * @param {ZipEntry|string} entry ZipEntry object or String with the full path of the entry\n         * @param {Buffer|string} [pass] - password\n         * @return Buffer or Null in case of error\n         */\n        readFile: function (entry, pass) {\n            var item = getEntry(entry);\n            return (item && item.getData(pass)) || null;\n        },\n\n        /**\n         * Returns how many child elements has on entry (directories) on files it is always 0\n         * @param {ZipEntry|string} entry ZipEntry object or String with the full path of the entry\n         * @returns {integer}\n         */\n        childCount: function (entry) {\n            const item = getEntry(entry);\n            if (item) {\n                return _zip.getChildCount(item);\n            }\n        },\n\n        /**\n         * Asynchronous readFile\n         * @param {ZipEntry|string} entry ZipEntry object or String with the full path of the entry\n         * @param {callback} callback\n         *\n         * @return Buffer or Null in case of error\n         */\n        readFileAsync: function (entry, callback) {\n            var item = getEntry(entry);\n            if (item) {\n                item.getDataAsync(callback);\n            } else {\n                callback(null, \"getEntry failed for:\" + entry);\n            }\n        },\n\n        /**\n         * Extracts the given entry from the archive and returns the content as plain text in the given encoding\n         * @param {ZipEntry|string} entry - ZipEntry object or String with the full path of the entry\n         * @param {string} encoding - Optional. If no encoding is specified utf8 is used\n         *\n         * @return String\n         */\n        readAsText: function (entry, encoding) {\n            var item = getEntry(entry);\n            if (item) {\n                var data = item.getData();\n                if (data && data.length) {\n                    return data.toString(encoding || \"utf8\");\n                }\n            }\n            return \"\";\n        },\n\n        /**\n         * Asynchronous readAsText\n         * @param {ZipEntry|string} entry ZipEntry object or String with the full path of the entry\n         * @param {callback} callback\n         * @param {string} [encoding] - Optional. If no encoding is specified utf8 is used\n         *\n         * @return String\n         */\n        readAsTextAsync: function (entry, callback, encoding) {\n            var item = getEntry(entry);\n            if (item) {\n                item.getDataAsync(function (data, err) {\n                    if (err) {\n                        callback(data, err);\n                        return;\n                    }\n\n                    if (data && data.length) {\n                        callback(data.toString(encoding || \"utf8\"));\n                    } else {\n                        callback(\"\");\n                    }\n                });\n            } else {\n                callback(\"\");\n            }\n        },\n\n        /**\n         * Remove the entry from the file or the entry and all it's nested directories and files if the given entry is a directory\n         *\n         * @param {ZipEntry|string} entry\n         * @returns {void}\n         */\n        deleteFile: function (entry, withsubfolders = true) {\n            // @TODO: test deleteFile\n            var item = getEntry(entry);\n            if (item) {\n                _zip.deleteFile(item.entryName, withsubfolders);\n            }\n        },\n\n        /**\n         * Remove the entry from the file or directory without affecting any nested entries\n         *\n         * @param {ZipEntry|string} entry\n         * @returns {void}\n         */\n        deleteEntry: function (entry) {\n            // @TODO: test deleteEntry\n            var item = getEntry(entry);\n            if (item) {\n                _zip.deleteEntry(item.entryName);\n            }\n        },\n\n        /**\n         * Adds a comment to the zip. The zip must be rewritten after adding the comment.\n         *\n         * @param {string} comment\n         */\n        addZipComment: function (comment) {\n            // @TODO: test addZipComment\n            _zip.comment = comment;\n        },\n\n        /**\n         * Returns the zip comment\n         *\n         * @return String\n         */\n        getZipComment: function () {\n            return _zip.comment || \"\";\n        },\n\n        /**\n         * Adds a comment to a specified zipEntry. The zip must be rewritten after adding the comment\n         * The comment cannot exceed 65535 characters in length\n         *\n         * @param {ZipEntry} entry\n         * @param {string} comment\n         */\n        addZipEntryComment: function (entry, comment) {\n            var item = getEntry(entry);\n            if (item) {\n                item.comment = comment;\n            }\n        },\n\n        /**\n         * Returns the comment of the specified entry\n         *\n         * @param {ZipEntry} entry\n         * @return String\n         */\n        getZipEntryComment: function (entry) {\n            var item = getEntry(entry);\n            if (item) {\n                return item.comment || \"\";\n            }\n            return \"\";\n        },\n\n        /**\n         * Updates the content of an existing entry inside the archive. The zip must be rewritten after updating the content\n         *\n         * @param {ZipEntry} entry\n         * @param {Buffer} content\n         */\n        updateFile: function (entry, content) {\n            var item = getEntry(entry);\n            if (item) {\n                item.setData(content);\n            }\n        },\n\n        /**\n         * Adds a file from the disk to the archive\n         *\n         * @param {string} localPath File to add to zip\n         * @param {string} [zipPath] Optional path inside the zip\n         * @param {string} [zipName] Optional name for the file\n         * @param {string} [comment] Optional file comment\n         */\n        addLocalFile: function (localPath, zipPath, zipName, comment) {\n            if (filetools.fs.existsSync(localPath)) {\n                // fix ZipPath\n                zipPath = zipPath ? fixPath(zipPath) : \"\";\n\n                // p - local file name\n                const p = pth.win32.basename(pth.win32.normalize(localPath));\n\n                // add file name into zippath\n                zipPath += zipName ? zipName : p;\n\n                // read file attributes\n                const _attr = filetools.fs.statSync(localPath);\n\n                // get file content\n                const data = _attr.isFile() ? filetools.fs.readFileSync(localPath) : Buffer.alloc(0);\n\n                // if folder\n                if (_attr.isDirectory()) zipPath += filetools.sep;\n\n                // add file into zip file\n                this.addFile(zipPath, data, comment, _attr);\n            } else {\n                throw Utils.Errors.FILE_NOT_FOUND(localPath);\n            }\n        },\n\n        /**\n         * Callback for showing if everything was done.\n         *\n         * @callback doneCallback\n         * @param {Error} err - Error object\n         * @param {boolean} done - was request fully completed\n         */\n\n        /**\n         * Adds a file from the disk to the archive\n         *\n         * @param {(object|string)} options - options object, if it is string it us used as localPath.\n         * @param {string} options.localPath - Local path to the file.\n         * @param {string} [options.comment] - Optional file comment.\n         * @param {string} [options.zipPath] - Optional path inside the zip\n         * @param {string} [options.zipName] - Optional name for the file\n         * @param {doneCallback} callback - The callback that handles the response.\n         */\n        addLocalFileAsync: function (options, callback) {\n            options = typeof options === \"object\" ? options : { localPath: options };\n            const localPath = pth.resolve(options.localPath);\n            const { comment } = options;\n            let { zipPath, zipName } = options;\n            const self = this;\n\n            filetools.fs.stat(localPath, function (err, stats) {\n                if (err) return callback(err, false);\n                // fix ZipPath\n                zipPath = zipPath ? fixPath(zipPath) : \"\";\n                // p - local file name\n                const p = pth.win32.basename(pth.win32.normalize(localPath));\n                // add file name into zippath\n                zipPath += zipName ? zipName : p;\n\n                if (stats.isFile()) {\n                    filetools.fs.readFile(localPath, function (err, data) {\n                        if (err) return callback(err, false);\n                        self.addFile(zipPath, data, comment, stats);\n                        return setImmediate(callback, undefined, true);\n                    });\n                } else if (stats.isDirectory()) {\n                    zipPath += filetools.sep;\n                    self.addFile(zipPath, Buffer.alloc(0), comment, stats);\n                    return setImmediate(callback, undefined, true);\n                }\n            });\n        },\n\n        /**\n         * Adds a local directory and all its nested files and directories to the archive\n         *\n         * @param {string} localPath - local path to the folder\n         * @param {string} [zipPath] - optional path inside zip\n         * @param {(RegExp|function)} [filter] - optional RegExp or Function if files match will be included.\n         */\n        addLocalFolder: function (localPath, zipPath, filter) {\n            // Prepare filter\n            filter = filenameFilter(filter);\n\n            // fix ZipPath\n            zipPath = zipPath ? fixPath(zipPath) : \"\";\n\n            // normalize the path first\n            localPath = pth.normalize(localPath);\n\n            if (filetools.fs.existsSync(localPath)) {\n                const items = filetools.findFiles(localPath);\n                const self = this;\n\n                if (items.length) {\n                    for (const filepath of items) {\n                        const p = pth.join(zipPath, relativePath(localPath, filepath));\n                        if (filter(p)) {\n                            self.addLocalFile(filepath, pth.dirname(p));\n                        }\n                    }\n                }\n            } else {\n                throw Utils.Errors.FILE_NOT_FOUND(localPath);\n            }\n        },\n\n        /**\n         * Asynchronous addLocalFolder\n         * @param {string} localPath\n         * @param {callback} callback\n         * @param {string} [zipPath] optional path inside zip\n         * @param {RegExp|function} [filter] optional RegExp or Function if files match will\n         *               be included.\n         */\n        addLocalFolderAsync: function (localPath, callback, zipPath, filter) {\n            // Prepare filter\n            filter = filenameFilter(filter);\n\n            // fix ZipPath\n            zipPath = zipPath ? fixPath(zipPath) : \"\";\n\n            // normalize the path first\n            localPath = pth.normalize(localPath);\n\n            var self = this;\n            filetools.fs.open(localPath, \"r\", function (err) {\n                if (err && err.code === \"ENOENT\") {\n                    callback(undefined, Utils.Errors.FILE_NOT_FOUND(localPath));\n                } else if (err) {\n                    callback(undefined, err);\n                } else {\n                    var items = filetools.findFiles(localPath);\n                    var i = -1;\n\n                    var next = function () {\n                        i += 1;\n                        if (i < items.length) {\n                            var filepath = items[i];\n                            var p = relativePath(localPath, filepath).split(\"\\\\\").join(\"/\"); //windows fix\n                            p = p\n                                .normalize(\"NFD\")\n                                .replace(/[\\u0300-\\u036f]/g, \"\")\n                                .replace(/[^\\x20-\\x7E]/g, \"\"); // accent fix\n                            if (filter(p)) {\n                                filetools.fs.stat(filepath, function (er0, stats) {\n                                    if (er0) callback(undefined, er0);\n                                    if (stats.isFile()) {\n                                        filetools.fs.readFile(filepath, function (er1, data) {\n                                            if (er1) {\n                                                callback(undefined, er1);\n                                            } else {\n                                                self.addFile(zipPath + p, data, \"\", stats);\n                                                next();\n                                            }\n                                        });\n                                    } else {\n                                        self.addFile(zipPath + p + \"/\", Buffer.alloc(0), \"\", stats);\n                                        next();\n                                    }\n                                });\n                            } else {\n                                process.nextTick(() => {\n                                    next();\n                                });\n                            }\n                        } else {\n                            callback(true, undefined);\n                        }\n                    };\n\n                    next();\n                }\n            });\n        },\n\n        /**\n         * Adds a local directory and all its nested files and directories to the archive\n         *\n         * @param {object | string} options - options object, if it is string it us used as localPath.\n         * @param {string} options.localPath - Local path to the folder.\n         * @param {string} [options.zipPath] - optional path inside zip.\n         * @param {RegExp|function} [options.filter] - optional RegExp or Function if files match will be included.\n         * @param {function|string} [options.namefix] - optional function to help fix filename\n         * @param {doneCallback} callback - The callback that handles the response.\n         *\n         */\n        addLocalFolderAsync2: function (options, callback) {\n            const self = this;\n            options = typeof options === \"object\" ? options : { localPath: options };\n            localPath = pth.resolve(fixPath(options.localPath));\n            let { zipPath, filter, namefix } = options;\n\n            if (filter instanceof RegExp) {\n                filter = (function (rx) {\n                    return function (filename) {\n                        return rx.test(filename);\n                    };\n                })(filter);\n            } else if (\"function\" !== typeof filter) {\n                filter = function () {\n                    return true;\n                };\n            }\n\n            // fix ZipPath\n            zipPath = zipPath ? fixPath(zipPath) : \"\";\n\n            // Check Namefix function\n            if (namefix == \"latin1\") {\n                namefix = (str) =>\n                    str\n                        .normalize(\"NFD\")\n                        .replace(/[\\u0300-\\u036f]/g, \"\")\n                        .replace(/[^\\x20-\\x7E]/g, \"\"); // accent fix (latin1 characers only)\n            }\n\n            if (typeof namefix !== \"function\") namefix = (str) => str;\n\n            // internal, create relative path + fix the name\n            const relPathFix = (entry) => pth.join(zipPath, namefix(relativePath(localPath, entry)));\n            const fileNameFix = (entry) => pth.win32.basename(pth.win32.normalize(namefix(entry)));\n\n            filetools.fs.open(localPath, \"r\", function (err) {\n                if (err && err.code === \"ENOENT\") {\n                    callback(undefined, Utils.Errors.FILE_NOT_FOUND(localPath));\n                } else if (err) {\n                    callback(undefined, err);\n                } else {\n                    filetools.findFilesAsync(localPath, function (err, fileEntries) {\n                        if (err) return callback(err);\n                        fileEntries = fileEntries.filter((dir) => filter(relPathFix(dir)));\n                        if (!fileEntries.length) callback(undefined, false);\n\n                        setImmediate(\n                            fileEntries.reverse().reduce(function (next, entry) {\n                                return function (err, done) {\n                                    if (err || done === false) return setImmediate(next, err, false);\n\n                                    self.addLocalFileAsync(\n                                        {\n                                            localPath: entry,\n                                            zipPath: pth.dirname(relPathFix(entry)),\n                                            zipName: fileNameFix(entry)\n                                        },\n                                        next\n                                    );\n                                };\n                            }, callback)\n                        );\n                    });\n                }\n            });\n        },\n\n        /**\n         * Adds a local directory and all its nested files and directories to the archive\n         *\n         * @param {string} localPath - path where files will be extracted\n         * @param {object} props - optional properties\n         * @param {string} [props.zipPath] - optional path inside zip\n         * @param {RegExp|function} [props.filter] - optional RegExp or Function if files match will be included.\n         * @param {function|string} [props.namefix] - optional function to help fix filename\n         */\n        addLocalFolderPromise: function (localPath, props) {\n            return new Promise((resolve, reject) => {\n                this.addLocalFolderAsync2(Object.assign({ localPath }, props), (err, done) => {\n                    if (err) reject(err);\n                    if (done) resolve(this);\n                });\n            });\n        },\n\n        /**\n         * Allows you to create a entry (file or directory) in the zip file.\n         * If you want to create a directory the entryName must end in / and a null buffer should be provided.\n         * Comment and attributes are optional\n         *\n         * @param {string} entryName\n         * @param {Buffer | string} content - file content as buffer or utf8 coded string\n         * @param {string} [comment] - file comment\n         * @param {number | object} [attr] - number as unix file permissions, object as filesystem Stats object\n         */\n        addFile: function (entryName, content, comment, attr) {\n            entryName = zipnamefix(entryName);\n            let entry = getEntry(entryName);\n            const update = entry != null;\n\n            // prepare new entry\n            if (!update) {\n                entry = new ZipEntry(opts);\n                entry.entryName = entryName;\n            }\n            entry.comment = comment || \"\";\n\n            const isStat = \"object\" === typeof attr && attr instanceof filetools.fs.Stats;\n\n            // last modification time from file stats\n            if (isStat) {\n                entry.header.time = attr.mtime;\n            }\n\n            // Set file attribute\n            var fileattr = entry.isDirectory ? 0x10 : 0; // (MS-DOS directory flag)\n\n            // extended attributes field for Unix\n            // set file type either S_IFDIR / S_IFREG\n            let unix = entry.isDirectory ? 0x4000 : 0x8000;\n\n            if (isStat) {\n                // File attributes from file stats\n                unix |= 0xfff & attr.mode;\n            } else if (\"number\" === typeof attr) {\n                // attr from given attr values\n                unix |= 0xfff & attr;\n            } else {\n                // Default values:\n                unix |= entry.isDirectory ? 0o755 : 0o644; // permissions (drwxr-xr-x) or (-r-wr--r--)\n            }\n\n            fileattr = (fileattr | (unix << 16)) >>> 0; // add attributes\n\n            entry.attr = fileattr;\n\n            entry.setData(content);\n            if (!update) _zip.setEntry(entry);\n\n            return entry;\n        },\n\n        /**\n         * Returns an array of ZipEntry objects representing the files and folders inside the archive\n         *\n         * @param {string} [password]\n         * @returns Array\n         */\n        getEntries: function (password) {\n            _zip.password = password;\n            return _zip ? _zip.entries : [];\n        },\n\n        /**\n         * Returns a ZipEntry object representing the file or folder specified by ``name``.\n         *\n         * @param {string} name\n         * @return ZipEntry\n         */\n        getEntry: function (/**String*/ name) {\n            return getEntry(name);\n        },\n\n        getEntryCount: function () {\n            return _zip.getEntryCount();\n        },\n\n        forEach: function (callback) {\n            return _zip.forEach(callback);\n        },\n\n        /**\n         * Extracts the given entry to the given targetPath\n         * If the entry is a directory inside the archive, the entire directory and it's subdirectories will be extracted\n         *\n         * @param {string|ZipEntry} entry - ZipEntry object or String with the full path of the entry\n         * @param {string} targetPath - Target folder where to write the file\n         * @param {boolean} [maintainEntryPath=true] - If maintainEntryPath is true and the entry is inside a folder, the entry folder will be created in targetPath as well. Default is TRUE\n         * @param {boolean} [overwrite=false] - If the file already exists at the target path, the file will be overwriten if this is true.\n         * @param {boolean} [keepOriginalPermission=false] - The file will be set as the permission from the entry if this is true.\n         * @param {string} [outFileName] - String If set will override the filename of the extracted file (Only works if the entry is a file)\n         *\n         * @return Boolean\n         */\n        extractEntryTo: function (entry, targetPath, maintainEntryPath, overwrite, keepOriginalPermission, outFileName) {\n            overwrite = get_Bool(false, overwrite);\n            keepOriginalPermission = get_Bool(false, keepOriginalPermission);\n            maintainEntryPath = get_Bool(true, maintainEntryPath);\n            outFileName = get_Str(keepOriginalPermission, outFileName);\n\n            var item = getEntry(entry);\n            if (!item) {\n                throw Utils.Errors.NO_ENTRY();\n            }\n\n            var entryName = canonical(item.entryName);\n\n            var target = sanitize(targetPath, outFileName && !item.isDirectory ? outFileName : maintainEntryPath ? entryName : pth.basename(entryName));\n\n            if (item.isDirectory) {\n                var children = _zip.getEntryChildren(item);\n                children.forEach(function (child) {\n                    if (child.isDirectory) return;\n                    var content = child.getData();\n                    if (!content) {\n                        throw Utils.Errors.CANT_EXTRACT_FILE();\n                    }\n                    var name = canonical(child.entryName);\n                    var childName = sanitize(targetPath, maintainEntryPath ? name : pth.basename(name));\n                    // The reverse operation for attr depend on method addFile()\n                    const fileAttr = keepOriginalPermission ? child.header.fileAttr : undefined;\n                    filetools.writeFileTo(childName, content, overwrite, fileAttr);\n                });\n                return true;\n            }\n\n            var content = item.getData(_zip.password);\n            if (!content) throw Utils.Errors.CANT_EXTRACT_FILE();\n\n            if (filetools.fs.existsSync(target) && !overwrite) {\n                throw Utils.Errors.CANT_OVERRIDE();\n            }\n            // The reverse operation for attr depend on method addFile()\n            const fileAttr = keepOriginalPermission ? entry.header.fileAttr : undefined;\n            filetools.writeFileTo(target, content, overwrite, fileAttr);\n\n            return true;\n        },\n\n        /**\n         * Test the archive\n         * @param {string} [pass]\n         */\n        test: function (pass) {\n            if (!_zip) {\n                return false;\n            }\n\n            for (var entry in _zip.entries) {\n                try {\n                    if (entry.isDirectory) {\n                        continue;\n                    }\n                    var content = _zip.entries[entry].getData(pass);\n                    if (!content) {\n                        return false;\n                    }\n                } catch (err) {\n                    return false;\n                }\n            }\n            return true;\n        },\n\n        /**\n         * Extracts the entire archive to the given location\n         *\n         * @param {string} targetPath Target location\n         * @param {boolean} [overwrite=false] If the file already exists at the target path, the file will be overwriten if this is true.\n         *                  Default is FALSE\n         * @param {boolean} [keepOriginalPermission=false] The file will be set as the permission from the entry if this is true.\n         *                  Default is FALSE\n         * @param {string|Buffer} [pass] password\n         */\n        extractAllTo: function (targetPath, overwrite, keepOriginalPermission, pass) {\n            keepOriginalPermission = get_Bool(false, keepOriginalPermission);\n            pass = get_Str(keepOriginalPermission, pass);\n            overwrite = get_Bool(false, overwrite);\n            if (!_zip) throw Utils.Errors.NO_ZIP();\n\n            _zip.entries.forEach(function (entry) {\n                var entryName = sanitize(targetPath, canonical(entry.entryName));\n                if (entry.isDirectory) {\n                    filetools.makeDir(entryName);\n                    return;\n                }\n                var content = entry.getData(pass);\n                if (!content) {\n                    throw Utils.Errors.CANT_EXTRACT_FILE();\n                }\n                // The reverse operation for attr depend on method addFile()\n                const fileAttr = keepOriginalPermission ? entry.header.fileAttr : undefined;\n                filetools.writeFileTo(entryName, content, overwrite, fileAttr);\n                try {\n                    filetools.fs.utimesSync(entryName, entry.header.time, entry.header.time);\n                } catch (err) {\n                    throw Utils.Errors.CANT_EXTRACT_FILE();\n                }\n            });\n        },\n\n        /**\n         * Asynchronous extractAllTo\n         *\n         * @param {string} targetPath Target location\n         * @param {boolean} [overwrite=false] If the file already exists at the target path, the file will be overwriten if this is true.\n         *                  Default is FALSE\n         * @param {boolean} [keepOriginalPermission=false] The file will be set as the permission from the entry if this is true.\n         *                  Default is FALSE\n         * @param {function} callback The callback will be executed when all entries are extracted successfully or any error is thrown.\n         */\n        extractAllToAsync: function (targetPath, overwrite, keepOriginalPermission, callback) {\n            callback = get_Fun(overwrite, keepOriginalPermission, callback);\n            keepOriginalPermission = get_Bool(false, keepOriginalPermission);\n            overwrite = get_Bool(false, overwrite);\n            if (!callback) {\n                return new Promise((resolve, reject) => {\n                    this.extractAllToAsync(targetPath, overwrite, keepOriginalPermission, function (err) {\n                        if (err) {\n                            reject(err);\n                        } else {\n                            resolve(this);\n                        }\n                    });\n                });\n            }\n            if (!_zip) {\n                callback(Utils.Errors.NO_ZIP());\n                return;\n            }\n\n            targetPath = pth.resolve(targetPath);\n            // convert entryName to\n            const getPath = (entry) => sanitize(targetPath, pth.normalize(canonical(entry.entryName)));\n            const getError = (msg, file) => new Error(msg + ': \"' + file + '\"');\n\n            // separate directories from files\n            const dirEntries = [];\n            const fileEntries = [];\n            _zip.entries.forEach((e) => {\n                if (e.isDirectory) {\n                    dirEntries.push(e);\n                } else {\n                    fileEntries.push(e);\n                }\n            });\n\n            // Create directory entries first synchronously\n            // this prevents race condition and assures folders are there before writing files\n            for (const entry of dirEntries) {\n                const dirPath = getPath(entry);\n                // The reverse operation for attr depend on method addFile()\n                const dirAttr = keepOriginalPermission ? entry.header.fileAttr : undefined;\n                try {\n                    filetools.makeDir(dirPath);\n                    if (dirAttr) filetools.fs.chmodSync(dirPath, dirAttr);\n                    // in unix timestamp will change if files are later added to folder, but still\n                    filetools.fs.utimesSync(dirPath, entry.header.time, entry.header.time);\n                } catch (er) {\n                    callback(getError(\"Unable to create folder\", dirPath));\n                }\n            }\n\n            fileEntries.reverse().reduce(function (next, entry) {\n                return function (err) {\n                    if (err) {\n                        next(err);\n                    } else {\n                        const entryName = pth.normalize(canonical(entry.entryName));\n                        const filePath = sanitize(targetPath, entryName);\n                        entry.getDataAsync(function (content, err_1) {\n                            if (err_1) {\n                                next(err_1);\n                            } else if (!content) {\n                                next(Utils.Errors.CANT_EXTRACT_FILE());\n                            } else {\n                                // The reverse operation for attr depend on method addFile()\n                                const fileAttr = keepOriginalPermission ? entry.header.fileAttr : undefined;\n                                filetools.writeFileToAsync(filePath, content, overwrite, fileAttr, function (succ) {\n                                    if (!succ) {\n                                        next(getError(\"Unable to write file\", filePath));\n                                    }\n                                    filetools.fs.utimes(filePath, entry.header.time, entry.header.time, function (err_2) {\n                                        if (err_2) {\n                                            next(getError(\"Unable to set times\", filePath));\n                                        } else {\n                                            next();\n                                        }\n                                    });\n                                });\n                            }\n                        });\n                    }\n                };\n            }, callback)();\n        },\n\n        /**\n         * Writes the newly created zip file to disk at the specified location or if a zip was opened and no ``targetFileName`` is provided, it will overwrite the opened zip\n         *\n         * @param {string} targetFileName\n         * @param {function} callback\n         */\n        writeZip: function (targetFileName, callback) {\n            if (arguments.length === 1) {\n                if (typeof targetFileName === \"function\") {\n                    callback = targetFileName;\n                    targetFileName = \"\";\n                }\n            }\n\n            if (!targetFileName && opts.filename) {\n                targetFileName = opts.filename;\n            }\n            if (!targetFileName) return;\n\n            var zipData = _zip.compressToBuffer();\n            if (zipData) {\n                var ok = filetools.writeFileTo(targetFileName, zipData, true);\n                if (typeof callback === \"function\") callback(!ok ? new Error(\"failed\") : null, \"\");\n            }\n        },\n\n        /**\n         *\n         * @param {string} targetFileName\n         * @param {object} [props]\n         * @param {boolean} [props.overwrite=true] If the file already exists at the target path, the file will be overwriten if this is true.\n         * @param {boolean} [props.perm] The file will be set as the permission from the entry if this is true.\n\n         * @returns {Promise<void>}\n         */\n        writeZipPromise: function (/**String*/ targetFileName, /* object */ props) {\n            const { overwrite, perm } = Object.assign({ overwrite: true }, props);\n\n            return new Promise((resolve, reject) => {\n                // find file name\n                if (!targetFileName && opts.filename) targetFileName = opts.filename;\n                if (!targetFileName) reject(\"ADM-ZIP: ZIP File Name Missing\");\n\n                this.toBufferPromise().then((zipData) => {\n                    const ret = (done) => (done ? resolve(done) : reject(\"ADM-ZIP: Wasn't able to write zip file\"));\n                    filetools.writeFileToAsync(targetFileName, zipData, overwrite, perm, ret);\n                }, reject);\n            });\n        },\n\n        /**\n         * @returns {Promise<Buffer>} A promise to the Buffer.\n         */\n        toBufferPromise: function () {\n            return new Promise((resolve, reject) => {\n                _zip.toAsyncBuffer(resolve, reject);\n            });\n        },\n\n        /**\n         * Returns the content of the entire zip file as a Buffer object\n         *\n         * @prop {function} [onSuccess]\n         * @prop {function} [onFail]\n         * @prop {function} [onItemStart]\n         * @prop {function} [onItemEnd]\n         * @returns {Buffer}\n         */\n        toBuffer: function (onSuccess, onFail, onItemStart, onItemEnd) {\n            if (typeof onSuccess === \"function\") {\n                _zip.toAsyncBuffer(onSuccess, onFail, onItemStart, onItemEnd);\n                return null;\n            }\n            return _zip.compressToBuffer();\n        }\n    };\n};\n"]}