@lerna/package-graph
Advanced tools
Comparing version 3.16.0 to 3.18.0
@@ -6,2 +6,13 @@ # Change Log | ||
# [3.18.0](https://github.com/lerna/lerna/compare/v3.17.0...v3.18.0) (2019-10-15) | ||
### Features | ||
* **package-graph:** Deprecate method `pruneCycleNodes()` ([ccf32e1](https://github.com/lerna/lerna/commit/ccf32e1d745e0ab2d633d8b72613d3c19ccdc0c7)) | ||
# [3.16.0](https://github.com/lerna/lerna/compare/v3.15.0...v3.16.0) (2019-07-18) | ||
@@ -8,0 +19,0 @@ |
197
index.js
"use strict"; | ||
const npa = require("npm-package-arg"); | ||
const semver = require("semver"); | ||
const log = require("npmlog"); | ||
const ValidationError = require("@lerna/validation-error"); | ||
const prereleaseIdFromVersion = require("@lerna/prerelease-id-from-version"); | ||
const { CyclicPackageGraphNode } = require("./lib/cyclic-package-graph-node"); | ||
const { PackageGraphNode } = require("./lib/package-graph-node"); | ||
const { reportCycles } = require("./lib/report-cycles"); | ||
/** | ||
* Represents a node in a PackageGraph. | ||
* @constructor | ||
* @param {!<Package>} pkg - A Package object to build the node from. | ||
*/ | ||
class PackageGraphNode { | ||
constructor(pkg) { | ||
Object.defineProperties(this, { | ||
// immutable properties | ||
name: { | ||
enumerable: true, | ||
value: pkg.name, | ||
}, | ||
location: { | ||
value: pkg.location, | ||
}, | ||
prereleaseId: { | ||
// an existing prerelease ID only matters at the beginning | ||
value: prereleaseIdFromVersion(pkg.version), | ||
}, | ||
// properties that might change over time | ||
version: { | ||
get() { | ||
return pkg.version; | ||
}, | ||
}, | ||
pkg: { | ||
get() { | ||
return pkg; | ||
}, | ||
}, | ||
}); | ||
this.externalDependencies = new Map(); | ||
this.localDependencies = new Map(); | ||
this.localDependents = new Map(); | ||
} | ||
/** | ||
* Determine if the Node satisfies a resolved semver range. | ||
* @see https://github.com/npm/npm-package-arg#result-object | ||
* | ||
* @param {!Result} resolved npm-package-arg Result object | ||
* @returns {Boolean} | ||
*/ | ||
satisfies({ gitCommittish, gitRange, fetchSpec }) { | ||
return semver.satisfies(this.version, gitCommittish || gitRange || fetchSpec); | ||
} | ||
/** | ||
* Returns a string representation of this node (its name) | ||
* | ||
* @returns {String} | ||
*/ | ||
toString() { | ||
return this.name; | ||
} | ||
} | ||
let lastCollapsedNodeId = 0; | ||
/** | ||
* Represents a cyclic collection of nodes in a PackageGraph. | ||
* It is meant to be used as a black box, where the only exposed | ||
* information are the connections to the other nodes of the graph. | ||
* It can contains either `PackageGraphNode`s or other `CyclicPackageGraphNode`s. | ||
*/ | ||
class CyclicPackageGraphNode extends Map { | ||
constructor() { | ||
super(); | ||
this.localDependencies = new Map(); | ||
this.localDependents = new Map(); | ||
Object.defineProperties(this, { | ||
// immutable properties | ||
name: { | ||
enumerable: true, | ||
value: `(cycle) ${(lastCollapsedNodeId += 1)}`, | ||
}, | ||
isCycle: { | ||
value: true, | ||
}, | ||
}); | ||
} | ||
/** | ||
* @returns {String} Returns a representation of a cycle, like like `A -> B -> C -> A`. | ||
*/ | ||
toString() { | ||
const parts = Array.from(this, ([key, node]) => | ||
node.isCycle ? `(nested cycle: ${node.toString()})` : key | ||
); | ||
// start from the origin | ||
parts.push(parts[0]); | ||
return parts.reverse().join(" -> "); | ||
} | ||
/** | ||
* Flattens a CyclicPackageGraphNode (which can have multiple level of cycles). | ||
* | ||
* @returns {PackageGraphNode[]} | ||
*/ | ||
flatten() { | ||
const result = []; | ||
for (const node of this.values()) { | ||
if (node.isCycle) { | ||
result.push(...node.flatten()); | ||
} else { | ||
result.push(node); | ||
} | ||
} | ||
return result; | ||
} | ||
/** | ||
* Checks if a given node is contained in this cycle (or in a nested one) | ||
* | ||
* @param {String} name The name of the package to search in this cycle | ||
* @returns {Boolean} | ||
*/ | ||
contains(name) { | ||
for (const [currentName, currentNode] of this) { | ||
if (currentNode.isCycle) { | ||
if (currentNode.contains(name)) { | ||
return true; | ||
} | ||
} else if (currentName === name) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
/** | ||
* Adds a graph node, or a nested cycle, to this group. | ||
* | ||
* @param {PackageGraphNode|CyclicPackageGraphNode} node | ||
*/ | ||
insert(node) { | ||
this.set(node.name, node); | ||
this.unlink(node); | ||
for (const [dependencyName, dependencyNode] of node.localDependencies) { | ||
if (!this.contains(dependencyName)) { | ||
this.localDependencies.set(dependencyName, dependencyNode); | ||
} | ||
} | ||
for (const [dependentName, dependentNode] of node.localDependents) { | ||
if (!this.contains(dependentName)) { | ||
this.localDependents.set(dependentName, dependentNode); | ||
} | ||
} | ||
} | ||
/** | ||
* Remove pointers to candidate node from internal collections. | ||
* @param {PackageGraphNode|CyclicPackageGraphNode} candidateNode instance to unlink | ||
*/ | ||
unlink(candidateNode) { | ||
// remove incoming edges ("indegree") | ||
this.localDependencies.delete(candidateNode.name); | ||
// remove outgoing edges ("outdegree") | ||
this.localDependents.delete(candidateNode.name); | ||
} | ||
} | ||
/** | ||
* A PackageGraph. | ||
@@ -436,2 +262,5 @@ * @constructor | ||
* Remove cycle nodes. | ||
* | ||
* @deprecated Spread set into prune() instead. | ||
* | ||
* @param {Set<PackageGraphNode>} cycleNodes | ||
@@ -473,16 +302,2 @@ */ | ||
function reportCycles(paths, rejectCycles) { | ||
if (!paths.length) { | ||
return; | ||
} | ||
const cycleMessage = ["Dependency cycles detected, you should fix these!"].concat(paths).join("\n"); | ||
if (rejectCycles) { | ||
throw new ValidationError("ECYCLE", cycleMessage); | ||
} | ||
log.warn("ECYCLE", cycleMessage); | ||
} | ||
module.exports = PackageGraph; |
{ | ||
"name": "@lerna/package-graph", | ||
"version": "3.16.0", | ||
"version": "3.18.0", | ||
"description": "Lerna's internal representation of a package graph", | ||
@@ -16,3 +16,4 @@ "keywords": [ | ||
"files": [ | ||
"index.js" | ||
"index.js", | ||
"lib" | ||
], | ||
@@ -41,3 +42,3 @@ "main": "index.js", | ||
}, | ||
"gitHead": "8ca18bedecf4f141c6242a099086e84b2ced72de" | ||
"gitHead": "0ea8fb136f408fb4de3fd39bb7069d976235d53d" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
23183
8
423