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
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
*.d.ts
node_modules

# compiled CDK entrypoint (replaced by ts-node)
index.js

# local deployment config — never commit real account_id
config.json

# CDK asset staging directory
.cdk.staging
cdk.out
Expand Down
2 changes: 1 addition & 1 deletion cdk.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"app": "node index"
"app": "npx ts-node --prefer-ts-exts index.ts"
}
152 changes: 69 additions & 83 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
#!/usr/bin/env node
import {Architecture, AssetCode, Function, Runtime} from "@aws-cdk/aws-lambda";
import {CfnApi, CfnDeployment, CfnIntegration, CfnRoute, CfnStage, CorsHttpMethod, HttpApi, HttpMethod} from "@aws-cdk/aws-apigatewayv2";
import {HttpLambdaIntegration} from '@aws-cdk/aws-apigatewayv2-integrations';
import {App, ConcreteDependable, Construct, Duration, RemovalPolicy, Stack, StackProps} from '@aws-cdk/core';
import {Effect, PolicyStatement, Role, ServicePrincipal} from "@aws-cdk/aws-iam";
import {AttributeType, BillingMode, Table} from "@aws-cdk/aws-dynamodb";
import { Architecture, AssetCode, Function, Runtime } from "aws-cdk-lib/aws-lambda";
import { CfnApi, CfnDeployment, CfnIntegration, CfnRoute, CfnStage, CorsHttpMethod, HttpApi, HttpMethod } from "aws-cdk-lib/aws-apigatewayv2";
import { HttpLambdaIntegration } from "aws-cdk-lib/aws-apigatewayv2-integrations";
import { App, Duration, RemovalPolicy, Stack, StackProps } from "aws-cdk-lib";
import { Construct } from "constructs";
import { Effect, PolicyStatement, Role, ServicePrincipal } from "aws-cdk-lib/aws-iam";
import { AttributeType, BillingMode, CfnTable, Table } from "aws-cdk-lib/aws-dynamodb";

import config from './config.json';
import config from "./config.json";

class ChatAppStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const tableName = "abovevtt";

