@grucloud/core
Version:
GruCloud core, generate infrastructure code
132 lines (125 loc) • 3.15 kB
JavaScript
const assert = require("assert");
const { pipe, map, tap, fork, switchCase } = require("rubico");
const {
callProp,
pluck,
groupBy,
values,
flatten,
isEmpty,
identity,
size,
} = require("rubico/x");
const logger = require("./logger")({ prefix: "GraphTree" });
const { tos } = require("./tos");
// https://plantuml.com/mindmap-diagram
const repeat = ({ depth, symbol = "+" }) =>
new Array(depth).fill(symbol).join("");
const buildPerType = ({ options, type, depth = 4, symbol, resources }) =>
pipe([
() => resources,
fork({
typeLabel: (resources) =>
`${repeat({ depth, symbol })} ${type} (${size(resources)})`,
resourcesLabel: pipe([
pluck("name"),
map((name) => `${repeat({ depth: depth + 1, symbol })} ${name}`),
]),
}),
switchCase([
() => options.full,
({ typeLabel, resourcesLabel }) => [typeLabel, ...resourcesLabel],
({ typeLabel }) => [typeLabel],
]),
tap((xxx) => {
assert(true);
}),
])();
const buildPerGroup = ({ options, group, resources, depth = 3, symbol }) =>
pipe([
tap(() => {
assert(resources);
}),
() => resources,
groupBy("type"),
map.entries(([type, resourcesPerType]) => [
type,
buildPerType({
options,
type,
depth: depth + 1,
symbol,
resources: resourcesPerType,
}),
]),
values,
flatten,
switchCase([
() => isEmpty(group),
identity,
(results) => [`${repeat({ depth, symbol })} ${group}`, ...results],
]),
tap((result) => {
assert(result);
}),
])();
const buildPerProvider =
({ options, depth = 2, symbol, index }) =>
(provider) =>
pipe([
tap(() => {
logger.debug(`${provider.name} ${index}`);
}),
() => provider.getTargetResources(),
groupBy("group"),
tap((resources) => {
assert(resources);
}),
map.entries(([group, resources]) => [
group,
buildPerGroup({
group,
depth: depth + (isEmpty(group) ? 0 : 1),
symbol,
options,
resources,
}),
]),
values,
flatten,
tap((result) => {
assert(result);
}),
callProp("join", "\n"),
tap((result) => {
assert(true);
}),
(result) => `${repeat({ depth, symbol })} ${provider.name}\n${result}`,
])();
const doBuildGraphTree = ({ root = "Infra", providers, options }) =>
pipe([
() => [
`+ ${root}`,
...map.withIndex((provider, index) =>
buildPerProvider({ options, depth: 2, symbol: index % 2 ? "-" : "+" })(
provider
)
)(providers),
],
callProp("join", "\n"),
])();
exports.buildGraphTree = ({ providers, options }) =>
pipe([
tap(() => {
assert(providers);
logger.info(`buildGraphTree ${tos(options)}`);
}),
() => `@startmindmap
title Resources for project ${options.title}
skinparam monochrome true
${doBuildGraphTree({ providers, options })}
@endmindmap`,
tap((result) => {
logger.info(`buildGraphTree done`);
}),
])();