#✅ - What is the best way to access the same GraphQL from different Lambda functions?

17 messages · Page 1 of 1 (latest)

wind scroll
#

I have multiple Lambda functions connected to the same ApiGateway and also some Auth triggers for a custom authentication flow.

At the moment im only accessing the GraphQL in one specific Lambda Function, but now I need to access it from another Function and also the Auth triggers.

I noticed that in the docs it show how to do it: https://docs.amplify.aws/react/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/#access-the-api-using-aws-amplify but its a solution that works per function and I know it has an alert about it.

Im wondering if there is a better way to generate the GraphQL files onces and maybe use the Amplify configure per functions. Otherwise I would need to have a bunch of duplicated content per function to be able to access the same GraphQL.

Thanks in advance

untold onyx
#

👋 we're working towards an experience that will enable the use of the data client in functions, though in the meantime the guidance is to generate the client code. you can generate this once, though, and use it in any function. it should all be the same and the bundling step will remove the operations you don't use

wind scroll
#

Nice, thanks (again) @untold onyx .

So can I export this data once and just use the env generated from one specific function for all functions to be able to use or I still need to run :
npx ampx generate graphql-client-code --out <path-function-handler-dir>/graphql
for every function?

and then setup this:

import { env } from '$amplify/env/myFunctName';
import { Amplify } from 'aws-amplify';
import { generateClient } from 'aws-amplify/data';
import { Schema } from '../../data/resource';

Amplify.configure(
  {
    API: {
      GraphQL: {
        endpoint: env.AMPLIFY_DATA_GRAPHQL_ENDPOINT,
        region: env.AWS_REGION,
        defaultAuthMode: 'identityPool',
      },
    },
  },
  {
    Auth: {
      credentialsProvider: {
        getCredentialsAndIdentityId: async () => ({
          credentials: {
            accessKeyId: env.AWS_ACCESS_KEY_ID,
            secretAccessKey: env.AWS_SECRET_ACCESS_KEY,
            sessionToken: env.AWS_SESSION_TOKEN,
          },
        }),
        clearCredentialsAndIdentityId: () => {
          /* noop */
        },
      },
    },
  }
);

export const dataClient = generateClient<Schema>();

If I need to have this setup for every function I will try to create a helper function to receive the env from the function calling it.

untold onyx
#

I would minimize usage of the env object only to the function it's for to mitigate inadvertent usage of env vars/secrets you may add to other functions. But yes you can generate the client code once and use wherever

wind scroll
#

Im also assuming that this script npx ampx generate graphql-client-code --out <path-function-handler-dir>/graphql that creates env.AMPLIFY_DATA_GRAPHQL_ENDPOINT in a specific function, is that correct?

untold onyx
#

no that env var will be generated if your function has access to the schema with .authorization((allow) => ([allow.resource(myFunction).to(["query"]))

#

graphql-client-code will generate just the graphql statements and types

wind scroll
#

ah! perfect then. will change my structure here and will get back to you.

untold onyx
#

sounds good, let us know how it goes!

wind scroll
#

Will do, cheers

#

So in theory the export script doesnt need to point to a function folder, could it be at any place inside the amplify/

npx ampx generate graphql-client-code --out data-client/graphql

then have a generic initialiser for the data client which the function will pass its env

something like:

import { Amplify } from 'aws-amplify';
import { generateClient } from 'aws-amplify/data';
import { Schema } from '../../data/resource';

type initDataClientVars = {
  AMPLIFY_DATA_GRAPHQL_ENDPOINT: string;
  AWS_REGION: string;
  AWS_ACCESS_KEY_ID: string;
  AWS_SECRET_ACCESS_KEY: string;
  AWS_SESSION_TOKEN: string;
};

export function initDataClient(env: initDataClientVars) {
  Amplify.configure(
    {
      API: {
        GraphQL: {
          endpoint: env.AMPLIFY_DATA_GRAPHQL_ENDPOINT,
          region: env.AWS_REGION,
          defaultAuthMode: 'identityPool',
        },
      },
    },
    {
      Auth: {
        credentialsProvider: {
          getCredentialsAndIdentityId: async () => ({
            credentials: {
              accessKeyId: env.AWS_ACCESS_KEY_ID,
              secretAccessKey: env.AWS_SECRET_ACCESS_KEY,
              sessionToken: env.AWS_SESSION_TOKEN,
            },
          }),
          clearCredentialsAndIdentityId: () => {
            /* noop */
          },
        },
      },
    }
  );

  return generateClient<Schema>();
}

(just deploying to test this approach atm)

#

this approach worked, deployed properly and the functions were able to access.

If a function that tries to use the dataClient instance doesnt have the env.AMPLIFY_DATA_GRAPHQL_ENDPOINT or any other required variables by the initDataClientVars it shows a TS error 🙌

untold onyx
#

oh nice! yeah that's perfect! to this note

So in theory the export script doesnt need to point to a function folder, could it be at any place inside the amplify/
it could be anywhere on the filesystem, from an npm package, etc.. the backend tooling is using esbuild under the hood to bundle which should resolve the imports, remove the code that's not being used, then bundle the dependencies

wind scroll
#

Thanks for the clarification, I got confused that I needed to run the script per function as per documentation. Glad that wans't the case.

untold onyx
#

ah yeah that docs page could use a clarification, but glad to hear you're up and running! We'll add this page to our list of pages to update when this experience is smoothed out with data client support 🙂

rare pebble
indigo marshBOT
#

✅ - What is the best way to access the same GraphQL from different Lambda functions?