Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
name: Deploy API
on:
push:
branches:
- "*"

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand All @@ -28,6 +26,11 @@ jobs:
aws-region: eu-west-1
- name: Check out repository code
uses: actions/checkout@v3

- name: Extract branch name
shell: bash
run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
id: extract_branch

- name: Install dependencies
run: |
Expand All @@ -42,3 +45,4 @@ jobs:
env:
AWS_REGION: ${{ secrets.AWS_REGION }}
AWS_ACCOUNT_NUMBER: ${{ secrets.AWS_ACCOUNT_NUMBER }}
GIT_BRANCH: ${{ steps.extract_branch.outputs.branch }}
45 changes: 30 additions & 15 deletions bin/lambda-sqlite-efs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,37 @@ import "source-map-support/register";
import { LambdaSqliteEfsStack } from "../lib/lambda-sqlite-efs-stack";
const process = require("process");

const GIT_BRANCH = process.env.GIT_BRANCH;

const getBranchprefix = (branchName: string) => {
console.log("branchName", branchName);
return branchName && branchName !== `master`
? `${branchName
.replace(/\b(feat\/|fix\/|chore\/)\b/g, "")
.substring(0, 5)}-`
: "";
};

const app = new cdk.App();
new LambdaSqliteEfsStack(app, "LambdaSqliteEfsStack", {
/* If you don't specify 'env', this stack will be environment-agnostic.
* Account/Region-dependent features and context lookups will not work,
* but a single synthesized template can be deployed anywhere. */
new LambdaSqliteEfsStack(
app,
`${getBranchprefix(GIT_BRANCH)}LambdaSqliteEfsStack`,
{
/* If you don't specify 'env', this stack will be environment-agnostic.
* Account/Region-dependent features and context lookups will not work,
* but a single synthesized template can be deployed anywhere. */

/* Uncomment the next line to specialize this stack for the AWS Account
* and Region that are implied by the current CLI configuration. */
// env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },
/* Uncomment the next line to specialize this stack for the AWS Account
* and Region that are implied by the current CLI configuration. */
// env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },

/* Uncomment the next line if you know exactly what Account and Region you
* want to deploy the stack to. */
env: {
account: process.env.AWS_ACCOUNT_NUMBER,
region: process.env.AWS_REGION,
},
/* Uncomment the next line if you know exactly what Account and Region you
* want to deploy the stack to. */
env: {
account: process.env.AWS_ACCOUNT_NUMBER,
region: process.env.AWS_REGION,
},

/* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */
});
/* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */
}
);
17 changes: 17 additions & 0 deletions lib/lambda/bootstrap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import SQLLite = require("better-sqlite3");
import { ApiContext } from "./common/types";

const EFS_PATH = process.env.EFS_PATH;

export default function bootstrap(): ApiContext {
const db = new SQLLite(EFS_PATH + "/lambda-efs.db", {});
setupDB(db);

return { db };
}

function setupDB(db: SQLLite.Database) {
db.prepare(
"create table if not exists users (name TEXT, age INTEGER)"
).run();
}
2 changes: 2 additions & 0 deletions lib/lambda/common/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const ENDPOINT_NOT_SUPPORTED = "Endpoint Not Supported";
export const INVALID_INPUT = "Invalid Input";
13 changes: 13 additions & 0 deletions lib/lambda/common/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Database } from "better-sqlite3";

export type Route = "/user" | "/users";

export type ApiEvent = {
route: Route;
method: "POST" | "GET" | "PUT" | "DELETE" | "PATCH";
data: Record<string, unknown>;
};

export type ApiContext = {
db: Database;
};
50 changes: 22 additions & 28 deletions lib/lambda/index.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,31 @@
import Database = require("better-sqlite3");
const EFS_PATH = process.env.EFS_PATH;
import bootstrap from "./bootstrap";
import { ApiContext, ApiEvent, Route } from "./common/types";
import { userRoute } from "./user";
import { usersRoute } from "./users";

const db = new Database(EFS_PATH + "/lambda-efs.db", {});
const { db } = bootstrap();

export const handler = async (event: any) => {
console.log(JSON.stringify({ event }));
export const handler = async (event: ApiEvent) => {
try {
const ctx: ApiContext = {
db,
};

bootstrap();
const routeHandler = routeHandlers[event.route];

createUser(event.name, event.age);
const res = routeHandler(event, ctx);

const users = getUsers();
console.log(res);

console.log(JSON.stringify({ users }));
return res;
} catch (e) {
return JSON.stringify(e);
}
};

function bootstrap() {
console.log("Bootstrapping function");
setupDB();
}

function setupDB() {
console.log("Setting up DB");

db.prepare(
"create table if not exists users (name TEXT, age INTEGER)"
).run();
}

function createUser(name: string, age: number) {
db.prepare(`INSERT into users (name, age) VALUES ('${name}', ${age})`).run();
}
const routeHandlers: Record<Route, RouteFunction> = {
"/user": userRoute,
"/users": usersRoute,
};

function getUsers() {
return db.prepare("SELECT * FROM users").all();
}
type RouteFunction = (event: ApiEvent, ctx: ApiContext) => unknown;
32 changes: 32 additions & 0 deletions lib/lambda/user/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { ENDPOINT_NOT_SUPPORTED, INVALID_INPUT } from "../common/constants";
import { ApiContext, ApiEvent } from "../common/types";

export const userRoute = (event: ApiEvent, ctx: ApiContext) => {
if (event.method === "POST") {
if (
event.data &&
event.data.name &&
typeof event.data.name === "string" &&
event.data.age &&
typeof event.data.age === "number"
) {
return createUser(ctx, event.data.name, event.data.age);
} else {
return INVALID_INPUT;
}
}

return ENDPOINT_NOT_SUPPORTED;
};

function createUser(ctx: ApiContext, name: string, age: number) {
const res = ctx.db
.prepare(`INSERT into users (name, age) VALUES ('${name}', ${age})`)
.run();

if (res) {
return true;
} else {
return false;
}
}
14 changes: 14 additions & 0 deletions lib/lambda/users/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ENDPOINT_NOT_SUPPORTED } from "../common/constants";
import { ApiContext, ApiEvent } from "../common/types";

export const usersRoute = (event: ApiEvent, ctx: ApiContext) => {
if (event.method === "GET") {
return getUsers(ctx);
}

return ENDPOINT_NOT_SUPPORTED;
};

function getUsers(ctx: ApiContext) {
return ctx.db.prepare("SELECT * FROM users").all();
}