@bitblit/epsilon
Version:
Tiny adapter to simplify building API gateway Lambda APIS
197 lines (196 loc) • 9.18 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EpsilonWebsiteStack = void 0;
const aws_s3_1 = require("aws-cdk-lib/aws-s3");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const path_1 = __importDefault(require("path"));
const aws_cloudfront_1 = require("aws-cdk-lib/aws-cloudfront");
const aws_route53_1 = require("aws-cdk-lib/aws-route53");
const aws_route53_targets_1 = require("aws-cdk-lib/aws-route53-targets");
const aws_s3_deployment_1 = require("aws-cdk-lib/aws-s3-deployment");
const epsilon_website_stack_props_1 = require("./epsilon-website-stack-props");
const string_ratchet_1 = require("@bitblit/ratchet/common/string-ratchet");
const error_ratchet_1 = require("@bitblit/ratchet/common/error-ratchet");
class EpsilonWebsiteStack extends aws_cdk_lib_1.Stack {
constructor(scope, id, props) {
var _a;
super(scope, id, props);
const originAccessId = new aws_cloudfront_1.OriginAccessIdentity(this, id + 'OriginAccessId');
const websiteBucket = new aws_s3_1.Bucket(this, id + 'DeployBucket', {
bucketName: props.targetBucketName,
//removalPolicy: RemovalPolicy.DESTROY,
//autoDeleteObjects: true,
versioned: false,
publicReadAccess: false,
encryption: aws_s3_1.BucketEncryption.S3_MANAGED,
/*
cors: [
{
allowedMethods: [
HttpMethods.GET,
HttpMethods.POST,
HttpMethods.PUT,
],
allowedOrigins: ['http://localhost:3000'],
allowedHeaders: ['*'],
},
],
lifecycleRules: [
{
abortIncompleteMultipartUploadAfter: cdk.Duration.days(90),
expiration: cdk.Duration.days(365),
transitions: [
{
storageClass: s3.StorageClass.INFREQUENT_ACCESS,
transitionAfter: cdk.Duration.days(30),
},
],
},
],
*/
});
const extraBucketAndSource = (props.simpleAdditionalMappings || []).map((eb) => {
const nextBucket = new aws_s3_1.Bucket(this, eb.bucketName + 'DeployBucket', {
bucketName: eb.bucketName,
//removalPolicy: RemovalPolicy.DESTROY,
//autoDeleteObjects: true,
versioned: false,
publicReadAccess: false,
encryption: aws_s3_1.BucketEncryption.S3_MANAGED,
});
const nextBS = {
bucket: nextBucket,
sourceConfig: {
s3OriginSource: {
s3BucketSource: nextBucket,
originAccessIdentity: originAccessId,
},
behaviors: [
{
pathPattern: eb.pathPattern,
isDefaultBehavior: false,
compress: true,
defaultTtl: aws_cdk_lib_1.Duration.seconds(1),
minTtl: aws_cdk_lib_1.Duration.seconds(1),
maxTtl: aws_cdk_lib_1.Duration.seconds(1),
forwardedValues: {
queryString: false,
},
},
],
},
};
return nextBS;
});
//websiteBucket.grantReadWrite(webHandler);
//websiteBucket.grantReadWrite(bgHandler);
const assetSource = {
s3OriginSource: {
s3BucketSource: websiteBucket,
originAccessIdentity: originAccessId,
},
behaviors: [
{
isDefaultBehavior: true,
compress: true,
defaultTtl: aws_cdk_lib_1.Duration.seconds(1),
minTtl: aws_cdk_lib_1.Duration.seconds(1),
maxTtl: aws_cdk_lib_1.Duration.seconds(1),
forwardedValues: {
queryString: false,
},
},
],
};
//const parseUrl: URL = new URL(fnUrl.url);
const apiSource = {
customOriginSource: {
domainName: props.apiDomainName,
originProtocolPolicy: aws_cloudfront_1.OriginProtocolPolicy.HTTPS_ONLY,
},
//originPath: '/',
behaviors: [
{
compress: true,
forwardedValues: {
queryString: true,
cookies: {
forward: 'whitelist',
whitelistedNames: ['idToken'],
},
headers: ['Accept', 'Referer', 'Authorization', 'Content-Type'],
},
pathPattern: 'graphql',
defaultTtl: aws_cdk_lib_1.Duration.seconds(0),
maxTtl: aws_cdk_lib_1.Duration.seconds(0),
minTtl: aws_cdk_lib_1.Duration.seconds(0),
allowedMethods: aws_cloudfront_1.CloudFrontAllowedMethods.ALL,
cachedMethods: aws_cloudfront_1.CloudFrontAllowedCachedMethods.GET_HEAD,
},
],
};
const distributionProps = {
httpVersion: aws_cloudfront_1.HttpVersion.HTTP2,
defaultRootObject: 'index.html',
originConfigs: [assetSource, apiSource, ...extraBucketAndSource.map((s) => s.sourceConfig)],
errorConfigurations: [
{
errorCode: 404,
errorCachingMinTtl: 300,
responseCode: 200,
responsePagePath: '/index.html',
},
{
errorCode: 403,
errorCachingMinTtl: 300,
responseCode: 200,
responsePagePath: '/index.html',
},
],
priceClass: aws_cloudfront_1.PriceClass.PRICE_CLASS_ALL,
viewerProtocolPolicy: aws_cloudfront_1.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
viewerCertificate: {
aliases: props.cloudFrontDomainNames,
props: {
acmCertificateArn: props.cloudFrontHttpsCertificateArn,
sslSupportMethod: 'sni-only',
},
},
};
const cloudfrontDistro = new aws_cloudfront_1.CloudFrontWebDistribution(this, id + 'CloudfrontDistro', distributionProps);
// Have to be able to skip this since SOME people don't do DNS in Route53
if ((props === null || props === void 0 ? void 0 : props.route53Handling) === epsilon_website_stack_props_1.EpsilonWebsiteStackPropsRoute53Handling.Update) {
if ((_a = props === null || props === void 0 ? void 0 : props.cloudFrontDomainNames) === null || _a === void 0 ? void 0 : _a.length) {
for (let i = 0; i < props.cloudFrontDomainNames.length; i++) {
const domain = new aws_route53_1.RecordSet(this, id + 'DomainName-' + props.cloudFrontDomainNames[i], {
recordType: aws_route53_1.RecordType.A,
recordName: props.cloudFrontDomainNames[i],
target: {
aliasTarget: new aws_route53_targets_1.CloudFrontTarget(cloudfrontDistro),
},
zone: aws_route53_1.HostedZone.fromLookup(this, id, { domainName: EpsilonWebsiteStack.extractApexDomain(props.cloudFrontDomainNames[i]) }),
});
}
}
}
// [Source.asset(path.resolve('../website/dist'))],
new aws_s3_deployment_1.BucketDeployment(this, id + 'SiteDeploy', {
sources: props.pathsToAssets.map((inPath) => aws_s3_deployment_1.Source.asset(path_1.default.resolve(inPath))),
destinationBucket: websiteBucket,
distribution: cloudfrontDistro,
distributionPaths: ['/*'], //'/locales/*', '/index.html', '/manifest.webmanifest', '/service-worker.js']
});
}
static extractApexDomain(domainName) {
const pieces = string_ratchet_1.StringRatchet.trimToEmpty(domainName).split('.');
if (pieces.length < 2) {
error_ratchet_1.ErrorRatchet.throwFormattedErr('Not a valid domain name : %s', domainName);
}
return pieces[pieces.length - 2] + '.' + pieces[pieces.length - 1];
}
}
exports.EpsilonWebsiteStack = EpsilonWebsiteStack;
//# sourceMappingURL=epsilon-website-stack.js.map