@aws-amplify/amplify-category-api
Version:
Amplify CLI API Category Plugin
144 lines (126 loc) • 4.35 kB
text/typescript
import * as crypto from 'crypto';
import { ISynthesisSession, Stack, LegacyStackSynthesizer, FileAssetSource, FileAssetLocation, CfnParameter } from 'aws-cdk-lib';
import { Template } from './deployment-resources';
import { TransformerRootStack } from './root-stack';
/**
* TransformerStackSythesizer
*/
export class TransformerStackSythesizer extends LegacyStackSynthesizer {
private readonly stackAssets: Map<string, Template> = new Map();
private readonly mapingTemplateAssets: Map<string, string> = new Map();
private _deploymentBucket?: CfnParameter;
private _deploymentRootKey?: CfnParameter;
/**
* synthesizeStackTemplate
*
* This method has been deprecated by cdk and is not used in runtime.
* @deprecated Replaced by synthesizeTemplate.
*/
protected synthesizeStackTemplate(stack: Stack, session: ISynthesisSession): void {
if (stack instanceof TransformerRootStack) {
const template = stack.renderCloudFormationTemplate(session) as string;
const templateName = stack.node.id;
this.setStackAsset(templateName, template);
return;
}
throw new Error(
'Error synthesizing the template. Expected Stack to be either instance of TransformerRootStack or TransformerNestedStack',
);
}
protected synthesizeTemplate(session: ISynthesisSession, _?: string): FileAssetSource {
const stack = this.boundStack;
if (stack instanceof TransformerRootStack) {
const template = stack.renderCloudFormationTemplate(session) as string;
const templateName = stack.node.id;
this.setStackAsset(templateName, template);
const contentHash = crypto.createHash('sha256').update(template).digest('hex');
return {
sourceHash: contentHash,
};
}
throw new Error(
'Error synthesizing the template. Expected Stack to be either instance of TransformerRootStack or TransformerNestedStack',
);
}
/**
* setStackAsset
*/
setStackAsset(templateName: string, template: string): void {
this.stackAssets.set(templateName, JSON.parse(template));
}
/**
* collectStacks
*/
collectStacks(): Map<string, Template> {
return new Map(this.stackAssets.entries());
}
/**
* setMappingTemplates
*/
setMappingTemplates(templateName: string, template: string): void {
this.mapingTemplateAssets.set(templateName, template);
}
/**
* collectMappingTemplates
*/
collectMappingTemplates(): Map<string, string> {
return new Map(this.mapingTemplateAssets.entries());
}
/**
* addFileAsset
*/
public addFileAsset(asset: FileAssetSource): FileAssetLocation {
const bucketName = this.deploymentBucket.valueAsString;
const rootKey = this.deploymentRootKey.valueAsString;
const objectKey = `${rootKey}/${asset.fileName}`;
const httpUrl = `https://s3.${this.boundStack.region}.${this.boundStack.urlSuffix}/${bucketName}/${rootKey}/${asset.fileName}`;
const s3ObjectUrl = `s3://${bucketName}/${rootKey}/${asset.fileName}`;
return {
bucketName,
objectKey,
httpUrl,
s3ObjectUrl,
};
}
/**
* ensureDeployementParameters
*/
private ensureDeployementParameters() {
if (!this._deploymentBucket) {
this._deploymentBucket = new CfnParameter(this.boundStack, 'S3DeploymentBucket', {
type: 'String',
description: 'An S3 Bucket name where assets are deployed',
});
}
if (!this._deploymentRootKey) {
this._deploymentRootKey = new CfnParameter(this.boundStack, 'S3DeploymentRootKey', {
type: 'String',
description: 'An S3 key relative to the S3DeploymentBucket that points to the root of the deployment directory.',
});
}
}
/**
* deploymentBucket
*/
private get deploymentBucket(): CfnParameter {
this.ensureDeployementParameters();
assertNotNull(this._deploymentBucket);
return this._deploymentBucket;
}
/**
* deploymentRootKey
*/
private get deploymentRootKey(): CfnParameter {
this.ensureDeployementParameters();
assertNotNull(this._deploymentRootKey);
return this._deploymentRootKey;
}
}
/**
* assertNotNull
*/
export function assertNotNull<A>(x: A | undefined): asserts x is NonNullable<A> {
if (x === null && x === undefined) {
throw new Error('You must call bindStack() first');
}
}