-
Notifications
You must be signed in to change notification settings - Fork 2.2k
/
dep-graph.ts
110 lines (99 loc) · 2.48 KB
/
dep-graph.ts
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import { readFileSync, writeFileSync } from 'fs';
import * as http from 'http';
import * as opn from 'opn';
import {
createProjectGraph,
onlyWorkspaceProjects,
ProjectGraph,
ProjectGraphNode
} from '../core/project-graph';
import { output } from '../utils/output';
import { join } from 'path';
export function generateGraph(
args: { file?: string; filter?: string[]; exclude?: string[] },
affectedProjects: string[]
): void {
const graph = onlyWorkspaceProjects(createProjectGraph());
const renderProjects: ProjectGraphNode[] = filterProjects(
graph,
args.filter,
args.exclude
);
if (args.file) {
writeFileSync(
args.file,
JSON.stringify(
{
graph,
affectedProjects,
criticalPath: affectedProjects
},
null,
2
)
);
} else {
startServer(renderProjects, graph, affectedProjects);
}
}
function startServer(
projects: ProjectGraphNode[],
graph: ProjectGraph,
affected: string[]
) {
const f = readFileSync(
join(__dirname, '../core/dep-graph/dep-graph.html')
).toString();
const html = f
.replace(
`window.projects = null`,
`window.projects = ${JSON.stringify(projects)}`
)
.replace(`window.graph = null`, `window.graph = ${JSON.stringify(graph)}`)
.replace(
`window.affected = null`,
`window.affected = ${JSON.stringify(affected)}`
);
const app = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(html);
});
app.listen(4211, '127.0.0.1');
output.note({
title: 'Dep graph started at http://localhost:4211'
});
opn('http://localhost:4211', {
wait: false
});
}
function filterProjects(
graph: ProjectGraph,
filter: string[],
exclude: string[]
) {
const filteredProjects = Object.values(graph.nodes).filter(p => {
const filtered =
filter && filter.length > 0
? filter.find(
f => hasPath(graph, f, p.name, []) || hasPath(graph, p.name, f, [])
)
: true;
return !exclude
? filtered
: exclude && exclude.indexOf(p.name) === -1 && filtered;
});
return filteredProjects;
}
function hasPath(
graph: ProjectGraph,
target: string,
node: string,
visited: string[]
) {
if (target === node) return true;
for (let d of graph.dependencies[node] || []) {
if (visited.indexOf(d.target) > -1) continue;
if (hasPath(graph, target, d.target, [...visited, d.target])) return true;
}
return false;
}