fast-extract
Version:
Extract contents from various archive types (tar, tar.bz2, tar.gz, tar.xz, tgz, zip)
147 lines • 5.63 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return createWriteStream;
}
});
var _calloncefn = /*#__PURE__*/ _interop_require_default(require("call-once-fn"));
var _onone = /*#__PURE__*/ _interop_require_default(require("on-one"));
var _flushwritestreamts = /*#__PURE__*/ _interop_require_default(require("./compat/flush-write-stream.js"));
var _createPipelinets = /*#__PURE__*/ _interop_require_default(require("./createPipeline.js"));
var _exitCleanupts = /*#__PURE__*/ _interop_require_default(require("./exitCleanup.js"));
function _define_property(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function _object_spread(target) {
for(var i = 1; i < arguments.length; i++){
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === "function") {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
}
ownKeys.forEach(function(key) {
_define_property(target, key, source[key]);
});
}
return target;
}
function createWriteStream(dest, options_) {
if (typeof options_ === 'string') options_ = {
type: options_
};
var options = _object_spread({}, options_);
var streams = (0, _createPipelinets.default)(dest, options);
_exitCleanupts.default.add(dest);
// Get first and last streams
var first = streams[0];
var last = streams[streams.length - 1];
var error = null;
var ended = false;
var lastFinished = false;
var finishCallback = null;
var errorEmittedOnWrite = false;
// Manually pipe streams (instead of using pump which has complex completion semantics)
for(var i = 0; i < streams.length - 1; i++){
streams[i].pipe(streams[i + 1]);
}
// Handle errors from all streams - use on-one to ensure each stream only triggers once
var errorHandling = false;
function handleError(err) {
if (!err || errorHandling) return; // only handle actual errors, once
errorHandling = true;
error = err;
// Emit error immediately to prevent 'finish' from being emitted (Node 12 timing issue)
if (!errorEmittedOnWrite) {
errorEmittedOnWrite = true;
write.destroy(err);
}
// Note: Don't clean up dest on error - if user retries with force, safeRm will handle it.
// Background cleanup here causes race conditions where new files get deleted.
_exitCleanupts.default.remove(dest);
}
// Listen for errors on all streams (errors may not propagate through all pipe types)
for(var i1 = 0; i1 < streams.length; i1++){
(0, _onone.default)(streams[i1], [
'error'
], handleError);
}
// Track when last stream finishes (use on-one for cross-version compatibility)
(0, _onone.default)(last, [
'end',
'close',
'finish'
], function() {
if (error) return; // don't complete if errored
lastFinished = true;
if (finishCallback) {
finishCallback();
finishCallback = null;
}
});
function onEnd(callback) {
if (error || ended) return callback();
ended = true;
_exitCleanupts.default.remove(dest);
callback();
}
var write = (0, _flushwritestreamts.default)(function write(chunk, encoding, callback) {
if (error) return callback(error);
first.write(chunk, encoding, function(err) {
if (error) return; // skip if errored
if (err) {
error = err;
errorEmittedOnWrite = true; // error will be emitted by Writable base class via callback
callback(err);
} else {
callback();
}
});
}, function flush(callback) {
if (error) {
errorEmittedOnWrite = true; // error will be emitted by Writable base class via callback
return callback(error);
}
// Ensure callback is only called once (race conditions on older Node)
var cb = (0, _calloncefn.default)(callback);
var onComplete = function() {
if (error) return cb(error);
onEnd(cb);
};
// If last already finished, complete immediately
if (lastFinished) {
onComplete();
} else {
// Wait for last stream to finish
finishCallback = onComplete;
// End the first stream to signal no more data - this propagates through the pipeline
first.end();
}
});
// Track when error is emitted on write stream (from any source)
write.on('error', function() {
errorEmittedOnWrite = true;
});
return write;
}
/* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }