Saturday, June 4, 2022
HomeWordPress Development๐Ÿคนโ€โ™‚ AWS CDK 101 - ๐Ÿ„ GraphQL Mutations utilizing AppSync with dynamodb

๐Ÿคนโ€โ™‚ AWS CDK 101 – ๐Ÿ„ GraphQL Mutations utilizing AppSync with dynamodb


๐Ÿ”ฐ 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.

gql front



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
}
Enter fullscreen mode

Exit fullscreen mode

schema update



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'
    })
Enter fullscreen mode

Exit fullscreen mode



Importing desk arn on this stack ๐Ÿฎ

const messages = Desk.fromTableArn(
      this,
      "MessagesTableImport",
      Fn.importValue("MessagesTableArn")
    );

const MessagesDS = AppSyncApi.addDynamoDbDataSource("MessagesDataSource", messages);
Enter fullscreen mode

Exit fullscreen mode

GQL visual



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 test

test result

mutation resolvers



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"
      ),
    });
Enter fullscreen mode

Exit fullscreen mode



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",
    },
  },
}
Enter fullscreen mode

Exit fullscreen mode



createMessagesTableResponse VTL template โ›ฑ๏ธ


$util.toJson($context.outcome)

Enter fullscreen mode

Exit fullscreen mode

create xray



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"
      ),
    });
Enter fullscreen mode

Exit fullscreen mode



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),
  },
}
Enter fullscreen mode

Exit fullscreen mode



deleteMessagesTableResponse VTL template ๐ŸŽฃ

$util.toJson($context.outcome)
Enter fullscreen mode

Exit fullscreen mode

delete xray



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"
      ),
    });
Enter fullscreen mode

Exit fullscreen mode



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",
    },
  }
}
Enter fullscreen mode

Exit fullscreen mode



updateMessagesTableResponse VTL template ๐Ÿ

$util.toJson($context.outcome)
Enter fullscreen mode

Exit fullscreen mode

update xray



Shopper to discover graphQl โ„๏ธ

client



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.

create

update

delete



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.

collection

create apollo

update apollo

del apollo

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 ๐Ÿ˜.

Buy Me a Coffee at ko-fi.com

๐Ÿ” Unique put up at ๐Ÿ”— Dev Publish

๐Ÿ” Reposted at ๐Ÿ”— dev to @aravindvcyber

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments