imbusy/infra/frontend.ts

96 lines
2.3 KiB
TypeScript

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as fg from "fast-glob";
import * as fs from "fs/promises";
import mime from "mime";
import * as common from "./common";
const tags = common.tags;
const prefix = `${common.prefix}-frontend`;
// ---- infra resouces ----
const bucket = new aws.s3.Bucket(`${prefix}-bucket`, {tags});
const oai = new aws.cloudfront.OriginAccessIdentity(`${prefix}-oai`);
const bucketPolicy = new aws.s3.BucketPolicy(`${prefix}-bucket-policy`, {
bucket: bucket.bucket,
policy: pulumi.all([oai.iamArn, bucket.bucket]).apply(([a, b]) => JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: {
AWS: a,
},
Action: ["s3:GetObject"],
Resource: [`arn:aws:s3:::${b}/*`],
}],
})),
});
export const cloudfront = new aws.cloudfront.Distribution(`${prefix}-cloudfront`, {
tags,
origins: [{
domainName: bucket.bucketRegionalDomainName,
originId: bucket.arn,
s3OriginConfig: {
originAccessIdentity: oai.cloudfrontAccessIdentityPath,
},
}],
enabled: true,
defaultRootObject: "index.html",
defaultCacheBehavior: {
targetOriginId: bucket.arn,
viewerProtocolPolicy: "redirect-to-https",
allowedMethods: ["GET", "HEAD", "OPTIONS"],
cachedMethods: ["GET", "HEAD", "OPTIONS"],
forwardedValues: {
queryString: false,
cookies: { forward: "none" },
},
},
customErrorResponses: [
{
errorCode: 403,
responseCode: 200,
responsePagePath: "/index.html",
},
{
errorCode: 404,
responseCode: 200,
responsePagePath: "/index.html",
},
],
priceClass: "PriceClass_100",
restrictions: {
geoRestriction: {
restrictionType: "none",
},
},
viewerCertificate: {
cloudfrontDefaultCertificate: true,
},
});
// ---- file uploads ----
(async () => {
const cwd = "../frontend/dist/";
const stats = await fs.stat(cwd);
if (!stats.isDirectory()) {
throw new Error("build the frontend firstly");
}
const files = await fg("**/*", {cwd, dot: true});
for (const file of files) {
new aws.s3.BucketObject(file, {
bucket: bucket,
source: new pulumi.asset.FileAsset(cwd+file),
contentType: mime.getType(file) || "application/octet-stream",
key: file,
});
}
})();