Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
calc-dep-flags.js104 linesDownload Raw Back to lib
1// Dep flag (dev, peer, etc.) calculation requires default or reset flags.
2// Flags are true by default and are unset to false as we walk deps.
3// We iterate outward edges looking for dep flags that can
4// be unset based on the current nodes flags and edge type.
5// Examples:
6// - a non-optional node with a non-optional edge out, the edge node should not be optional
7// - a non-peer node with a non-peer edge out, the edge node should not be peer
8// If a node is changed, we add to the queue and continue until no more changes.
9// Flags that remain after all this unsetting should be valid.
10// Examples:
11// - a node still flagged optional must only be reachable via optional edges
12// - a node still flagged peer must only be reachable via peer edges
13const calcDepFlags = (tree, resetRoot = true) => {
14  if (resetRoot) {
15    tree.unsetDepFlags()
16  }
17
18  const seen = new Set()
19  const queue = [tree]
20
21  let node
22  while (node = queue.pop()) {
23    seen.add(node)
24
25    // Unset extraneous from all parents to avoid removal of children.
26    if (!node.extraneous) {
27      for (let n = node.resolveParent; n?.extraneous; n = n.resolveParent) {
28        n.extraneous = false
29      }
30    }
31
32    // for links, map their hierarchy appropriately
33    if (node.isLink) {
34      // node.target can be null, we check to ensure it's not null before proceeding
35      if (node.target == null) {
36        continue
37      }
38      node.target.dev = node.dev
39      node.target.optional = node.optional
40      node.target.devOptional = node.devOptional
41      node.target.peer = node.peer
42      node.target.extraneous = node.extraneous
43      queue.push(node.target)
44      continue
45    }
46
47    for (const { peer, optional, dev, to } of node.edgesOut.values()) {
48      // if the dep is missing, then its flags are already maximally unset
49      if (!to) {
50        continue
51      }
52
53      let changed = false
54
55      // only optional peer dependencies should stay extraneous
56      if (to.extraneous && !node.extraneous && !(peer && optional)) {
57        to.extraneous = false
58        changed = true
59      }
60
61      if (to.dev && !node.dev && !dev) {
62        to.dev = false
63        changed = true
64      }
65
66      if (to.optional && !node.optional && !optional) {
67        to.optional = false
68        changed = true
69      }
70
71      // devOptional is the *overlap* of the dev and optional tree.
72      // A node may be depended on by separate dev and optional nodes.
73      // It SHOULD NOT be removed when pruning dev OR optional.
74      // It SHOULD be removed when pruning dev AND optional.
75      // We only unset here if a node is not dev AND not optional because
76      // if we did unset, it would prevent any overlap deeper in the tree.
77      // We correct this later by removing if dev OR optional is set.
78      if (to.devOptional && !node.devOptional && !node.dev && !node.optional && !dev && !optional) {
79        to.devOptional = false
80        changed = true
81      }
82
83      if (to.peer && !node.peer && !peer) {
84        to.peer = false
85        changed = true
86      }
87
88      if (changed) {
89        queue.push(to)
90      }
91    }
92  }
93
94  // Remove incorrect devOptional flags now that we have walked all deps.
95  seen.delete(tree)
96  for (const node of seen.values()) {
97    if (node.devOptional && (node.dev || node.optional)) {
98      node.devOptional = false
99    }
100  }
101}
102
103module.exports = calcDepFlags
104 
codekingpro/portable-devtools · Team Ai