Socket
Socket
Sign inDemoInstall

@lerna/package-graph

Package Overview
Dependencies
Maintainers
2
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@lerna/package-graph - npm Package Compare versions

Comparing version 3.16.0 to 3.18.0

lib/cyclic-package-graph-node.js

11

CHANGELOG.md

@@ -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"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc