Skip to content

Commit

Permalink
TerraformElement, make list & map argument
Browse files Browse the repository at this point in the history
  • Loading branch information
Chang Zhe Jiet authored and Chang Zhe Jiet committed Nov 25, 2023
1 parent f063935 commit 8a6e9ee
Show file tree
Hide file tree
Showing 56 changed files with 9,661 additions and 1,363 deletions.
27 changes: 14 additions & 13 deletions src/TerraformGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import fs from 'fs';
import path from 'path';
import shell from 'shelljs';
import { Block, Comment, Resource, Data, Module, Output, Provider, Variable, Backend, Provisioner, ResourceToDataOptions, Locals, Import, ImportArgs, VariableArgs, ModuleArgs, OutputArgs } from './blocks';
import { BlockArgs, Util } from './utils';
import { TerraformArgs, Util } from './utils';

/**
* @category TerraformGenerator
Expand Down Expand Up @@ -42,9 +42,9 @@ export interface WriteOptions {
*/
export class TerraformGenerator {

readonly #arguments?: BlockArgs;
readonly #arguments?: TerraformArgs;
readonly #blocks: Block[] = [];
#variables: BlockArgs = {};
#variables: TerraformArgs = {};

/**
* Construct Terraform generator.
Expand All @@ -53,7 +53,7 @@ export class TerraformGenerator {
*
* @param args arguments
*/
constructor(args?: BlockArgs) {
constructor(args?: TerraformArgs) {
this.#arguments = args;
}

Expand Down Expand Up @@ -170,7 +170,7 @@ export class TerraformGenerator {
* @param type type
* @param args arguments
*/
provider(type: string, args: BlockArgs): Provider {
provider(type: string, args: TerraformArgs): Provider {
const block = new Provider(type, args);
this.addBlocks(block);
return block;
Expand All @@ -186,7 +186,7 @@ export class TerraformGenerator {
* @param args arguments
* @param provisioners provisioners
*/
resource(type: string, name: string, args: BlockArgs, provisioners?: Provisioner[]): Resource {
resource(type: string, name: string, args: TerraformArgs, provisioners?: Provisioner[]): Resource {
const block = new Resource(type, name, args, provisioners);
this.addBlocks(block);
return block;
Expand All @@ -201,7 +201,8 @@ export class TerraformGenerator {
* use array for name mapping, position 0 = original resource's argument name, position 1 = mapped data source's argument name
* @param args extra arguments
*/
dataFromResource(resource: Resource, options: ResourceToDataOptions | undefined, argNames: (string | [string, string])[], args?: BlockArgs): Data {
dataFromResource(
resource: Resource, options: ResourceToDataOptions | undefined, argNames: (string | [string, string])[], args?: TerraformArgs): Data {
const block = resource.toData(options, argNames, args);
this.addBlocks(block);
return block;
Expand All @@ -216,7 +217,7 @@ export class TerraformGenerator {
* @param name name
* @param args arguments
*/
data(type: string, name: string, args: BlockArgs): Data {
data(type: string, name: string, args: TerraformArgs): Data {
const block = new Data(type, name, args);
this.addBlocks(block);
return block;
Expand Down Expand Up @@ -257,7 +258,7 @@ export class TerraformGenerator {
*
* @param args arguments
*/
locals(args: BlockArgs): Locals {
locals(args: TerraformArgs): Locals {
const block = new Locals(args);
this.addBlocks(block);
return block;
Expand Down Expand Up @@ -302,7 +303,7 @@ export class TerraformGenerator {
* @param type type
* @param args arguments
*/
backend(type: string, args: BlockArgs): Backend {
backend(type: string, args: TerraformArgs): Backend {
const block = new Backend(type, args);
this.addBlocks(block);
return block;
Expand All @@ -313,7 +314,7 @@ export class TerraformGenerator {
*
* @param variables variables
*/
addVars(variables: BlockArgs): this {
addVars(variables: TerraformArgs): this {
this.#variables = {
...this.#variables,
...variables
Expand All @@ -337,7 +338,7 @@ export class TerraformGenerator {
/**
* Get arguments.
*/
getArguments(): BlockArgs | undefined {
getArguments(): TerraformArgs | undefined {
return this.#arguments;
}

Expand All @@ -351,7 +352,7 @@ export class TerraformGenerator {
/**
* Get variables.
*/
getVars(): BlockArgs {
getVars(): TerraformArgs {
return this.#variables;
}

Expand Down
36 changes: 13 additions & 23 deletions src/arguments/Argument.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
import { Util } from '../utils';
import { TerraformElement, Util } from '../utils';

/**
* @category Argument
*/
export class Argument<T extends string | Argument = string | Argument<string>> {
export class Argument<T extends string = string> extends TerraformElement {

readonly argument: T;
readonly #argument: T;

/**
* Construct argument.
*
* @param arg argument as string or copy from another argument object
* @param escape escape the value
*/
constructor(arg: T) {
super();

if (!arg || (typeof arg === 'string' && !arg.trim())) {
throw new Error('Argument cannot be empty.');
throw new Error('Argument cannot be undefined.');
}

this.argument = arg;
this.#argument = arg;
}

/**
Expand All @@ -26,11 +29,7 @@ export class Argument<T extends string | Argument = string | Argument<string>> {
* @param name attribute name
*/
attr(name: string): Argument {
name = name.trim();
if (this.argument instanceof Argument) {
return this.argument.attr(name);
}
return new Argument(`${this.argument}.${name}`);
return new Argument(`${this.#argument}.${name.trim()}`);
}

/**
Expand All @@ -39,25 +38,16 @@ export class Argument<T extends string | Argument = string | Argument<string>> {
* @param idx element index
*/
element(idx: number): Argument {
if (this.argument instanceof Argument) {
return this.argument.element(idx);
}
return new Argument(`${this.argument}[${idx}]`);
return new Argument(`${this.#argument}[${idx}]`);
}

/**
* To Terraform representation.
*
* Use this method when argument is used as an interpolation in another Terraform argument or code.
*/
toTerraform(): string {
let str = '';
if (this.argument instanceof Argument) {
str += this.argument.toTerraform();
} else {
str += this.argument;
}
return Util.escape(str);
override toTerraform(): string {
return Util.escape(this.#argument);
}

/**
Expand All @@ -80,4 +70,4 @@ export class Argument<T extends string | Argument = string | Argument<string>> {
*
* @category Argument
*/
export const arg = <T extends string | Argument = string | Argument<string>>(arg: T): Argument<T> => new Argument(arg);
export const arg = <T extends string = string>(arg: T): Argument<T> => new Argument(arg);
4 changes: 2 additions & 2 deletions src/arguments/Attribute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ export class Attribute extends Argument {

static #constructArgument(block: Block, attrName: string): string {
if (!block) {
throw new Error('Attribute block cannot be null.');
throw new Error('Attribute block cannot be undefined.');
}
if (!attrName?.trim()) {
throw new Error('Attribute name cannot be empty.');
throw new Error('Attribute name cannot be undefined.');
}

return `${block.asArgument().toTerraform()}.${attrName.trim()}`;
Expand Down
2 changes: 1 addition & 1 deletion src/arguments/Function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class Function extends Argument {

static #constructArgument(fn: string, ...args: any[]): string {
if (!fn.trim()) {
throw new Error('Function name cannot be empty.');
throw new Error('Function name cannot be undefined.');
}
if (args.filter(arg => arg == null).length > 0) {
throw new Error(`Invalid function argument: ${args}`);
Expand Down
36 changes: 36 additions & 0 deletions src/arguments/List.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Util } from '../utils';
import { Argument } from '.';

/**
* @category Argument
*/
export class List extends Argument {

/**
* Construct list.
*
* @param elements list elements
*/
constructor(...elements: any[]) {
super(List.#constructArgument(elements));
}

static #constructArgument(elements: any[]): string {
let str = '[\n';
elements.forEach((element, i) => {
str += `${Util.argumentValueToString(element)}${i < elements.length - 1 ? ',' : ''}\n`;
});
str += ']';
return str;
}

}

/**
* Convenient function to construct new [[List]].
*
* @param elements list elements
*
* @category Argument
*/
export const list = (...elements: any[]): List => new List(...elements);
34 changes: 34 additions & 0 deletions src/arguments/Map.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { TerraformArgs, Util } from '../utils';
import { Argument } from '.';

/**
* @category Argument
*/
export class Map extends Argument {

readonly arguments: TerraformArgs;

/**
* Construct map.
*
* @param args map values
*/
constructor(args: TerraformArgs) {
super(Map.#constructArgument(args));
this.arguments = args;
}

static #constructArgument(args: TerraformArgs): string {
return Util.argumentValueToString(args)!;
}

}

/**
* Convenient function to construct new [[Map]].
*
* @param args map values
*
* @category Argument
*/
export const map = (args: TerraformArgs): Map => new Map(args);
2 changes: 2 additions & 0 deletions src/arguments/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ export * from './Argument';
export * from './Attribute';
export * from './Function';
export * from './Heredoc';
export * from './List';
export * from './Map';
6 changes: 3 additions & 3 deletions src/blocks/Backend.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Argument, Attribute } from '../arguments';
import { BlockArgs } from '../utils';
import { TerraformArgs, Util } from '../utils';
import { Block } from '.';

/**
Expand All @@ -17,7 +17,7 @@ export class Backend extends Block {
* @param type type
* @param args arguments
*/
constructor(type: string, args: BlockArgs) {
constructor(type: string, args: TerraformArgs) {
super('backend', [type], args, undefined, true);

this.type = type;
Expand All @@ -28,7 +28,7 @@ export class Backend extends Block {
}

override attr(_name: string): Attribute {
throw new Error('Inaccessible method.');
throw Util.inaccessibleMethod();
}

}
11 changes: 5 additions & 6 deletions src/blocks/Block.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Argument, Attribute } from '../arguments';
import { BlockArgs, Util } from '../utils';
import { TerraformArgs, TerraformElement, Util } from '../utils';

/**
* @category Block
*/
export abstract class Block<Args extends BlockArgs = BlockArgs> {
export abstract class Block<Args extends TerraformArgs = TerraformArgs> extends TerraformElement {

readonly blockType: string;
readonly blockNames: string[];
Expand All @@ -20,6 +20,8 @@ export abstract class Block<Args extends BlockArgs = BlockArgs> {
* @param args arguments
*/
constructor(type: string, names: string[], args: Args, innerBlocks?: Block[], insideTerraformBlock = false) {
super();

this.#validateIdentifier(type);
names.forEach(name => {
this.#validateIdentifier(name);
Expand Down Expand Up @@ -104,10 +106,7 @@ export abstract class Block<Args extends BlockArgs = BlockArgs> {
return this;
}

/**
* To Terraform representation.
*/
toTerraform(): string {
override toTerraform(): string {
let str = this.blockType;
this.blockNames.forEach(name => {
str += ` "${name}"`;
Expand Down
5 changes: 3 additions & 2 deletions src/blocks/Comment.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Argument, Attribute } from '../arguments';
import { Util } from '../utils';
import { Block } from '.';

/**
Expand All @@ -24,11 +25,11 @@ export class Comment extends Block<Record<string, never>> {
}

override asArgument(): Argument {
throw new Error('Inaccessible method.');
throw Util.inaccessibleMethod();
}

override attr(_name: string): Attribute {
throw new Error('Inaccessible method.');
throw Util.inaccessibleMethod();
}

}
4 changes: 2 additions & 2 deletions src/blocks/Data.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Argument, Attribute } from '../arguments';
import { BlockArgs } from '../utils';
import { TerraformArgs } from '../utils';
import { Block } from '.';

/**
Expand All @@ -19,7 +19,7 @@ export class Data extends Block {
* @param name name
* @param args arguments
*/
constructor(type: string, name: string, args: BlockArgs) {
constructor(type: string, name: string, args: TerraformArgs) {
super('data', [type, name], args);

this.type = type;
Expand Down
Loading

0 comments on commit 8a6e9ee

Please sign in to comment.