node/deps/npm/node_modules/@npmcli/arborist/lib/calc-dep-flags.js
Myles Borins 2e54524955
deps: update npm to 7.0.0-rc.3
PR-URL: https://github.com/nodejs/node/pull/35474
Reviewed-By: Ruy Adorno <ruyadorno@github.com>
Reviewed-By: Ujjwal Sharma <ryzokuken@disroot.org>
Reviewed-By: Ben Coe <bencoe@gmail.com>
Reviewed-By: Geoffrey Booth <webmaster@geoffreybooth.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Shelley Vohr <codebytere@gmail.com>
Reviewed-By: Guy Bedford <guybedford@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2020-10-07 09:59:49 -04:00

95 lines
2.7 KiB
JavaScript

const { depth } = require('treeverse')
const calcDepFlags = (tree, resetRoot = true) => {
if (resetRoot) {
tree.dev = false
tree.optional = false
tree.devOptional = false
tree.peer = false
}
const ret = depth({
tree,
visit: node => calcDepFlagsStep(node),
filter: node => node,
getChildren: node => [...node.edgesOut.values()].map(edge => edge.to),
})
return ret
}
const calcDepFlagsStep = (node) => {
// This rewalk is necessary to handle cases where devDep and optional
// or normal dependency graphs overlap deep in the dep graph.
// Since we're only walking through deps that are not already flagged
// as non-dev/non-optional, it's typically a very shallow traversal
node.extraneous = false
// for links, map their hierarchy appropriately
if (node.target) {
node.target.dev = node.dev
node.target.optional = node.optional
node.target.devOptional = node.devOptional
node.target.peer = node.peer
node.target.extraneous = false
node = node.target
}
node.edgesOut.forEach(({peer, optional, dev, to}) => {
// if the dep is missing, then its flags are already maximally unset
if (!to)
return
// everything with any kind of edge into it is not extraneous
to.extraneous = false
// devOptional is the *overlap* of the dev and optional tree.
// however, for convenience and to save an extra rewalk, we leave
// it set when we are in *either* tree, and then omit it from the
// package-lock if either dev or optional are set.
const unsetDevOpt = !node.devOptional && !node.dev && !node.optional &&
!dev && !optional
// if we are not in the devOpt tree, then we're also not in
// either the dev or opt trees
const unsetDev = unsetDevOpt || !node.dev && !dev
const unsetOpt = unsetDevOpt ||
!node.optional && !optional
const unsetPeer = !node.peer && !peer
if (unsetPeer)
unsetFlag(to, 'peer')
if (unsetDevOpt)
unsetFlag(to, 'devOptional')
if (unsetDev)
unsetFlag(to, 'dev')
if (unsetOpt)
unsetFlag(to, 'optional')
})
return node
}
// typically a short walk, since it only traverses deps that
// have the flag set.
const unsetFlag = (node, flag) => {
if (node[flag]) {
node[flag] = false
depth({
tree: node,
visit: node => {
node.extraneous = node[flag] = false
if (node.target)
node.target.extraneous = node.target[flag] = false
},
getChildren: node => [...(node.target || node).edgesOut.values()]
.filter(edge => edge.to && edge.to[flag] &&
(flag !== 'peer' && edge.type === 'peer' || edge.type === 'prod'))
.map(edge => edge.to),
})
}
}
module.exports = calcDepFlags