From db885a6617a0108211b4b3f6f440296271e17281 Mon Sep 17 00:00:00 2001 From: Dane Pilcher Date: Mon, 2 Dec 2024 11:37:15 -0700 Subject: [PATCH 1/7] add batch ddb operations page --- src/directory/directory.mjs | 3 + .../batch-ddb-operations/index.mdx | 149 ++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx diff --git a/src/directory/directory.mjs b/src/directory/directory.mjs index 269af6f34ad..adfc7fdcd44 100644 --- a/src/directory/directory.mjs +++ b/src/directory/directory.mjs @@ -292,6 +292,9 @@ export const directory = { }, { path: 'src/pages/[platform]/build-a-backend/data/custom-business-logic/connect-http-datasource/index.mdx' + }, + { + path: 'src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx' } ] }, diff --git a/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx b/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx new file mode 100644 index 00000000000..ee19a70521a --- /dev/null +++ b/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx @@ -0,0 +1,149 @@ +import { getCustomStaticPath } from '@/utils/getCustomStaticPath'; + +export const meta = { + title: 'Batch DynamoDB Operations', + description: + 'Batch DynamoDB Operations', + platforms: [ + 'android', + 'angular', + 'flutter', + 'javascript', + 'nextjs', + 'react', + 'react-native', + 'swift', + 'vue' + ] +}; + +export const getStaticPaths = async () => { + return getCustomStaticPath(meta.platforms); +}; + +export function getStaticProps() { + return { + props: { + meta + } + }; +} + +Batch DynamoDB operations allow you to add multiple items in single mutation. + +## Step 1 - Define a custom mutation + +```ts +import { type ClientSchema, a, defineData } from '@aws-amplify/backend'; + +const schema = a.schema({ + // 1. Define your return type as a custom type or model + Post: a.model({ + id: a.id(), + content: a.string(), + likes: a.integer() + }), + + // 2. Define your mutation with the return type and, optionally, arguments + BatchCreatePost: a + .mutation() + // arguments that this query accepts + .arguments({ + content: a.string().array() + }) + .returns(a.ref("Post").array()) + // only allow signed-in users to call this API + .authorization(allow => [allow.authenticated()]) + .handler( + a.handler.custom({ + dataSource: a.ref("Post"), + entry: "./BatchCreatePostHandler.js", + }) + ) +}); + +export type Schema = ClientSchema; + +export const data = defineData({ + schema +}); +``` + +## Step 2 - Configure custom business logic handler code + +After your query or mutation is defined, you need to author your custom business logic using a [custom resolver powered by AppSync JavaScript resolver](https://docs.aws.amazon.com/appsync/latest/devguide/tutorials-js.html). + +Custom resolvers work on a "request/response" basis. You choose a data source, map your request to the data source's input parameters, and then map the data source's response back to the query/mutation's return type. Custom resolvers provide the benefit of no cold starts, less infrastructure to manage, and no additional charge for Lambda function invocations. Review [Choosing between custom resolver and function](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html#choosing-data-source). + +In your `amplify/data/resource.ts` file, define a custom handler using `a.handler.custom`. + +```ts title="amplify/data/resource.ts" +import { type ClientSchema, a, defineData } from '@aws-amplify/backend'; + +const schema = a.schema({ + Post: a.model({ + id: a.id(), + content: a.string(), + likes: a.integer() + }), + + BatchCreatePost: a + .mutation() + .arguments({ + contents: a.string().array() + }) + .returns(a.ref("Post").array()) + .authorization(allow => [allow.authenticated()]) + // 1. Add the custom handler + .handler( + a.handler.custom({ + dataSource: a.ref("Post"), + entry: "./BatchCreatePostHandler.js", + }) + ) +}); + +export type Schema = ClientSchema; + +export const data = defineData({ + schema +}); +``` + +```ts title="amplify/data/BatchCreatePostHandler.js" +import { util } from '@aws-appsync/utils'; +export function request(ctx) { + var now = util.time.nowISO8601(); + + return { + operation: "BatchPutItem", + tables: { + [`Post-${ctx.stash.awsAppsyncApiId}-${ctx.stash.amplifyBranchName}`]: ctx.args.contents.map((content) => + util.dynamodb.toMapValues({ + content, + id: util.autoId(), + createdAt: now, + updatedAt: now, + }) + ), + }, + }; +} + +export function response(ctx) { + if (ctx.error) { + util.error(ctx.error.message, ctx.error.type); + } + return ctx.result.data[`Post-${ctx.stash.awsAppsyncApiId}-${ctx.stash.amplifyBranchName}`]; +} +``` + +## Step 3 - Invoke the custom query or mutation + +From your generated Data client, you can find all your custom queries and mutations under the `client.queries.` and `client.mutations.` APIs respectively. + +```ts +const { data, errors } = await client.mutations.BatchCreatePost({ + contents: ['Post 1', 'Post 2', 'Post 3'] +}); +``` From 36d034aeb25fafcd7fcce810ef40c4c90cd3b8d9 Mon Sep 17 00:00:00 2001 From: Dane Pilcher Date: Tue, 3 Dec 2024 10:31:45 -0700 Subject: [PATCH 2/7] remove handler from first code block --- .../custom-business-logic/batch-ddb-operations/index.mdx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx b/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx index ee19a70521a..d1672154549 100644 --- a/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx @@ -54,12 +54,6 @@ const schema = a.schema({ .returns(a.ref("Post").array()) // only allow signed-in users to call this API .authorization(allow => [allow.authenticated()]) - .handler( - a.handler.custom({ - dataSource: a.ref("Post"), - entry: "./BatchCreatePostHandler.js", - }) - ) }); export type Schema = ClientSchema; From 03dd5ca8c4494e4e811f1d6e555909d1826d08a5 Mon Sep 17 00:00:00 2001 From: Dane Pilcher Date: Tue, 3 Dec 2024 10:43:04 -0700 Subject: [PATCH 3/7] add details on values in context stash --- .../custom-business-logic/batch-ddb-operations/index.mdx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx b/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx index d1672154549..ccaf92785c4 100644 --- a/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx @@ -104,6 +104,15 @@ export const data = defineData({ }); ``` +Amplify will store some values in the resolver context stash that can be accessed in the custom resolver. + +| Name | Description | +| ----------------- | ------------------------------------------- | +| awsAppsyncApiId | The ID of the AppSync API. | +| amplifyBranchName | The Amplify branch name. (`NONE` in sandbox) | + +The Amplify generated DynamoDB table names can be constructed from the variables in the context stash. The table name is in the format `--`. For example, the table name for the `Post` model would be `Post-123456-dev` where `123456` is the AppSync API ID and `dev` is the Amplify branch name. + ```ts title="amplify/data/BatchCreatePostHandler.js" import { util } from '@aws-appsync/utils'; export function request(ctx) { From 4ff92bc0250b22951281c1ba74bac27cc9e7256a Mon Sep 17 00:00:00 2001 From: Dane Pilcher Date: Wed, 11 Dec 2024 08:44:54 -0700 Subject: [PATCH 4/7] use single quotes --- .../batch-ddb-operations/index.mdx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx b/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx index ccaf92785c4..90319a0cd55 100644 --- a/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx @@ -51,7 +51,7 @@ const schema = a.schema({ .arguments({ content: a.string().array() }) - .returns(a.ref("Post").array()) + .returns(a.ref('Post').array()) // only allow signed-in users to call this API .authorization(allow => [allow.authenticated()]) }); @@ -86,13 +86,13 @@ const schema = a.schema({ .arguments({ contents: a.string().array() }) - .returns(a.ref("Post").array()) + .returns(a.ref('Post').array()) .authorization(allow => [allow.authenticated()]) // 1. Add the custom handler .handler( a.handler.custom({ - dataSource: a.ref("Post"), - entry: "./BatchCreatePostHandler.js", + dataSource: a.ref('Post'), + entry: './BatchCreatePostHandler.js', }) ) }); @@ -119,7 +119,7 @@ export function request(ctx) { var now = util.time.nowISO8601(); return { - operation: "BatchPutItem", + operation: 'BatchPutItem', tables: { [`Post-${ctx.stash.awsAppsyncApiId}-${ctx.stash.amplifyBranchName}`]: ctx.args.contents.map((content) => util.dynamodb.toMapValues({ From 81fc2adb763a21cc248b625e985b936485f7d9ca Mon Sep 17 00:00:00 2001 From: Dane Pilcher Date: Wed, 11 Dec 2024 08:45:33 -0700 Subject: [PATCH 5/7] add extra new line --- .../data/custom-business-logic/batch-ddb-operations/index.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx b/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx index 90319a0cd55..78118eccccc 100644 --- a/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx @@ -115,6 +115,7 @@ The Amplify generated DynamoDB table names can be constructed from the variables ```ts title="amplify/data/BatchCreatePostHandler.js" import { util } from '@aws-appsync/utils'; + export function request(ctx) { var now = util.time.nowISO8601(); From 67f21b30c341278c6b72dc564ea2afa3ed54a160 Mon Sep 17 00:00:00 2001 From: Dane Pilcher Date: Wed, 18 Dec 2024 10:24:16 -0700 Subject: [PATCH 6/7] Update src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx Co-authored-by: josef --- .../data/custom-business-logic/batch-ddb-operations/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx b/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx index 78118eccccc..a762b937738 100644 --- a/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx @@ -33,7 +33,7 @@ Batch DynamoDB operations allow you to add multiple items in single mutation. ## Step 1 - Define a custom mutation -```ts +```ts title="amplify/data/resource.ts" import { type ClientSchema, a, defineData } from '@aws-amplify/backend'; const schema = a.schema({ From e2439dcd8e895c3410813836203ae3f1315a9d87 Mon Sep 17 00:00:00 2001 From: Dane Pilcher Date: Wed, 18 Dec 2024 10:26:43 -0700 Subject: [PATCH 7/7] update to use amplifyApiEnvironmentName --- .../batch-ddb-operations/index.mdx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx b/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx index a762b937738..7a1ed30efc5 100644 --- a/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx @@ -106,12 +106,12 @@ export const data = defineData({ Amplify will store some values in the resolver context stash that can be accessed in the custom resolver. -| Name | Description | -| ----------------- | ------------------------------------------- | -| awsAppsyncApiId | The ID of the AppSync API. | -| amplifyBranchName | The Amplify branch name. (`NONE` in sandbox) | +| Name | Description | +| ------------------------- | -------------------------------------------- | +| awsAppsyncApiId | The ID of the AppSync API. | +| amplifyApiEnvironmentName | The Amplify api environment name. (`NONE` in sandbox) | -The Amplify generated DynamoDB table names can be constructed from the variables in the context stash. The table name is in the format `--`. For example, the table name for the `Post` model would be `Post-123456-dev` where `123456` is the AppSync API ID and `dev` is the Amplify branch name. +The Amplify generated DynamoDB table names can be constructed from the variables in the context stash. The table name is in the format `--`. For example, the table name for the `Post` model would be `Post-123456-dev` where `123456` is the AppSync API ID and `dev` is the Amplify API environment name. ```ts title="amplify/data/BatchCreatePostHandler.js" import { util } from '@aws-appsync/utils'; @@ -122,7 +122,7 @@ export function request(ctx) { return { operation: 'BatchPutItem', tables: { - [`Post-${ctx.stash.awsAppsyncApiId}-${ctx.stash.amplifyBranchName}`]: ctx.args.contents.map((content) => + [`Post-${ctx.stash.awsAppsyncApiId}-${ctx.stash.amplifyApiEnvironmentName}`]: ctx.args.contents.map((content) => util.dynamodb.toMapValues({ content, id: util.autoId(), @@ -138,7 +138,7 @@ export function response(ctx) { if (ctx.error) { util.error(ctx.error.message, ctx.error.type); } - return ctx.result.data[`Post-${ctx.stash.awsAppsyncApiId}-${ctx.stash.amplifyBranchName}`]; + return ctx.result.data[`Post-${ctx.stash.awsAppsyncApiId}-${ctx.stash.amplifyApiEnvironmentName}`]; } ```