From dc5d987a43049733d9510a03920cde899bb8b3db Mon Sep 17 00:00:00 2001 From: Aaron S Date: Fri, 15 Nov 2024 13:47:18 -0600 Subject: [PATCH 1/8] feat: Fix examples to use lambda data client --- .../index.mdx | 108 ++++++------------ .../create-user-profile-record/index.mdx | 62 ++-------- 2 files changed, 45 insertions(+), 125 deletions(-) diff --git a/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx b/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx index e0d025f2572..98fd6f308b5 100644 --- a/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx @@ -35,19 +35,16 @@ Function access to `defineData` can be configured using an authorization rule on import { a, defineData, - defineFunction, type ClientSchema } from '@aws-amplify/backend'; - -const functionWithDataAccess = defineFunction({ - entry: '../functions/data-access.ts' -}); +import { functionWithDataAccess } from '../function/data-access/resource.ts'; const schema = a .schema({ Todo: a.model({ name: a.string(), - description: a.string() + description: a.string(), + isDone: a.boolean() }) }) // highlight-next-line @@ -60,14 +57,26 @@ export const data = defineData({ }); ``` +Create a new directory and a resource file, `amplify/functions/data-access/resource.ts`. Then, define the Function with `defineFunction`: + +```ts title="amplify/functions/data-access/resource.ts" +import { defineFunction } from '@aws-amplify/backend'; + +export const functionWithDataAccess = defineFunction({ + name: 'data-access', + entry: './handler.ts' +}); +``` + The object returned from `defineFunction` can be passed directly to `allow.resource()` in the schema authorization rules. This will grant the function the ability to execute Query, Mutation, and Subscription operations against the GraphQL API. Use the `.to()` method to narrow down access to one or more operations. -```ts +```ts title="amplify/data/resource.ts" const schema = a .schema({ Todo: a.model({ name: a.string(), - description: a.string() + description: a.string(), + isDone: a.boolean() }) }) // highlight-start @@ -77,8 +86,6 @@ const schema = a // highlight-end ``` -When configuring function access, the function will be provided the API endpoint as an environment variable named `_GRAPHQL_ENDPOINT`, where `defineDataName` is transformed to SCREAMING_SNAKE_CASE. The default name is `AMPLIFY_DATA_GRAPHQL_ENDPOINT` unless you have specified a different name in `defineData`. - Function access can only be configured on the schema object. It cannot be configured on individual models or fields. @@ -89,86 +96,39 @@ Function access can only be configured on the schema object. It cannot be config In the handler file for your function, configure the Amplify data client -```ts title="amplify/functions/data-access.ts" +```ts title="amplify/functions/data-access/handler.ts" +import type { Handler } from 'aws-lambda'; import { Amplify } from 'aws-amplify'; import { generateClient } from 'aws-amplify/data'; -import { Schema } from '../data/resource'; +import { Schema } from '../../data/resource'; +import { getAmplifyDataClientConfig } from '@aws-amplify/backend/function/runtime'; import { env } from '$amplify/env/'; // replace with your function name +const { resourceConfig, libraryOptions } = await getAmplifyDataClientConfig(env); -Amplify.configure( - { - API: { - GraphQL: { - endpoint: env._GRAPHQL_ENDPOINT, // replace with your defineData name - 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 */ - }, - }, - }, - } -); - -const dataClient = generateClient(); +Amplify.configure(resourceConfig, libraryOptions); + +const client = generateClient(); export const handler = async (event) => { // your function code goes here } ``` -Use the command below to generate GraphQL client code to call your data backend. - - -**Note**: We are working on bringing the end-to-end typed experience to connect to your data from within function resources without needing this step. If you'd like to provide feedback the experience or have early access, join our [Discord community](https://discord.gg/amplify). - - - -```sh title="Terminal" showLineNumbers={false} -npx ampx generate graphql-client-code --out /graphql -``` - - - - -**Note:** Whenever you update your data model, you will need to run the command above again. - - - Once you have generated the client code, update the function to access the data. The following code creates a todo and then lists all todos. ```ts title="amplify/functions/data-access.ts" const client = generateClient(); -export const handler = async (event) => { - await client.graphql({ - query: createTodo, - variables: { - input: { - name: "My first todo", - description: "This is my first todo", - }, - }, - }); - - - await client.graphql({ - query: listTodos, - }); +export const handler: Handler = async (event) => { + const { errors: createErrors, data: newTodo } = await client.models.Todo.create({ + name: "My new todo", + description: "Todo description", + isDone: false, + }) + + + const { errors: listErrors, data: todos } = await client.models.Todo.list(); return event; }; diff --git a/src/pages/[platform]/build-a-backend/functions/examples/create-user-profile-record/index.mdx b/src/pages/[platform]/build-a-backend/functions/examples/create-user-profile-record/index.mdx index 0d9dab76926..e638a3184d7 100644 --- a/src/pages/[platform]/build-a-backend/functions/examples/create-user-profile-record/index.mdx +++ b/src/pages/[platform]/build-a-backend/functions/examples/create-user-profile-record/index.mdx @@ -89,20 +89,10 @@ import { defineFunction } from '@aws-amplify/backend'; export const postConfirmation = defineFunction({ name: 'post-confirmation', + entry: './handler.ts' }); ``` -Run the command `npx ampx sandbox` to create the backend, then use the command below to generate GraphQL client code to call your data backend. - - -**Note**: We are working on bringing the end-to-end typed experience to connect to your data from within function resources without needing this step. If you'd like to provide feedback on the experience or want to have early access, join our [Discord community](https://discord.gg/amplify). - - - -```sh title="Terminal" showLineNumbers={false} -npx ampx generate graphql-client-code --out /graphql -``` - Then, create the corresponding handler file, `amplify/auth/post-confirmation/handler.ts`, file with the following contents: ```ts title="amplify/auth/post-confirmation/handler.ts" @@ -110,50 +100,21 @@ import type { PostConfirmationTriggerHandler } from "aws-lambda"; import { type Schema } from "../../data/resource"; import { Amplify } from "aws-amplify"; import { generateClient } from "aws-amplify/data"; +import { getAmplifyDataClientConfig } from '@aws-amplify/backend/function/runtime'; import { env } from "$amplify/env/post-confirmation"; -import { createUserProfile } from "./graphql/mutations"; - -Amplify.configure( - { - API: { - GraphQL: { - endpoint: env.AMPLIFY_DATA_GRAPHQL_ENDPOINT, - region: env.AWS_REGION, - defaultAuthMode: "iam", - }, - }, - }, - { - Auth: { - credentialsProvider: { - getCredentialsAndIdentityId: async () => ({ - credentials: { - accessKeyId: env.AWS_ACCESS_KEY_ID, - secretAccessKey: env.AWS_SECRET_ACCESS_KEY, - sessionToken: env.AWS_SESSION_TOKEN, - }, - }), - clearCredentialsAndIdentityId: () => { - /* noop */ - }, - }, - }, - } + +const { resourceConfig, libraryOptions } = await getAmplifyDataClientConfig( + env ); -const client = generateClient({ - authMode: "iam", -}); +Amplify.configure(resourceConfig, libraryOptions); + +const client = generateClient(); export const handler: PostConfirmationTriggerHandler = async (event) => { - await client.graphql({ - query: createUserProfile, - variables: { - input: { - email: event.request.userAttributes.email, - profileOwner: `${event.request.userAttributes.sub}::${event.userName}`, - }, - }, + await client.models.UserProfile.create({ + email: event.request.userAttributes.email, + profileOwner: `${event.request.userAttributes.sub}::${event.userName}`, }); return event; @@ -162,7 +123,6 @@ export const handler: PostConfirmationTriggerHandler = async (event) => { ``` - Lastly, set the newly created Function resource on your auth resource: ```ts title="amplify/auth/resource.ts" From f5f6616fad501fa466986caa7ab4966533e683c0 Mon Sep 17 00:00:00 2001 From: Aaron S Date: Fri, 15 Nov 2024 15:28:58 -0600 Subject: [PATCH 2/8] fix: Schema import pattern --- .../grant-lambda-function-access-to-api/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx b/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx index 98fd6f308b5..9bd1dc88565 100644 --- a/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx @@ -98,9 +98,9 @@ In the handler file for your function, configure the Amplify data client ```ts title="amplify/functions/data-access/handler.ts" import type { Handler } from 'aws-lambda'; +import { type Schema } from '../../data/resource'; import { Amplify } from 'aws-amplify'; import { generateClient } from 'aws-amplify/data'; -import { Schema } from '../../data/resource'; import { getAmplifyDataClientConfig } from '@aws-amplify/backend/function/runtime'; import { env } from '$amplify/env/'; // replace with your function name From 6a7ce14a3177960c38fd0a1c0a43393f3d0f5028 Mon Sep 17 00:00:00 2001 From: "Aaron S." <94858815+stocaaro@users.noreply.github.com> Date: Tue, 19 Nov 2024 08:01:10 -0600 Subject: [PATCH 3/8] Update src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx Co-authored-by: josef --- .../grant-lambda-function-access-to-api/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx b/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx index 9bd1dc88565..1ef21fe3410 100644 --- a/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx @@ -98,7 +98,7 @@ In the handler file for your function, configure the Amplify data client ```ts title="amplify/functions/data-access/handler.ts" import type { Handler } from 'aws-lambda'; -import { type Schema } from '../../data/resource'; +import type { Schema } from '../../data/resource'; import { Amplify } from 'aws-amplify'; import { generateClient } from 'aws-amplify/data'; import { getAmplifyDataClientConfig } from '@aws-amplify/backend/function/runtime'; From bc73c5c0b3402c06cde1c704bbf64fdd58be321f Mon Sep 17 00:00:00 2001 From: Aaron S Date: Wed, 20 Nov 2024 17:48:09 -0600 Subject: [PATCH 4/8] Add warning after data client handler examples --- .../grant-lambda-function-access-to-api/index.mdx | 6 ++++++ .../functions/examples/create-user-profile-record/index.mdx | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx b/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx index 9bd1dc88565..909a93b2b5f 100644 --- a/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx @@ -115,6 +115,12 @@ export const handler = async (event) => { } ``` + + When configuring Amplify with `getAmplifyDataClientConfig`, your function consumes schema information from an S3 bucket + created during backend deployment with grants for the access your function need to use it. Any changes to this + bucket outside of backend deployment may break your function. + + Once you have generated the client code, update the function to access the data. The following code creates a todo and then lists all todos. ```ts title="amplify/functions/data-access.ts" diff --git a/src/pages/[platform]/build-a-backend/functions/examples/create-user-profile-record/index.mdx b/src/pages/[platform]/build-a-backend/functions/examples/create-user-profile-record/index.mdx index e638a3184d7..6b169907e90 100644 --- a/src/pages/[platform]/build-a-backend/functions/examples/create-user-profile-record/index.mdx +++ b/src/pages/[platform]/build-a-backend/functions/examples/create-user-profile-record/index.mdx @@ -122,6 +122,12 @@ export const handler: PostConfirmationTriggerHandler = async (event) => { ``` + + When configuring Amplify with `getAmplifyDataClientConfig`, your function consumes schema information from an S3 bucket + created during backend deployment with grants for the access your function need to use it. Any changes to this + bucket outside of backend deployment may break your function. + + Lastly, set the newly created Function resource on your auth resource: From 7665a12e025f89556712ba2f7d4d56f3b879e4c5 Mon Sep 17 00:00:00 2001 From: "Aaron S." <94858815+stocaaro@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:23:27 -0600 Subject: [PATCH 5/8] Update src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx Co-authored-by: josef --- .../grant-lambda-function-access-to-api/index.mdx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx b/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx index f8d77d3ccc8..9c5804c607b 100644 --- a/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx @@ -116,9 +116,7 @@ export const handler = async (event) => { ``` - When configuring Amplify with `getAmplifyDataClientConfig`, your function consumes schema information from an S3 bucket - created during backend deployment with grants for the access your function need to use it. Any changes to this - bucket outside of backend deployment may break your function. +When configuring Amplify with `getAmplifyDataClientConfig`, your function consumes schema information from an S3 bucket created during backend deployment with grants for the access your function need to use it. Any changes to this bucket outside of backend deployment may break your function. Once you have generated the client code, update the function to access the data. The following code creates a todo and then lists all todos. From 387d0e79faccea628653c82e0c50420f95ec1315 Mon Sep 17 00:00:00 2001 From: "Aaron S." <94858815+stocaaro@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:31:48 -0600 Subject: [PATCH 6/8] Update src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx Co-authored-by: josef --- .../grant-lambda-function-access-to-api/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx b/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx index 9c5804c607b..1db072540ce 100644 --- a/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx @@ -37,7 +37,7 @@ import { defineData, type ClientSchema } from '@aws-amplify/backend'; -import { functionWithDataAccess } from '../function/data-access/resource.ts'; +import { functionWithDataAccess } from '../function/data-access/resource'; const schema = a .schema({ From 66decc70cd8dc787e5670e8fce02f9717358e7cc Mon Sep 17 00:00:00 2001 From: "Aaron S." <94858815+stocaaro@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:33:37 -0600 Subject: [PATCH 7/8] Update src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx Co-authored-by: josef --- .../grant-lambda-function-access-to-api/index.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx b/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx index 1db072540ce..04da21c3ebf 100644 --- a/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx @@ -64,7 +64,6 @@ import { defineFunction } from '@aws-amplify/backend'; export const functionWithDataAccess = defineFunction({ name: 'data-access', - entry: './handler.ts' }); ``` From 8925b77aca9ab0da09ae2f2c97afeecdea9f12f0 Mon Sep 17 00:00:00 2001 From: "Aaron S." <94858815+stocaaro@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:34:37 -0600 Subject: [PATCH 8/8] Apply suggestions from code review Co-authored-by: josef --- .../functions/examples/create-user-profile-record/index.mdx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/pages/[platform]/build-a-backend/functions/examples/create-user-profile-record/index.mdx b/src/pages/[platform]/build-a-backend/functions/examples/create-user-profile-record/index.mdx index 6b169907e90..26a5dcd39fc 100644 --- a/src/pages/[platform]/build-a-backend/functions/examples/create-user-profile-record/index.mdx +++ b/src/pages/[platform]/build-a-backend/functions/examples/create-user-profile-record/index.mdx @@ -89,7 +89,6 @@ import { defineFunction } from '@aws-amplify/backend'; export const postConfirmation = defineFunction({ name: 'post-confirmation', - entry: './handler.ts' }); ``` @@ -123,9 +122,7 @@ export const handler: PostConfirmationTriggerHandler = async (event) => { ``` - When configuring Amplify with `getAmplifyDataClientConfig`, your function consumes schema information from an S3 bucket - created during backend deployment with grants for the access your function need to use it. Any changes to this - bucket outside of backend deployment may break your function. +When configuring Amplify with `getAmplifyDataClientConfig`, your function consumes schema information from an S3 bucket created during backend deployment with grants for the access your function need to use it. Any changes to this bucket outside of backend deployment may break your function.