amazon-web-servicesaws-lambdaamazon-dynamodbaws-amplify

Using AWS Amplify, I'm trying to find the table name for the dynamodb table that is created with the data/resource. How Can I find that?


I'm trying to find the table name to use the dynamo db that is auto generated using AWS Amplify after creating a schema using 'data'. How can I find that?

Here is what I've tried:

resource.ts file

const schema = a
  .schema({
    UserProfileFlags: a.customType({
      isBetaUser: a.boolean(),
      isFounder: a.boolean(),
      isBanned: a.boolean(),
      isSuspended: a.boolean(),
      isVerified: a.boolean(),
      isDeleted: a.boolean(),
    }),

    UserProfile: a
      .model({
        userName: a.string().required(),
        owner: a
          .string()
          .authorization((allow) => [allow.owner().to(['read', 'delete'])]),
...

to define a database in dynamo named UserProfile. That works fine, the db is created and the table exists. Now I'm trying to create a function to access that table. I've tried many iterations, but they all have errors/won't compile or work:

I found this:

import { DynamoDB } from 'aws-sdk';
import { getDataSource } from '@aws-amplify/backend-function';
import type { Schema } from '../../data/resource';

const dynamodb = new DynamoDB.DocumentClient();

export const handler: Schema['createEmptyProfile']['handler'] = async (event, context) => {
  const dataSource = getDataSource(context);
  const TABLE_NAME = dataSource.resources.UserProfile.tableName;

This one tells me that import { getDataSource } from '@aws-amplify/backend-function'; is a problem:

Module '"@aws-amplify/backend-function"' has no exported member 'getDataSource'.ts(2305)

I've also tried running this: npx ampx generate graphql-client-code --out /graphql

and then

import { env } from "$amplify/env/post-confirmation";
...
        endpoint: env.AMPLIFY_DATA_GRAPHQL_ENDPOINT,
...

But this too shows AMPLIFY_DATA_GRAPHQL_ENDPOINT is undefined, and if I look in the generated .ts files, I don't see it either.

That kind of makes sense, since I'm not sure how that would work when deployed, as it needs a different table name. This is all running against a local sandbox.

Here is the docs link that I can find: https://docs.amplify.aws/react/build-a-backend/functions/examples/create-user-profile-record/


Solution

  • I'm running Amplify Gen 2 also; here's what worked for me.

    I wasn't able to get any solution involving setting environment variables to work reliably. But what did work was to create SSM parameters with the values I needed, and grant my lambda permissions to read them.

    In my backend, after creating the resources I need (AccountTable's ARN, in this case):

    const envName = process.env.AMPLIFY_BRANCH || 'dev';
    const accountTableParam = new cdk.aws_ssm.StringParameter(
      apiStack,
      "AccountTableParam",
      {
        parameterName: `/secure-site/${envName}/account-table-name`,
        stringValue: accountTable.tableName,
      }
    );
    
    const allowSignLambdaToAccessAccountTablePolicy = new Policy(
      cdk.Stack.of(accountTable),
      "allowSignLambdaToAccessAccountTablePolicy",
      {
        statements: [
          new PolicyStatement({
            effect: Effect.ALLOW,
            actions: [
              "dynamodb:GetItem",
              "dynamodb:UpdateItem",
              "dynamodb:Query",
              "dynamodb:Scan",
            ],
            resources: [accountTable.tableArn],
          }),
          new PolicyStatement({
            effect: Effect.ALLOW,
            actions: ["ssm:GetParameter"],
            resources: [
              accountTableParam.parameterArn,
            ],
          }),
        ],
      }
    );
    

    Then in my lambda's code, I could read the parameter:

    const ssmClient = new SSMClient();
    const envName = process.env.AMPLIFY_BRANCH || 'dev';
    
    async function getParameter(name: string): Promise<string> {
      const paramPath = `/secure-site/${envName}/${name}`;
      const command = new GetParameterCommand({ Name: paramPath });
      const response = await ssmClient.send(command);
      return response.Parameter?.Value || '';
    }
    
    const table = await getParameter('account-table-name');