Skip to content

Commit

Permalink
feat: add frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
rehanvandermerwe committed Feb 22, 2024
1 parent 6894434 commit c309617
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 33 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Test PR
on:
pull_request:
types:
- opened
- reopened
- synchronize
- edited
jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
cache: 'npm'
- run: npm ci
- run: npm run build-src
- run: npm run validate
17 changes: 2 additions & 15 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Validate PR
name: Validate PR Title
on:
pull_request:
pull_request_target:
types:
- labeled
- opened
Expand Down Expand Up @@ -28,16 +28,3 @@ jobs:
chore
release
requireScope: false

pr-lint:
name: Lint on PR
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
cache: 'npm'
- run: npm ci
- run: npm run build-src
- run: npm run validate
21 changes: 10 additions & 11 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { config, Environment } from "@config/index";
import * as cdk from "aws-cdk-lib";
import Backend from "./stacks/backend";
import { Frontend } from "./stacks/frontend";

const app = new cdk.App();

Expand All @@ -10,17 +11,15 @@ async function Main() {
console.log("Env", env);
const envConfig = config[env];

new Backend(
app,
"starter-backend-" + envConfig.env,
{
env: {
account: envConfig.aws.account,
region: envConfig.aws.region,
},
},
envConfig
);
const awsEnv = {
account: envConfig.aws.account,
region: envConfig.aws.region,
};
const backend = new Backend(app, "starter-backend-" + envConfig.env, { env: awsEnv }, envConfig);

new Frontend(app, "starter-frontend-" + envConfig.env, { env: awsEnv }, envConfig, {
apiOrigin: backend.apiOrigin,
});

cdk.Tags.of(app).add("blog", "starter-backend");
app.synth();
Expand Down
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
"cdk:deploy:dev": "wireit",
"cdk:deploy:stage": "wireit",
"cdk:deploy:prod": "wireit",
"cdk-hotswap": "wireit",
"test-unit": "vitest",
"test-e2e": "TEST_TYPE=E2E vitest"
},
Expand All @@ -24,10 +23,10 @@
"command": "esr ./scripts/index.ts -c build-src",
"files": [
"scripts/index.ts",
"src/backend/**/*.ts"
"src/**"
],
"output": [
"dist/backend/**"
"dist/**"
]
},
"cdk:diff:dev": {
Expand Down
13 changes: 13 additions & 0 deletions scripts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ import * as esbuild from "esbuild";
import execa from "execa";
import { config, environments, Environment } from "@config/index";
import * as process from "process";
import fs from "fs";
import * as fse from "fs-extra";

const baseDir = "../";
const paths = {
workingDir: path.resolve(__dirname, baseDir),
src: path.resolve(__dirname, baseDir, "src"),
srcBackend: path.resolve(__dirname, baseDir, "src", "backend"),
srcFrontend: path.resolve(__dirname, baseDir, "src", "frontend"),
dist: path.resolve(__dirname, baseDir, "dist"),
distBackend: path.resolve(__dirname, baseDir, "dist", "backend"),
distFrontend: path.resolve(__dirname, baseDir, "dist", "frontend"),
};

async function runCommand(
Expand Down Expand Up @@ -62,6 +66,7 @@ const argv = yargs(hideBin(process.argv))
break;
case "build-src":
await buildTsLambdas();
await buildFrontend();
break;

case "cdk":
Expand Down Expand Up @@ -123,6 +128,14 @@ async function buildTsLambdas() {
console.log("LAMBDAS TS BUILD");
}

async function buildFrontend() {
console.log("BUILDING FRONTEND");

await fse.copy(paths.srcFrontend, paths.distFrontend);

console.log("BUILDING FRONTEND");
}

async function cdkCommand(command: "diff" | "deploy" | "hotswap", environment: Environment) {
let extraArgs = "--context env=" + environment;
if (command === "deploy" || command === "hotswap") extraArgs += " --require-approval never";
Expand Down
14 changes: 14 additions & 0 deletions src/frontend/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Frontend</title>
</head>
<body>

<h1>Frontend</h1>

<h2>Test the api by navigating to <a href="/api/">/api/</a></h2>

</body>
</html>
10 changes: 6 additions & 4 deletions stacks/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { ApiEnv, envToObject as apiEnvToObject } from "@backend/lambda/api/envir
import { EnvironmentConfig } from "@config/index";

export class Backend extends cdk.Stack {
public readonly apiOrigin: string;

constructor(scope: Construct, id: string, stackProps: cdk.StackProps, config: EnvironmentConfig) {
super(scope, id, stackProps);

Expand All @@ -19,7 +21,7 @@ export class Backend extends cdk.Stack {
RANDOM_NUMBER_MIN: config.randomNumberMin,
RANDOM_NUMBER_MAX: config.randomNumberMax,
};
// TODO: do I pass scope or this here?

const apiLambda = new lambda.Function(this, name("lambda-api"), {
functionName: name("api"),
code: new lambda.AssetCode("dist/backend/lambda/api/"),
Expand All @@ -42,9 +44,9 @@ export class Backend extends cdk.Stack {
},
});

new cdk.CfnOutput(this, "Lambda API Host", {
value: apiLambdaUrl.url,
});
this.apiOrigin = cdk.Fn.select(2, cdk.Fn.split("/", apiLambdaUrl.url));
new cdk.CfnOutput(this, "Lambda API Host", { value: apiLambdaUrl.url });
new cdk.CfnOutput(this, "Lambda API Origin", { value: this.apiOrigin });
}
}

Expand Down
75 changes: 75 additions & 0 deletions stacks/frontend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as cloudfront from "aws-cdk-lib/aws-cloudfront";
import { CachePolicy } from "aws-cdk-lib/aws-cloudfront";
import * as origins from "aws-cdk-lib/aws-cloudfront-origins";
import * as s3 from "aws-cdk-lib/aws-s3";
import * as s3deploy from "aws-cdk-lib/aws-s3-deployment";
import * as path from "path";
import { EnvironmentConfig } from "@config/index";

export type FrontendProps = {
apiOrigin: string;
};

export class Frontend extends cdk.Stack {
constructor(
scope: Construct,
id: string,
stackProps: cdk.StackProps,
config: EnvironmentConfig,
props: FrontendProps
) {
super(scope, id, stackProps);

function name(name: string): string {
return id + "-" + name;
}

const frontendBucket = new s3.Bucket(this, name("web-bucket"), {
bucketName: name("web-bucket"),
autoDeleteObjects: true,
removalPolicy: cdk.RemovalPolicy.DESTROY,
});

const frontendDist = new cloudfront.Distribution(this, name("web-dist"), {
comment: name("web-dist"),
defaultBehavior: {
origin: new origins.S3Origin(frontendBucket),
compress: true,
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
},
additionalBehaviors: {
"/api/*": {
origin: new origins.HttpOrigin(props.apiOrigin, {
readTimeout: cdk.Duration.seconds(60),
}),
allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
compress: false,
cachePolicy: CachePolicy.CACHING_DISABLED,
},
},
defaultRootObject: "index.html",
});

new s3deploy.BucketDeployment(this, name("deploy-with-invalidation"), {
sources: [s3deploy.Source.asset(path.join(__dirname, "dist/frontend"))],
destinationBucket: frontendBucket,
distribution: frontendDist,
distributionPaths: ["/*"],
});

new cdk.CfnOutput(this, name("CloudFrontURL"), {
description: "Frontend Url",
value: cdk.Fn.join("", ["https://", frontendDist.distributionDomainName]),
});
new cdk.CfnOutput(this, name("APIURL"), {
description: "Api Url",
value: cdk.Fn.join("", ["https://", frontendDist.distributionDomainName, "/api/"]),
});
}
}

export default Frontend;

0 comments on commit c309617

Please sign in to comment.