JezK
Edit File: package-hoister.js
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.NohoistResolver = exports.HoistManifest = void 0; function _toConsumableArray2() { var data = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); _toConsumableArray2 = function _toConsumableArray2() { return data; }; return data; } function _slicedToArray2() { var data = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); _slicedToArray2 = function _slicedToArray2() { return data; }; return data; } function _typeof2() { var data = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); _typeof2 = function _typeof2() { 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 _defineProperty2() { var data = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); _defineProperty2 = function _defineProperty2() { return data; }; return data; } function _config() { var data = _interopRequireDefault(require("./config.js")); _config = function _config() { return data; }; return data; } function _misc() { var data = require("./util/misc.js"); _misc = function _misc() { return data; }; return data; } function _micromatch() { var data = _interopRequireDefault(require("micromatch")); _micromatch = function _micromatch() { return data; }; return data; } function _workspaceLayout() { var data = _interopRequireDefault(require("./workspace-layout.js")); _workspaceLayout = function _workspaceLayout() { return data; }; return data; } 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 _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } var invariant = require('invariant'); var path = require('path'); var historyCounter = 0; var LINK_TYPES = new Set(['workspace', 'link']); var HoistManifest = /*#__PURE__*/function () { function HoistManifest(key, parts, pkg, loc, isDirectRequire, isRequired, isIncompatible) { (0, _classCallCheck2()["default"])(this, HoistManifest); (0, _defineProperty2()["default"])(this, "isRequired", void 0); (0, _defineProperty2()["default"])(this, "isIncompatible", void 0); (0, _defineProperty2()["default"])(this, "isDirectRequire", void 0); (0, _defineProperty2()["default"])(this, "pkg", void 0); (0, _defineProperty2()["default"])(this, "loc", void 0); (0, _defineProperty2()["default"])(this, "parts", void 0); (0, _defineProperty2()["default"])(this, "previousPaths", void 0); (0, _defineProperty2()["default"])(this, "history", void 0); (0, _defineProperty2()["default"])(this, "key", void 0); (0, _defineProperty2()["default"])(this, "originalKey", void 0); (0, _defineProperty2()["default"])(this, "shallowPaths", void 0); (0, _defineProperty2()["default"])(this, "isShallow", void 0); (0, _defineProperty2()["default"])(this, "isNohoist", void 0); (0, _defineProperty2()["default"])(this, "nohoistList", void 0); (0, _defineProperty2()["default"])(this, "originalParentPath", void 0); this.isDirectRequire = isDirectRequire; this.isRequired = isRequired; this.isIncompatible = isIncompatible; this.loc = loc; this.pkg = pkg; this.key = key; this.parts = parts; this.originalKey = key; this.previousPaths = []; this.history = []; this.addHistory("Start position = ".concat(key)); this.isNohoist = false; this.originalParentPath = ''; this.shallowPaths = []; this.isShallow = false; } (0, _createClass2()["default"])(HoistManifest, [{ key: "addHistory", value: function addHistory(msg) { this.history.push("".concat(++historyCounter, ": ").concat(msg)); } }]); return HoistManifest; }(); exports.HoistManifest = HoistManifest; var PackageHoister = /*#__PURE__*/function () { function PackageHoister(config, resolver) { var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, ignoreOptional = _ref.ignoreOptional, workspaceLayout = _ref.workspaceLayout; (0, _classCallCheck2()["default"])(this, PackageHoister); (0, _defineProperty2()["default"])(this, "resolver", void 0); (0, _defineProperty2()["default"])(this, "config", void 0); (0, _defineProperty2()["default"])(this, "nohoistResolver", void 0); (0, _defineProperty2()["default"])(this, "workspaceLayout", void 0); (0, _defineProperty2()["default"])(this, "ignoreOptional", void 0); (0, _defineProperty2()["default"])(this, "levelQueue", void 0); (0, _defineProperty2()["default"])(this, "tree", void 0); (0, _defineProperty2()["default"])(this, "taintedKeys", void 0); this.resolver = resolver; this.config = config; this.ignoreOptional = ignoreOptional; this.taintedKeys = new Map(); this.levelQueue = []; this.tree = new Map(); this.workspaceLayout = workspaceLayout; this.nohoistResolver = new NohoistResolver(config, resolver); } (0, _createClass2()["default"])(PackageHoister, [{ key: "taintKey", value: /** * Taint this key and prevent any modules from being hoisted to it. */ function taintKey(key, info) { var existingTaint = this.taintedKeys.get(key); if (existingTaint && existingTaint.loc !== info.loc) { return false; } else { this.taintedKeys.set(key, info); return true; } } /** * Implode an array of ancestry parts into a key. */ }, { key: "implodeKey", value: function implodeKey(parts) { return parts.join('#'); } /** * Seed the hoister with patterns taken from the included resolver. */ }, { key: "seed", value: function seed(patterns) { var _this = this; this.prepass(patterns); var _iterator = _createForOfIteratorHelper(this.resolver.dedupePatterns(patterns)), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var pattern = _step.value; this._seed(pattern, { isDirectRequire: true }); } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } var _loop = function _loop() { var queue = _this.levelQueue; if (!queue.length) { _this._propagateRequired(); return { v: void 0 }; } _this.levelQueue = []; // sort queue to get determinism between runs queue = queue.sort(function (_ref2, _ref3) { var _ref4 = (0, _slicedToArray2()["default"])(_ref2, 1), aPattern = _ref4[0]; var _ref5 = (0, _slicedToArray2()["default"])(_ref3, 1), bPattern = _ref5[0]; return (0, _misc().sortAlpha)(aPattern, bPattern); }); // sort the queue again to hoist packages without peer dependencies first var sortedQueue = []; var availableSet = new Set(); var hasChanged = true; while (queue.length > 0 && hasChanged) { hasChanged = false; var queueCopy = queue; queue = []; for (var t = 0; t < queueCopy.length; ++t) { var queueItem = queueCopy[t]; var _pattern = queueItem[0]; var pkg = _this.resolver.getStrictResolvedPattern(_pattern); var peerDependencies = Object.keys(pkg.peerDependencies || {}); var areDependenciesFulfilled = peerDependencies.every(function (peerDependency) { return availableSet.has(peerDependency); }); if (areDependenciesFulfilled) { // Move the package inside our sorted queue sortedQueue.push(queueItem); // Add it to our set, so that we know it is available availableSet.add(_pattern); // Schedule a next pass, in case other packages had peer dependencies on this one hasChanged = true; } else { queue.push(queueItem); } } } // We might end up with some packages left in the queue, that have not been sorted. We reach this codepath if two // packages have a cyclic dependency, or if the peer dependency is provided by a parent package. In these case, // nothing we can do, so we just add all of these packages to the end of the sorted queue. sortedQueue = sortedQueue.concat(queue); var _iterator2 = _createForOfIteratorHelper(sortedQueue), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var _step2$value = (0, _slicedToArray2()["default"])(_step2.value, 2), _pattern2 = _step2$value[0], parent = _step2$value[1]; var info = _this._seed(_pattern2, { isDirectRequire: false, parent: parent }); if (info) { _this.hoist(info); } } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } }; while (true) { var _ret = _loop(); if ((0, _typeof2()["default"])(_ret) === "object") return _ret.v; } } /** * Seed the hoister with a specific pattern. */ }, { key: "_seed", value: function _seed(pattern, _ref6) { var isDirectRequire = _ref6.isDirectRequire, parent = _ref6.parent; // var pkg = this.resolver.getStrictResolvedPattern(pattern); var ref = pkg._reference; invariant(ref, 'expected reference'); // var parentParts = []; var isIncompatible = ref.incompatible; var isMarkedAsOptional = ref.optional && this.ignoreOptional; var isRequired = isDirectRequire && !ref.ignore && !isIncompatible && !isMarkedAsOptional; if (parent) { if (!this.tree.get(parent.key)) { return null; } // non ignored dependencies inherit parent's ignored status // parent may transition from ignored to non ignored when hoisted if it is used in another non ignored branch if (!isDirectRequire && !isIncompatible && parent.isRequired && !isMarkedAsOptional) { isRequired = true; } parentParts = parent.parts; } // var loc = this.config.generateModuleCachePath(ref); var parts = parentParts.concat(pkg.name); var key = this.implodeKey(parts); var info = new HoistManifest(key, parts, pkg, loc, isDirectRequire, isRequired, isIncompatible); this.nohoistResolver.initNohoist(info, parent); this.tree.set(key, info); this.taintKey(key, info); // var pushed = new Set(); var _iterator3 = _createForOfIteratorHelper(ref.dependencies), _step3; try { for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { var depPattern = _step3.value; if (!pushed.has(depPattern)) { this.levelQueue.push([depPattern, info]); pushed.add(depPattern); } } } catch (err) { _iterator3.e(err); } finally { _iterator3.f(); } return info; } /** * Propagate inherited ignore statuses from non-ignored to ignored packages */ }, { key: "_propagateRequired", value: function _propagateRequired() { // var toVisit = []; // enumerate all non-ignored packages var _iterator4 = _createForOfIteratorHelper(this.tree.entries()), _step4; try { for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) { var entry = _step4.value; if (entry[1].isRequired) { toVisit.push(entry[1]); } } // visit them } catch (err) { _iterator4.e(err); } finally { _iterator4.f(); } while (toVisit.length) { var info = toVisit.shift(); var ref = info.pkg._reference; invariant(ref, 'expected reference'); var _iterator5 = _createForOfIteratorHelper(ref.dependencies), _step5; try { for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) { var depPattern = _step5.value; var depinfo = this._lookupDependency(info, depPattern); if (!depinfo) { continue; } var depRef = depinfo.pkg._reference; // If it's marked as optional, but the parent is required and the // dependency was not listed in `optionalDependencies`, then we mark the // dependency as required. var isMarkedAsOptional = depRef && depRef.optional && this.ignoreOptional && !(info.isRequired && depRef.hint !== 'optional'); if (!depinfo.isRequired && !depinfo.isIncompatible && !isMarkedAsOptional) { depinfo.isRequired = true; depinfo.addHistory("Mark as non-ignored because of usage by ".concat(info.key)); toVisit.push(depinfo); } } } catch (err) { _iterator5.e(err); } finally { _iterator5.f(); } } } /** * Looks up the package a dependency resolves to */ }, { key: "_lookupDependency", value: function _lookupDependency(info, depPattern) { // var pkg = this.resolver.getStrictResolvedPattern(depPattern); var ref = pkg._reference; invariant(ref, 'expected reference'); // for (var i = info.parts.length; i >= 0; i--) { var checkParts = info.parts.slice(0, i).concat(pkg.name); var checkKey = this.implodeKey(checkParts); var existing = this.tree.get(checkKey); if (existing) { return existing; } } return null; } /** * Find the highest position we can hoist this module to. */ }, { key: "getNewParts", value: function getNewParts(key, info, parts) { var _this2 = this; var stepUp = false; var highestHoistingPoint = this.nohoistResolver.highestHoistingPoint(info) || 0; var fullKey = this.implodeKey(parts); var stack = []; // stack of removed parts var name = parts.pop(); if (info.isNohoist) { info.addHistory("Marked as nohoist, will not be hoisted above '".concat(parts[highestHoistingPoint], "'")); } for (var i = parts.length - 1; i >= highestHoistingPoint; i--) { var checkParts = parts.slice(0, i).concat(name); var checkKey = this.implodeKey(checkParts); info.addHistory("Looked at ".concat(checkKey, " for a match")); var existing = this.tree.get(checkKey); if (existing) { if (existing.loc === info.loc) { // switch to non ignored if earlier deduped version was ignored (must be compatible) if (!existing.isRequired && info.isRequired) { existing.addHistory("Deduped ".concat(fullKey, " to this item, marking as required")); existing.isRequired = true; } else { existing.addHistory("Deduped ".concat(fullKey, " to this item")); } return { parts: checkParts, duplicate: true }; } else { // everything above will be shadowed and this is a conflict info.addHistory("Found a collision at ".concat(checkKey)); break; } } var existingTaint = this.taintedKeys.get(checkKey); if (existingTaint && existingTaint.loc !== info.loc) { info.addHistory("Broken by ".concat(checkKey)); break; } } var peerDependencies = Object.keys(info.pkg.peerDependencies || {}); // remove redundant parts that wont collide hoistLoop: while (parts.length > highestHoistingPoint) { // we must not hoist a package higher than its peer dependencies var _iterator6 = _createForOfIteratorHelper(peerDependencies), _step6; try { for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) { var peerDependency = _step6.value; var _checkParts2 = parts.concat(peerDependency); var _checkKey2 = this.implodeKey(_checkParts2); info.addHistory("Looked at ".concat(_checkKey2, " for a peer dependency match")); var _existing2 = this.tree.get(_checkKey2); if (_existing2) { info.addHistory("Found a peer dependency requirement at ".concat(_checkKey2)); break hoistLoop; } } } catch (err) { _iterator6.e(err); } finally { _iterator6.f(); } var _checkParts = parts.concat(name); var _checkKey = this.implodeKey(_checkParts); // var _existing = this.tree.get(_checkKey); if (_existing) { stepUp = true; break; } // check if we're trying to hoist ourselves to a previously unflattened module key, // this will result in a conflict and we'll need to move ourselves up if (key !== _checkKey && this.taintedKeys.has(_checkKey)) { stepUp = true; break; } // stack.push(parts.pop()); } // parts.push(name); // var isValidPosition = function isValidPosition(parts) { // nohoist package can't be hoisted to the "root" if (parts.length <= highestHoistingPoint) { return false; } var key = _this2.implodeKey(parts); var existing = _this2.tree.get(key); if (existing && existing.loc === info.loc) { return true; } // ensure there's no taint or the taint is us var existingTaint = _this2.taintedKeys.get(key); if (existingTaint && existingTaint.loc !== info.loc) { return false; } return true; }; // we need to special case when we attempt to hoist to the top level as the `existing` logic // wont be hit in the above `while` loop and we could conflict if (!isValidPosition(parts)) { stepUp = true; } // sometimes we need to step up to a parent module to install ourselves while (stepUp && stack.length) { info.addHistory("Stepping up from ".concat(this.implodeKey(parts))); parts.pop(); // remove `name` parts.push(stack.pop(), name); if (isValidPosition(parts)) { info.addHistory("Found valid position ".concat(this.implodeKey(parts))); stepUp = false; } } return { parts: parts, duplicate: false }; } /** * Hoist all seeded patterns to their highest positions. */ }, { key: "hoist", value: function hoist(info) { var oldKey = info.key, rawParts = info.parts; // remove this item from the `tree` map so we can ignore it this.tree["delete"](oldKey); var _this$getNewParts = this.getNewParts(oldKey, info, rawParts.slice()), parts = _this$getNewParts.parts, duplicate = _this$getNewParts.duplicate; var newKey = this.implodeKey(parts); if (duplicate) { info.addHistory("Satisfied from above by ".concat(newKey)); this.declareRename(info, rawParts, parts); this.updateHoistHistory(this.nohoistResolver._originalPath(info), this.implodeKey(parts)); return; } // update to the new key if (oldKey === newKey) { info.addHistory("Didn't hoist - see reason above"); this.setKey(info, oldKey, rawParts); return; } // this.declareRename(info, rawParts, parts); this.setKey(info, newKey, parts); } /** * Declare that a module has been hoisted and update our internal references. */ }, { key: "declareRename", value: function declareRename(info, oldParts, newParts) { // go down the tree from our new position reserving our name this.taintParents(info, oldParts.slice(0, -1), newParts.length - 1); } /** * Crawl upwards through a list of ancestry parts and taint a package name. */ }, { key: "taintParents", value: function taintParents(info, processParts, start) { for (var i = start; i < processParts.length; i++) { var parts = processParts.slice(0, i).concat(info.pkg.name); var key = this.implodeKey(parts); if (this.taintKey(key, info)) { info.addHistory("Tainted ".concat(key, " to prevent collisions")); } } } }, { key: "updateHoistHistory", value: function updateHoistHistory(fromPath, toKey) { var info = this.tree.get(toKey); invariant(info, "expect to find hoist-to ".concat(toKey)); info.previousPaths.push(fromPath); } /** * Update the key of a module and update our references. */ }, { key: "setKey", value: function setKey(info, newKey, parts) { var oldKey = info.key; info.key = newKey; info.parts = parts; this.tree.set(newKey, info); if (oldKey === newKey) { return; } var fromInfo = this.tree.get(newKey); invariant(fromInfo, "expect to find hoist-from ".concat(newKey)); info.previousPaths.push(this.nohoistResolver._originalPath(fromInfo)); info.addHistory("New position = ".concat(newKey)); } /** * Perform a prepass and if there's multiple versions of the same package, hoist the one with * the most dependents to the top. */ }, { key: "prepass", value: function prepass(patterns) { var _this3 = this; patterns = this.resolver.dedupePatterns(patterns).sort(); var visited = new Map(); var occurences = {}; // visitor to be used inside add() to mark occurences of packages var visitAdd = function visitAdd(pkg, ancestry, pattern) { var versions = occurences[pkg.name] = occurences[pkg.name] || {}; var version = versions[pkg.version] = versions[pkg.version] || { occurences: new Set(), pattern: pattern }; if (ancestry.length) { version.occurences.add(ancestry[ancestry.length - 1]); } }; // add an occurring package to the above data structure var add = function add(pattern, ancestry, ancestryPatterns) { var pkg = _this3.resolver.getStrictResolvedPattern(pattern); if (ancestry.indexOf(pkg) >= 0) { // prevent recursive dependencies return; } var visitedPattern = visited.get(pattern); if (visitedPattern) { // if a package has been visited before, simply increment occurrences of packages // like last time this package was visited visitedPattern.forEach(function (visitPkg) { visitAdd(visitPkg.pkg, visitPkg.ancestry, visitPkg.pattern); }); visitAdd(pkg, ancestry, pattern); return; } var ref = pkg._reference; invariant(ref, 'expected reference'); visitAdd(pkg, ancestry, pattern); var _iterator7 = _createForOfIteratorHelper(ref.dependencies), _step7; try { for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) { var depPattern = _step7.value; var depAncestry = ancestry.concat(pkg); var depAncestryPatterns = ancestryPatterns.concat(depPattern); add(depPattern, depAncestry, depAncestryPatterns); } } catch (err) { _iterator7.e(err); } finally { _iterator7.f(); } visitedPattern = visited.get(pattern) || []; visited.set(pattern, visitedPattern); visitedPattern.push({ pkg: pkg, ancestry: ancestry, pattern: pattern }); ancestryPatterns.forEach(function (ancestryPattern) { var visitedAncestryPattern = visited.get(ancestryPattern); if (visitedAncestryPattern) { visitedAncestryPattern.push({ pkg: pkg, ancestry: ancestry, pattern: pattern }); } }); }; // get a list of root package names since we can't hoist other dependencies to these spots! var rootPackageNames = new Set(); var _iterator8 = _createForOfIteratorHelper(patterns), _step8; try { for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) { var pattern = _step8.value; var pkg = this.resolver.getStrictResolvedPattern(pattern); rootPackageNames.add(pkg.name); add(pattern, [], []); } } catch (err) { _iterator8.e(err); } finally { _iterator8.f(); } var _iterator9 = _createForOfIteratorHelper(Object.keys(occurences).sort()), _step9; try { for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) { var _packageName = _step9.value; var versionOccurences = occurences[_packageName]; var versions = Object.keys(versionOccurences); if (versions.length === 1) { // only one package type so we'll hoist this to the top anyway continue; } if (this.tree.get(_packageName)) { // a transitive dependency of a previously hoisted dependency exists continue; } if (rootPackageNames.has(_packageName)) { // can't replace top level packages continue; } var mostOccurenceCount = void 0; var mostOccurencePattern = void 0; var _iterator10 = _createForOfIteratorHelper(Object.keys(versionOccurences).sort()), _step10; try { for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) { var _version = _step10.value; var _versionOccurences$_v = versionOccurences[_version], _occurences = _versionOccurences$_v.occurences, _pattern3 = _versionOccurences$_v.pattern; var occurenceCount = _occurences.size; if (!mostOccurenceCount || occurenceCount > mostOccurenceCount) { mostOccurenceCount = occurenceCount; mostOccurencePattern = _pattern3; } } } catch (err) { _iterator10.e(err); } finally { _iterator10.f(); } invariant(mostOccurencePattern, 'expected most occurring pattern'); invariant(mostOccurenceCount, 'expected most occurring count'); // only hoist this module if it occured more than once if (mostOccurenceCount > 1) { this._seed(mostOccurencePattern, { isDirectRequire: false }); } } } catch (err) { _iterator9.e(err); } finally { _iterator9.f(); } } }, { key: "markShallowWorkspaceEntries", value: function markShallowWorkspaceEntries() { var _this4 = this; var targetWorkspace = this.config.focusedWorkspaceName; var targetHoistManifest = this.tree.get(targetWorkspace); invariant(targetHoistManifest, "targetHoistManifest from ".concat(targetWorkspace, " missing")); //dedupe with a set var dependentWorkspaces = Array.from(new Set(this._getDependentWorkspaces(targetHoistManifest))); var entries = Array.from(this.tree); entries.forEach(function (_ref7) { var _ref8 = (0, _slicedToArray2()["default"])(_ref7, 2), key = _ref8[0], info = _ref8[1]; var splitPath = key.split('#'); //mark the workspace and any un-hoisted dependencies it has for shallow installation var isShallowDependency = dependentWorkspaces.some(function (w) { if (splitPath[0] !== w) { //entry is not related to the workspace return false; } if (!splitPath[1]) { //entry is the workspace return true; } //don't bother marking dev dependencies or nohoist packages for shallow installation var treeEntry = _this4.tree.get(w); invariant(treeEntry, 'treeEntry is not defined for ' + w); var pkg = treeEntry.pkg; return !info.isNohoist && (!pkg.devDependencies || !(splitPath[1] in pkg.devDependencies)); }); if (isShallowDependency) { info.shallowPaths = [null]; return; } //if package foo is at TARGET_WORKSPACE/node_modules/foo, the hoisted version of foo //should be installed under each shallow workspace that uses it //(unless that workspace has its own version of foo, in which case that should be installed) if (splitPath.length !== 2 || splitPath[0] !== targetWorkspace) { return; } var unhoistedDependency = splitPath[1]; var unhoistedInfo = _this4.tree.get(unhoistedDependency); if (!unhoistedInfo) { return; } dependentWorkspaces.forEach(function (w) { if (_this4._packageDependsOnHoistedPackage(w, unhoistedDependency, false)) { unhoistedInfo.shallowPaths.push(w); } }); }); } }, { key: "_getDependentWorkspaces", value: function _getDependentWorkspaces(parent) { var _this5 = this; var allowDevDeps = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var alreadySeen = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : new Set(); var parentName = parent.pkg.name; if (alreadySeen.has(parentName)) { return []; } alreadySeen.add(parentName); invariant(this.workspaceLayout, 'missing workspaceLayout'); var _this$workspaceLayout = this.workspaceLayout, virtualManifestName = _this$workspaceLayout.virtualManifestName, workspaces = _this$workspaceLayout.workspaces; var directDependencies = []; var ignored = []; Object.keys(workspaces).forEach(function (workspace) { if (alreadySeen.has(workspace) || workspace === virtualManifestName) { return; } //skip a workspace if a different version of it is already being installed under the parent workspace var info = _this5.tree.get("".concat(parentName, "#").concat(workspace)); if (info) { var workspaceVersion = workspaces[workspace].manifest.version; if (info.isNohoist && info.originalParentPath.startsWith("/".concat(WS_ROOT_ALIAS, "/").concat(parentName)) && info.pkg.version === workspaceVersion) { //nohoist installations are exceptions directDependencies.push(info.key); } else { ignored.push(workspace); } return; } var searchPath = "/".concat(WS_ROOT_ALIAS, "/").concat(parentName); info = _this5.tree.get(workspace); invariant(info, 'missing workspace tree entry ' + workspace); if (!info.previousPaths.some(function (p) { return p.startsWith(searchPath); })) { return; } if (allowDevDeps || !parent.pkg.devDependencies || !(workspace in parent.pkg.devDependencies)) { directDependencies.push(workspace); } }); var nested = directDependencies.map(function (d) { var dependencyEntry = _this5.tree.get(d); invariant(dependencyEntry, 'missing dependencyEntry ' + d); return _this5._getDependentWorkspaces(dependencyEntry, false, alreadySeen); }); nested = [].concat.apply([], nested); //flatten var directDependencyNames = directDependencies.map(function (d) { return d.split('#').slice(-1)[0]; }); return directDependencyNames.concat(nested).filter(function (w) { return ignored.indexOf(w) === -1; }); } }, { key: "_packageDependsOnHoistedPackage", value: function _packageDependsOnHoistedPackage(p, hoisted) { var _this6 = this; var checkDevDeps = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var checked = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : new Set(); //don't check the same package more than once, and ignore any package that has its own version of hoisted if (checked.has(p) || this.tree.has("".concat(p, "#").concat(hoisted))) { return false; } checked.add(p); var info = this.tree.get(p); if (!info) { return false; } var pkg = info.pkg; if (!pkg) { return false; } var deps = []; if (pkg.dependencies) { deps = deps.concat(Object.keys(pkg.dependencies)); } if (checkDevDeps && pkg.devDependencies) { deps = deps.concat(Object.keys(pkg.devDependencies)); } if (deps.indexOf(hoisted) !== -1) { return true; } return deps.some(function (dep) { return _this6._packageDependsOnHoistedPackage(dep, hoisted, false, checked); }); } /** * Produce a flattened list of module locations and manifests. */ }, { key: "init", value: function init() { var _this7 = this; var flatTree = []; // var _iterator11 = _createForOfIteratorHelper(this.tree.entries()), _step11; try { var _loop2 = function _loop2() { var _step11$value = (0, _slicedToArray2()["default"])(_step11.value, 2), key = _step11$value[0], info = _step11$value[1]; // decompress the location and push it to the flat tree. this path could be made // up of modules from different registries so we need to handle this specially var parts = []; var keyParts = key.split('#'); var isWorkspaceEntry = _this7.workspaceLayout && keyParts[0] === _this7.workspaceLayout.virtualManifestName; // Don't add the virtual manifest (keyParts.length === 1) // or ws childs which were not hoisted to the root (keyParts.length === 2). // If a ws child was hoisted its key would not contain the virtual manifest name if (isWorkspaceEntry && keyParts.length <= 2) { return "continue"; } for (var i = 0; i < keyParts.length; i++) { var _key = keyParts.slice(0, i + 1).join('#'); var hoisted = _this7.tree.get(_key); invariant(hoisted, "expected hoisted manifest for \"".concat(_key, "\"")); parts.push(_this7.config.getFolder(hoisted.pkg)); parts.push(keyParts[i]); } // Check if the destination is pointing to a sub folder of the virtualManifestName // e.g. _project_/node_modules/workspace-aggregator-123456/node_modules/workspaceChild/node_modules/dependency // This probably happened because the hoister was not able to hoist the workspace child to the root // So we have to change the folder to the workspace package location if (_this7.workspaceLayout && isWorkspaceEntry) { var wspPkg = _this7.workspaceLayout.workspaces[keyParts[1]]; invariant(wspPkg, "expected workspace package to exist for \"".concat(keyParts[1], "\"")); parts.splice(0, 4, wspPkg.loc); } else { if (_this7.config.modulesFolder) { // remove the first part which will be the folder name and replace it with a // hardcoded modules folder parts.splice(0, 1, _this7.config.modulesFolder); } else { // first part will be the registry-specific module folder parts.splice(0, 0, _this7.config.lockfileFolder); } } var shallowLocs = []; info.shallowPaths.forEach(function (shallowPath) { var shallowCopyParts = parts.slice(); shallowCopyParts[0] = _this7.config.cwd; if (_this7.config.modulesFolder) { //add back the module folder name for the shallow installation var treeEntry = _this7.tree.get(keyParts[0]); invariant(treeEntry, 'expected treeEntry for ' + keyParts[0]); var moduleFolderName = _this7.config.getFolder(treeEntry.pkg); shallowCopyParts.splice(1, 0, moduleFolderName); } if (shallowPath) { var targetWorkspace = _this7.config.focusedWorkspaceName; var _treeEntry = _this7.tree.get("".concat(targetWorkspace, "#").concat(shallowPath)) || _this7.tree.get(shallowPath); invariant(_treeEntry, 'expected treeEntry for ' + shallowPath); var _moduleFolderName = _this7.config.getFolder(_treeEntry.pkg); shallowCopyParts.splice(1, 0, _moduleFolderName, shallowPath); } shallowLocs.push(path.join.apply(path, (0, _toConsumableArray2()["default"])(shallowCopyParts))); }); var loc = path.join.apply(path, parts); flatTree.push([loc, info]); shallowLocs.forEach(function (shallowLoc) { var newManifest = _objectSpread(_objectSpread({}, info), {}, { isShallow: true }); flatTree.push([shallowLoc, newManifest]); }); }; for (_iterator11.s(); !(_step11 = _iterator11.n()).done;) { var _ret2 = _loop2(); if (_ret2 === "continue") continue; } // remove ignored modules from the tree } catch (err) { _iterator11.e(err); } finally { _iterator11.f(); } var visibleFlatTree = []; for (var _i = 0, _flatTree = flatTree; _i < _flatTree.length; _i++) { var _flatTree$_i = (0, _slicedToArray2()["default"])(_flatTree[_i], 2), loc = _flatTree$_i[0], info = _flatTree$_i[1]; var ref = info.pkg._reference; invariant(ref, 'expected reference'); if (!info.isRequired) { info.addHistory('Deleted as this module was ignored'); } else { visibleFlatTree.push([loc, info]); } } return visibleFlatTree; } }]); return PackageHoister; }(); exports["default"] = PackageHoister; var WS_ROOT_ALIAS = '_project_'; var NohoistResolver = /*#__PURE__*/function () { function NohoistResolver(config, resolver) { var _this8 = this; (0, _classCallCheck2()["default"])(this, NohoistResolver); (0, _defineProperty2()["default"])(this, "_resolver", void 0); (0, _defineProperty2()["default"])(this, "_config", void 0); (0, _defineProperty2()["default"])(this, "_wsRootNohoistList", void 0); (0, _defineProperty2()["default"])(this, "_wsRootPackageName", void 0); (0, _defineProperty2()["default"])(this, "initNohoist", function (info, parent) { var parentNohoistList; var originalParentPath = info.originalParentPath; if (parent) { parentNohoistList = parent.nohoistList; originalParentPath = _this8._originalPath(parent); } else { invariant(_this8._isTopPackage(info), "".concat(info.key, " doesn't have parent nor a top package")); if (info.pkg.name !== _this8._wsRootPackageName) { parentNohoistList = _this8._wsRootNohoistList; originalParentPath = _this8._wsRootPackageName || ''; } } info.originalParentPath = originalParentPath; var nohoistList = _this8._extractNohoistList(info.pkg, _this8._originalPath(info)) || []; if (parentNohoistList) { nohoistList = nohoistList.concat(parentNohoistList); } info.nohoistList = nohoistList.length > 0 ? nohoistList : null; info.isNohoist = _this8._isNohoist(info); }); (0, _defineProperty2()["default"])(this, "highestHoistingPoint", function (info) { return info.isNohoist && info.parts.length > 1 ? 1 : null; }); (0, _defineProperty2()["default"])(this, "_isNohoist", function (info) { if (_this8._isTopPackage(info)) { return false; } if (info.nohoistList && info.nohoistList.length > 0 && _micromatch()["default"].any(_this8._originalPath(info), info.nohoistList)) { return true; } if (_this8._config.plugnplayEnabled) { return true; } return false; }); (0, _defineProperty2()["default"])(this, "_isRootPackage", function (pkg) { return pkg.name === _this8._wsRootPackageName; }); (0, _defineProperty2()["default"])(this, "_originalPath", function (info) { return _this8._makePath(info.originalParentPath, info.pkg.name); }); (0, _defineProperty2()["default"])(this, "_isTopPackage", function (info) { var parentParts = info.parts.slice(0, -1); var result = !parentParts || parentParts.length <= 0 || parentParts.length === 1 && parentParts[0] === _this8._wsRootPackageName; return result; }); (0, _defineProperty2()["default"])(this, "_isLink", function (info) { return info.pkg._remote != null && LINK_TYPES.has(info.pkg._remote.type); }); (0, _defineProperty2()["default"])(this, "_extractNohoistList", function (pkg, pathPrefix) { var nohoistList; var ws = _this8._config.getWorkspaces(pkg); if (ws && ws.nohoist) { nohoistList = ws.nohoist.map(function (p) { return _this8._makePath(pathPrefix, p); }); } return nohoistList; }); this._resolver = resolver; this._config = config; if (resolver.workspaceLayout) { this._wsRootPackageName = resolver.workspaceLayout.virtualManifestName; var _resolver$workspaceLa = resolver.workspaceLayout.getWorkspaceManifest(this._wsRootPackageName), manifest = _resolver$workspaceLa.manifest; this._wsRootNohoistList = this._extractNohoistList(manifest, manifest.name); } } (0, _createClass2()["default"])(NohoistResolver, [{ key: "_makePath", value: function _makePath() { var _this9 = this; for (var _len = arguments.length, args = new Array(_len), _key2 = 0; _key2 < _len; _key2++) { args[_key2] = arguments[_key2]; } var parts = args.map(function (s) { return s === _this9._wsRootPackageName ? WS_ROOT_ALIAS : s; }); var result = parts.join('/'); return result[0] === '/' ? result : '/' + result; } }]); return NohoistResolver; }(); exports.NohoistResolver = NohoistResolver; //# sourceMappingURL=package-hoister.js.map