AWS & Typescript Masterclass - AWS DynamoDb with CDK and Lambda

September 12th, 2022

32-43

 

(32) section intro

(33) put item

npm i @types/aws-lambda

 

(34) getting data from ApiGateway

const item = typeof event.body == 'object' ? event.body : JSON.parse(event.body)

>? why this check for parsing? is this testing only, or is this random in prod?


(35-36) DynamoDB  + lambda

// create table

const table = new Table(this.stack, this.props.tableName, {

partitionKey: {

name: this.props.primaryKey,

type: AttributeType.STRING,

},

tableName: this.props.tableName

})

 

// create lambda

const id = `${this.props.tableName}-${lambdaName}`;

const createLambda = new NodejsFunction(this.stack, id, {

entry: (join(__dirname, '..', 'services', this.props.tableName, `${lambdaName}.ts`)),

handler: 'handler',

functionName: id,

environment: {

TABLE_NAME: this.props.tableName,

PRIMARY_KEY: this.props.primaryKey,

}

})

// create integration

const createLambdaIntegration = new LambdaIntegration(createLambda)

 

// grant table rights to lambda

table.grantWriteData(createLambda)

// table.grantReadData(readLambda)

 

// add to api gateway

const spaceResource = this.api.root.addResource('spaces');

spaceResource.addMethod('POST', this.spacesTable.createLambdaIntegration)

 


 

(37) Scan operation

const queryResponse = await dbClient.scan({

TableName: TABLE_NAME,

}).promise()

(38) Query Operation

const queryResponse = await dbClient.query({

TableName: TABLE_NAME,

KeyConditionExpression: '#zz = :zzzz',

ExpressionAttributeNames: {

'#zz': PRIMARY_KEY,

},

ExpressionAttributeValues: {

':zzzz': keyValue,

},

}).promise();

(39) Query on secondary indexes

const queryResponse = await dbClient.query({

TableName: TABLE_NAME,

KeyConditionExpression: '#zz = :zzzz',

ExpressionAttributeNames: {

'#zz': PRIMARY_KEY,

},

ExpressionAttributeValues: {

':zzzz': keyValue,

},

}).promise();

(40) Update Operation

const updateResult = await dbClient.update({

TableName: TABLE_NAME,

Key: {

[PRIMARY_KEY]: spaceId

},

UpdateExpression: 'set #zzzNew = :new',

ExpressionAttributeNames: {

'#zzzNew': requestBodyKey

},

ExpressionAttributeValues: {

':new': requestBodyValue

},

ReturnValues: 'UPDATED_NEW',

}).promise()

(41) Delete Operation

const deleteResult = await dbClient.delete({

TableName: TABLE_NAME,

Key: {

[PRIMARY_KEY]: spaceId

},

}).promise()

 


 

(42) Data Validation

Concepts like 'interfaces' and 'types' are not available at runtime.

runtime type validation is like a missing feature of typescript

 

options:

 

export interface Space {

spaceId: string

name: string,

location: string,

photoUrl?: string,

}

 

export class MissingFieldError extends Error {}

 

export function validateAsSpaceEntry(arg:any) {

if(!(arg as Space).name) {

throw new MissingFieldError('Value for name required!')

}

if(!(arg as Space).location) {

throw new MissingFieldError('Value for location required!')

}

if(!(arg as Space).spaceId) {

throw new MissingFieldError('Value for spaceId required!')

}

}

 


 

(43) refactors

a) uuid

import {v4} from "uuid";

this means the WHOLE uuid lib will be packaged up for the lambda

this library does not allow to `from "uuid/v4"`