diff --git a/src/generators/index.ts b/src/generators/index.ts new file mode 100644 index 0000000..5728a3b --- /dev/null +++ b/src/generators/index.ts @@ -0,0 +1,2 @@ +export {default as v1} from './v1'; +export {default as v2} from './v2'; diff --git a/src/generators/v1.ts b/src/generators/v1.ts new file mode 100644 index 0000000..e2c3eeb --- /dev/null +++ b/src/generators/v1.ts @@ -0,0 +1,30 @@ +import {enriched_layer_config, layer_region_config} from '../types'; +import replaceVars from '../utils/replaceVars'; + +export default async ( + source: string, + { + regions, + defaultRegion, + }: {regions: Record; defaultRegion: string}, + vars: Record, + _: enriched_layer_config, +) => { + return Object.entries(regions).map( + ([rCode, r]: [string, layer_region_config]) => { + 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, + ]; + }, + ) as [string, string][]; +}; diff --git a/src/generators/v2.ts b/src/generators/v2.ts new file mode 100644 index 0000000..532fb2a --- /dev/null +++ b/src/generators/v2.ts @@ -0,0 +1,66 @@ +import {enriched_layer_config, layer_region_config} from '../types'; +import replaceVars from '../utils/replaceVars'; + +export default async ( + source: string, + { + regions, + defaultRegion, + }: {regions: Record; defaultRegion: string}, + vars: Record, + _: enriched_layer_config, +) => { + return [ + // terraform file + [ + `terraform.tf`, + replaceVars(source, { + ...vars, + is_terraform_file: true, + }) as unknown as string, + ], + // providers file + [ + `providers.tf`, + replaceVars(source, { + ...vars, + is_providers_file: true, + }) as unknown as string, + ], + // data file + [ + `data.tf`, + replaceVars(source, { + ...vars, + is_data_file: true, + }) as unknown as string, + ], + // outputs file + [ + `outputs.tf`, + replaceVars(source, { + ...vars, + is_outputs_file: true, + }) as unknown as string, + ], + // region files + ...Object.entries(regions).map( + ([rCode, r]: [string, layer_region_config]) => { + 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_main_file: true, + is_default_region: isMain, + rsuffix: isMain ? '' : `-${rCode}`, + ...r, + ...(vars?.id ? {id: vars.id} : {}), + }) as unknown as string, + ]; + }, + ), + ] as [string, string][]; +}; diff --git a/src/types.ts b/src/types.ts index bfa8069..9602338 100644 --- a/src/types.ts +++ b/src/types.ts @@ -18,6 +18,13 @@ export type layer_config = { envs?: Record; }; +export type generated_file = [string, string]; +export type generator = ( + source: string, + ctx: {regions: Record; defaultRegion: string}, + vars: Record, + layerConfig: enriched_layer_config, +) => Promise | generated_file[]; export type layer_region_config = { id?: string; [key: string]: unknown; @@ -25,6 +32,7 @@ export type layer_region_config = { export type enriched_layer_config = { defaultRegion: string; regions?: Record; + format?: string; }; export type loggable = { diff --git a/src/utils/generateEnvLayerFromFile.ts b/src/utils/generateEnvLayerFromFile.ts index 5e9d4a0..2e146ff 100644 --- a/src/utils/generateEnvLayerFromFile.ts +++ b/src/utils/generateEnvLayerFromFile.ts @@ -1,6 +1,6 @@ import {existsSync, mkdirSync, readFileSync, writeFileSync} from 'fs'; -import replaceVars from './replaceVars'; -import {enriched_layer_config, layer_region_config} from '../types'; +import {enriched_layer_config, generator, layer_region_config} from '../types'; +import * as generators from '../generators'; export const generateEnvLayerFromFile = async ( sourceFile: string, @@ -13,52 +13,30 @@ export const generateEnvLayerFromFile = async ( const defaultRegion = layerConfig.defaultRegion; const regions: Record = layerConfig.regions || {}; + const format = layerConfig.format || 'v1'; + const generator = (generators as Record)[format]; - const mappedRegions = Object.entries( - regions && Object.keys(regions).length - ? regions - : ({[defaultRegion]: {}} as Record), - ).map( - ([rCode, r]: [string, layer_region_config]) => - [ - r, - `${targetDir}/main${(r?.id || rCode) === defaultRegion ? '' : `_${rCode.replace(/-/g, '_')}`}.tf`, - rCode, - ] as [layer_region_config, string, string], - ); + if (!generator) throw new Error(`Unsupported layer format '${format}'`); - const reports = await Promise.allSettled( - mappedRegions.map( - async ([r, targetFile, rCode]: [ - layer_region_config, - string, - string, - ]) => { - const isMain = (r?.id || rCode) === defaultRegion; - writeFileSync( - targetFile, - replaceVars(readFileSync(sourceFile, 'utf8') as string, { - ...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, - ); - }, - ), + const files = await generator( + readFileSync(sourceFile, 'utf8') as string, + { + regions: + regions && Object.keys(regions).length + ? regions + : ({[defaultRegion]: {}} as Record< + string, + layer_region_config + >), + defaultRegion, + }, + vars, + layerConfig, ); - const errors: {reason: Error}[] = reports.filter( - x => x.status !== 'fulfilled', - ) as unknown as {reason: Error}[]; - - if (errors.length) - throw new Error( - `Unable to generate all env layer files for ${sourceFile}: ${errors.map((x: {reason: Error}) => x.reason.message).join('\n')}`, - ); + (files || []).map(([file, content]) => + writeFileSync(`${targetDir}/${file}`, content), + ); }; export default generateEnvLayerFromFile;