-
Notifications
You must be signed in to change notification settings - Fork 546
/
Copy pathgraph.js
85 lines (76 loc) · 1.91 KB
/
graph.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import fs from "node:fs"
function toDot(modules, output) {
let buffer = "digraph G {\n"
buffer += "edge [dir=back]\n"
for (const m of modules) {
for (const dep of m.deps) {
buffer += `"${dep}" -> "${m.id}"\n`
}
}
buffer += "}\n"
fs.writeFileSync(output, buffer, { encoding: "utf8" })
}
function prune(modules) {
let avail = modules.filter((m) => m.deps.length == 0)
if (!avail.length) {
return
}
let id = avail[0].id
// console.log("pruning", id);
let index = modules.indexOf(avail[0])
modules.splice(index, 1)
for (const m of modules) {
m.deps = m.deps.filter((dep) => dep != id)
}
prune(modules)
}
function getPrefix(ids) {
if (ids.length < 2) {
return ""
}
return ids.reduce((prefix, val) => {
while (val.indexOf(prefix) != 0) {
prefix = prefix.substring(0, prefix.length - 1)
}
return prefix
})
}
/**
* Plugin which will generate .dot file with dependency graph
* @param options {{exclude: string, output: string, prune: boolean, prefix: string}}
*/
export default function plugin(options) {
let exclude = (str) => options.exclude && str.match(options.exclude)
let output = options.output
if (!output) throw new Error("Please specify output file")
return {
generateBundle(bundleOptions, bundle, isWrite) {
let ids = []
for (const moduleId of this.moduleIds) {
if (!exclude(moduleId)) {
ids.push(moduleId)
}
}
let prefix = options.prefix || getPrefix(ids)
let strip = (str) => (str.startsWith(prefix) ? str.substring(prefix.length) : str)
let modules = []
for (const id of ids) {
let m = {
id: strip(id),
deps: this.getModuleInfo(id)
.importedIds.filter((x) => !exclude(x))
.concat(this.getModuleInfo(id).dynamicImporters.filter((x) => !exclude(x)))
.map(strip),
}
if (exclude(m.id)) {
continue
}
modules.push(m)
}
if (options.prune) {
prune(modules)
}
toDot(modules, output)
},
}
}