Building a resolver to modify a DynamoDB item via AppSync using the AWS Cloud Development Kit (CDK)

After successfully creating a resolver to add an item in the table using the code provided below, I am now seeking assistance for replicating the same functionality for an update operation.

const configSettingsDS = api.addDynamoDbDataSource('configSettingsDynamoTable', configurationSettingsTable);

    configSettingsDS.createResolver({
        typeName:'Mutation',
        fieldName: 'createConfigSettings',
        requestMappingTemplate: appsync.MappingTemplate.dynamoDbPutItem(
            appsync.PrimaryKey.partition('id').auto(),
            appsync.Values.projecting('configSettings')),
        responseMappingTemplate: appsync.MappingTemplate.dynamoDbResultItem(),
    });

If anyone has any tips or guidance on how to achieve the same functionality for updates, I would greatly appreciate it. Thank you!

Answer №1

When it comes to the update resolver in DynamoDB, it operates similarly to the create resolver using the PutItem operation. This means that the same mapping template can be applied for both operations. The only change required is adjusting the first parameter from

appsync.PrimaryKey.partion('id').auto()
to
appsync.PrimaryKey.partion('id').is('<PATH_TO_YOUR_ID>')
.

While the id can be included as part of the input object, some prefer to keep it separate to avoid having the id within the input object. Here's a basic example illustrating both approaches:

graphql schema:

// Input A includes ID
input InputA {
    id: ID!
    name: String!
}

// Input B does not include an ID
input InputB {
    name: String!
}

type Mutation {
    // Id is part of input
    updateA(input: InputA)

    // Id needs to be provided separately
    updateB(id: ID!, InputB)
}

resolver code:

// Configure the resolver where ID is part of the input
const resolverA = datasource.createResolver({
    typeName: `Mutation`,
    fieldName: `updateA`,
    requestMappingTemplate: appsync.MappingTemplate.dynamoDbPutItem(
        appsync.PrimaryKey.partition('id').is('input.id'),
        appsync.Values.projecting('input'),
    ),
    responseMappingTemplate: appsync.MappingTemplate.dynamoDbResultItem(),
});

// Configure the resolver where ID is provided as a separate input parameter.
const resolverB = datasource.createResolver({
    typeName: `Mutation`,
    fieldName: `updateB`,
    requestMappingTemplate: appsync.MappingTemplate.dynamoDbPutItem(
        appsync.PrimaryKey.partition('id').is('id'),
        appsync.Values.projecting('input'),
    ),
    responseMappingTemplate: appsync.MappingTemplate.dynamoDbResultItem(),
});

In a recent project, I encountered and addressed a similar issue. Here are snippets depicting how I tackled this:

Part of the graphql schema:

input Label {
    id: ID!
    name: String!
    imageUrl: String
}

input LabelInput {
    name: String!
    imageUrl: String
}

type Mutation {
    createLabel(input: LabelInput!): Label
    updateLabel(id: ID!, input: LabelInput!): Label
}

Corresponding resolvers in cdk:

datasource.createResolver({
    typeName: `Mutation`,
    fieldName: `createLabel`,
    requestMappingTemplate: appsync.MappingTemplate.dynamoDbPutItem(
        appsync.PrimaryKey.partition('id').auto(),
        appsync.Values.projecting('input'),
    ),
    responseMappingTemplate: appsync.MappingTemplate.dynamoDbResultItem(),
});

datasource.createResolver({
    typeName: 'Mutation',
    fieldName: `updateLabel`,
    requestMappingTemplate: appsync.MappingTemplate.dynamoDbPutItem(
        appsync.PrimaryKey.partition('id').is('id'),
        appsync.Values.projecting('input'),
    ),
    responseMappingTemplate: appsync.MappingTemplate.dynamoDbResultItem(),
});

Answer №2

It appears that DynamoDB offers an operation called UpdateItem, which is not currently implemented in CDK from my understanding. My concern with using appsync.Values.projecting is that when executing a PutItem, if I am not aware of all the fields in the table, existing fields may be lost.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to find the average time in Typescript?

I am dealing with an object that contains the following properties: numberOfReturns: number = 0; returns_explanations: string [] = []; departure_time: string = ''; arrival_time: string = ''; The departure_time property hold ...

Handling HTTP errors in Angular when receiving a JSON response