// initialise api
const name = id + "-api"
const name = id + "-api";
const api = new CfnApi(this, name, {
name: "AboveVTTBackend",
protocolType: "WEBSOCKET",
Expand All @@ -27,14 +27,18 @@ class ChatAppStack extends Stack {
name: "campaignId",
type: AttributeType.STRING,
},
sortKey:{
sortKey: {
name: "objectId",
type: AttributeType.STRING
type: AttributeType.STRING,
},
billingMode: BillingMode.PAY_PER_REQUEST,
removalPolicy: RemovalPolicy.RETAIN,
});

// Preserve the CloudFormation logical ID so CDK v1→v2 migration does not
// replace the live table. Verify the ID with `cdk diff` before first deploy.
(table.node.defaultChild as CfnTable).overrideLogicalId("abovevttbackendapitableF5D5D98F");

table.addGlobalSecondaryIndex({
indexName: "connectionIds",
partitionKey: {
Expand All @@ -49,114 +53,101 @@ class ChatAppStack extends Stack {
name: "campaignId",
type: AttributeType.STRING,
},
sortKey:{
sortKey: {
name: "sceneId",
type: AttributeType.STRING
type: AttributeType.STRING,
},
});

const httpApi = new HttpApi(this, 'HttpApi',{
corsPreflight:{
allowHeaders:[
'Content-Type',
],
const httpApi = new HttpApi(this, "HttpApi", {
corsPreflight: {
allowHeaders: ["Content-Type"],
allowMethods: [
CorsHttpMethod.OPTIONS,
CorsHttpMethod.GET,
CorsHttpMethod.POST,
CorsHttpMethod.PUT,
CorsHttpMethod.PATCH,
CorsHttpMethod.DELETE,
],
allowOrigins:['*'],
}
],
allowOrigins: ["*"],
},
});

const abovevttServicesFunc = new Function(this,"abovevtt-services-lambda",{
code: new AssetCode('./abovevttServices'),
const abovevttServicesFunc = new Function(this, "abovevtt-services-lambda", {
code: new AssetCode("./abovevttServices"),
architecture: Architecture.X86_64,
handler: 'app.handler',
handler: "app.handler",
runtime: Runtime.NODEJS_12_X,
timeout: Duration.seconds(30),
memorySize: 256,
environment: {
"TABLE_NAME": tableName,
}
TABLE_NAME: tableName,
},
});
table.grantReadWriteData(abovevttServicesFunc);

const abovevttServicesIntegration=new HttpLambdaIntegration('abovevttServices',abovevttServicesFunc,{
});
const abovevttServicesIntegration = new HttpLambdaIntegration("abovevttServices", abovevttServicesFunc);

httpApi.addRoutes({
path: '/services',
methods: [ HttpMethod.GET , HttpMethod.PUT, HttpMethod.POST],
path: "/services",
methods: [HttpMethod.GET, HttpMethod.PUT, HttpMethod.POST],
integration: abovevttServicesIntegration,
});




});

const connectFunc = new Function(this, 'connect-lambda', {
code: new AssetCode('./onconnect'),
handler: 'app.handler',
const connectFunc = new Function(this, "connect-lambda", {
code: new AssetCode("./onconnect"),
handler: "app.handler",
runtime: Runtime.NODEJS_12_X,
timeout: Duration.seconds(30),
memorySize: 256,
environment: {
"TABLE_NAME": tableName,
}
TABLE_NAME: tableName,
},
});
table.grantReadWriteData(connectFunc);

table.grantReadWriteData(connectFunc)

const disconnectFunc = new Function(this, 'disconnect-lambda', {
code: new AssetCode('./ondisconnect'),
handler: 'app.handler',
const disconnectFunc = new Function(this, "disconnect-lambda", {
code: new AssetCode("./ondisconnect"),
handler: "app.handler",
runtime: Runtime.NODEJS_12_X,
timeout: Duration.seconds(30),
memorySize: 256,
environment: {
"TABLE_NAME": tableName,
}
TABLE_NAME: tableName,
},
});
table.grantReadWriteData(disconnectFunc);

table.grantReadWriteData(disconnectFunc)

const keepaliveFunc = new Function(this, 'keepalive-lambda', {
code: new AssetCode('./keepalive'),
handler: 'app.handler',
const keepaliveFunc = new Function(this, "keepalive-lambda", {
code: new AssetCode("./keepalive"),
handler: "app.handler",
runtime: Runtime.NODEJS_12_X,
timeout: Duration.seconds(2),
memorySize: 128,
});

const messageFunc = new Function(this, 'message-lambda', {
code: new AssetCode('./sendmessage'),
handler: 'app.handler',
const messageFunc = new Function(this, "message-lambda", {
code: new AssetCode("./sendmessage"),
handler: "app.handler",
runtime: Runtime.NODEJS_12_X,
timeout: Duration.seconds(30),
memorySize: 256,
initialPolicy: [
new PolicyStatement({
actions: [
'execute-api:ManageConnections'
],
actions: ["execute-api:ManageConnections"],
resources: [
"arn:aws:execute-api:" + config["region"] + ":" + config["account_id"] + ":" + api.ref + "/*"
"arn:aws:execute-api:" + config["region"] + ":" + config["account_id"] + ":" + api.ref + "/*",
],
effect: Effect.ALLOW,
})
}),
],
environment: {
"TABLE_NAME": tableName,
}
TABLE_NAME: tableName,
},
});
table.grantReadWriteData(messageFunc);

table.grantReadWriteData(messageFunc)

// access role for the socket api to access the socket lambda
const policy = new PolicyStatement({
effect: Effect.ALLOW,
resources: [
Expand All @@ -165,39 +156,38 @@ class ChatAppStack extends Stack {
messageFunc.functionArn,
keepaliveFunc.functionArn,
],
actions: ["lambda:InvokeFunction"]
actions: ["lambda:InvokeFunction"],
});

const role = new Role(this, `${name}-iam-role`, {
assumedBy: new ServicePrincipal("apigateway.amazonaws.com")
assumedBy: new ServicePrincipal("apigateway.amazonaws.com"),
});
role.addToPolicy(policy);

// lambda integration
const connectIntegration = new CfnIntegration(this, "connect-lambda-integration", {
apiId: api.ref,
integrationType: "AWS_PROXY",
integrationUri: "arn:aws:apigateway:" + config["region"] + ":lambda:path/2015-03-31/functions/" + connectFunc.functionArn + "/invocations",
credentialsArn: role.roleArn,
})
});
const disconnectIntegration = new CfnIntegration(this, "disconnect-lambda-integration", {
apiId: api.ref,
integrationType: "AWS_PROXY",
integrationUri: "arn:aws:apigateway:" + config["region"] + ":lambda:path/2015-03-31/functions/" + disconnectFunc.functionArn + "/invocations",
credentialsArn: role.roleArn
})
credentialsArn: role.roleArn,
});
const messageIntegration = new CfnIntegration(this, "message-lambda-integration", {
apiId: api.ref,
integrationType: "AWS_PROXY",
integrationUri: "arn:aws:apigateway:" + config["region"] + ":lambda:path/2015-03-31/functions/" + messageFunc.functionArn + "/invocations",
credentialsArn: role.roleArn,
})
});
const keepaliveIntegration = new CfnIntegration(this, "keepalive-lambda-integration", {
apiId: api.ref,
integrationType: "AWS_PROXY",
integrationUri: "arn:aws:apigateway:" + config["region"] + ":lambda:path/2015-03-31/functions/" + keepaliveFunc.functionArn + "/invocations",
credentialsArn: role.roleArn,
})
});

