JezK
Edit File: tarball-fetcher.js
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.LocalTarballFetcher = void 0; function _regenerator() { var data = _interopRequireDefault(require("@babel/runtime/regenerator")); _regenerator = function _regenerator() { return data; }; return data; } function _slicedToArray2() { var data = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); _slicedToArray2 = function _slicedToArray2() { return data; }; return data; } function _asyncToGenerator2() { var data = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); _asyncToGenerator2 = function _asyncToGenerator2() { return data; }; return data; } function _classCallCheck2() { var data = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); _classCallCheck2 = function _classCallCheck2() { return data; }; return data; } function _createClass2() { var data = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); _createClass2 = function _createClass2() { return data; }; return data; } function _assertThisInitialized2() { var data = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized")); _assertThisInitialized2 = function _assertThisInitialized2() { return data; }; return data; } function _inherits2() { var data = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); _inherits2 = function _inherits2() { return data; }; return data; } function _possibleConstructorReturn2() { var data = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); _possibleConstructorReturn2 = function _possibleConstructorReturn2() { return data; }; return data; } function _getPrototypeOf2() { var data = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); _getPrototypeOf2 = function _getPrototypeOf2() { return data; }; return data; } function _defineProperty2() { var data = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); _defineProperty2 = function _defineProperty2() { return data; }; return data; } function _errors() { var data = require("../errors.js"); _errors = function _errors() { return data; }; return data; } function constants() { var data = _interopRequireWildcard(require("../constants.js")); constants = function constants() { return data; }; return data; } function _baseFetcher() { var data = _interopRequireDefault(require("./base-fetcher.js")); _baseFetcher = function _baseFetcher() { return data; }; return data; } function fsUtil() { var data = _interopRequireWildcard(require("../util/fs.js")); fsUtil = function fsUtil() { return data; }; return data; } function _misc() { var data = require("../util/misc.js"); _misc = function _misc() { return data; }; return data; } function _normalizeUrl() { var data = _interopRequireDefault(require("normalize-url")); _normalizeUrl = function _normalizeUrl() { return data; }; return data; } function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2()["default"])(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2()["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2()["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2()["default"])(this, result); }; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } var crypto = require('crypto'); var path = require('path'); var tarFs = require('tar-fs'); var url = require('url'); var fs = require('fs'); var stream = require('stream'); var gunzip = require('gunzip-maybe'); var invariant = require('invariant'); var ssri = require('ssri'); var RE_URL_NAME_MATCH = /\/(?:(@[^/]+)(?:\/|%2f))?[^/]+\/(?:-|_attachments)\/(?:@[^/]+\/)?([^/]+)$/; var isHashAlgorithmSupported = function isHashAlgorithmSupported(name) { var cachedResult = isHashAlgorithmSupported.__cache[name]; if (cachedResult != null) { return cachedResult; } var supported = true; try { crypto.createHash(name); } catch (error) { if (error.message !== 'Digest method not supported') { throw error; } supported = false; } isHashAlgorithmSupported.__cache[name] = supported; return supported; }; isHashAlgorithmSupported.__cache = {}; var TarballFetcher = /*#__PURE__*/function (_BaseFetcher) { (0, _inherits2()["default"])(TarballFetcher, _BaseFetcher); var _super = _createSuper(TarballFetcher); function TarballFetcher() { var _this; (0, _classCallCheck2()["default"])(this, TarballFetcher); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _super.call.apply(_super, [this].concat(args)); (0, _defineProperty2()["default"])((0, _assertThisInitialized2()["default"])(_this), "validateError", null); (0, _defineProperty2()["default"])((0, _assertThisInitialized2()["default"])(_this), "validateIntegrity", null); return _this; } (0, _createClass2()["default"])(TarballFetcher, [{ key: "setupMirrorFromCache", value: function () { var _setupMirrorFromCache = (0, _asyncToGenerator2()["default"])( /*#__PURE__*/_regenerator()["default"].mark(function _callee() { var tarballMirrorPath, tarballCachePath; return _regenerator()["default"].wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: tarballMirrorPath = this.getTarballMirrorPath(); tarballCachePath = this.getTarballCachePath(); if (!(tarballMirrorPath == null)) { _context.next = 4; break; } return _context.abrupt("return"); case 4: _context.next = 6; return fsUtil().exists(tarballMirrorPath); case 6: _context.t0 = !_context.sent; if (!_context.t0) { _context.next = 11; break; } _context.next = 10; return fsUtil().exists(tarballCachePath); case 10: _context.t0 = _context.sent; case 11: if (!_context.t0) { _context.next = 16; break; } _context.next = 14; return fsUtil().mkdirp(path.dirname(tarballMirrorPath)); case 14: _context.next = 16; return fsUtil().copy(tarballCachePath, tarballMirrorPath, this.reporter); case 16: case "end": return _context.stop(); } }, _callee, this); })); function setupMirrorFromCache() { return _setupMirrorFromCache.apply(this, arguments); } return setupMirrorFromCache; }() }, { key: "getTarballCachePath", value: function getTarballCachePath() { return path.join(this.dest, constants().TARBALL_FILENAME); } }, { key: "getTarballMirrorPath", value: function getTarballMirrorPath() { var _url$parse = url.parse(this.reference), pathname = _url$parse.pathname; if (pathname == null) { return null; } var match = pathname.match(RE_URL_NAME_MATCH); var packageFilename; if (match) { var _match = (0, _slicedToArray2()["default"])(match, 3), scope = _match[1], tarballBasename = _match[2]; packageFilename = scope ? "".concat(scope, "-").concat(tarballBasename) : tarballBasename; } else { // fallback to base name packageFilename = path.basename(pathname); } return this.config.getOfflineMirrorPath(packageFilename); } }, { key: "createExtractor", value: function createExtractor(resolve, reject, tarballPath) { var _this2 = this; var hashInfo = this._supportedIntegrity({ hashOnly: true }); var integrityInfo = this._supportedIntegrity({ hashOnly: false }); var now = new Date(); var fs = require('fs'); var patchedFs = Object.assign({}, fs, { utimes: function utimes(path, atime, mtime, cb) { fs.stat(path, function (err, stat) { if (err) { cb(err); return; } if (stat.isDirectory()) { fs.utimes(path, atime, mtime, cb); return; } fs.open(path, 'a', function (err, fd) { if (err) { cb(err); return; } fs.futimes(fd, atime, mtime, function (err) { if (err) { fs.close(fd, function () { return cb(err); }); } else { fs.close(fd, function (err) { return cb(err); }); } }); }); }); } }); var hashValidateStream = new ssri.integrityStream(hashInfo); var integrityValidateStream = new ssri.integrityStream(integrityInfo); var untarStream = tarFs.extract(this.dest, { strip: 1, dmode: 493, // all dirs should be readable fmode: 420, // all files should be readable chown: false, // don't chown. just leave as it is map: function map(header) { header.mtime = now; if (header.linkname) { var basePath = path.posix.dirname(path.join('/', header.name)); var jailPath = path.posix.join(basePath, header.linkname); header.linkname = path.posix.relative('/', jailPath); } return header; }, fs: patchedFs }); var extractorStream = gunzip(); hashValidateStream.once('error', function (err) { _this2.validateError = err; }); integrityValidateStream.once('error', function (err) { _this2.validateError = err; }); integrityValidateStream.once('integrity', function (sri) { _this2.validateIntegrity = sri; }); untarStream.on('error', function (err) { reject(new (_errors().MessageError)(_this2.config.reporter.lang('errorExtractingTarball', err.message, tarballPath))); }); extractorStream.pipe(untarStream).on('finish', function () { var error = _this2.validateError; var hexDigest = _this2.validateIntegrity ? _this2.validateIntegrity.hexDigest() : ''; if (_this2.config.updateChecksums && _this2.remote.integrity && _this2.validateIntegrity && _this2.remote.integrity !== _this2.validateIntegrity.toString()) { _this2.remote.integrity = _this2.validateIntegrity.toString(); } else if (_this2.validateIntegrity) { _this2.remote.cacheIntegrity = _this2.validateIntegrity.toString(); } if (integrityInfo.integrity && Object.keys(integrityInfo.integrity).length === 0) { return reject(new (_errors().SecurityError)(_this2.config.reporter.lang('fetchBadIntegrityAlgorithm', _this2.packageName, _this2.remote.reference))); } if (error) { if (_this2.config.updateChecksums) { _this2.remote.integrity = error.found.toString(); } else { return reject(new (_errors().SecurityError)(_this2.config.reporter.lang('fetchBadHashWithPath', _this2.packageName, _this2.remote.reference, error.found.toString(), error.expected.toString()))); } } return resolve({ hash: _this2.hash || hexDigest }); }); return { hashValidateStream: hashValidateStream, integrityValidateStream: integrityValidateStream, extractorStream: extractorStream }; } }, { key: "getLocalPaths", value: function getLocalPaths(override) { var paths = [override ? path.resolve(this.config.cwd, override) : null, this.getTarballMirrorPath(), this.getTarballCachePath()]; // $FlowFixMe: https://github.com/facebook/flow/issues/1414 return paths.filter(function (path) { return path != null; }); } }, { key: "fetchFromLocal", value: function () { var _fetchFromLocal = (0, _asyncToGenerator2()["default"])( /*#__PURE__*/_regenerator()["default"].mark(function _callee2(override) { var _this3 = this; var tarPaths, stream; return _regenerator()["default"].wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: tarPaths = this.getLocalPaths(override); _context2.next = 3; return fsUtil().readFirstAvailableStream(tarPaths); case 3: stream = _context2.sent; return _context2.abrupt("return", new Promise(function (resolve, reject) { if (!stream) { reject(new (_errors().MessageError)(_this3.reporter.lang('tarballNotInNetworkOrCache', _this3.reference, tarPaths))); return; } invariant(stream, 'stream should be available at this point'); // $FlowFixMe - This is available https://nodejs.org/api/fs.html#fs_readstream_path var tarballPath = stream.path; var _this3$createExtracto = _this3.createExtractor(resolve, reject, tarballPath), hashValidateStream = _this3$createExtracto.hashValidateStream, integrityValidateStream = _this3$createExtracto.integrityValidateStream, extractorStream = _this3$createExtracto.extractorStream; stream.pipe(hashValidateStream); hashValidateStream.pipe(integrityValidateStream); integrityValidateStream.pipe(extractorStream).on('error', function (err) { reject(new (_errors().MessageError)(_this3.config.reporter.lang('fetchErrorCorrupt', err.message, tarballPath))); }); })); case 5: case "end": return _context2.stop(); } }, _callee2, this); })); function fetchFromLocal(_x) { return _fetchFromLocal.apply(this, arguments); } return fetchFromLocal; }() }, { key: "fetchFromExternal", value: function () { var _fetchFromExternal = (0, _asyncToGenerator2()["default"])( /*#__PURE__*/_regenerator()["default"].mark(function _callee3() { var _this4 = this; var registry, headers, tarballMirrorPath, tarballCachePath; return _regenerator()["default"].wrap(function _callee3$(_context3) { while (1) switch (_context3.prev = _context3.next) { case 0: registry = this.config.registries[this.registry]; _context3.prev = 1; headers = this.requestHeaders(); _context3.next = 5; return registry.request(this.reference, { headers: _objectSpread({ 'Accept-Encoding': 'gzip' }, headers), buffer: true, process: function process(req, resolve, reject) { // should we save this to the offline cache? var tarballMirrorPath = _this4.getTarballMirrorPath(); var tarballCachePath = _this4.getTarballCachePath(); var _this4$createExtracto = _this4.createExtractor(resolve, reject), hashValidateStream = _this4$createExtracto.hashValidateStream, integrityValidateStream = _this4$createExtracto.integrityValidateStream, extractorStream = _this4$createExtracto.extractorStream; req.pipe(hashValidateStream); hashValidateStream.pipe(integrityValidateStream); if (tarballMirrorPath) { integrityValidateStream.pipe(fs.createWriteStream(tarballMirrorPath)).on('error', reject); } if (tarballCachePath) { integrityValidateStream.pipe(fs.createWriteStream(tarballCachePath)).on('error', reject); } integrityValidateStream.pipe(extractorStream).on('error', reject); } }, this.packageName); case 5: return _context3.abrupt("return", _context3.sent); case 8: _context3.prev = 8; _context3.t0 = _context3["catch"](1); tarballMirrorPath = this.getTarballMirrorPath(); tarballCachePath = this.getTarballCachePath(); _context3.t1 = tarballMirrorPath; if (!_context3.t1) { _context3.next = 17; break; } _context3.next = 16; return fsUtil().exists(tarballMirrorPath); case 16: _context3.t1 = _context3.sent; case 17: if (!_context3.t1) { _context3.next = 20; break; } _context3.next = 20; return fsUtil().unlink(tarballMirrorPath); case 20: _context3.t2 = tarballCachePath; if (!_context3.t2) { _context3.next = 25; break; } _context3.next = 24; return fsUtil().exists(tarballCachePath); case 24: _context3.t2 = _context3.sent; case 25: if (!_context3.t2) { _context3.next = 28; break; } _context3.next = 28; return fsUtil().unlink(tarballCachePath); case 28: throw _context3.t0; case 29: case "end": return _context3.stop(); } }, _callee3, this, [[1, 8]]); })); function fetchFromExternal() { return _fetchFromExternal.apply(this, arguments); } return fetchFromExternal; }() }, { key: "requestHeaders", value: function requestHeaders() { var registry = this.config.registries.yarn; var config = registry.config; var requestParts = urlParts(this.reference); return Object.keys(config).reduce(function (headers, option) { var parts = option.split(':'); if (parts.length === 3 && parts[1] === '_header') { var registryParts = urlParts(parts[0]); if (requestParts.host === registryParts.host && requestParts.path.startsWith(registryParts.path)) { var headerName = parts[2]; var headerValue = config[option]; headers[headerName] = headerValue; } } return headers; }, {}); } }, { key: "_fetch", value: function _fetch() { var _this5 = this; var isFilePath = this.reference.startsWith('file:'); this.reference = (0, _misc().removePrefix)(this.reference, 'file:'); var urlParse = url.parse(this.reference); // legacy support for local paths in yarn.lock entries var isRelativePath = urlParse.protocol ? urlParse.protocol.match(/^[a-z]:$/i) : urlParse.pathname ? urlParse.pathname.match(/^(?:\.{1,2})?[\\\/]/) : false; if (isFilePath || isRelativePath) { return this.fetchFromLocal(this.reference); } return this.fetchFromLocal()["catch"](function (err) { return _this5.fetchFromExternal(); }); } }, { key: "_findIntegrity", value: function _findIntegrity(_ref) { var hashOnly = _ref.hashOnly; if (this.remote.integrity && !hashOnly) { return ssri.parse(this.remote.integrity); } if (this.hash) { return ssri.fromHex(this.hash, 'sha1'); } return null; } }, { key: "_supportedIntegrity", value: function _supportedIntegrity(_ref2) { var hashOnly = _ref2.hashOnly; var expectedIntegrity = this._findIntegrity({ hashOnly: hashOnly }) || {}; var expectedIntegrityAlgorithms = Object.keys(expectedIntegrity); var shouldValidateIntegrity = (this.hash || this.remote.integrity) && !this.config.updateChecksums; if (expectedIntegrityAlgorithms.length === 0 && (!shouldValidateIntegrity || hashOnly)) { var _algorithms = this.config.updateChecksums ? ['sha512'] : ['sha1']; // for consistency, return sha1 for packages without a remote integrity (eg. github) return { integrity: null, algorithms: _algorithms }; } var algorithms = new Set(['sha512', 'sha1']); var integrity = {}; for (var _i = 0, _expectedIntegrityAlg = expectedIntegrityAlgorithms; _i < _expectedIntegrityAlg.length; _i++) { var algorithm = _expectedIntegrityAlg[_i]; if (isHashAlgorithmSupported(algorithm)) { algorithms.add(algorithm); integrity[algorithm] = expectedIntegrity[algorithm]; } } return { integrity: integrity, algorithms: Array.from(algorithms) }; } }]); return TarballFetcher; }(_baseFetcher()["default"]); exports["default"] = TarballFetcher; var LocalTarballFetcher = /*#__PURE__*/function (_TarballFetcher) { (0, _inherits2()["default"])(LocalTarballFetcher, _TarballFetcher); var _super2 = _createSuper(LocalTarballFetcher); function LocalTarballFetcher() { (0, _classCallCheck2()["default"])(this, LocalTarballFetcher); return _super2.apply(this, arguments); } (0, _createClass2()["default"])(LocalTarballFetcher, [{ key: "_fetch", value: function _fetch() { return this.fetchFromLocal(this.reference); } }]); return LocalTarballFetcher; }(TarballFetcher); exports.LocalTarballFetcher = LocalTarballFetcher; function urlParts(requestUrl) { var normalizedUrl = (0, _normalizeUrl()["default"])(requestUrl); var parsed = url.parse(normalizedUrl); var host = parsed.host || ''; var path = parsed.path || ''; return { host: host, path: path }; } //# sourceMappingURL=tarball-fetcher.js.map