Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mermaid support #139

Merged
merged 3 commits into from
Jun 30, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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
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 : " "}\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
@@ -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
@@ -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