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" }, }, }, 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, }); } })();