I'm struggling to resolve this issue and I've searched online with no luck. The problem lies in my post call implementation, which looks like this: return this.http.post(url, body, { headers: ConnectFunctions.getHeader() }).pipe( map(result =&g ...

Using Typescript to Import One Namespace into Another Namespace

Is it possible to export a namespace from one typescript .d.ts file and then import that namespace into another .d.ts file where it is utilized inside of a namespace? For instance: namespace_export.d.ts export namespace Foo { interface foo { ...

What is preventing the getters for form errors from functioning in my Angular Reactive Form component template, while a direct reference does work?

I have a question regarding a small issue with an Angular reactive form in a lazily loaded signup module. The code structure is structured as follows: TS get email() { return this.myForm.get('email'); } // While this code works from within th ...

What is the method for storing a JSON object path in a variable for use in a template?

Trying to fetch data from a lengthy path has proven challenging for me. I attempted to store the path in a variable and incorporate it into the template, but encountered some issues. Could someone assist me with this? Here is what I have tried: My store ...

When attempting to send a token from an account to a marketplace in ERC721, the transfer caller must either be the owner

Currently, I am in the process of transferring my NFT to a marketplace pragma solidity ^0.8.7; import "@openzeppelin/contracts/utils/Counters.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; import & ...

Where does tsc retrieve its definitions from when utilizing npm definitions?

After transitioning from using typings to just relying on npm, I noticed that the @types directory in node_modules is present, but there are no additional files required. Previously with typings, I always had to include the index.d.ts file within the typi ...

Tips for selecting an image from the gallery with IONIC 3

Looking for guidance on extracting an image from the gallery in IONIC 3? I attempted to grab an image from the gallery but encountered some issues. Visit this link for more information This resource may also be helpful ...

Error in Visual Studio 2019 - TypeScript version discrepancy

I am completely puzzled by the mismatch in Typescript versions when using Visual Studio 2019 with my .NET Core 2.2.x project. Every time I make changes to a .ts file, I receive the following warning (found in the error list): Your project is built using ...

Pass a React component as a required prop in Typescript when certain props are necessary

I am currently working on a project where I need to create a custom TreeView component using React and Typescript. My goal is to have the ability to inject a template for each TreeNode in order to render them dynamically. My main challenge right now is fi ...

What is the process of invoking an external JavaScript function in Angular 5?

I recently downloaded a theme from this source. I need to specify script and CSS in the index.html file. The body section of index.html looks like this: <body> <app-root></app-root> <script type="text/javascript" src="./assets/js ...

Declaration of dependencies for NestJS must include dependencies of dependencies

I'm encountering an issue where NestJS is not automatically resolving dependencies-of-dependencies: I have created an AWSModule which is a simple link to Amazon AWS with only a dependency on the ConfigService: @Module({ imports: [ConfigModule], ...

Utilizing React forwardRef with a functional component

Looking at my code, I have defined an interface as follows: export interface INTERFACE1{ name?: string; label?: string; } Additionally, there is a function component implemented like this: export function FUNCTION1({ name, label }: INTERFACE1) { ...

Typescript not being transpiled by Webpack

As I set out to create a basic website, I opted to utilize webpack for packaging. TypeScript and SASS were my choice of tools due to their familiarity from daily use. Following the documentation at https://webpack.js.org, I encountered issues with loaders ...

The Object filter is experiencing a delay with processing 10,000 items

When an API returns over 10,000 objects in the format of {firstName:'john',lastName:'Cena'}, I am faced with a performance issue. In my parent React component, I make the API call in componentDidMount and pass this object to child compo ...

Issue with Jest/SuperTest Express integration tests: encountering "Can't set headers after they are sent" error when making requests to the same endpoint in multiple test cases

Dealing with a tricky situation here.. I'm currently in the process of writing integration tests for an Express (Typescript) app, using Jest and Supertest. My challenge lies in having multiple tests for the same endpoint, specifically to test respon ...

Prevent the Vue page from loading until the data has been fetched successfully

I'm in the process of finding a way to prevent my page from loading until my fetch task is completed. I'm facing some issues that need to be addressed: I have to re-fetch the data each time because I can't reuse the same data. (Changing vie ...

How to use sinon to create a mock for an independently imported function

Is there a way to successfully mock the axios import using sinon and then set expectations? Here is my attempted code: import axios from 'axios'; axiosMock = sinon.mock(axios); However, the expectation does not pass: describe('Custom test ...

Check out the computed typescript types

In my work with TypeScript types, I find myself frequently using Omit, Pick, and similar tools based on other types. While it generally gets the job done, I often struggle with readability when dealing with complex type manipulations. I am interested in f ...

Merging Two JSON Objects into a Single Object Using Angular 4-6

Two JSONs are available: The first one (with a length of 200): {date_end: "2099-12-31", id: "2341"} {date_end: "2099-12-31" id: "2342"} ... The second one (length 200): {type: "free", discount:"none", warranty: "yes"} {type: "free", discount:"none", ...