arminhammer/wolkenkratzer

View on GitHub
src/intrinsic.ts

Summary

Maintainability
B
5 hrs
Test Coverage
import {
  Conditional,
  IFnAnd,
  IFnBase64,
  IFnEquals,
  IFnFindInMap,
  IFnGetAtt,
  IFnGetAZs,
  IFnIf,
  IFnImportValue,
  IFnJoin,
  IFnNot,
  IFnOr,
  IFnSelect,
  IFnSplit,
  IFnSub,
  IIntrinsic,
  IParameter,
  IRef,
  IResource,
} from './types';

/**
 * Returns an Fn::And object
 * @param {*} one
 * @param {*} two
 */
export function FnAnd(one: Conditional, two: Conditional): IFnAnd {
  return { kind: 'FnAnd', FnAnd: [buildIntrinsic(one), buildIntrinsic(two)] };
}

/**
 * @hidden
 * @param items
 * @param fnType
 */
function _fnConditional(
  items: Array<string | IIntrinsic>,
  fnType: 'FnOr' | 'FnNot' | 'FnIf'
): any {
  return { kind: fnType, [fnType]: items.map(x => buildIntrinsic(x)) };
}

/**
 * Returns an Fn::Or object
 * @param {*} array
 */
export function FnOr(items: Array<string | IIntrinsic>): IFnOr {
  return _fnConditional(items, 'FnOr');
}

/**
 * Returns an Fn::Not object
 * @param {*} array
 */
export function FnNot(items: Array<string | IIntrinsic>): IFnNot {
  return _fnConditional(items, 'FnNot');
}

/**
 * Returns an Fn::If object
 * @param {*} array
 */
export function FnIf(items: Array<string | IIntrinsic>): IFnIf {
  return _fnConditional(items, 'FnIf');
}

/**
 * Returns a Ref object that references another element in the template
 * @param {*} target
 */
export function Ref(target: IResource | IParameter | string): IRef {
  if (typeof target === 'string') {
    return { kind: 'Ref', Ref: target };
  } else {
    return { kind: 'Ref', Ref: target.Name };
  }
}

/**
 * Returns an Fn::GetAtt object that references another element in the template
 * @param {*} target
 * @param {*} attr
 */
export function FnGetAtt(target: IResource | string, attr: string): IFnGetAtt {
  if (typeof target === 'string') {
    return { kind: 'FnGetAtt', FnGetAtt: [target, attr] };
  } else {
    return { kind: 'FnGetAtt', FnGetAtt: [target.Name, attr] };
  }
}

/**
 * Returns an Fn::Join object
 */
export function FnJoin(
  delimiter: string,
  values: Array<string | IFnGetAtt | IRef> | IFnGetAtt
): IFnJoin {
  let newValues = values;
  if (Array.isArray(values)) {
    newValues = values.map(v => {
      return buildIntrinsic(v);
    });
  }
  return { kind: 'FnJoin', Delimiter: delimiter, Values: newValues };
}

/**
 * Returns an Fn::Equals object
 * @param {*} one
 * @param {*} two
 */
export function FnEquals(one: Conditional, two: Conditional): IFnEquals {
  return { kind: 'FnEquals', FnEquals: [one, two] };
}

/**
 * Returns an Fn::Sub object
 * @param {*} input
 */
export function FnSub(input: string): IFnSub {
  return { kind: 'FnSub', FnSub: input };
}

/**
 * Returns an Fn::Base64 object
 * @param {*} input
 */
export function FnBase64(input: string): IFnBase64 {
  return { kind: 'FnBase64', FnBase64: input };
}

/**
 * Returns an Fn::FindInMap object
 * @param {*} mapName
 * @param {*} topLevelKey
 * @param {*} secondLevelKey
 */
export function FnFindInMap(
  mapName: string,
  topLevelKey: string,
  secondLevelKey: string
): IFnFindInMap {
  return {
    FnFindInMap: [mapName, topLevelKey, secondLevelKey],
    kind: 'FnFindInMap',
  };
}

/**
 * Returns an Fn::GetAZs object
 * @param {*} region
 */
export function FnGetAZs(region: string | IRef): IFnGetAZs {
  if (!region) {
    region = Ref('AWS::Region');
  }
  return { kind: 'FnGetAZs', FnGetAZs: region };
}

/**
 * Returns an Fn::Select object
 * @param {*} index
 * @param {*} list
 */
export function FnSelect(
  index: string | number,
  list: Array<
    string | IFnFindInMap | IFnGetAtt | IFnGetAZs | IFnIf | IFnSplit | IRef
  >
): IFnSelect {
  if (typeof index === 'string') {
    index = parseInt(index, 10);
  }
  return {
    FnSelect: list,
    index: index,
    kind: 'FnSelect',
  };
}

export function buildIntrinsic(input) {
  if (input['Fn::Equals']) {
    return FnEquals(
      buildIntrinsic(input['Fn::Equals'][0]),
      buildIntrinsic(input['Fn::Equals'][1])
    );
  } else if (input.Ref) {
    return Ref(input.Ref);
  } else if (input['Fn::GetAtt']) {
    return FnGetAtt(
      buildIntrinsic(input['Fn::GetAtt'][0]),
      buildIntrinsic(input['Fn::GetAtt'][1])
    );
  } else if (input['Fn::Or']) {
    return FnOr(input['Fn::Or'].map(x => buildIntrinsic(x)));
  } else if (input['Fn::Not']) {
    return FnNot(input['Fn::Not'].map(x => buildIntrinsic(x)));
  } else if (input['Fn::If']) {
    return FnIf(input['Fn::If'].map(x => buildIntrinsic(x)));
  } else if (input['Fn::And']) {
    return FnAnd(
      buildIntrinsic(input['Fn::And'][0]),
      buildIntrinsic(input['Fn::And'][1])
    );
  } else {
    return input;
  }
}

/**
 * Returns an Fn::ImportValue object
 * @param {*} region
 */
export function FnImportValue(
  value:
    | string
    | IFnBase64
    | IFnFindInMap
    | IFnIf
    | IFnJoin
    | IFnSelect
    | IFnSplit
    | IFnSub
    | IRef
): IFnImportValue {
  return { kind: 'FnImportValue', FnImportValue: value };
}

/**
 * Returns an Fn::Split object
 * @param {*} mapName
 * @param {*} topLevelKey
 * @param {*} secondLevelKey
 */
export function FnSplit(delimiter: string, value: string): IFnSplit {
  return {
    delimiter: delimiter,
    kind: 'FnSplit',
    value: value,
  };
}