Skip to content

Commit

Permalink
Mermaid support (#139)
Browse files Browse the repository at this point in the history
* mermaid support wip

* feat: adding support for mermaid output

* feat: adding support for mermaid output

Co-authored-by: ljacobsson <lars@mathem.se>
  • Loading branch information
ljacobsson and ljacobsson committed Jun 30, 2022
1 parent 68d047d commit 523fefb
Show file tree
Hide file tree
Showing 7 changed files with 1,527 additions and 12 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,25 @@ Renders a simple Ascii-art diagram of your template directly in the console. Use
Video demo of using the `--watch` option:
[![Demo of watch command](https://img.youtube.com/vi/2V3zimGWTcU/0.jpg)](https://www.youtube.com/watch?v=2V3zimGWTcU)

### Mermaid
```
Usage: cfn-dia mermaid|m [options]
Generates a mermaid graph from a template
Options:
-t, --template-file [templateFile] Path to template or cdk.json file (default: "template.yaml or cdk.json")
-all --render-all If set, all nested stacks will be rendered. By default only root template is rendered (default: false)
-o, --output-path [outputPath] Name of output file
-co, --cdk-output [cdkOutputPath] CDK synth output path (default: "cdk.out")
-s, --skip-synth Skips CDK synth (default: false)
-h, --help display help for command
```

Renders a [mermaid](https://mermaid-js.github.io/mermaid/#/) diagram of your template directly in the console or to a file. Useful to gain a quick overview of smaller stacks and to generate as part of your CI/CD flow for up-to-date documentation.

![Demo](https://raw.githubusercontent.com/mhlabs/cfn-diagram/master/images/demo-mermaid.gif)


### CI-mode
This functionality lives in its own CLI, [cfn-diagram-ci](https://github.com/mhlabs/cfn-diagram-ci). This is beacuse it requires headless Chromium to be installed which makes the package size very large
Expand Down
100 changes: 100 additions & 0 deletions commands/mermaid/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
const Vis = require("../../graph/Vis");
const program = require("commander");
const template = require("../../shared/templateParser");
const fs = require("fs");
program
.command("mermaid")
.alias("m")
.option(
"-t, --template-file [templateFile]",
"Path to template or cdk.json file",
"template.yaml or cdk.json"
)
.option("-all --render-all", "If set, all nested stacks will be rendered. By default only root template is rendered", false)
.option(
"-o, --output-path [outputPath]",
"Name of output file"
)
.option("-co, --cdk-output [cdkOutputPath]", "CDK synth output path", `cdk.out`)
.option("-s, --skip-synth", "Skips CDK synth", false)
.description("Generates a mermaid graph from a template")
.action(async (cmd) => {
ciMode = cmd.ciMode;
const templateObj = template.get(cmd);
const graph = await Vis.makeGraph(
templateObj.template,
"root",
false,
cmd.renderAll
);

const groups = {};
for (const edge of graph.edges) {
const owner = edge.from.split(".")[0];

if (edge.to.startsWith(`${owner}.`) && edge.from.startsWith(`${owner}.`)) {
if (!groups[owner]) {
groups[owner] = [];
}
groups[owner].push(edge);
} else {
if (!groups["crossgroup"]) {
groups["crossgroup"] = [];
}
groups["crossgroup"].push(edge);
}
}
const uniqueRelations = [];
let mermaidString = `\`\`\`mermaid\n\tflowchart TB;\n`;
for (const groupKey in groups) {
const group = groups[groupKey];
if (groupKey !== "crossgroup") {
mermaidString += `\t\tsubgraph ${groupKey !== "root" ? groupKey : "&nbsp;"}\n`;
}

mermaidString += `${group.map(p => {
const fromResource = graph.nodes.find(n => n.id === p.from);
const toResource = graph.nodes.find(n => n.id === p.to);
const from = createShape(fromResource);
const to = createShape(toResource);
const relation = `\t\t${from}-->${to}`;
if (!uniqueRelations.includes(relation)) {
uniqueRelations.push(relation);
return relation;
}
}).filter(p => p).join("\n")}
`
if (groupKey !== "crossgroup") {
mermaidString += `\tend\n`;
}

}

mermaidString += `\n\`\`\``;
if (cmd.outputPath) {
fs.writeFileSync(cmd.outputPath, mermaidString);
console.log(`Wrote Mermaid diagram to ${cmd.outputPath}`);
} else {
console.log(mermaidString)
}
});

function createShape(resource, cmd) {
const label = resource.label.replace(/[^a-z0-9\n]/gmi, "").replace(/\s+/g, "");
const id = resource.id.replace(/[^a-z0-9\n]/gmi, "").replace(/\s+/g, "");;
const type = resource.type.replace("AWS::", "");
switch (resource.type) {
case "AWS::Serverless::Function":
case "AWS::Lambda::Function":
return `${id}[[${label}<br/>${type}]]`;
case "AWS::Serverless::SimpleTable":
case "AWS::DynamoDB::Table":
case "AWS::RDS::DBInstance":
case "AWS::RDS::DBCluster":
return `${id}[(${label}<br/>${type})]`;
}
return `${id}[${label}<br/>${type}]`;

}
1 change: 1 addition & 0 deletions graph/Vis.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,5 @@ async function renderTemplate(
module.exports = {
renderTemplate,
reset,
makeGraph
};
Binary file added images/demo-mermaid.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ require("./commands/draw.io");
require("./commands/html");
require("./commands/asciiart");
require("./commands/browse");
const package = require("./package.json");
program.version(package.version, "-v, --vers", "output the current version");
require("./commands/mermaid");
const packag = require("./package.json");
program.version(packag.version, "-v, --vers", "output the current version");
program.parse(process.argv);
Loading

0 comments on commit 523fefb

Please sign in to comment.