Juan Guillermo
Juan Guillermo

Reputation: 31

Amplify Gen 2: Put data in DynamoDB using Lambda

I am having trouble getting Lambda to insert data into the Todo table defined in Amplify.

Specifically, how do I obtain 'DATA_TODO_TABLE_NAME' and 'AWS_REGION'? I am encountering the error "Property 'DATA_TODO_TABLE_NAME' does not exist on type 'LambdaProvidedEnvVars & AmplifyBackendEnvVars'" in the 'env' object.

I have seen examples with S3, where Amplify automatically creates an environment variable for the created bucket, but I am unable to resolve this for DynamoDB.

According to the documentation, I have two options to grant Lambda access to other resources: the access property and CDK. However, it seems that my skills to resolve this are insufficient.

I hope to be able to add data from Lambda to the Todo table defined in amplify/data/resource.ts.

I have this code:

// amplify/data/resource.ts
import { type ClientSchema, a, defineData } from "@aws-amplify/backend";
import { generateStory } from "../functions/generate-story/resource";

const schema = a.schema({
  Todo: a
    .model({
      content: a.string(),
    })
    .authorization((allow) => [allow.guest()]),
});

export type Schema = ClientSchema<typeof schema>;

export const data = defineData({
  schema,
});

And this:

// amplify/functions/generate-story/handler.ts
import { DynamoDBClient, PutItemCommand } from "@aws-sdk/client-dynamodb";
import { env } from "$amplify/env/generate-story";

const ddbClient = new DynamoDBClient({ region: env.AWS_REGION });

export const handler = async (event) => {
  const command = new PutItemCommand({
    TableName: env.DATA_TODO_TABLE_NAME,
    Item: {
      id: { S: 'example-id' },
      content: { S: 'example-content' }
    },
  });

  try {
    await ddbClient.send(command);
    
    return {
      statusCode: 200,
      body: JSON.stringify({ message: "Item inserted successfully" }),
    };
  } catch (error) {
    console.error("Error inserting item:", error);
    return {
      statusCode: 500,
      body: JSON.stringify({ message: "Error inserting item" }),
    };
  }
};

Upvotes: 3

Views: 647

Answers (2)

Nishit Raval
Nishit Raval

Reputation: 69

To resolve your issue with inserting data into the Todo table from a Lambda function in Amplify Gen 2, here’s a step-by-step approach that should help you get DATA_TODO_TABLE_NAME and AWS_REGION working.

First, when you're developing locally, run your Amplify backend in a sandbox environment using this command:

npx ampx sandbox --stream-function-logs

When you do this, Amplify generates environment variables based on your setup, and they get stored in a temporary .amplify/generated/. These variables are automatically populated from your defineFunction configuration or any environment variables you’ve set in the Amplify console later when you deploy.

Now you can use process.env.AWS_REGION

Also by importing

import { env } from '$amplify/env/generate-story';

console.log(env.AWS_REGION)
console.log(env.AMPLIFY_DATA_GRAPHQL_ENDPOINT)

Upvotes: -1

upp22
upp22

Reputation: 46

Looking at your code I presume you're using Amplify Gen 2 backend?

They've moved from the Gen 1 way of doing this (where amplify generates the table variables etc.). The Lambda should use the schema with generateClient from aws-amplify/data to access the dynamodb tables. This is far better than messing around with env variables everywhere IMO. The schema has to allow the lambda function to do this - permissions defined in the (amplify/data/resource.ts).

Follow the guide here:

https://docs.amplify.aws/react-native/build-a-backend/functions/examples/create-user-profile-record/

You need the latest version of everything amplify. To support importing env from "$amplify/env/post-confirmation" I had to add the path to the amplify/tsconfig.json:

{
  "compilerOptions": {
    "target": "es2022",
    "module": "es2022",
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "paths": {
      "$amplify/*": ["../.amplify/generated/*"]
    }
  },
}

Upvotes: 0

Related Questions