UNPKG

@ayonli/jsext

Version:

A JavaScript extension package for building strong and modern applications.

197 lines (192 loc) 7.96 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var bytes = require('../bytes.js'); var env = require('../env.js'); var event = require('../event.js'); var fs = require('../fs.js'); var fs_util = require('../fs/util.js'); var path = require('../path.js'); var runtime = require('../runtime.js'); var archive_Tarball = require('./Tarball.js'); async function untar(src, dest = {}, options = {}) { var _a; let _dest = undefined; if (typeof dest === "string") { _dest = options.root ? dest : path.resolve(dest); } else if (typeof dest === "object") { if (typeof FileSystemDirectoryHandle === "function" && dest instanceof FileSystemDirectoryHandle) { _dest = dest; } else { options = dest; } } src = typeof src === "string" && options.root ? path.resolve(src) : src; let input = src instanceof ReadableStream ? src : fs.createReadableStream(src, options); if (options.gzip) { const gzip = new DecompressionStream("gzip"); input = input.pipeThrough(gzip); } const { signal } = options; signal === null || signal === void 0 ? void 0 : signal.addEventListener("abort", () => { input.cancel(signal.reason); }); if (!_dest) { return await archive_Tarball.default.load(input); } else if (typeof _dest === "string") { await fs.ensureDir(_dest, options); } let totalWrittenBytes = 0; let totalBytes = (_a = options.size) !== null && _a !== void 0 ? _a : 0; if (!totalBytes && options.onProgress) { if (typeof src === "string") { const info = await fs.stat(src, options); totalBytes = info.size; } else if (typeof FileSystemFileHandle === "function" && src instanceof FileSystemFileHandle) { const info = await src.getFile(); totalBytes = info.size; } } const entries = []; const reader = input.getReader(); let lastChunk = new Uint8Array(0); let entry = null; let writer = null; let writtenBytes = 0; let paddingSize = 0; try { outer: while (true) { const { done, value } = await reader.read(); if (done) { break; } lastChunk = lastChunk.byteLength ? bytes.concat(lastChunk, value) : value; while (true) { if (paddingSize > 0 && lastChunk.byteLength >= paddingSize) { lastChunk = lastChunk.subarray(paddingSize); paddingSize = 0; } if (!entry) { if (lastChunk.byteLength >= archive_Tarball.HEADER_LENGTH) { const _header = archive_Tarball.parseHeader(lastChunk); if (_header) { lastChunk = _header[2]; entry = archive_Tarball.createEntry(_header[0]); entries.push(entry); } else { lastChunk = new Uint8Array(0); break outer; } } else { break; } } const fileSize = entry.size; let filename = undefined; if (writer) { const chunk = lastChunk.subarray(0, fileSize - writtenBytes); await writer.write(chunk); lastChunk = lastChunk.subarray(fileSize - writtenBytes); writtenBytes += chunk.byteLength; if (chunk.byteLength) { totalWrittenBytes += chunk.byteLength; if (options.onProgress) { options.onProgress(event.createProgressEvent("progress", { lengthComputable: !!totalBytes, loaded: totalWrittenBytes, total: totalBytes })); } } } else if (entry.kind === "directory") { if (typeof FileSystemDirectoryHandle === "function" && _dest instanceof FileSystemDirectoryHandle) { await fs.ensureDir(entry.relativePath, { ...options, root: _dest }); } else { filename = path.join(_dest, entry.relativePath); await fs.ensureDir(filename, options); } } else { let _options = options; if (typeof FileSystemDirectoryHandle === "function" && _dest instanceof FileSystemDirectoryHandle) { _options = { ...options, root: _dest }; filename = entry.relativePath; } else { filename = path.join(_dest, entry.relativePath); } const dir = path.dirname(filename); if (dir && dir !== "." && dir !== "/") { await fs.ensureDir(dir, _options); } const output = fs.createWritableStream(filename, _options); writer = output.getWriter(); continue; } if (writtenBytes === fileSize) { paddingSize = archive_Tarball.HEADER_LENGTH - (fileSize % archive_Tarball.HEADER_LENGTH || archive_Tarball.HEADER_LENGTH); writtenBytes = 0; writer === null || writer === void 0 ? void 0 : writer.close(); writer = null; entry = null; } else { break; } } } if (lastChunk.byteLength) { throw new Error("The archive is corrupted"); } else if (totalBytes && totalWrittenBytes < totalBytes && options.onProgress) { totalWrittenBytes = totalBytes; options.onProgress(event.createProgressEvent("progress", { lengthComputable: true, loaded: totalWrittenBytes, total: totalBytes, })); } } finally { reader.releaseLock(); } if ((env.isDeno || env.isNodeLike) && typeof _dest === "string") { const isWindows = runtime.platform() === "windows"; const tree = fs_util.makeTree(path.basename(_dest), entries); await (async function restoreStats(nodes) { var _a; for (const entry of nodes) { const filename = path.join(_dest, entry.relativePath); if (entry.kind === "directory" && ((_a = entry.children) === null || _a === void 0 ? void 0 : _a.length)) { // must restore contents' stats before the directory itself await restoreStats(entry.children); } // Only restore the permission mode and the last modified time, // don't restore the owner and group, because they may not exist // and may cause an error. // // This behavior is consistent with `tar -xf archive.tar` in // Unix-like systems. if (entry.mode && !isWindows) { await fs.chmod(filename, entry.mode); } if (entry.mtime) { await fs.utimes(filename, new Date(), entry.mtime); } } })(tree.children); } } exports.default = untar; //# sourceMappingURL=untar.js.map