๐ฐ Freshmen new to AWS CDK, please do have a look at my earlier articles one after the other on this collection.
If in case missed my earlier article, do discover it with the under hyperlinks.
๐ Unique earlier put up at ๐ Dev Publish
๐ Reposted the earlier put up at ๐ dev to @aravindvcyber
On this article, we will probably be introducing an information entry layer as a wrapper on high of our dynamodb desk. Right here particularly now we have chosen graphql utilizing AWS appsync to carry out mutations in our dynamodb desk.
Building ๐๏ธ
Allow us to begin by updating our earlier file lib/appsync-stack.ts
for our new stack.
Schema definition for Mutations ๐ข
You might also use the AWS console to replace the schema earlier than we replace in CDK asset information once we know for positive.
Right here you will discover the mutations half which now we have appended to our schema file which we created in our earlier article above.
enter CreateMessagesTableInput {
createdAt: Int!
messageId: String!
occasion: AWSJSON
}
enter UpdateMessagesTableInput {
createdAt: Int!
messageId: String!
occasion: AWSJSON
}
enter DeleteMessagesTableInput {
createdAt: Int!
messageId: String!
}
kind Mutation {
createMessagesTable(enter: CreateMessagesTableInput!): MessagesTable
updateMessagesTable(enter: UpdateMessagesTableInput!): MessagesTable
deleteMessagesTable(enter: DeleteMessagesTableInput!): MessagesTable
}
Dynamodb connection as an information supply ๐ถ
Right here now we have already instantly built-in dynamodb API with graphql as an information supply.
Moreover we’re updating our earlier article by making use of the import worth of desk arn to get the desk title instantly from the earlier stack exports.
Exporting desk arn from one other stack ๐
new CfnOutput(this, "MessagesTableExport", {
worth: messages.tableArn,
exportName: 'MessagesTableArn'
})
Importing desk arn on this stack ๐ฎ
const messages = Desk.fromTableArn(
this,
"MessagesTableImport",
Fn.importValue("MessagesTableArn")
);
const MessagesDS = AppSyncApi.addDynamoDbDataSource("MessagesDataSource", messages);
VTL Mapping template ๐ฉ๏ธ
Right here we have to use VTL (Velocity Template Language) to remodel/manipulate our request and the response we ship/obtain from the under resolvers. Utilizing this generally is a good technique as this can be utilized in lots of locations not solely in appsync and API gateway.
You might also use the AWS console to check these transformations utilizing the pattern payload from logs earlier than we replace in CDK asset information.
Create message resolver ๐
Right here you may as well look into the Xray hint to know when these blocks are utilized for createMessagesTable
resolver
MessagesDS.createResolver({
typeName: "Mutation",
fieldName: "createMessagesTable",
requestMappingTemplate: MappingTemplate.fromFile(
"property/createMessagesTableRequest.vtl"
),
responseMappingTemplate: MappingTemplate.fromFile(
"property/createMessagesTableResponse.vtl"
),
});
createMessagesTableRequest VTL template ๐
{
"model": "2017-02-28",
"operation": "PutItem",
"key": {
"messageId": $util.dynamodb.toDynamoDBJson($ctx.args.enter.messageId),
"createdAt": $util.dynamodb.toDynamoDBJson($ctx.args.enter.createdAt),
},
"attributeValues": $util.dynamodb.toMapValuesJson($ctx.args.enter),
"situation": {
"expression": "attribute_not_exists(#messageId) AND attribute_not_exists(#createdAt)",
"expressionNames": {
"#messageId": "messageId",
"#createdAt": "createdAt",
},
},
}
createMessagesTableResponse VTL template โฑ๏ธ
$util.toJson($context.outcome)
Delete message resolver ๐คก
Right here you may as well look into the Xray hint to know when these blocks are utilized for deleteMessagesTable
resolver
MessagesDS.createResolver({
typeName: "Mutation",
fieldName: "deleteMessagesTable",
requestMappingTemplate: MappingTemplate.fromFile(
"property/deleteMessagesTableRequest.vtl"
),
responseMappingTemplate: MappingTemplate.fromFile(
"property/deleteMessagesTableResponse.vtl"
),
});
deleteMessagesTableRequest VTL template ๐
{
"model": "2017-02-28",
"operation": "DeleteItem",
"key": {
"messageId": $util.dynamodb.toDynamoDBJson($ctx.args.enter.messageId),
"createdAt": $util.dynamodb.toDynamoDBJson($ctx.args.enter.createdAt),
},
}
deleteMessagesTableResponse VTL template ๐ฃ
$util.toJson($context.outcome)
Replace messages resolver ๐ฆ
Right here you may as well look into the xray hint to know when these blocks are utilized for updateMessagesTable
resolver
MessagesDS.createResolver({
typeName: "Mutation",
fieldName: "updateMessagesTable",
requestMappingTemplate: MappingTemplate.fromFile(
"property/updateMessagesTableRequest.vtl"
),
responseMappingTemplate: MappingTemplate.fromFile(
"property/updateMessagesTableResponse.vtl"
),
});
updateMessagesTableRequest VTL template ๐ฟ๏ธ
This replace logic could look complicated however simply do not forget that whereas updating we have to care for up to date attributes, eliminated attributes, and new attributes.
{
"model": "2017-02-28",
"operation": "UpdateItem",
"key": {
"messageId": $util.dynamodb.toDynamoDBJson($ctx.args.enter.messageId),
"createdAt": $util.dynamodb.toDynamoDBJson($ctx.args.enter.createdAt),
},
#set( $expNames = {} )
#set( $expValues = {} )
#set( $expSet = {} )
#set( $expAdd = {} )
#set( $expRemove = [] )
## Looping by every argument, besides keys **
#foreach( $entry in $util.map.copyAndRemoveAllKeys($ctx.args.enter, ["messageId", "createdAt"]).entrySet() )
#if( $util.isNull($entry.worth) )
#set( $discard = ${expRemove.add("#${entry.key}")} )
$!{expNames.put("#${entry.key}", "${entry.key}")}
#else
$!{expSet.put("#${entry.key}", ":${entry.key}")}
$!{expNames.put("#${entry.key}", "${entry.key}")}
$!{expValues.put(":${entry.key}", $util.dynamodb.toDynamoDB($entry.worth))}
#finish
#finish
## Updating current attributes **
#set( $expression = "" )
#if( !${expSet.isEmpty()} )
#set( $expression = "SET" )
#foreach( $entry in $expSet.entrySet() )
#set( $expression = "${expression} ${entry.key} = ${entry.worth}" )
#if ( $foreach.hasNext )
#set( $expression = "${expression}," )
#finish
#finish
#finish
## Including new attributes **
#if( !${expAdd.isEmpty()} )
#set( $expression = "${expression} ADD" )
#foreach( $entry in $expAdd.entrySet() )
#set( $expression = "${expression} ${entry.key} ${entry.worth}" )
#if ( $foreach.hasNext )
#set( $expression = "${expression}," )
#finish
#finish
#finish
## Eradicating undesirable attributes **
#if( !${expRemove.isEmpty()} )
#set( $expression = "${expression} REMOVE" )
#foreach( $entry in $expRemove )
#set( $expression = "${expression} ${entry}" )
#if ( $foreach.hasNext )
#set( $expression = "${expression}," )
#finish
#finish
#finish
## Closing replace expression **
"replace": {
"expression": "${expression}",
#if( !${expNames.isEmpty()} )
"expressionNames": $utils.toJson($expNames),
#finish
#if( !${expValues.isEmpty()} )
"expressionValues": $utils.toJson($expValues),
#finish
},
"situation": {
"expression": "attribute_exists(#messageId) AND attribute_exists(#createdAt)",
"expressionNames": {
"#messageId": "messageId",
"#createdAt": "createdAt",
},
}
}
updateMessagesTableResponse VTL template ๐
$util.toJson($context.outcome)
Shopper to discover graphQl โ๏ธ
Appsync Explorer Queries โจ๏ธ
Within the AWS console, you’ll be able to navigate the appsync and begin querying. One benefit you may have right here is that now we have cloud watch and tracing logs available if in case you need to verify.
Apollo Studio Queries ๐๏ธ
However usually choose the darkish mode in apollo graphql studio, you might also strive it out for those who choose that, perhaps we might get that within the AWS console as effectively sometime.
We will probably be refining this in our coming articles to realize optimum velocity and useful resource utilization.
We will probably be including extra connections to our stack and making it extra usable within the upcoming articles by creating new constructs, so do contemplate following and subscribing to my e-newsletter.
โญ Now we have our subsequent article in serverless, do take a look at
๐ Thanks for supporting! ๐
Could be nice for those who prefer to โ Purchase Me a Espresso, to assist enhance my efforts ๐.
๐ Unique put up at ๐ Dev Publish
๐ Reposted at ๐ dev to @aravindvcyber