@cdktf/hcl2cdk
Version:
Transform HCL into CDK
668 lines • 114 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateConfigType = exports.buildImports = exports.providerConstructImports = exports.wrapCodeInConstructor = exports.addImportForCodeContainer = exports.gen = exports.moduleImports = exports.providerImports = exports.constructsImport = exports.cdktfImport = exports.provider = exports.imports = exports.modules = exports.local = exports.variable = exports.variableTypeToAst = exports.output = exports.resource = exports.backendToExpression = exports.valueToTs = exports.attributeNameToCdktfName = void 0;
// Copyright (c) HashiCorp, Inc
// SPDX-License-Identifier: MPL-2.0
const generator_1 = __importDefault(require("@babel/generator"));
const template_1 = __importDefault(require("@babel/template"));
const t = __importStar(require("@babel/types"));
const prettier_1 = __importDefault(require("prettier"));
const utils_1 = require("./utils");
const expressions_1 = require("./expressions");
const references_1 = require("./references");
const provider_generator_1 = require("@cdktf/provider-generator");
const terraformSchema_1 = require("./terraformSchema");
const commons_1 = require("@cdktf/commons");
const hcl2json_1 = require("@cdktf/hcl2json");
const dynamic_blocks_1 = require("./dynamic-blocks");
const variables_1 = require("./variables");
const util_1 = require("cdktf/lib/util");
const partialCode_1 = require("./partialCode");
function getReference(graph, id) {
utils_1.logger.debug(`Finding reference for ${id}`);
const neighbors = graph.outNeighbors(id);
if (neighbors.length > 0) {
utils_1.logger.debug(`Found neighbors ${neighbors} for ${id}`);
const edge = graph.directedEdge(id, neighbors[0]);
if (edge) {
utils_1.logger.debug(`Found first edge ${edge} for ${id}`);
utils_1.logger.debug(`Returning reference ${graph.getEdgeAttribute(edge, "ref")}`);
return graph.getEdgeAttribute(edge, "ref");
}
else {
utils_1.logger.debug(`Found no edge for ${id}`);
return undefined;
}
}
else {
return undefined;
}
}
function attributeNameToCdktfName(name) {
return (0, provider_generator_1.escapeAttributeName)((0, utils_1.camelCase)(name));
}
exports.attributeNameToCdktfName = attributeNameToCdktfName;
const valueToTs = async (scope, item, path, isModule = false) => {
switch (typeof item) {
case "string":
if ((await (0, references_1.findUsedReferences)(scope.nodeIds, item)).some((ref) => path.startsWith(ref.referencee.id))) {
return t.stringLiteral(item);
}
return await (0, expressions_1.convertTerraformExpressionToTs)(scope, `"${item}"`, () => (0, terraformSchema_1.getDesiredType)(scope, path));
case "boolean":
return await (0, expressions_1.convertTerraformExpressionToTs)(scope, `${item}`, () => (0, terraformSchema_1.getDesiredType)(scope, path));
case "number":
return await (0, expressions_1.convertTerraformExpressionToTs)(scope, `${item}`, () => (0, terraformSchema_1.getDesiredType)(scope, path));
case "object": {
if (item === undefined || item === null) {
return t.nullLiteral();
}
// For iterators and dynamic blocks we put the correct TS expression in the config ahead of time
if (t.isNode(item) && t.isExpression(item)) {
return item;
}
const attributeType = (0, terraformSchema_1.getTypeAtPath)(scope.providerSchema, path);
function shouldRemoveArrayBasedOnType(attributeType) {
if (!attributeType) {
return false; // The default assumption is we need the array
}
// maps and object don't need to be wrapped in an array
if (Array.isArray(attributeType) &&
(attributeType[0] === "map" || attributeType[0] === "object")) {
return true;
}
// If it's a block type with max_items = 1 we don't need to wrap it in an array
if (typeof attributeType === "object" &&
"max_items" in attributeType &&
attributeType.max_items === 1) {
return true;
}
return false;
}
const unwrappedItem = Array.isArray(item) &&
(shouldRemoveArrayBasedOnType(attributeType) ||
path.endsWith("lifecycle") ||
path.endsWith("connection"))
? item[0]
: item;
if (Array.isArray(unwrappedItem)) {
return t.arrayExpression(await Promise.all(unwrappedItem.map((i) => (0, exports.valueToTs)(scope, i, `${path}.[]`))));
}
return t.objectExpression((await Promise.all(Object.entries(unwrappedItem).map(async ([key, value]) => {
if (value === undefined) {
return undefined;
}
if (key === "dynamic") {
const { for_each, ...others } = value;
const dynamicRef = Object.keys(others)[0];
return t.objectProperty(t.identifier(scope.withinOverrideExpression
? dynamicRef
: (0, provider_generator_1.escapeAttributeName)((0, utils_1.camelCase)(dynamicRef))), t.arrayExpression());
}
const itemPath = `${path}.${key}`;
const itemAttributeType = (0, terraformSchema_1.getTypeAtPath)(scope.providerSchema, itemPath);
const typeMetadata = (0, terraformSchema_1.getTypeAtPath)(scope.providerSchema, itemPath);
const isSingleItemBlock = typeMetadata &&
typeof typeMetadata === "object" &&
Object.prototype.hasOwnProperty.call(typeMetadata, "max_items")
? typeMetadata.max_items === 1
: false;
const shouldBeArray = typeof value === "object" &&
!Array.isArray(value) &&
!(t.isNode(value) && t.isExpression(value)) &&
!isSingleItemBlock &&
// Map type attributes must not be wrapped in arrays
!(0, terraformSchema_1.isMapAttribute)(itemAttributeType) &&
key !== "tags" &&
key !== "forEach" &&
key !== "lifecycle";
const keepKeyName = !isModule &&
key !== "depends_on" &&
!path.includes("lifecycle") &&
(key === "for_each" ||
!typeMetadata ||
(0, terraformSchema_1.isMapAttribute)(attributeType)) &&
!(path.startsWith("var.") && path.includes("validation"));
return t.objectProperty(t.stringLiteral(keepKeyName ? key : attributeNameToCdktfName(key)), shouldBeArray
? t.arrayExpression([await (0, exports.valueToTs)(scope, value, itemPath)])
: await (0, exports.valueToTs)(scope, value, itemPath));
}))).filter((expr) => expr !== undefined));
}
}
throw new Error("Unsupported type " + item);
};
exports.valueToTs = valueToTs;
async function backendToExpression(scope, tf) {
return (await Promise.all(Object.entries(tf || {}).map(async ([type, [config]]) => {
const backendIdentifier = (0, utils_1.pascalCase)(`${type}Backend`);
scope.importables.push({
constructName: backendIdentifier,
provider: "cdktf",
});
return t.expressionStatement(t.newExpression(t.identifier(backendIdentifier), [
t.thisExpression(),
t.objectExpression((await Promise.all(Object.entries(config).map(async ([property, value]) => t.objectProperty(t.identifier((0, utils_1.camelCase)(property)), await (0, exports.valueToTs)(scope, value, "path-for-backends-can-be-ignored"))))).reduce((carry, item) => [...carry, item], [])),
]));
}))).reduce((carry, item) => [...carry, item], []);
}
exports.backendToExpression = backendToExpression;
function addOverrideExpression(variable, path, value, explanatoryComment) {
const ast = t.expressionStatement(t.callExpression(t.memberExpression(t.identifier(variable), t.identifier("addOverride")), [t.stringLiteral(path), value]));
if (explanatoryComment) {
t.addComment(ast, "leading", explanatoryComment);
}
return ast;
}
function addOverrideLogicalIdExpression(variable, logicalId) {
const ast = t.expressionStatement(t.callExpression(t.memberExpression(t.identifier(variable), t.identifier("overrideLogicalId")), [t.stringLiteral(logicalId)]));
t.addComment(ast, "leading", "This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.");
return ast;
}
function getRemoteStateType(item) {
const backendRecord = item.find((val) => val.backend);
if (backendRecord) {
const backend = backendRecord.backend;
switch (backend) {
case "remote":
return "";
case "etcdv3":
return "_etcd_v3";
default:
return `_${backend}`;
}
}
else {
return "";
}
}
function resourceType(provider, name, item) {
switch (provider) {
case "data.terraform":
return `cdktf.data_terraform_${name.join("_")}${getRemoteStateType(item)}`;
case "null":
return `NullProvider.${name.join("_")}`;
default:
return `${provider}.${name.join("_")}`;
}
}
function mapConfigPerResourceType(resource, item) {
// Backends have a slightly different API
if (resource.startsWith("cdktf.data_terraform_")) {
return item.config;
}
return item;
}
const loopComment = `In most cases loops should be handled in the programming language context and
not inside of the Terraform context. If you are looping over something external, e.g. a variable or a file input
you should consider using a for loop. If you are looping over something only known to Terraform, e.g. a result of a data source
you need to keep this like it is.`;
async function resource(scope, type, key, id, item, graph) {
const [provider, ...name] = type.split("_");
const resource = resourceType(provider, name, item);
if (!provider) {
throw new Error(`Could not parse resource type '${type}'`);
}
let expressions = [];
const varName = (0, variables_1.variableName)(scope, resource, key);
const { for_each, count, provisioner, ...config } = item[0];
const mappedConfig = mapConfigPerResourceType(resource, config);
let forEachIteratorName;
if (for_each) {
forEachIteratorName = (0, variables_1.variableName)(scope, resource, `${key}_for_each_iterator`);
const referenceAst = await (0, expressions_1.convertTerraformExpressionToTs)(scope, `"${for_each}"`, () => ["list", "dynamic"]);
scope.importables.push({
provider: "cdktf",
constructName: "TerraformIterator",
});
const iterator = t.variableDeclaration("const", [
t.variableDeclarator(t.identifier(forEachIteratorName), t.callExpression(t.memberExpression(t.identifier("TerraformIterator"), t.identifier("fromList")), [referenceAst])),
]);
t.addComment(iterator, "leading", loopComment);
expressions.push(iterator);
mappedConfig.forEach = t.identifier(forEachIteratorName);
}
let countIteratorName;
if (count) {
countIteratorName = (0, variables_1.variableName)(scope, resource, `${key}_count`);
const referenceAst = await (0, expressions_1.convertTerraformExpressionToTs)(scope, `"${count}"`, () => "number");
scope.importables.push({
provider: "cdktf",
constructName: "TerraformCount",
});
const iterator = t.variableDeclaration("const", [
t.variableDeclarator(t.identifier(countIteratorName), t.callExpression(t.memberExpression(t.identifier("TerraformCount"), t.identifier("of")), [referenceAst])),
]);
t.addComment(iterator, "leading", loopComment);
mappedConfig.count = t.identifier(countIteratorName);
expressions.push(iterator);
}
const dynBlocks = (0, dynamic_blocks_1.extractDynamicBlocks)(mappedConfig);
const nestedDynamicBlocks = dynBlocks.filter((block) => (0, dynamic_blocks_1.isNestedDynamicBlock)(dynBlocks, block));
const dynamicBlocksUsingOverrides = dynBlocks.filter((block) =>
// nested blocks need overrides
nestedDynamicBlocks.includes(block) ||
// blocks that contain nested blocks need them as well
nestedDynamicBlocks.some((nestedBlock) => nestedBlock.path.startsWith(block.path)));
// all others can be handled by the CDKTF runtime
const dynamicBlocksUsingRuntime = dynBlocks.filter((block) => !dynamicBlocksUsingOverrides.includes(block));
for (const [i, block] of dynamicBlocksUsingRuntime.entries()) {
const dynamicBlockIteratorName = (0, variables_1.variableName)(scope, resource, `${key}_dynamic_iterator_${i}`);
const referenceAst = await (0, expressions_1.convertTerraformExpressionToTs)(scope, `"${block.for_each}"`, () => ["list", "dynamic"]);
scope.importables.push({
provider: "cdktf",
constructName: "TerraformIterator",
});
const iterator = t.variableDeclaration("const", [
t.variableDeclarator(t.identifier(dynamicBlockIteratorName), t.callExpression(t.memberExpression(t.identifier("TerraformIterator"), t.identifier("fromList")), [referenceAst])),
]);
t.addComment(iterator, "leading", loopComment);
expressions.push(iterator);
const dynamicCallExpression = t.callExpression(t.memberExpression(t.identifier(dynamicBlockIteratorName), t.identifier("dynamic")), [
await (0, exports.valueToTs)({
...scope,
scopedVariables: {
[block.scopedVar]: dynamicBlockIteratorName,
},
}, (0, partialCode_1.fillWithConfigAccessors)(scope, Array.isArray(block.content) ? block.content[0] : block.content, block.path.replace(block.scopedVar, "")), block.path.replace(block.scopedVar, ""), false),
]);
const parts = block.path
.replace(`dynamic.${block.scopedVar}`, "")
.split(".")
.filter((p) => p.length > 0);
const parent = parts.reduce((acc, part) => {
if (Array.isArray(acc) && !Number.isNaN(parseInt(part, 10))) {
return acc[parseInt(part, 10)];
}
else {
return acc[part];
}
}, mappedConfig);
parent[block.scopedVar] = dynamicCallExpression;
delete parent.dynamic;
}
const overrideReference = dynamicBlocksUsingOverrides.length
? {
start: 0,
end: 0,
referencee: {
id: `${type}.${key}`,
full: `${type}.${key}`,
},
}
: undefined;
if (provisioner) {
mappedConfig.provisioners = await Promise.all(Object.entries(provisioner).flatMap(([type, p]) => p.map((pp) => (0, exports.valueToTs)(scope, { type, ...pp }, "path-for-provisioners-can-be-ignored"))));
}
const importGraphId = `import.${resource.replace(".", "_")}.${key}`;
const importDefinition = graph.hasNode(importGraphId)
? graph.getNodeAttribute(importGraphId, "value")
: undefined;
expressions = expressions.concat(await asExpression({ ...scope, forEachIteratorName, countIteratorName }, resource, key, mappedConfig, false, false, getReference(graph, id) || overrideReference, importDefinition));
// Check for dynamic blocks
expressions = expressions.concat(await Promise.all(dynamicBlocksUsingOverrides.map(async ({ path, for_each, content }) => {
// We need to let the expression conversion know all available
// dynamic block names, so we don't replace them. The "dynamic-block"
// scoped variable indicates to the expression conversion to use the
// key name instead of an iterator
const scopedVariablesInPath = Object.fromEntries(path
.substring(1) // The path starts with a dot that results in an empty split
.split(".")
.filter((p) => !["dynamic", "content"].includes(p) && isNaN(parseInt(p)))
.map((p) => [p, "dynamic-block"]));
return addOverrideExpression(varName, path.substring(1), // The path starts with a dot that we don't want
await (0, exports.valueToTs)({
...scope,
withinOverrideExpression: true,
scopedVariables: scopedVariablesInPath,
}, {
for_each,
content,
}, "path-for-dynamic-blocks-can-be-ignored"), loopComment);
})));
return expressions;
}
exports.resource = resource;
async function asExpression(scope, type, name, config, isModuleImport, isProvider, reference, imported) {
const { providers, ...otherOptions } = config;
const constructId = (0, utils_1.uniqueId)(scope.constructs, name);
const overrideId = !isProvider && constructId !== name;
const completeObject = (0, partialCode_1.fillWithConfigAccessors)(scope, otherOptions, type);
const expression = t.newExpression((0, variables_1.constructAst)(scope, type, isModuleImport), [
t.thisExpression(),
t.stringLiteral(constructId),
await (0, exports.valueToTs)(scope, {
...completeObject,
providers: providers && Object.keys(providers).length
? Object.entries(providers).map(([key, value]) => ({
moduleAlias: key,
provider: value,
}))
: undefined,
}, `${type}`, isModuleImport),
]);
const statements = [];
const varName = reference
? (0, variables_1.referenceToVariableName)(scope, reference)
: (0, variables_1.variableName)(scope, type, name);
if (reference || overrideId || imported) {
statements.push(t.variableDeclaration("const", [
t.variableDeclarator(t.identifier(varName), expression),
]));
}
else {
statements.push(t.expressionStatement(expression));
}
if (overrideId) {
statements.push(addOverrideLogicalIdExpression(varName, name));
}
if (imported) {
// Adds myVar.importFrom("my-arn")
const importExpression = t.expressionStatement(t.callExpression(t.memberExpression(t.identifier(varName), t.identifier("importFrom")), [t.stringLiteral(imported.id)]));
if (imported.provider) {
t.addComment(importExpression, "leading", `This import was configured with a provider. CDKTF does support this, but the cdktf convert command does not yet. Please add the provider reference manually. See https://developer.hashicorp.com/terraform/cdktf/concepts/resources#importing-resources for more information.`);
}
statements.push(importExpression);
}
return statements;
}
async function output(scope, key, _id, item, _graph) {
const [{ value, description, sensitive }] = item;
return asExpression(scope, "cdktf.TerraformOutput", key, {
value,
description,
sensitive,
}, false, false, undefined, undefined);
}
exports.output = output;
async function variableTypeToAst(scope, type) {
const addVariableTypeToImports = () => scope.importables.push({
constructName: "VariableType",
provider: "cdktf",
});
function parsedTypeToAst(type) {
if (hcl2json_1.TFExpressionSyntaxTree.isScopeTraversalExpression(type)) {
addVariableTypeToImports();
switch (type.meta.value) {
case "string":
return t.identifier("VariableType.STRING");
case "number":
return t.identifier("VariableType.NUMBER");
case "bool":
return t.identifier("VariableType.BOOL");
case "any":
default:
return t.identifier("VariableType.ANY");
}
}
if (hcl2json_1.TFExpressionSyntaxTree.isFunctionCallExpression(type)) {
addVariableTypeToImports();
switch (type.meta.name) {
case "list":
case "set":
case "map":
case "tuple":
case "object":
return t.callExpression(t.identifier(`VariableType.${type.meta.name}`), type.children.map((child) => parsedTypeToAst(child)));
}
}
if (hcl2json_1.TFExpressionSyntaxTree.isObjectExpression(type)) {
return t.objectExpression(Object.entries(type.meta.items).map(([key, value]) => t.objectProperty(t.stringLiteral(key),
// This does not deal with complex types nested within objects
// If such a type is found it will result in an Any type
// e.g. { foo: list(string) } will result in { foo: any }
parsedTypeToAst({
type: "scopeTraversal",
meta: { value },
}))));
}
addVariableTypeToImports();
return t.identifier("VariableType.ANY");
}
return parsedTypeToAst(await (0, expressions_1.expressionAst)(type));
}
exports.variableTypeToAst = variableTypeToAst;
async function variable(scope, key, id, item, graph) {
const [{ type, ...props }] = item;
if (!getReference(graph, id)) {
return [];
}
return asExpression(scope, id, key, { ...props, type: type ? await variableTypeToAst(scope, type) : undefined }, false, false, getReference(graph, id), undefined);
}
exports.variable = variable;
async function local(scope, key, id, item, graph) {
utils_1.logger.debug(`Initializing local resource ${key} with id ${id}`);
if (!getReference(graph, id)) {
utils_1.logger.debug(`No reference found for ${key}`);
return [];
}
return [
t.variableDeclaration("const", [
t.variableDeclarator(t.identifier((0, variables_1.variableName)(scope, "local", key)), await (0, exports.valueToTs)(scope, item, "path-for-local-blocks-can-be-ignored")),
]),
];
}
exports.local = local;
async function modules(scope, key, id, item, graph) {
const [{ source, version, ...props }] = item;
const moduleConstraint = new provider_generator_1.TerraformModuleConstraint(source);
return asExpression(scope, moduleConstraint.className, key, props, true, false, getReference(graph, id), undefined);
}
exports.modules = modules;
async function imports(scope, _id, item, graph) {
// Move from ${aws_instance.example} to aws_instance.example
const target = item.to.startsWith("${") && item.to.endsWith("}")
? item.to.substring(2, item.to.length - 1)
: item.to;
// Check if the import goes into a module
if (target.startsWith("module.")) {
return [
t.addComment(t.emptyStatement(), "leading", `CDKTF does not support imports into modules yet, please remove the import block importing ${item.id} into ${target} from your configuration`),
];
}
// We now know that the import goes into a resource, e.g. aws_instance.example
const [resourceTypeIdentifier, resourceName] = target.split(".");
if (resourceName.includes("[")) {
return [
t.addComment(t.emptyStatement(), "leading", `CDKTF does not support imports into resources with count or for_each yet, please remove the import block importing ${item.id} into ${target} from your configuration`),
];
}
// Check if we have a existing resource config with the given name
if (graph.hasNode(target)) {
// We will handle this case in the resource function
// so we can skip over it
return [];
}
const [provider, ...resourceTypeNameParts] = resourceTypeIdentifier.split("_");
const constructId = (0, utils_1.uniqueId)(scope.constructs, (0, utils_1.camelCase)(resourceName));
const constructClass = (0, variables_1.constructAst)(scope, `${provider}.${resourceTypeNameParts.join("_")}`, false);
return [
t.expressionStatement(t.callExpression(t.memberExpression(constructClass, t.identifier("generateConfigForImport")), [
t.thisExpression(),
t.stringLiteral(constructId),
t.stringLiteral(item.id),
])),
];
}
exports.imports = imports;
async function provider(scope, key, id, item, graph) {
const { version, ...props } = item;
const importKey = key === "null" ? "NullProvider" : key;
return asExpression(scope, `${importKey}.${(0, utils_1.pascalCase)(key)}Provider`, key, props, false, true, getReference(graph, id), undefined);
}
exports.provider = provider;
exports.cdktfImport = (0, template_1.default)(`import * as cdktf from "cdktf"`)();
exports.constructsImport = (0, template_1.default)(`import * as constructs from "constructs"`)();
const providerImports = (providers) => providers.map((providerName) => {
const parts = providerName.split("/");
const name = parts.length > 1 ? parts[1] : parts[0];
const importName = name === "null" ? "NullProvider" : name;
return (0, template_1.default)(`import * as ${importName} from "./.gen/providers/${name.replace("./", "")}"`)();
});
exports.providerImports = providerImports;
const moduleImports = (modules) => {
const uniqueModules = new Set();
Object.values(modules || {}).map(([module]) => uniqueModules.add(module.source));
const imports = [];
uniqueModules.forEach((m) => {
const moduleConstraint = new provider_generator_1.TerraformModuleConstraint(m);
imports.push(template_1.default.ast(`import * as ${moduleConstraint.className} from "./.gen/modules/${moduleConstraint.fileName}"`));
});
return imports;
};
exports.moduleImports = moduleImports;
async function gen(statements) {
utils_1.logger.debug(`Generating code for ${JSON.stringify(statements, null, 2)}`);
const code = prettier_1.default.format((0, generator_1.default)(t.program(statements)).code, {
parser: "babel",
});
utils_1.logger.debug(`Generated code:\n${code}`);
return code;
}
exports.gen = gen;
function addImportForCodeContainer(scope, codeContainer) {
switch (codeContainer) {
case "constructs.Construct":
scope.importables.push({
provider: "constructs",
constructName: "Construct",
});
break;
case "cdktf.TerraformStack":
scope.importables.push({
provider: "cdktf",
constructName: "TerraformStack",
});
break;
default:
throw commons_1.Errors.Internal("Unsupported code container: " + codeContainer);
}
}
exports.addImportForCodeContainer = addImportForCodeContainer;
function wrapCodeInConstructor(codeContainer, code, className, configTypeName) {
let baseContainerClass;
switch (codeContainer) {
case "constructs.Construct":
baseContainerClass = t.identifier("Construct");
break;
case "cdktf.TerraformStack":
baseContainerClass = t.identifier("TerraformStack");
break;
default:
throw commons_1.Errors.Internal("Unsupported code container: " + codeContainer);
}
if (configTypeName) {
return template_1.default.statement(`
class %%className%% extends %%base%% {
constructor(scope: Construct, name: string, config: ${configTypeName}) {
super(scope, name);
%%code%%
}
}
`, { syntacticPlaceholders: true, plugins: ["typescript"] })({
code,
base: baseContainerClass,
className: t.identifier(className),
});
}
return template_1.default.statement(`
class %%className%% extends %%base%% {
constructor(scope: Construct, name: string) {
super(scope, name);
%%code%%
}
}
`, { syntacticPlaceholders: true, plugins: ["typescript"] })({
code,
base: baseContainerClass,
className: t.identifier(className),
});
}
exports.wrapCodeInConstructor = wrapCodeInConstructor;
const providerConstructImports = (importable) => {
let provider = importable[0].provider;
let namespace = importable[0].namespace;
const names = importable.map((i) => i.constructName);
if (provider === "cdktf" || provider === "constructs") {
return (0, template_1.default)(`import { ${names.join(", ")} } from "${provider}"`)();
}
if (namespace) {
namespace = (0, util_1.snakeCase)(namespace).replace(/_/g, "-");
}
// Special cases to undo provider names that we override
if (provider === "NullProvider") {
provider = "null";
}
return (0, template_1.default)(`import { ${names.join(", ")} } from "./.gen/providers/${provider}/${namespace}"`)();
};
exports.providerConstructImports = providerConstructImports;
function buildImports(importables) {
const groupedImportables = importables.reduce((acc, importable) => {
const ns = importable.namespace || "";
// Doing some hacky ordering of the imports to make them look a bit nicer
const prefix = importable.provider === "constructs"
? "1"
: importable.provider === "cdktf"
? "2"
: "3";
const groupName = `${prefix}.${importable.provider}.${ns}`;
const fullName = `${importable.provider}.${ns}.${importable.constructName}`;
if (acc[groupName]) {
const existsAlready = acc[groupName].some((importable) => `${importable.provider}.${ns}.${importable.constructName}` ===
fullName);
if (existsAlready) {
return acc;
}
acc[groupName].push(importable);
acc[groupName].sort();
}
else {
acc[groupName] = [importable];
}
return acc;
}, {});
let commentAdded = false;
const constructImports = Object.keys(groupedImportables)
.sort()
.map((groupName) => {
const importStatement = (0, exports.providerConstructImports)(groupedImportables[groupName]);
if (groupName.startsWith("3.") && !commentAdded) {
commentAdded = true;
t.addComment(importStatement, "leading", `\n* Provider bindings are generated by running \`cdktf get\`.
* See https://cdk.tf/provider-generation for more details.\n`);
}
return importStatement;
});
return constructImports;
}
exports.buildImports = buildImports;
function generateConfigType(name, config) {
return t.tsInterfaceDeclaration(t.identifier(name), undefined, undefined, t.tsInterfaceBody(Object.entries(config).map(([key, _value]) => t.tsPropertySignature(t.identifier(key), t.tSTypeAnnotation(t.tsAnyKeyword())))));
}
exports.generateConfigType = generateConfigType;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImdlbmVyYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwrQkFBK0I7QUFDL0IsbUNBQW1DO0FBQ25DLGlFQUF3QztBQUN4QywrREFBdUM7QUFDdkMsZ0RBQWtDO0FBRWxDLHdEQUFnQztBQVNoQyxtQ0FBa0U7QUFVbEUsK0NBQThFO0FBRTlFLDZDQUFrRDtBQUNsRCxrRUFHbUM7QUFDbkMsdURBSTJCO0FBQzNCLDRDQUEwRTtBQUMxRSw4Q0FBZ0U7QUFDaEUscURBQThFO0FBQzlFLDJDQUlxQjtBQUNyQix5Q0FBMkM7QUFDM0MsK0NBQXdEO0FBRXhELFNBQVMsWUFBWSxDQUFDLEtBQW9CLEVBQUUsRUFBVTtJQUNwRCxjQUFNLENBQUMsS0FBSyxDQUFDLHlCQUF5QixFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzVDLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLENBQUM7SUFFekMsSUFBSSxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3pCLGNBQU0sQ0FBQyxLQUFLLENBQUMsbUJBQW1CLFNBQVMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZELE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxZQUFZLENBQUMsRUFBRSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRWxELElBQUksSUFBSSxFQUFFLENBQUM7WUFDVCxjQUFNLENBQUMsS0FBSyxDQUFDLG9CQUFvQixJQUFJLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUNuRCxjQUFNLENBQUMsS0FBSyxDQUNWLHVCQUF1QixLQUFLLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQzdELENBQUM7WUFDRixPQUFPLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxJ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