Skip to content

Commit

Permalink
feat: add ejs support
Browse files Browse the repository at this point in the history
  • Loading branch information
ohoareau committed Sep 4, 2024
1 parent 39a029f commit 0f6081c
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 76 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"devDependencies": {
"@eslint/js": "^9.9.0",
"@types/jest": "^29.5.12",
"@types/ejs": "^3.1.5",
"eslint": "^9.9.0",
"globals": "^15.9.0",
"jest": "^29.7.0",
Expand All @@ -49,7 +50,8 @@
"dependencies": {
"@types/node": "^20.16.3",
"typescript": "^5.5.4",
"handlebars": "^4.7.6"
"handlebars": "^4.7.6",
"ejs": "^3.1.10"
},
"bin": {
"tfgen": "./bin/tfgen",
Expand Down
31 changes: 20 additions & 11 deletions src/generators/v1.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import {enriched_layer_config, layer_region_config} from '../types';
import replaceVars from '../utils/replaceVars';
import replace from '../utils/replaceVars';

export default async (
source: string,
{
regions,
defaultRegion,
}: {regions: Record<string, layer_region_config>; defaultRegion: string},
format,
}: {
regions: Record<string, layer_region_config>;
defaultRegion: string;
format: string;
},
vars: Record<string, unknown>,
_: enriched_layer_config,
) => {
Expand All @@ -15,15 +20,19 @@ export default async (
const isMain = (r?.id || rCode) === defaultRegion;
return [
`main${(r?.id || rCode) === defaultRegion ? '' : `_${rCode.replace(/-/g, '_')}`}.tf`,
replaceVars(source, {
...vars,
region: r?.id || rCode,
is_main: isMain,
is_default_region: isMain,
rsuffix: isMain ? '' : `-${rCode}`,
...r,
...(vars?.id ? {id: vars.id} : {}),
}) as unknown as string,
replace(
source,
{
...vars,
region: r?.id || rCode,
is_main: isMain,
is_default_region: isMain,
rsuffix: isMain ? '' : `-${rCode}`,
...r,
...(vars?.id ? {id: vars.id} : {}),
},
{format},
) as unknown as string,
];
},
) as [string, string][];
Expand Down
162 changes: 106 additions & 56 deletions src/generators/v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,51 +6,93 @@ export default async (
{
regions,
defaultRegion,
}: {regions: Record<string, layer_region_config>; defaultRegion: string},
format,
}: {
regions: Record<string, layer_region_config>;
defaultRegion: string;
format: string;
},
vars: Record<string, unknown>,
_: enriched_layer_config,
) => {
const defaultVars = {
region: '',
is_default_outputs: false,
is_outputs_file: false,
is_default_region: false,
is_terraform_file: false,
is_data_file: false,
is_locals_file: false,
is_variables_file: false,
is_providers_file: false,
is_main: false,
is_default_main: false,
is_main_file: false,
is_sub: false,
is_default_sub: false,
is_sub_file: false,
extra_providers: [],
psuffix: '',
rsuffix: '',
};
vars = {...vars, ...defaultVars};
return [
[`terraform.tf`, replace(s, {...vars, is_terraform_file: true})],
[`data.tf`, replace(s, {...vars, is_data_file: true})],
[`locals.tf`, replace(s, {...vars, is_locals_file: true})],
[`variables.tf`, replace(s, {...vars, is_variables_file: true})],
[
`terraform.tf`,
replace(s, {...vars, is_terraform_file: true}, {format}),
],
[`data.tf`, replace(s, {...vars, is_data_file: true}, {format})],
[`locals.tf`, replace(s, {...vars, is_locals_file: true}, {format})],
[
`variables.tf`,
replace(s, {...vars, is_variables_file: true}, {format}),
],
[
`providers.tf`,
replace(s, {
...vars,
extra_providers: Object.entries(regions)
.map(([rCode, r]: [string, layer_region_config]) => {
const region = r?.id || rCode;
const isMain = region === defaultRegion;
return isMain
? undefined
: {type: 'aws', alias: rCode, region};
})
.filter(x => !!x)
.sort((a, b) =>
(a?.alias as string).localeCompare(b?.alias as string),
),
is_providers_file: true,
}) as unknown as string,
replace(
s,
{
...vars,
extra_providers: Object.entries(regions)
.map(([rCode, r]: [string, layer_region_config]) => {
const region = r?.id || rCode;
const isMain = region === defaultRegion;
return isMain
? undefined
: {type: 'aws', alias: rCode, region};
})
.filter(x => !!x)
.sort((a, b) =>
(a?.alias as string).localeCompare(
b?.alias as string,
),
),
is_providers_file: true,
},
{format},
) as unknown as string,
],
// region outputs files
...Object.entries(regions).map(
([rCode, r]: [string, layer_region_config]) => {
const isDefault = (r?.id || rCode) === defaultRegion;
return [
`outputs${isDefault ? '' : `_${rCode.replace(/-/g, '_')}`}.tf`,
replace(s, {
...vars,
region: r?.id || rCode,
is_default_outputs: isDefault,
is_outputs_file: true,
is_default_region: isDefault,
psuffix: isDefault ? '' : `.${rCode}`,
rsuffix: isDefault ? '' : `-${rCode}`,
...r,
...(vars?.id ? {id: vars.id} : {}),
}) as unknown as string,
replace(
s,
{
...vars,
region: r?.id || rCode,
is_default_outputs: isDefault,
is_outputs_file: true,
is_default_region: isDefault,
psuffix: isDefault ? '' : `.${rCode}`,
rsuffix: isDefault ? '' : `-${rCode}`,
...r,
...(vars?.id ? {id: vars.id} : {}),
},
{format},
) as unknown as string,
];
},
),
Expand All @@ -60,18 +102,22 @@ export default async (
const isMain = (r?.id || rCode) === defaultRegion;
return [
`main${(r?.id || rCode) === defaultRegion ? '' : `_${rCode.replace(/-/g, '_')}`}.tf`,
replace(s, {
...vars,
region: r?.id || rCode,
is_main: isMain,
is_default_main: isMain,
is_main_file: true,
is_default_region: isMain,
psuffix: isMain ? '' : `.${rCode}`,
rsuffix: isMain ? '' : `-${rCode}`,
...r,
...(vars?.id ? {id: vars.id} : {}),
}) as unknown as string,
replace(
s,
{
...vars,
region: r?.id || rCode,
is_main: isMain,
is_default_main: isMain,
is_main_file: true,
is_default_region: isMain,
psuffix: isMain ? '' : `.${rCode}`,
rsuffix: isMain ? '' : `-${rCode}`,
...r,
...(vars?.id ? {id: vars.id} : {}),
},
{format},
) as unknown as string,
];
},
),
Expand All @@ -81,18 +127,22 @@ export default async (
const isSub = (r?.id || rCode) === defaultRegion;
return [
`sub${(r?.id || rCode) === defaultRegion ? '' : `_${rCode.replace(/-/g, '_')}`}.tf`,
replace(s, {
...vars,
region: r?.id || rCode,
is_sub: isSub,
is_default_sub: isSub,
is_sub_file: true,
is_default_region: isSub,
psuffix: isSub ? '' : `.${rCode}`,
rsuffix: isSub ? '' : `-${rCode}`,
...r,
...(vars?.id ? {id: vars.id} : {}),
}) as unknown as string,
replace(
s,
{
...vars,
region: r?.id || rCode,
is_sub: isSub,
is_default_sub: isSub,
is_sub_file: true,
is_default_region: isSub,
psuffix: isSub ? '' : `.${rCode}`,
rsuffix: isSub ? '' : `-${rCode}`,
...r,
...(vars?.id ? {id: vars.id} : {}),
},
{format},
) as unknown as string,
];
},
),
Expand Down
7 changes: 6 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ export type layer_config = {
export type generated_file = [string, string];
export type generator = (
source: string,
ctx: {regions: Record<string, layer_region_config>; defaultRegion: string},
ctx: {
regions: Record<string, layer_region_config>;
defaultRegion: string;
format: string;
},
vars: Record<string, unknown>,
layerConfig: enriched_layer_config,
) => Promise<generated_file[]> | generated_file[];
Expand All @@ -33,6 +37,7 @@ export type enriched_layer_config = {
defaultRegion: string;
regions?: Record<string, layer_region_config>;
format?: string;
version?: string;
};

export type loggable = {
Expand Down
4 changes: 2 additions & 2 deletions src/utils/fetchLayers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ export const fetchLayers = async (
sourceDir: string,
): Promise<fetched_layer[]> => {
return readdirSync(sourceDir, {withFileTypes: true})
.filter(e => !e.isDirectory() && /.tmpl.tf$/.test(e.name))
.filter(e => !e.isDirectory() && /\.(tf\.ejs|tmpl\.tf)$/.test(e.name))
.map(e => ({
name: e.name.replace(/\.tmpl\.tf$/, ''),
name: e.name.replace(/(\.tmpl\.tf|\.tf\.ejs)$/, ''),
file: e.name,
filePath: `${sourceDir}/${e.name}`,
}));
Expand Down
9 changes: 6 additions & 3 deletions src/utils/generateEnvLayerFromFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ export const generateEnvLayerFromFile = async (
const defaultRegion = layerConfig.defaultRegion;
const regions: Record<string, layer_region_config> =
layerConfig.regions || {};
const format = layerConfig.format || 'v1';
const generator = (generators as Record<string, generator>)[format];
const format = layerConfig.format || 'handlebars';
const version = layerConfig.version || 'v1';
const generator = (generators as Record<string, generator>)[version];

if (!generator) throw new Error(`Unsupported layer format '${format}'`);
if (!generator)
throw new Error(`Unsupported layer generator version '${version}'`);

const files = await generator(
readFileSync(sourceFile, 'utf8') as string,
Expand All @@ -29,6 +31,7 @@ export const generateEnvLayerFromFile = async (
layer_region_config
>),
defaultRegion,
format,
},
vars,
layerConfig,
Expand Down
21 changes: 19 additions & 2 deletions src/utils/replaceVars.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import Handlebars from 'handlebars';
import ejs from 'ejs';

Handlebars.registerHelper('slugify', s => s.replace(/[^a-z0-9_]+/g, '-'));

export const replaceVars = (a: unknown, b: Record<string, unknown>) => {
const replaceHandlebars = (a: unknown, b: unknown) => Handlebars.compile(a)(b);
const replaceEjs = (a: string, b: Record<string, unknown>) =>
ejs.render(a, b, {debug: false});

const defaultFormat = 'handlebars';
export const replaceVars = (
a: unknown,
b: Record<string, unknown>,
{format = defaultFormat} = {},
) => {
if (Array.isArray(a)) {
a.forEach((v, i) => {
a[i] = replaceVars(v, b);
Expand All @@ -17,7 +28,13 @@ export const replaceVars = (a: unknown, b: Record<string, unknown>) => {
a as Record<string, unknown>,
);
}
return Handlebars.compile(a)(b);
switch (format) {
case 'ejs':
return replaceEjs(a as string, b);
default:
case 'handlebars':
return replaceHandlebars(a, b);
}
};

export default replaceVars;
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1157,6 +1157,11 @@
dependencies:
"@babel/types" "^7.20.7"

"@types/ejs@^3.1.5":
version "3.1.5"
resolved "https://registry.yarnpkg.com/@types/ejs/-/ejs-3.1.5.tgz#49d738257cc73bafe45c13cb8ff240683b4d5117"
integrity sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==

"@types/graceful-fs@^4.1.3":
version "4.1.9"
resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4"
Expand Down

0 comments on commit 0f6081c

Please sign in to comment.