aws-amplify / amplify-category-api

The AWS Amplify CLI is a toolchain for simplifying serverless web and mobile development. This plugin provides functionality for the API category, allowing for the creation and management of GraphQL and REST based backends for your amplify project.
https://docs.amplify.aws/
Apache License 2.0
88 stars 75 forks source link

Get ApiId or Table Name in custom handler #2708

Open godrimcom opened 2 months ago

godrimcom commented 2 months ago

Environment information

System:
  OS: macOS 14.5
  CPU: (10) arm64 Apple M1 Pro
  Memory: 153.83 MB / 16.00 GB
  Shell: /bin/zsh
Binaries:
  Node: 20.12.0 - ~/.nvm/versions/node/v20.12.0/bin/node
  Yarn: undefined - undefined
  npm: 10.5.0 - ~/.nvm/versions/node/v20.12.0/bin/npm
  pnpm: undefined - undefined
NPM Packages:
  @aws-amplify/backend: 1.0.0
  @aws-amplify/backend-cli: 1.0.1
  aws-amplify: 6.3.8
  aws-cdk: 2.140.0
  aws-cdk-lib: 2.140.0
  typescript: 5.4.5
AWS environment variables:
  AWS_STS_REGIONAL_ENDPOINTS = regional
  AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1
  AWS_SDK_LOAD_CONFIG = 1
No CDK environment variables

Description

I'm using amplify gen 2 and I added a custom handler in my schema:

deleteTickets: a
    .mutation()
    .arguments({
      ids: a.id().array(),
    })
    .returns(a.json())
    .authorization((allow) => [allow.authenticated()])
    .handler(
      a.handler.custom({
        dataSource: a.ref('Ticket'),
        entry: './handlers/tickets/deleteTickets.js',
      })
    ),

this is my handler:

export function request(ctx) {
  const { ids } = ctx.args

  return {
    operation: 'BatchDeleteItem',
    tables: {
      TABLE_NAME: ids.map((id) => util.dynamodb.toMapValues({ id })),
     // How can I access the table name? in ctx. This is the actual table name Ticket-ruzu7wa7dzcbflfe2qpamijr5a-NONE
    },
  }
}

export function response(ctx) {
  if (ctx.error) {
    util.error(ctx.error.message, ctx.error.type)
  }
  return ctx.result || {}
}

I just want to do a BatchDeleteItem operation. This should be a basic operation, please help

ykethan commented 1 month ago

Hey,👋 thanks for raising this! I'm going to transfer this over to our API repository for better assistance 🙂

AnilMaktala commented 1 month ago

Hey @godrimcom, Thank you for bringing this up. Could you please clarify if you have already reviewed the relevant documentation on this topic?

chrisbonifacio commented 1 month ago

Hi @godrimcom At the moment there is no way, at least that I'm aware of, to access and pass the table name to a resolver without incurring a "circular dependency" error. You may have to hard code the table name and pass it as an environment variable.

ex:

backend.data.resources.cfnResources.cfnGraphqlApi.environmentVariables = {
  TODO_TABLE:
    // replace with your own table name
    `Todo-md4n36jl7za7xi4mie3cs3wyey-NONE`,
};

in the resolver you'd access environment variables from the context:

import { util } from "@aws-appsync/utils";

export const request = (ctx) => {
  const todos = [];

  ctx.args.todos.forEach(({id}) => {
    todo.push(util.dynamodb.toMapValues({ id }));
  });

  return {
    operation: "BatchGetItem",
    tables: {
      [ctx.env.TODO_TABLE]: {
        keys: todos,
      },
    },
  };
};

export const response = (ctx) => {
  return ctx.result.data[ctx.env.TODO_TABLE];
};

we are working on a way to make the DDB tables accessible.

UPDATE: You can also compute the name of the table because it will be in the format <model>-<apiId>-<environment>.

I'm not sure what determines <environment>, in my sandbox environment it's set to NONE, hence the table name "Todo-md4n36jl7za7xi4mie3cs3wyey-NONE"

andrew-clark-dev commented 1 month ago

Hi @chrisbonifacio , just checking that you know you can access the table name from the data resources. So


const { tables } = backend.data.resources

backend.data.resources.cfnResources.cfnGraphqlApi.environmentVariables = {
  TODO_TABLE: tables['Todo'],
};