@datapith/cdk4j-diagram 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BUILD.md +12 -0
- package/commands/asciiart/index.js +58 -0
- package/commands/asciiart/mxgraph-to-asciiart.js +203 -0
- package/commands/browse/index.js +61 -0
- package/commands/draw.io/index.js +40 -0
- package/commands/html/index.js +40 -0
- package/commands/mermaid/index.js +100 -0
- package/graph/MxGenerator.js +400 -0
- package/graph/Vis.js +231 -0
- package/graph/ui/icons.js +228 -0
- package/graph/ui/index.html +164 -0
- package/graph/ui/index_standalone.template +166 -0
- package/index.js +10 -0
- package/index.spec.js +36 -0
- package/package.json +61 -0
- package/resources/FilterConfig.js +9 -0
- package/resources/IconMap.js +330 -0
- package/resources/JsonUtil.js +186 -0
- package/shared/templateCache.js +6 -0
- package/shared/templateParser.js +128 -0
- package/tests/resources/JsonUtil.spec.js +32 -0
- package/tests/template.json +143 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<style type="text/css">
|
|
5
|
+
#mynetwork {
|
|
6
|
+
width: 100%;
|
|
7
|
+
height: 100vh;
|
|
8
|
+
border: 1px solid lightgray;
|
|
9
|
+
}
|
|
10
|
+
.body {
|
|
11
|
+
font-family: Arial, Helvetica, sans-serif;
|
|
12
|
+
}
|
|
13
|
+
#filtersContainer {
|
|
14
|
+
left: 0px;
|
|
15
|
+
top: 0px;
|
|
16
|
+
height: 100vh;
|
|
17
|
+
width: 400px;
|
|
18
|
+
background-color: rgba(80, 197, 251, 0.7);
|
|
19
|
+
border: blue 4px;
|
|
20
|
+
padding: 3px 3px 3px 3px;
|
|
21
|
+
z-index: 2999;
|
|
22
|
+
position: absolute;
|
|
23
|
+
font-family: "Courier New", Courier, monospace;
|
|
24
|
+
overflow: scroll;
|
|
25
|
+
}
|
|
26
|
+
</style>
|
|
27
|
+
<script
|
|
28
|
+
type="text/javascript"
|
|
29
|
+
src="https://visjs.github.io/vis-network/standalone/umd/vis-network.min.js"
|
|
30
|
+
></script>
|
|
31
|
+
|
|
32
|
+
<script src="./data.js"></script>
|
|
33
|
+
|
|
34
|
+
<script type="text/javascript">
|
|
35
|
+
let network;
|
|
36
|
+
const rule = {
|
|
37
|
+
EventPattern: '{"source":["aws.events"]}',
|
|
38
|
+
EventBusName: "default",
|
|
39
|
+
Target: "MyFunction",
|
|
40
|
+
Name: "AllAWSEvents -> MyFunction",
|
|
41
|
+
InputPath: undefined,
|
|
42
|
+
Input: undefined,
|
|
43
|
+
InputTransformer: {
|
|
44
|
+
InputPathsMap: {
|
|
45
|
+
source: "$.source",
|
|
46
|
+
detailType: "$.detail-type",
|
|
47
|
+
time: "$.time",
|
|
48
|
+
},
|
|
49
|
+
InputTemplate:
|
|
50
|
+
'{"source": <source>, "detail-type": <detailType>, "time": <time> }',
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
function preTitle(text) {
|
|
54
|
+
const container = document.createElement("pre");
|
|
55
|
+
container.innerText = text; // You may also use innerHTML if your source is trusted.
|
|
56
|
+
return container;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function draw() {
|
|
60
|
+
// create a network
|
|
61
|
+
var container = document.getElementById("mynetwork");
|
|
62
|
+
nodes.forEach((node => {
|
|
63
|
+
node.title = preTitle(node.title);
|
|
64
|
+
}));
|
|
65
|
+
var data = {
|
|
66
|
+
nodes: nodes,
|
|
67
|
+
edges: edges,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
var options = {
|
|
71
|
+
nodes: {
|
|
72
|
+
shape: "dot",
|
|
73
|
+
size: 16,
|
|
74
|
+
},
|
|
75
|
+
edges: {
|
|
76
|
+
arrows: {
|
|
77
|
+
to: {
|
|
78
|
+
enabled: true,
|
|
79
|
+
imageHeight: undefined,
|
|
80
|
+
imageWidth: undefined,
|
|
81
|
+
scaleFactor: 1,
|
|
82
|
+
src: undefined,
|
|
83
|
+
type: "arrow",
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
physics: {
|
|
88
|
+
forceAtlas2Based: {
|
|
89
|
+
gravitationalConstant: -26,
|
|
90
|
+
centralGravity: 0.005,
|
|
91
|
+
springLength: 230,
|
|
92
|
+
springConstant: 0.18,
|
|
93
|
+
},
|
|
94
|
+
maxVelocity: 146,
|
|
95
|
+
solver: "forceAtlas2Based",
|
|
96
|
+
timestep: 0.35,
|
|
97
|
+
stabilization: { iterations: 150 },
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
network = new vis.Network(container, data, options);
|
|
101
|
+
network.body.emitter.emit("_dataChanged");
|
|
102
|
+
}
|
|
103
|
+
function populateFilters(conatainerName, data, checked, func) {
|
|
104
|
+
var container = document.getElementById(conatainerName);
|
|
105
|
+
if (!data.length) {
|
|
106
|
+
container.style.visibility = "hidden";
|
|
107
|
+
}
|
|
108
|
+
for (const name of data) {
|
|
109
|
+
var checkbox = document.createElement("input");
|
|
110
|
+
checkbox.type = "checkbox";
|
|
111
|
+
checkbox.id = name;
|
|
112
|
+
checkbox.checked = checked;
|
|
113
|
+
checkbox.name = conatainerName;
|
|
114
|
+
checkbox.value = name;
|
|
115
|
+
checkbox.addEventListener("click", func);
|
|
116
|
+
var label = document.createElement("label");
|
|
117
|
+
label.htmlFor = name;
|
|
118
|
+
label.appendChild(document.createTextNode(name));
|
|
119
|
+
|
|
120
|
+
var br = document.createElement("br");
|
|
121
|
+
|
|
122
|
+
container.appendChild(checkbox);
|
|
123
|
+
container.appendChild(label);
|
|
124
|
+
container.appendChild(br);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
</script>
|
|
128
|
+
</head>
|
|
129
|
+
|
|
130
|
+
<body>
|
|
131
|
+
<div id="mynetwork"></div>
|
|
132
|
+
<div id="filtersContainer">
|
|
133
|
+
<div id="resource-types">
|
|
134
|
+
<strong>Include resource types:</strong><br />
|
|
135
|
+
</div>
|
|
136
|
+
<div id="nested-stacks">
|
|
137
|
+
<hr />
|
|
138
|
+
<strong>Include nested stack(s):</strong><br />
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
<script>
|
|
142
|
+
window.onload = function (event) {
|
|
143
|
+
if (!showSidebar) {
|
|
144
|
+
document.getElementById("filtersContainer").hidden = true;
|
|
145
|
+
}
|
|
146
|
+
populateFilters("nested-stacks", nested, renderAll, (x) => {
|
|
147
|
+
const ns = nodes.get({ filter: (p) => p.prefix === x.target.value });
|
|
148
|
+
for (const n of ns) {
|
|
149
|
+
nodes.update({ id: n.id, hidden: !x.target.checked });
|
|
150
|
+
}
|
|
151
|
+
network.redraw();
|
|
152
|
+
});
|
|
153
|
+
populateFilters("resource-types", types, true, (x) => {
|
|
154
|
+
const ns = nodes.get({ filter: (p) => p.type === x.target.value });
|
|
155
|
+
for (const n of ns) {
|
|
156
|
+
nodes.update({ id: n.id, hidden: !x.target.checked });
|
|
157
|
+
}
|
|
158
|
+
network.redraw();
|
|
159
|
+
});
|
|
160
|
+
draw();
|
|
161
|
+
};
|
|
162
|
+
</script>
|
|
163
|
+
</body>
|
|
164
|
+
</html>
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<style type="text/css">
|
|
5
|
+
#mynetwork {
|
|
6
|
+
width: 100%;
|
|
7
|
+
height: 100vh;
|
|
8
|
+
border: 1px solid lightgray;
|
|
9
|
+
}
|
|
10
|
+
.body {
|
|
11
|
+
font-family: Arial, Helvetica, sans-serif;
|
|
12
|
+
}
|
|
13
|
+
#filtersContainer {
|
|
14
|
+
left: 0px;
|
|
15
|
+
top: 0px;
|
|
16
|
+
height: 100vh;
|
|
17
|
+
width: 400px;
|
|
18
|
+
background-color: rgba(80, 197, 251, 0.7);
|
|
19
|
+
border: blue 4px;
|
|
20
|
+
padding: 3px 3px 3px 3px;
|
|
21
|
+
z-index: 2999;
|
|
22
|
+
position: absolute;
|
|
23
|
+
font-family: "Courier New", Courier, monospace;
|
|
24
|
+
overflow: scroll;
|
|
25
|
+
}
|
|
26
|
+
</style>
|
|
27
|
+
<script
|
|
28
|
+
type="text/javascript"
|
|
29
|
+
src="https://visjs.github.io/vis-network/standalone/umd/vis-network.min.js"
|
|
30
|
+
></script>
|
|
31
|
+
|
|
32
|
+
<script type="text/javascript">
|
|
33
|
+
%DATA_JS%
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<script type="text/javascript">
|
|
37
|
+
let network;
|
|
38
|
+
const rule = {
|
|
39
|
+
EventPattern: '{"source":["aws.events"]}',
|
|
40
|
+
EventBusName: "default",
|
|
41
|
+
Target: "MyFunction",
|
|
42
|
+
Name: "AllAWSEvents -> MyFunction",
|
|
43
|
+
InputPath: undefined,
|
|
44
|
+
Input: undefined,
|
|
45
|
+
InputTransformer: {
|
|
46
|
+
InputPathsMap: {
|
|
47
|
+
source: "$.source",
|
|
48
|
+
detailType: "$.detail-type",
|
|
49
|
+
time: "$.time",
|
|
50
|
+
},
|
|
51
|
+
InputTemplate:
|
|
52
|
+
'{"source": <source>, "detail-type": <detailType>, "time": <time> }',
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
function preTitle(text) {
|
|
56
|
+
const container = document.createElement("pre");
|
|
57
|
+
container.innerText = text; // You may also use innerHTML if your source is trusted.
|
|
58
|
+
return container;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function draw() {
|
|
62
|
+
// create a network
|
|
63
|
+
var container = document.getElementById("mynetwork");
|
|
64
|
+
nodes.forEach((node => {
|
|
65
|
+
node.title = preTitle(node.title);
|
|
66
|
+
}));
|
|
67
|
+
var data = {
|
|
68
|
+
nodes: nodes,
|
|
69
|
+
edges: edges,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
var options = {
|
|
73
|
+
nodes: {
|
|
74
|
+
shape: "dot",
|
|
75
|
+
size: 16,
|
|
76
|
+
},
|
|
77
|
+
edges: {
|
|
78
|
+
arrows: {
|
|
79
|
+
to: {
|
|
80
|
+
enabled: true,
|
|
81
|
+
imageHeight: undefined,
|
|
82
|
+
imageWidth: undefined,
|
|
83
|
+
scaleFactor: 1,
|
|
84
|
+
src: undefined,
|
|
85
|
+
type: "arrow",
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
physics: {
|
|
90
|
+
forceAtlas2Based: {
|
|
91
|
+
gravitationalConstant: -26,
|
|
92
|
+
centralGravity: 0.005,
|
|
93
|
+
springLength: 230,
|
|
94
|
+
springConstant: 0.18,
|
|
95
|
+
},
|
|
96
|
+
maxVelocity: 146,
|
|
97
|
+
solver: "forceAtlas2Based",
|
|
98
|
+
timestep: 0.35,
|
|
99
|
+
stabilization: { iterations: 150 },
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
network = new vis.Network(container, data, options);
|
|
103
|
+
network.body.emitter.emit("_dataChanged");
|
|
104
|
+
}
|
|
105
|
+
function populateFilters(conatainerName, data, checked, func) {
|
|
106
|
+
var container = document.getElementById(conatainerName);
|
|
107
|
+
if (!data.length) {
|
|
108
|
+
container.style.visibility = "hidden";
|
|
109
|
+
}
|
|
110
|
+
for (const name of data) {
|
|
111
|
+
var checkbox = document.createElement("input");
|
|
112
|
+
checkbox.type = "checkbox";
|
|
113
|
+
checkbox.id = name;
|
|
114
|
+
checkbox.checked = checked;
|
|
115
|
+
checkbox.name = conatainerName;
|
|
116
|
+
checkbox.value = name;
|
|
117
|
+
checkbox.addEventListener("click", func);
|
|
118
|
+
var label = document.createElement("label");
|
|
119
|
+
label.htmlFor = name;
|
|
120
|
+
label.appendChild(document.createTextNode(name));
|
|
121
|
+
|
|
122
|
+
var br = document.createElement("br");
|
|
123
|
+
|
|
124
|
+
container.appendChild(checkbox);
|
|
125
|
+
container.appendChild(label);
|
|
126
|
+
container.appendChild(br);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
</script>
|
|
130
|
+
</head>
|
|
131
|
+
|
|
132
|
+
<body>
|
|
133
|
+
<div id="mynetwork"></div>
|
|
134
|
+
<div id="filtersContainer">
|
|
135
|
+
<div id="resource-types">
|
|
136
|
+
<strong>Include resource types:</strong><br />
|
|
137
|
+
</div>
|
|
138
|
+
<div id="nested-stacks">
|
|
139
|
+
<hr />
|
|
140
|
+
<strong>Include nested stack(s):</strong><br />
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
<script>
|
|
144
|
+
window.onload = function (event) {
|
|
145
|
+
if (!showSidebar) {
|
|
146
|
+
document.getElementById("filtersContainer").hidden = true;
|
|
147
|
+
}
|
|
148
|
+
populateFilters("nested-stacks", nested, renderAll, (x) => {
|
|
149
|
+
const ns = nodes.get({ filter: (p) => p.prefix === x.target.value });
|
|
150
|
+
for (const n of ns) {
|
|
151
|
+
nodes.update({ id: n.id, hidden: !x.target.checked });
|
|
152
|
+
}
|
|
153
|
+
network.redraw();
|
|
154
|
+
});
|
|
155
|
+
populateFilters("resource-types", types, true, (x) => {
|
|
156
|
+
const ns = nodes.get({ filter: (p) => p.type === x.target.value });
|
|
157
|
+
for (const n of ns) {
|
|
158
|
+
nodes.update({ id: n.id, hidden: !x.target.checked });
|
|
159
|
+
}
|
|
160
|
+
network.redraw();
|
|
161
|
+
});
|
|
162
|
+
draw();
|
|
163
|
+
};
|
|
164
|
+
</script>
|
|
165
|
+
</body>
|
|
166
|
+
</html>
|
package/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const program = require("commander");
|
|
3
|
+
require("./commands/draw.io");
|
|
4
|
+
require("./commands/html");
|
|
5
|
+
require("./commands/asciiart");
|
|
6
|
+
require("./commands/browse");
|
|
7
|
+
require("./commands/mermaid");
|
|
8
|
+
const packag = require("./package.json");
|
|
9
|
+
program.version(packag.version, "-v, --vers", "output the current version");
|
|
10
|
+
program.parse(process.argv);
|
package/index.spec.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
let os = require('os');
|
|
2
|
+
let path = require('path');
|
|
3
|
+
let exec = require('child_process').exec;
|
|
4
|
+
|
|
5
|
+
test('Code should be 0', async () => {
|
|
6
|
+
jest.setTimeout(30000);
|
|
7
|
+
|
|
8
|
+
console.log("output path set to " + os.tmpdir() + '/template.drawio')
|
|
9
|
+
let result = await cli(['draw.io', '--template-file', './tests/template.json', '--output-file', os.tmpdir() + '/template.drawio', '--ci-mode' ], '.');
|
|
10
|
+
console.log(result.stdout)
|
|
11
|
+
console.log(result.stderr)
|
|
12
|
+
expect(result.code).toBe(0);
|
|
13
|
+
|
|
14
|
+
console.log("output path set to " + os.tmpdir())
|
|
15
|
+
result = await cli(['html', '--template-file', './tests/template.json', '--output-path', os.tmpdir(), '--ci-mode'], '.');
|
|
16
|
+
console.log(result.stdout)
|
|
17
|
+
console.log(result.stderr)
|
|
18
|
+
expect(result.code).toBe(0);
|
|
19
|
+
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
function cli(args, cwd) {
|
|
24
|
+
return new Promise(resolve => {
|
|
25
|
+
exec(`node ${path.resolve('./index.js')} ${args.join(' ')}`,
|
|
26
|
+
{ cwd },
|
|
27
|
+
(error, stdout, stderr) => {
|
|
28
|
+
resolve({
|
|
29
|
+
code: error && error.code ? error.code : 0,
|
|
30
|
+
error,
|
|
31
|
+
stdout,
|
|
32
|
+
stderr
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@datapith/cdk4j-diagram",
|
|
3
|
+
"version": "0.4.1",
|
|
4
|
+
"description": "CLI tool to visualise CloudFormation, SAM or CDK stacks as draw.io, visjs networks, ascii-art or mermaid",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "jest"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"aws",
|
|
11
|
+
"sam",
|
|
12
|
+
"draw.io",
|
|
13
|
+
"cloudformation"
|
|
14
|
+
],
|
|
15
|
+
"author": "datapith",
|
|
16
|
+
"license": "ISC",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@aws-sdk/client-cloudformation": "^3.445.0",
|
|
19
|
+
"@aws-sdk/credential-provider-sso": "^3.445.0",
|
|
20
|
+
"@mhlabs/cfn-diagram": "^1.1.40",
|
|
21
|
+
"aws-icons-directory": "^0.0.6",
|
|
22
|
+
"cli-color": "^2.0.0",
|
|
23
|
+
"color-convert": "^2.0.1",
|
|
24
|
+
"color-hash": "^1.0.3",
|
|
25
|
+
"commander": "^7.1.0",
|
|
26
|
+
"fast-xml-parser": "^4.3.2",
|
|
27
|
+
"inquirer": "^8.2.0",
|
|
28
|
+
"jdom": "^3.1.11",
|
|
29
|
+
"jsdom": "^16.4.0",
|
|
30
|
+
"latest": "^0.2.0",
|
|
31
|
+
"mxgraph": "^4.1.1",
|
|
32
|
+
"n": "^10.2.0",
|
|
33
|
+
"open": "^8.4.0",
|
|
34
|
+
"open-in-editor": "^2.2.0",
|
|
35
|
+
"pkg": "^5.8.1",
|
|
36
|
+
"temp-dir": "^2.0.0",
|
|
37
|
+
"yaml-cfn": "^0.2.3"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@aws-cdk/core": "^1.19.0",
|
|
41
|
+
"jest": "^27.3.1",
|
|
42
|
+
"node-notifier": ">=8.0.1"
|
|
43
|
+
},
|
|
44
|
+
"bin": {
|
|
45
|
+
"cdk4j-diagram": "index.js"
|
|
46
|
+
},
|
|
47
|
+
"pkg": {
|
|
48
|
+
"assets": "graph/ui/index.html"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
},
|
|
53
|
+
"repository": {
|
|
54
|
+
"type": "git",
|
|
55
|
+
"url": "git+https://github.com/ljacobsson/cfn-diagram.git"
|
|
56
|
+
},
|
|
57
|
+
"bugs": {
|
|
58
|
+
"url": "https://github.com/ljacobsson/cfn-diagram/issues"
|
|
59
|
+
},
|
|
60
|
+
"homepage": "https://github.com/ljacobsson/cfn-diagram#readme"
|
|
61
|
+
}
|