# Noctilucent Transpiler v1
The goal of noctilucent is to take any template and transform it completely to a working CDK application in typescript.
The remainder of this document is focusing on how that will be done.
## Breakdown of a CDK Typescript Class in Noctilucent
Let's look at a simple cdk application:
```
import * as core from '@aws-cdk/core';
import * as ec2 from '@aws-cdk/ec2';
public interface BasicStackProps extends core.StackProps{
readonly AmiId: string;
}
export class BasicStack extends core.Stack {
constructor(scope: core.App, id: string, props?: BasicStackProps) {
super(scope, id, props);
const vpc = new ec2.Vpc(this, "MyVpc", {
maxAzs: 3 // Default is all AZs in region
});
}
}
```
Each stack file *can* be modelled off a template. Breaking down you have:
```
import * as core from '@aws-cdk/core';
import * as ec2 from '@aws-cdk/ec2';
public interface BasicStackProps extends core.StackProps{
readonly AmiId: string;
}
export class NAME extends core.Stack {
constructor(scope: core.App, id: string, props?: PROPNAME) {
super(scope, id, props;
}
const vpc = new ec2.Vpc(this, "MyVpc", {
maxAzs: 3 // Default is all AZs in region
});
}
```
### Static Imports
As part of the core template of a stack, there will always be classes that need importing, such as the core libraries.
These don't need to be programmatically thought about, just add them at will.
### Resource Imports
In cloudformation, every resource in your yaml has a type association. This section is identifying all your resource
types and importing their names.
### Parameter Usage
If you think of a cloudformation template as a giant "function", Parameters are the inputs into the function. If you
have a single parameter called AmiId in your cloudformation template, then you need a prop that corresponds to that
in your properties.
There is an argument to be had about retaining parameters in the stack using `new CfnParameter` instead of props.
Generally, a secondary goal of this project is to create *best practices* for the output CDK Class. CDK doesn't really
`like` parameters, preferring properties instead. Until the need arises, we will not create CfnParameters in v1 because
of this.
### Preconditions
Conditions are booleans for later use in the template. Preconditions is the equivalent `Conditions` block, where every
name of a condition will correspond with a variable that is a boolean.
As an example, in one template, there is a Condition named `IsMxp`, which is an `Fn::Equal` of "eu-south-1 and AWS::Region.
This would translate to:
```typescript
const isMxp = ("eu-south-1" == this.region);
```
We will support all `AWS::` pseudo parameters, and all meta-functions in Cloudformation.
* [List of pseudo-parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html)
* [List of all Intrinsic Functions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html)
* [List of all Condition Functions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-conditions.html)
It seems Condition Functions are a subset of Intrinsic functions, and we will support all Intrinsic function rewrites.
### Instructions
The core of instructions is attempting to replicate the entire `Resources` section of a Cloudformation template.
Because of the additional work of intrinsic functions and condition rewrites, Instructions will be a mix of:
* resolving intrinsic functions
* ordering references / variables
* generating resources
As an example, let's say we have:
```
"NewVolume" : {
"Type" : "AWS::EC2::Volume",
"Condition" : "CreateProdResources",
"Properties" : {
"Size" : { "Ref": "SizeParam" },
"AvailabilityZone" : { "Fn::GetAtt" : [ "EC2Instance", "AvailabilityZone" ]}
}
```
This translates to:
```
let ec2Instance = ...;
if (createProdResources) {
new ec2.Volume(this, 'NewVolume', {
size: props.sizeParam,
availabilityZone: ec2Instance.availabilityZone
});
}
```
As you can see, we can't create a volume, without an instance because of the GetAtt call. We have to resolve conditions
to then refer to them in Instructions, and we have to create a lookup table of Parameters + Logical Ids + Mappings to
know what to output for certain values (size in this case was a parameter, so must refer to a prop from the parameter
section). We will go into more detail about this in a later document.
### Lookup Table
All Mappings will be in a Lookup Table area that are just giant hashmaps.
If you have a large mappings like...
```
"AccessRole": {
"ARN": {
"PrincipalArn": "11111111111:role/Role",
},
...
}
```
then this gets translated to
```
const AccessRole = Map> {
"ARN" : {
"PrincipalArn": "11111111111:role/Role",
}
}
```
and then all meta lookups into the table will be replaced with hashmap lookups.