const connectRoute = new CfnRoute(this, "connect-route", {
apiId: api.ref,
Expand Down Expand Up @@ -228,24 +218,20 @@ class ChatAppStack extends Stack {
});

const deployment = new CfnDeployment(this, `${name}-deployment`, {
apiId: api.ref
apiId: api.ref,
});

new CfnStage(this, `${name}-stage`, {
apiId: api.ref,
autoDeploy: true,
deploymentId: deployment.ref,
stageName: "v1"
stageName: "v1",
});

const dependencies = new ConcreteDependable();
dependencies.add(connectRoute)
dependencies.add(disconnectRoute)
dependencies.add(messageRoute)
dependencies.add(keepaliveRoute);
deployment.node.addDependency(dependencies);
deployment.node.addDependency(connectRoute, disconnectRoute, messageRoute, keepaliveRoute);
}
}

const app = new App();
new ChatAppStack(app, `abovevtt-backend`);
app.synth();
new ChatAppStack(app, "abovevtt-backend");
app.synth();
14 changes: 6 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "api-websocket-lambda-dynamodb",
"version": "1.0.0",
"description": "Use of an Application Load Balancer with an AutoScaling Group",
"description": "AboveVTT serverless backend",
"private": true,
"scripts": {
"build": "tsc",
Expand All @@ -15,14 +15,12 @@
},
"license": "Apache-2.0",
"devDependencies": {
"@types/node": "^10.17.0",
"typescript": "~3.7.2"
"@types/node": "^20.0.0",
"ts-node": "^10.9.0",
"typescript": "~5.6.0"
},
"dependencies": {
"@aws-cdk/aws-apigatewayv2": "^1.143.0",
"@aws-cdk/aws-apigatewayv2-integrations": "^1.143.0",
"@aws-cdk/aws-dynamodb": "^1.143.0",
"@aws-cdk/aws-lambda": "^1.143.0",
"@aws-cdk/core": "^1.143.0"
"aws-cdk-lib": "^2.200.0",
"constructs": "^10.0.0"
}
}
Loading